private IntersectInfo IntersectSlab(Ray ray, Vector P1, Vector P2, Vector P3) { Vector N = (P1 - P3).Cross(P2 - P3).Normalize(); double d = N.Dot(P1); IntersectInfo info = new IntersectInfo(); double Vd = N.Dot(ray.Direction); if (Vd == 0) { return(info); // no intersection } double t = -(N.Dot(ray.Position) - d) / Vd; if (t <= 0) { return(info); } Vector hit = ray.Position + ray.Direction * t; if ((hit.x < P1.x || hit.x > P2.x) && (P1.x != P2.x)) { return(info); } if ((hit.y < P3.y || hit.y > P1.y) && (P1.y != P2.y)) { return(info); } //if ((hit.z < P1.z || hit.z > P3.z) && (P1.z != P3.z)) return info; if ((hit.z < P1.z || hit.z > P2.z) && (P1.z != P2.z)) { return(info); } info.Element = this; info.IsHit = true; info.Position = hit; info.Normal = N;// *-1; info.Distance = t; if (Material.HasTexture) { //Vector vecU = new Vector(hit.y - Position.y, hit.z - Position.z, Position.x-hit.x); Vector vecU = new Vector((P1.y + P2.y) / 2 - Position.y, (P1.z + P2.z) / 2 - Position.z, Position.x - (P1.x + P2.x) / 2).Normalize(); Vector vecV = vecU.Cross((P1 + P2) / 2 - Position).Normalize(); double u = info.Position.Dot(vecU); double v = info.Position.Dot(vecV); info.Color = Material.GetColor(u, v); } else { info.Color = Material.GetColor(0, 0); } return(info); }
public override IntersectInfo Intersect(Ray ray) { IntersectInfo info = new IntersectInfo(); info.Element = this; Vector dst = ray.Position - this.Position; double B = dst.Dot(ray.Direction); double C = dst.Dot(dst) - (R * R); double D = B * B - C; if (D > 0) { info.IsHit = true; info.Distance = -B - (double)Math.Sqrt(D); info.Position = ray.Position + ray.Direction * info.Distance; info.Normal = (info.Position - Position).Normalize(); if (Material.HasTexture) { Vector vn = new Vector(0, 1, 0).Normalize(); Vector ve = new Vector(0, 0, 1).Normalize(); Vector vp = (info.Position - Position).Normalize(); double phi = Math.Acos(-vp.Dot(vn)); double v = (phi / Math.PI); double sinphi = ve.Dot(vp) / Math.Sin(phi); double theta = Math.Acos(sinphi) / (Math.PI * 2); double u; if (vn.Cross(ve).Dot(vp) > 0) { u = theta; } else { u = 1 - theta; } info.Color = this.Material.GetColor(1 - u, 1 - v); } else { info.Color = this.Material.GetColor(0, 0); } } else { info.IsHit = false; } return(info); }
/// <summary> /// 返回光线跟踪后的颜色 /// </summary> /// <param name="ray">射线</param> /// <param name="scene">场景</param> /// <returns></returns> public Color CalculateColor(Ray ray, Scene scene) { IntersectInfo info = TestIntersection(ray, scene, null); if (info.IsHit) { // 进行光线跟踪 Color c = RayTrace(info, ray, scene, 0); return(c); } return(scene.Background.Color); }
private IntersectInfo TestIntersection(Ray ray, Scene scene, IShape exclude) { int hitcount = 0; IntersectInfo best = new IntersectInfo(); best.Distance = double.MaxValue; foreach (IShape elt in scene.Shapes) { if (elt == exclude) { continue; } IntersectInfo info = elt.Intersect(ray); if (info.IsHit && info.Distance < best.Distance && info.Distance >= 0) { best = info; hitcount++; } } best.HitCount = hitcount; return(best); }
/// <summary> /// 进行真正的光线跟踪 /// </summary> /// <param name="info">击中信息</param> /// <param name="ray">射线</param> /// <param name="scene">场景</param> /// <param name="depth">递归深度</param> /// <returns></returns> private Color RayTrace(IntersectInfo info, Ray ray, Scene scene, int depth) { // 计算环境光 Color color = info.Color * scene.Background.Ambience; double shininess = Math.Pow(10, info.Element.Material.Gloss + 1); foreach (Light light in scene.Lights) { // 计算漫射光 Vector v = (light.Position - info.Position).Normalize(); if (RenderDiffuse) { double L = v.Dot(info.Normal); if (L > 0.0f) { color += info.Color * light.Color * L; } } //最大深度 if (depth < 10) { // 计算反射 if (RenderReflection && info.Element.Material.Reflection > 0) { Ray reflectionray = GetReflectionRay(info.Position, info.Normal, ray.Direction); IntersectInfo refl = TestIntersection(reflectionray, scene, info.Element); if (refl.IsHit && refl.Distance > 0) { // 递归计算反射 ----要改成迭代 refl.Color = RayTrace(refl, reflectionray, scene, depth + 1); } else //MISS 返回背景色 { refl.Color = scene.Background.Color; } color = color.Blend(refl.Color, info.Element.Material.Reflection); } //计算折射 if (RenderRefraction && info.Element.Material.Transparency > 0) { Ray refractionray = GetRefractionRay(info.Position, info.Normal, ray.Direction, info.Element.Material.Refraction); IntersectInfo refr = info.Element.Intersect(refractionray); if (refr.IsHit) { refractionray = GetRefractionRay(refr.Position, refr.Normal, refractionray.Direction, refr.Element.Material.Refraction); refr = TestIntersection(refractionray, scene, info.Element); if (refr.IsHit && refr.Distance > 0) { // 递归计算折射 ----要改成迭代 refr.Color = RayTrace(refr, refractionray, scene, depth + 1); } else { refr.Color = scene.Background.Color; } } else { refr.Color = scene.Background.Color; } color = color.Blend(refr.Color, info.Element.Material.Transparency); } } IntersectInfo shadow = new IntersectInfo(); if (RenderShadow) { // 计算阴影 Ray shadowray = new Ray(info.Position, v); // 该点的直射光线是否被遮挡 shadow = TestIntersection(shadowray, scene, info.Element); if (shadow.IsHit && shadow.Element != info.Element) { color *= 0.5 + 0.5 * Math.Pow(shadow.Element.Material.Transparency, 0.5); // Math.Pow(.5, shadow.HitCount); } } if (RenderHighlights && !shadow.IsHit && info.Element.Material.Gloss > 0) { // Phong 模型计算 Vector Lv = (info.Element.Position - light.Position).Normalize(); Vector E = (scene.Camera.Position - info.Element.Position).Normalize(); Vector H = (E - Lv).Normalize(); double Glossweight = 0.0; Glossweight = Math.Pow(Math.Max(info.Normal.Dot(H), 0), shininess); color += light.Color * (Glossweight); } } //整合光照 color.Limit(); return(color); }
public override IntersectInfo Intersect(Ray ray) { IntersectInfo best = new IntersectInfo(); best.Distance = double.MaxValue; IntersectInfo info = null; Vector P1 = null; Vector P2 = null; Vector P3 = null; if (ray.Direction.z > 0) { //前 P1 = UpperLeftFront; P2 = new Vector(LowerRightBack.x, LowerRightBack.y, P1.z); P3 = new Vector(P1.x, P2.y, P1.z); info = IntersectSlab(ray, P1, P2, P3); if (info.IsHit && info.Distance < best.Distance) { best = info; } } else { //后 P1 = new Vector(UpperLeftFront.x, UpperLeftFront.y, LowerRightBack.z); P2 = LowerRightBack; P3 = new Vector(P1.x, P2.y, P1.z); info = IntersectSlab(ray, P1, P2, P3); if (info.IsHit && info.Distance < best.Distance) { best = info; } } if (ray.Direction.x < 0) { //左 P1 = new Vector(LowerRightBack.x, UpperLeftFront.y, UpperLeftFront.z); P2 = LowerRightBack; P3 = new Vector(P1.x, P2.y, P1.z); info = IntersectSlab(ray, P1, P2, P3); if (info.IsHit && info.Distance < best.Distance) { best = info; } } else { //右 P1 = UpperLeftFront; P2 = new Vector(UpperLeftFront.x, LowerRightBack.y, LowerRightBack.z); P3 = new Vector(P1.x, P2.y, P1.z); info = IntersectSlab(ray, P1, P2, P3); if (info.IsHit && info.Distance < best.Distance) { best = info; } } if (ray.Direction.y < 0) { //上 P1 = UpperLeftFront; P2 = new Vector(LowerRightBack.x, UpperLeftFront.y, LowerRightBack.z); P3 = new Vector(P2.x, P1.y, P1.z); info = IntersectSlab(ray, P1, P2, P3); if (info.IsHit && info.Distance < best.Distance) { best = info; } } else { //下 P1 = new Vector(UpperLeftFront.x, LowerRightBack.y, UpperLeftFront.z); P2 = LowerRightBack; P3 = new Vector(P2.x, P1.y, P1.z); info = IntersectSlab(ray, P1, P2, P3); if (info.IsHit && info.Distance < best.Distance) { best = info; } } return(best); }