private ColorAccumulator CalculateLighting(HitInfo info, int count) { ColorAccumulator ca = new ColorAccumulator(); foreach (Light lt in Scene.Lights) { GetColor(info, lt, ca, count); } return ca; }
private bool InShadow(HitInfo info, Light lt, Vector3D lightNormal) { Ray shadowRay = new Ray(lt.Location, lightNormal); HitInfo shadinfo = FindHitObject(shadowRay, info.hitObj, HitMode.Closest); if (shadinfo.hitObj != null && Vector3D.Subtract(lt.Location, info.hitPoint).Length > Vector3D.Subtract(lt.Location, shadinfo.hitPoint).Length) { return true; } return false; }
private HitInfo FindHitObject(Ray ray, Geometry originator, HitMode mode) { Vector3D intPoint = new Vector3D(double.MaxValue, double.MaxValue, double.MaxValue); HitInfo info = new HitInfo(null, intPoint, ray); double dist = double.MaxValue; foreach (Geometry geom in Scene.Geoms) { if (geom != originator && geom.Intersects(ray, ref intPoint)) { double distToObj = Vector3D.Subtract(ray.Source, intPoint).Length; if (distToObj < dist) { info.hitPoint = intPoint; dist = distToObj; info.hitObj = geom; if (mode == HitMode.Any) { break; } } } } return info; }
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 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; } } } } }