public Color3 Calculate(Intersection intersection, bool ignoreLight) { Color3 result; switch (intersection.Material.MaterialType) { case MaterialType.Light: if (_nee) { result = ignoreLight ? Color4.Black : intersection.Material.Color; } else { result = intersection.Material.Color; } break; case MaterialType.Diffuse: result = Diffuse(intersection); break; case MaterialType.Specular: result = Specular(intersection); break; case MaterialType.Dielectric: result = Dielectric(intersection); break; default: throw new Exception("Materialtype is not supported"); } //return result / (1 - Constants.RussianRouletteDieChance); return result; }
public Color3 Calculate(Intersection intersection) { switch (intersection.Material.MaterialType) { case MaterialType.Light: case MaterialType.Diffuse: return DirectIllumination(intersection); case MaterialType.Specular: return Specular(intersection); case MaterialType.Dielectric: return Dielectric(intersection); } throw new Exception("Materialtype is not supported"); }
public Color3 Dielectric(Intersection intersection) { var n1 = intersection.Ray.Medium.RefractiveIndex; var n2 = intersection.Material.RefractiveIndex; float n = n1 / n2; var ray = intersection.Ray; var normal = intersection.SurfaceNormal; float cost = Vector3.Dot(normal, -ray.Direction); float k = 1 - n * n * (1 - cost * cost); if (k < 0) { //internal reflection return Specular(intersection); } var T = n * ray.Direction + normal * (n * cost - (float)Math.Sqrt(k)); var refracted = Ray.CreateFromIntersection(intersection, T, float.MaxValue, true); float R0 = (n1 - n2) / (n1 + n2); R0 *= R0; var a = 1 - cost; float Fr = R0 + (1 - R0) * a * a * a * a * a; float Ft = 1 - Fr; var transparency = new Vector3(1); if (intersection.InsidePrimitive) { var absorbance = intersection.Ray.Medium.Color * intersection.Ray.Medium.Absorbance * -intersection.Distance; transparency = new Vector3( (float)Math.Exp(-absorbance.R), (float)Math.Exp(-absorbance.G), (float)Math.Exp(-absorbance.B)); } //go inside if (_rng.RandomFloat() < Ft) { return transparency*_scene.Sample(refracted, _rng, false); } //reflect outside return transparency*Specular(intersection); }
public static Intersection GetMinimumIntersection(Intersection i1, Intersection i2) { if (i1 == null) { return i2; } if (i2 == null) { return i1; } if (i1.Distance < i2.Distance) { return i1; } return i2; }
public bool Intersect(Ray ray, out Intersection intersection) { intersection = null; var nodes = new Stack<BVHNode>(_logNumBoundables); nodes.Push(Root); while (nodes.Count > 0) { var node = nodes.Pop(); if (node.IsLeaf) { var i = IntersectionHelper.GetClosestIntersection(ray, node.Boundables); intersection = IntersectionHelper.GetMinimumIntersection(intersection, i); } Intersection i1 = null, i2 = null; float t1 = float.MaxValue, t2 = float.MaxValue; var goLeft = node._left != null && node._left.BoundingBox.Intersect(ray, out t1); var goRight = node._right != null && node._right.BoundingBox.Intersect(ray, out t2); if (goLeft && goRight) { //choose shortest if (t1 < t2) { nodes.Push(node._right); nodes.Push(node._left); } else { nodes.Push(node._left); nodes.Push(node._right); } } else if (goLeft) { nodes.Push(node._left); } else if (goRight) { nodes.Push(node._right); } } return intersection != null; }
public Color3 DirectIllumination(Intersection intersection) { var totalIntensity = 0.0f; foreach (var light in _scene.PointLights) { var lightVector = light.Position - intersection.Location; var invLightDistance2 = 1/lightVector.LengthSquared; var shadowRay = Ray.CreateFromIntersection(intersection, lightVector, lightVector.LengthFast); if (IntersectionHelper.DoesIntersect(shadowRay, _scene.Objects) && !(intersection.IntersectsWith is DebugSphere)) //todo debug { continue; } var intensity = Vector3.Dot(intersection.SurfaceNormal, shadowRay.Direction); totalIntensity += Math.Max(intensity, 0) * invLightDistance2*light.Intensity; } return totalIntensity * intersection.Material.CalculateColor(intersection.Location); }
public Color3 Specular(Intersection intersection) { var mat = intersection.Material; var reflectedRay = Ray.Reflect(intersection.Ray, intersection); Color3 specColor = Color4.Black; foreach (var lightSource in _scene.PointLights) { var lightDir = (lightSource.Position - intersection.Location).Normalized(); var h = (-intersection.Ray.Direction + lightDir).Normalized(); var dot = Vector3.Dot(h, intersection.SurfaceNormal); if (dot > 0) { var spec = (float)Math.Pow(dot, 32) * intersection.Material.Specularity; specColor += lightSource.Color * spec; } } return mat.Specularity * (specColor + _scene.Sample(reflectedRay, _rng, false)) + (1 - mat.Specularity) * DirectIllumination(intersection); }
private Color3 SampleLightDirectly(ISurfaceLight light, Color3 brdf, Intersection intersection) { var rPoint = light.GetRandomPoint(_rng, intersection); //get random point on light var l = rPoint.Location - intersection.Location; //vector to light var dist = l.LengthFast; l.Normalize(); var lightRay = Ray.CreateFromIntersection(intersection, l, dist); //ray to light var nlightDotL = Vector3.Dot(rPoint.Normal, -l); //light normal dot light var nDotL = Vector3.Dot(intersection.SurfaceNormal, l); //normal dot light if (nDotL > 0 && nlightDotL > 0 && !IntersectionHelper.DoesIntersect(lightRay, _scene.Objects, light)) { var solidAngle = (nlightDotL * light.Area) / (dist * dist); //light area on hemisphere return light.Color * solidAngle * brdf * nDotL; } return Color4.Black; }
public Color3 Specular(Intersection intersection) { var reflectedRay = Ray.Reflect(intersection.Ray, intersection); return intersection.Material.CalculateColor(intersection) * _scene.Sample(reflectedRay, _rng, false); }
public Color3 Diffuse(Intersection intersection) { float killChance = 0; if (_russianRoulette) { killChance = GetKillChance(intersection.Material.Color); if (_rng.TestChance(killChance)) { return Color4.Black; } } //random reflected ray Vector3 rDir; if (_cosineDist) { rDir = _rng.CosineDistributed(intersection.SurfaceNormal); } else { rDir = _rng.RandomVectorOnHemisphere(intersection.SurfaceNormal); } var reflected = Ray.CreateFromIntersection(intersection, rDir, goesIntoMaterial: true); //brdf of material var brdf = intersection.Material.CalculateColor(intersection)/MathHelper.Pi; //irradiance var nDotR = Vector3.Dot(intersection.SurfaceNormal, rDir); var Ei = _scene.Sample(reflected, _rng, true) * nDotR; Color3 Ld = Color4.Black; //use next event estimation? if (_nee) { if (_scene.SurfaceLights.Count > 0) { //sample light directly - next event estimation var ranLight = _scene.SurfaceLights.GetRandom(_rng.R); //get random light Ld = SampleLightDirectly(ranLight, brdf, intersection)*_scene.SurfaceLights.Count*ranLight.Brightness; } } Color3 result; if (_cosineDist) { //probability density function var pdf = nDotR/MathHelper.Pi; result = brdf*Ei/pdf + Ld; } else { result = MathHelper.TwoPi * brdf * Ei + Ld; } return result/(1 - killChance); }