public double3 RefractRay(Scene scene, Traceable traceable, IntersectData data, Ray ray, TraceData traceData, double3 n, double nDotRay, RefractionIndex refractionIndex, out bool traceDataExceed) { traceDataExceed = false; double criticalAngleCos = nDotRay <= 0 ? refractionIndex.CriticalInAngleCos : refractionIndex.CriticalOutAngleCos; if (Math.Abs(nDotRay) >= criticalAngleCos) { if (traceData.Refractions > 0) { double k = nDotRay <= 0 ? refractionIndex.CoefficientIn : refractionIndex.CoefficientOut; double3 f = ray.l.RefractI(n, nDotRay, k); double3 p = traceable.Advance(data.P, f); Ray refractedRay = new Ray(p, f); traceData = traceData.GetRefracted(); double3 color = scene.Trace(refractedRay, traceData); return(RefractionAttenuation * color); } else { TraceData.RefractionLimitExceedCount++; traceDataExceed = true; return(TraceData.RefractionLimitExceedColor); } } else { if (traceData.Reflections > 0) { double3 r = ray.l.ReflectI(n, nDotRay); double3 p = traceable.Advance(data.P, r); Ray reflectedRay = new Ray(p, r); traceData = traceData.GetReflected(); double3 color = scene.Trace(reflectedRay, traceData); return(RefractionAttenuation * color); } else { TraceData.ReflectionLimitExceedCount++; traceDataExceed = true; return(TraceData.ReflectionLimitExceedColor); } } }
public override double3 CalculateColor(Scene scene, Traceable traceable, IntersectData data, Ray ray, TraceData traceData) { double3 n = traceable.GetNormal(data); double nDotRay = n & ray.l; double criticalAngleCos = nDotRay <= 0 ? RefractionIndex.CriticalInAngleCos : RefractionIndex.CriticalOutAngleCos; if (Math.Abs(nDotRay) >= criticalAngleCos) { if (traceData.Refractions > 0) { double k = nDotRay <= 0 ? RefractionIndex.CoefficientIn : RefractionIndex.CoefficientOut; double3 f = ray.l.RefractI(n, nDotRay, k); double3 p = traceable.Advance(data.P, f); Ray refractedRay = new Ray(p, f); traceData = traceData.GetRefracted(); double3 color = scene.Trace(refractedRay, traceData); return(RefractionAttenuation * color); } else { TraceData.RefractionLimitExceedCount++; return(TraceData.RefractionLimitExceedCount); } } else { if (traceData.Reflections > 0) { double3 r = ray.l.ReflectI(n, nDotRay); double3 p = traceable.Advance(data.P, r); Ray reflectedRay = new Ray(p, r); traceData = traceData.GetReflected(); double3 color = scene.Trace(reflectedRay, traceData); return(RefractionAttenuation * color); } else { TraceData.ReflectionLimitExceedCount++; return(TraceData.ReflectionLimitExceedColor); } } }
public override double3 CalculateColor(Scene scene, Traceable traceable, IntersectData data, Ray ray, TraceData traceData) { double3 resultColor = double3.Zero; double3 n = traceable.GetNormal(data); foreach (SpotLight light in scene.Lights) { double3 l = light.Pos - data.P; double distance = l.Length; l = l.Normalized; double nDotL = n & l; if (nDotL <= 0) { continue; } double shadowEdgeAttenuation = 1; List <IntersectData> shadowIsecs = scene.Intersect(new Ray(traceable.Advance(data.P, l), l)); if (shadowIsecs.Count > 0) { IntersectData obstacleIsecData = shadowIsecs.OrderBy(shadowIsecData => (shadowIsecData.P - data.P).Length).First(); if ((obstacleIsecData.P - data.P).Length < distance) { double3 obstacleL = light.Pos - obstacleIsecData.P; obstacleL = obstacleL.Normalized; double3 obstacleN = obstacleIsecData.Object.GetNormal(obstacleIsecData); double3 obstacleR = l.ReflectI(obstacleN); shadowEdgeAttenuation = obstacleR & obstacleL; if (shadowEdgeAttenuation <= 0) { continue; } shadowEdgeAttenuation = Math.Pow(shadowEdgeAttenuation, 3); } } double3 diffuse = BaseColor ^ light.DiffuseColor * nDotL; double3 r = l.Reflect(n, nDotL); double rDotV = Math.Max(0, (-ray.l) & r); double3 specular = Math.Pow(rDotV, SpecularPower) * light.SpecularColor; double attenuation = Math.Log(distance + light.AttenuationBase, light.AttenuationBase); resultColor += (diffuse + specular) * shadowEdgeAttenuation / attenuation; } return(resultColor + scene.AmbientColor); }
public override double3 CalculateColor(Scene scene, Traceable traceable, IntersectData data, Ray ray, TraceData traceData) { if (traceData.Reflections > 0) { double3 n = traceable.GetNormal(data); double3 r = ray.l.ReflectI(n); double3 p = traceable.Advance(data.P, r); return(ReflectionAttenuation * scene.Trace(new Ray(p, r), traceData.GetReflected())); } else { TraceData.ReflectionLimitExceedCount++; return(TraceData.ReflectionLimitExceedColor); } }