using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RayTracing
{
public partial class Form1 : Form
{
public Form1(){InitializeComponent();}
private voidForm1_Load(object sender, EventArgs e){}
private voidbutton1_Click(object sender, EventArgs e){// 眼睛
Camera camera = new Camera();
camera.loc = new Point3D(0,0,10);// 成像平面
ViewPlain vp = new ViewPlain();
vp.topLeftLoc = new Point3D(-4,3,0);
vp.w =8;
vp.h =6;
vp.wRes =800;
vp.hRes =600;// 位图
Bitmap bmp = new Bitmap(vp.wRes, vp.hRes);// 求每一小格的偏移量double wStep = vp.w / vp.wRes;double hStep = vp.h / vp.hRes;// 球体
Sphere sphere = new Sphere();
sphere.Center = new Point3D(0,0,-10);
sphere.Radius =3;// 在成像平面成像for(int i =0; i < vp.wRes; i++){for(int j =0; j < vp.hRes; j++){
Point3D pLoc = new Point3D(vp.topLeftLoc.X + wStep * i,
vp.topLeftLoc.Y - hStep * j,0);
Ray ray = new Ray(camera.loc, pLoc - camera.loc);
ray.Dir.Normalize();
HitRecord hitRecord = ray.isHit(sphere);// 光源的位置
Point3D lightLoc = new Point3D(-10,10,0);// 光源的颜色
Color lightColor = Color.FromArgb(0,255,0);if(hitRecord.isHit){// 光源到交点的向量
Vector3D vLight = lightLoc - hitRecord.hitPoint;
vLight.Normalize();// 算夹角double d = vLight * hitRecord.normal;if(d <0){
d =0;}// 算颜色
Color color = Color.FromArgb((int)(d * lightColor.R),(int)(d * lightColor.G),(int)(d * lightColor.B));
bmp.SetPixel(i, j, color);}else{
bmp.SetPixel(i, j, Color.Gray);}}}
pictureBox1.BackgroundImage = bmp;}}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
相关类
HitRecord
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RayTracing
{
class HitRecord
{
public bool isHit;
public double t;
public Point3D hitPoint;
public Vector3D normal;}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Point3D
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RayTracing
{
class Point3D
{// 私有的字段
private double x;
private double y;
private double z;// 公共的属性
public double X { get => x; set => x = value;}
public double Y { get => y; set => y = value;}
public double Z { get => z; set => z = value;}// 构造函数
public Point3D(){
x =0;
y =0;
z =0;}
public Point3D(double x,double y,double z){
this.x = x;
this.y = y;
this.z = z;}
public Point3D(double a){
x = a;
y = a;
z = a;}/// /// 点 + 向量/// /// /// ///
public static Point3D operator +(Point3D p, Vector3D v){return new Point3D(p.X + v.X, p.Y + v.Y, p.Z + v.Z);}/// /// 两个点之间的减法,得到向量/// /// /// ///
public static Vector3D operator -(Point3D p1, Point3D p2){return new Vector3D(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z);}}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
Ray
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RayTracing
{/// /// 射线///
class Ray
{// 字段
private Point3D org;
private Vector3D dir;// 属性
internal Point3D Org { get => org; set => org = value;}
internal Vector3D Dir { get => dir; set => dir = value;}// 构造函数
public Ray(){
Org = new Point3D();
Dir = new Vector3D();}
public Ray(Point3D org, Vector3D dir){
this.Org = org;
this.Dir = dir;}/// /// 判断是否与球体相交/// /// ///
public HitRecord isHit(Sphere sphere){// 计算delta
Vector3D oc = Org - sphere.Center;double a = dir * dir;double b =2.0*(dir * oc);double c = oc * oc - sphere.Radius * sphere.Radius;double delta = b * b -4.0* a * c;
HitRecord hitRecord = new HitRecord();// 有交点if(delta >0){
hitRecord.isHit = true;// 求tdouble t =(-b - Math.Sqrt(delta))/(2.0* a);if(t <0){
t =(-b + Math.Sqrt(delta))/(2.0* a);}
hitRecord.t = t;// 求交点
hitRecord.hitPoint =GetPoint(t);// 求法线
hitRecord.normal = sphere.GetNormalVector(hitRecord.hitPoint);
hitRecord.normal.Normalize();}else{
hitRecord.isHit = false;}return hitRecord;}/// /// 依据参数t的值,得到射线上某点/// /// ///
public Point3D GetPoint(double t){return org + t * dir;}}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
Sphere
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RayTracing
{
class Sphere
{
private Point3D center;
private double radius;
public double Radius { get => radius; set => radius = value;}
internal Point3D Center { get => center; set => center = value;}
public Sphere(double radius, Point3D center){
Radius = radius;
Center = center;}
public Sphere(){
center = new Point3D();
radius =1.0;}/// /// 获得球面某点的法线向量/// /// ///
public Vector3D GetNormalVector(Point3D p){
Vector3D v = p - Center;// 单位化,简化后续计算
v.Normalize();return v;}}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Vector
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RayTracing
{
class Vector3D
{// 私有的字段
private double x;
private double y;
private double z;// 公共的属性
public double X { get => x; set => x = value;}
public double Y { get => y; set => y = value;}
public double Z { get => z; set => z = value;}// 构造函数
public Vector3D(){
x =1;
y =0;
z =0;}
public Vector3D(double x,double y,double z){
this.x = x;
this.y = y;
this.z = z;}
public Vector3D(double a){
x = a;
y = a;
z = a;}/// /// 点乘/// /// /// ///
public static Double operator*(Vector3D v1, Vector3D v2){return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;}/// /// 数*向量/// /// /// ///
public static Vector3D operator*(double d, Vector3D v){return new Vector3D(d * v.X, d * v.Y, d * v.Z);}/// /// 向量*数/// /// /// ///
public static Vector3D operator*(Vector3D v,double d){return new Vector3D(d * v.X, d * v.Y, d * v.Z);}/// /// 向量加法/// /// /// ///
public static Vector3D operator +(Vector3D v1, Vector3D v2){return new Vector3D(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);}/// /// 向量减法/// /// /// ///
public static Vector3D operator -(Vector3D v1, Vector3D v2){return new Vector3D(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);}/// /// 向量的模/// /// 模
public doubleMagnitude(){return Math.Sqrt(X * X + Y * Y + Z * Z);}/// /// 向量单位化,本向量被改变///
public voidNormalize(){double d =Magnitude();
X = X / d;
Y = Y / d;
Z = Z / d;}/// /// 返回本向量的归一化向量,本向量不变/// /// 单位化后的向量
public Vector3D GetNormalizeVector(){double d =Magnitude();return new Vector3D(X/d, Y/d, Z/d);}}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
viewPlain
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RayTracing
{
class ViewPlain
{
public Point3D topLeftLoc;
public double w;
public double h;
public int wRes;
public int hRes;}}