光线追踪算法
作者:互联网
1.三维点 Point3D类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WindowsFormsApp1 { 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(){ this.X=0; this.Y = 0; this.Z = 0; } public Point3d(double x,double y,double z) { this.X = x; this.Y = y; this.Z = z; } public static Vector3D operator -(Point3d a,Point3d b) { return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z); } public static Vector3D operator -(Point3d a,Vector3D b) { return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z); } public static Vector3D operator -(Vector3D a, Point3d b) { return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z); } } }
2.Ray光线类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WindowsFormsApp1 { class Ray { private Point3d _origin; private Vector3D _direction; public Ray() { this.Origin = new Point3d(); this.Direction = new Vector3D(); } public Ray(Point3d origin,Vector3D direction) { this.Origin = origin; this.Direction = direction; } internal Point3d Origin { get => _origin; set => _origin = value; } internal Vector3D Direction { get => _direction; set => _direction = value; } public Point3d GetRayAtSp(double t) { return Origin+ t * Direction; } public bool isHit(Sphere sphere,out Point3d phit,out Vector3D normal) { double t; Vector3D co = Origin-sphere.Center; double a = Direction * Direction; double b = 2.0 * (Direction * co); double c = co * co - sphere.Radiu * sphere.Radiu; double delta = b * b - 4 * a * c; if (delta >= 0) { t=(-b - Math.Sqrt(delta)) / (2 * a); if (t < 0) { t = (-b + Math.Sqrt(delta)) / (2 * a); } phit = GetRayAtSp(t); Vector3D v = phit - sphere.Center; normal = v.GetNormalizeVector(); return true; } else { phit = new Point3d(); normal = new Vector3D(); return false; } } /*public SColor ColorRS(Ray r) { bool k; k = r.isHit(new Sphere(new Point3d(0, 0, -1), 0.5),out new Point3d(),out new Vector3D()); if (k) { return new SColor(1, 0, 0); } else { Vector3D UnitVec = r.Direction.GetNormalizeVector(); double t = 0.5 * (UnitVec.Y + 1.0); return new SColor((1.0-t)+t*0.5,(1.0-t)+t*0.7,(1.0-t)+t*1); } /*具体算法 blended_value = (1-t)*start_value + t* end_value,函数里 start_value = Color3D(1.0, 1.0, 1.0), end_value = Color3D(0.5, 0.7, 1.0)*/ } }
3. 自定义颜色类 Scolor
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WindowsFormsApp1 { class SColor { private double _r; private double _g; private double _b; public double R { get { return _r; } set { _r = value; if (_r < 0.0) { _r = 0.0; } if (_r > 1.0) { _r = 1.0; } } } public double G { get { return _g; } set { _g = value; if (_g < 0.0) { _g = 0.0; } if (_g > 1.0) { _g = 1.0; } } } public double B { get { return _b; } set { _b = value; if (_b < 0.0) { _b = 0.0; } if (_b > 1.0) { _b = 1.0; } } } public SColor() { this.R = 0.0; this.G = 0.0; this.B = 0.0; } public SColor(double r,double g,double b) { this.R = r; this.G = g; this.B = b; } public static SColor operator *(SColor sc,double k) { return new SColor(sc.R * k, sc.G * k, sc.B * k); } public static SColor operator *(double k,SColor sc) { return new SColor(sc.R * k, sc.G * k, sc.B * k); } public Color Get255() { return Color.FromArgb((int) (R * 255), (int) (G * 255), (int) (B * 255)); } public static SColor operator +(SColor s1,SColor s2) { return new SColor(s1.R + s2.R, s1.G + s2.G, s1.B + s2.B); } } }
4.球类Sphere
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WindowsFormsApp1 { class Sphere { private Point3d _center; private double _radiu; public double Radiu { get => _radiu; set => _radiu = value; } internal Point3d Center { get => _center; set => _center = value; } public Sphere() { this.Center = new Point3d(0, 0,0); this.Radiu = 1; } public Sphere(Point3d center,double radiu) { this.Center = center; this.Radiu = radiu; } } }
5.向量类Vector3D
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WindowsFormsApp1 { 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() { this.X = 0; this.Y = 0; this.Z = 0; } public Vector3D(double x, double y, double z) { this.X = x; this.Y = y; this.Z = z; } public static double operator *(Vector3D a,Vector3D b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; } public static Vector3D operator *(double number,Vector3D vec) { return new Vector3D(number * vec.X, number * vec.Y, number * vec.Z); } public static Vector3D operator *(Vector3D vec,double number) { return new Vector3D(number * vec.X, number * vec.Y, number * vec.Z); } public static Vector3D operator +(Vector3D vec1,Vector3D vec2) { return new Vector3D(vec1.X + vec2.X, vec1.Y + vec2.Y, vec1.Z + vec2.Z); } public static Point3d operator +(Point3d a,Vector3D b) { return new Point3d(a.X + b.X, a.Y + b.Y, a.Z + b.Z); } public static Vector3D operator -(Vector3D vec1, Vector3D vec2) { return new Vector3D(vec1.X - vec2.X, vec1.Y - vec2.Y, vec1.Z - vec2.Z); } public double Magnitude() { return Math.Sqrt(X * X + Y * Y + Z * Z); } public void Normalize() { 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); } } }
FORM1:
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 WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button2_Click(object sender, EventArgs e) { /*Ray primaryRay = new Ray(); primaryRay.Origin = new Point3d(10, 20, 20); primaryRay.Direction = new Vector3D(0, 0, -1); Ray shadowray = new Ray(new Point3d(10, 20, 20), new Vector3D(0, 0, -1)); Point3d hitpoint = new Point3d(10, 20, 20); Vector3D dir = new Vector3D(0, 0, -1); Ray reflectray = new Ray(hitpoint, dir); double d = primaryRay.Direction * dir; Point3d a = new Point3d(2, 1, 1); Vector3D b = new Vector3D(1, 1, 1); Vector3D c = a - b;*/ int hor = 2000; int ver = 1000; double resx = 4.0/hor; double rexy= 2.0/ ver; /*double mag = ray1.Direction.Magnitude(); Vector3D normalvec = ray1.Direction.GetNormalizeVector();*/ //观察点 Point3d eye = new Point3d(0, 0, 0); //光源 Point3d light = new Point3d(-1, 2, -1); SColor Id = new SColor(1, 1, 1); double kd = 0.8; //环境光源 SColor Ia = new SColor(1, 1, 1); double ka = 0.2; //球体 Sphere sp = new Sphere(new Point3d(0, 0, -2), 0.8); Bitmap btm = new Bitmap(hor, ver); for (int i = 0; i < hor; i++) { for(int j = 0; j < ver; j++) { //成像平面上的点 Point3d p = new Point3d(-2 + i * resx, 1 - j * rexy, -1); Vector3D dir =p-eye; Ray ray = new Ray(eye, dir); Point3d phit; Vector3D normal; bool isHit = ray.isHit(sp, out phit, out normal); Vector3D L = light - phit; Vector3D Ln= L.GetNormalizeVector(); //漫反射 SColor idiffuse = Id * kd * (Ln * normal) + Ia * ka; if (isHit) { btm.SetPixel(i, j, idiffuse.Get255()); } else { btm.SetPixel(i, j, Color.Black); } pictureBox1.BackgroundImage = btm; } } /*Ray ray1 = new Ray(new Point3d(1, -2, -1), new Vector3D(1, 2, 4)); Sphere sp = new Sphere(new Point3d(3, 0, 5), 3.0); bool isHit=ray1.isHit(sp);*/ /*int nx = 200; int ny = 100; Bitmap bitmap= new Bitmap(nx, ny); Point3d lowerLeftConor = new Point3d(-2, 1, 1); Vector3D horizontal = new Vector3D(4, 0, 0); Vector3D vertical = new Vector3D(0, 2, 0); Point3d origin = new Point3d(0, 0, 0); for(int i = 0; i < nx; i++) { for(int j = ny - 1 ; j >= 0; j--) { double u = i / nx; double v = j / ny; Ray r = new Ray(origin, lowerLeftConor + u * horizontal + v * vertical); SColor clr = r.ColorRS(r); int ir= (int)(255.99 * clr.R); int ig = (int)(255.99 * clr.G); int ib = (int)(255.99 * clr.B); bitmap.SetPixel(i, j, Color.FromArgb(ir, ig, ib)); pictureBox1.BackgroundImage = bitmap; pictureBox1.BackgroundImageLayout = ImageLayout.Stretch; } } */ } } }
效果
标签:光线,Vector3D,double,算法,using,new,Point3d,public,追踪 来源: https://www.cnblogs.com/jcahsy/p/12540089.html