private ColorAccumulator CalculateLighting(HitInfo info, int count) { ColorAccumulator ca = new ColorAccumulator(); foreach (Light lt in Scene.Lights) { GetColor(info, lt, ca, count); } return ca; }
public static ColorAccumulator operator +(ColorAccumulator left, ColorAccumulator right) { ColorAccumulator sum = new ColorAccumulator(); sum.R = left.R + right.R; sum.G = left.G + right.G; sum.B = left.B + right.B; return(sum); }
private ColorAccumulator CastRay(Ray ray, int count) { if (count > RayDepth) { return(null); } ColorAccumulator colorAccumulator = null; HitInfo info = FindHitObject(ray); if (info.hitObject != null) { colorAccumulator = CalculateLighting(info, count); //colorAccumulator.Clamp(); } else { colorAccumulator = new ColorAccumulator(BackColor.R, BackColor.G, BackColor.B); } return(colorAccumulator); }
private ColorAccumulator CalculateLighting(HitInfo info, int count) { ColorAccumulator colorAccumulator = new ColorAccumulator(); foreach (Light light in Scene.Lights) { GetColor(info, light, colorAccumulator, count); //Bidirectional ray tracing var randomDirection = StaticRandom.RandomVectorInUnitSphere(); var randomRay = new Ray(light.Location + randomDirection, randomDirection); var hitInfo = FindHitObject(randomRay); var secondaryLight = new Light(); secondaryLight.Location = hitInfo.hitPoint - randomRay.Direction; int squaredDistance = (int)(secondaryLight.Location - randomRay.Source).LengthSquared + 1; secondaryLight.Color = light.Color; secondaryLight.Intensity = light.Intensity / squaredDistance; GetColor(info, secondaryLight, colorAccumulator, count); } return(colorAccumulator); }
public static ColorAccumulator operator +(ColorAccumulator left, ColorAccumulator right) { ColorAccumulator sum = new ColorAccumulator(); sum.accumR = left.accumR + right.accumR; sum.accumG = left.accumG + right.accumG; sum.accumB = left.accumB + right.accumB; return sum; }
private void GetColor(HitInfo info, Light lt, ColorAccumulator ca, int count) { Vector3D lightNormal = info.hitPoint - lt.Location; lightNormal.Normalize(); if (InShadow(info, lt, lightNormal)) { return; } double lambert = Vector3D.DotProduct(lightNormal, info.normal); if (lambert <= 0) { int r, g, b; r = b = g = 0; int r2 = 0; int g2 = 0; int b2 = 0; info.hitObj.GetColor(info.hitPoint, ref r, ref g, ref b); if (info.hitObj.Material != null && info.hitObj.Material is SolidColor) { double phongTerm = Math.Pow(lambert, 20) * (info.hitObj.Material as SolidColor).Phong * 2; r2 = (int)(lt.Color.R * phongTerm); g2 = (int)(lt.Color.G * phongTerm); b2 = (int)(lt.Color.B * phongTerm); double reflet = 2.0f * (Vector3D.DotProduct(info.normal, info.ray.Direction)); Vector3D dir = info.ray.Direction - info.normal * reflet; Ray reflect = new Ray(info.hitPoint + dir, dir); ColorAccumulator rca = CastRay(reflect, ++count); if (rca != null) { ca.accumR = ca.accumR + rca.accumR; ca.accumG = ca.accumG + rca.accumG; ca.accumB = ca.accumB + rca.accumB; } } ca.accumR += (int)((lt.Color.R * r * -lambert) / 255) + r2; ca.accumG += (int)((lt.Color.G * g * -lambert) / 255) + g2; ca.accumB += (int)((lt.Color.B * b * -lambert) / 255) + b2; } }
private ColorAccumulator CastRay(Ray ray, int count) { if (count > RayDepth) { return null; } ColorAccumulator ca = null; HitInfo info = FindHitObject(ray); if (info.hitObj != null) { ca = CalculateLighting(info, count); ca.Clamp(); } else { ca = new ColorAccumulator(BackColor.R, BackColor.G, BackColor.B); } return ca; }
private void GetColor(HitInfo info, Light light, ColorAccumulator colorAccu, int count) { Vector3D lightLocation = light.Location; Vector3D lightNormal = info.hitPoint - lightLocation; lightNormal.Normalize(); double lambert = Vector3D.DotProduct(lightNormal, info.normal); if (lambert <= 0) { int r, g, b; r = g = b = 0; int r2 = 0; int g2 = 0; int b2 = 0; info.hitObject.GetColor(info.hitPoint, ref r, ref g, ref b); if (info.hitObject.Material != null) { var objectMaterial = info.hitObject.Material; //Phong if (objectMaterial is SolidColor) { if (InShadow(info, lightLocation, lightNormal)) { return; } double phongTerm = Math.Pow(lambert, 20) * (objectMaterial as SolidColor).Phong * 2 * light.Intensity; r2 = (int)(light.Color.R * phongTerm); g2 = (int)(light.Color.G * phongTerm); b2 = (int)(light.Color.B * phongTerm); var intensityFactor = light.Intensity * -lambert / 255; colorAccu.R += (int)(light.Color.R * r * intensityFactor) + r2; colorAccu.G += (int)(light.Color.G * g * intensityFactor) + g2; colorAccu.B += (int)(light.Color.B * b * intensityFactor) + b2; } //Reflection else if (objectMaterial is Metal) { var metal = objectMaterial as Metal; //double phongTerm = Math.Pow(lambert, 20) * 0.6 * 2 * light.Intensity; //r2 = (int)(light.Color.R * phongTerm); //g2 = (int)(light.Color.G * phongTerm); //b2 = (int)(light.Color.B * phongTerm); double reflet = 2.0f * (Vector3D.DotProduct(info.normal, info.ray.Direction)); Vector3D direction = info.ray.Direction - info.normal * reflet; direction.Normalize(); direction += metal.Fuzz * StaticRandom.RandomVectorInUnitSphere(); //Random in cone //direction.Normalize(); Ray reflect = new Ray(info.hitPoint + direction / 100000, direction); ColorAccumulator reflectedColorAccu = CastRay(reflect, ++count); if (reflectedColorAccu != null) { var attenuation = metal.Reflection * light.Intensity; colorAccu.R += (int)(reflectedColorAccu.R * attenuation) + r2; colorAccu.G += (int)(reflectedColorAccu.G * attenuation) + g2; colorAccu.B += (int)(reflectedColorAccu.B * attenuation) + b2; } } } } }