private ColorVector RenderShadowAndHighlights(ColorVector currentColor, IntersectionInfo intersectionInfo, ILight light) { var v = (light.Position - intersectionInfo.Position).Normalize(); var shadowRay = new Ray(intersectionInfo.Position, v); var color = currentColor; if (Scene.TryGetShape(intersectionInfo.ElementId, out var shape)) { if (RenderData.RenderShadow) { var shadowIntersection = TestIntersection(shadowRay, shape.Id); if (shadowIntersection.IsHit) { if (Scene.TryGetShape(shadowIntersection.ElementId, out var shadowShape)) { if (shadowShape.Id != shape.Id) { var trans = shadowShape.GetMaterial().KTransparent; var transPower = Math.Pow(trans, 0.5); color = color * (0.5 + 0.5 * transPower); } } } color = RenderHighlights(color, shape, shadowIntersection, light); } } return(color); }
private ColorVector RenderDiffuse(ColorVector currentColor, IntersectionInfo intersectionInfo, ILight light) { if (RenderData.RenderDiffuse) { var v = (light.Position - intersectionInfo.Position).Normalize(); var l = v.Dot(intersectionInfo.Normal); if (l > 0.0) { return(currentColor + intersectionInfo.Color * light.Color * l); } } return(currentColor); }
private ColorVector RenderHighlights(ColorVector currentColor, IShape shape, IntersectionInfo shadowIntersection, ILight light) { if (RenderData.RenderHighlights && !shadowIntersection.IsHit && shape.GetMaterial().Gloss > 0.0) { var lv = (shape.Position - light.Position).Normalize(); var e = (Camera.Position - shape.Position).Normalize(); var h = (e - lv).Normalize(); var glossWeight = 0.0; // todo: pow(max(dot(info.Normal, h), 0.0), shininess) return(currentColor + light.Color * glossWeight); } return(currentColor); }
private IntersectionInfo TestIntersectionBasic(Ray ray, int excludeId) { var bestInfo = new IntersectionInfo(); foreach (var shape in Scene.Shapes.Where(s => s.Id != excludeId)) { var info = shape.Intersect(ray); if (info.IsHit && info.Distance < bestInfo.Distance && info.Distance >= 0.0) { bestInfo = info; } } return(bestInfo); }
private ColorVector RayTrace(IntersectionInfo intersectionInfo, Ray ray, int depth) { var color = intersectionInfo.Color * Scene.Background.Ambience; foreach (var light in Scene.Lights) { color = RenderDiffuse(color, intersectionInfo, light); if (depth < RenderData.RayTraceDepth) { color = RenderReflection(color, intersectionInfo, ray, depth); color = RenderRefraction(color, intersectionInfo, ray, depth); color = RenderShadowAndHighlights(color, intersectionInfo, light); } } return(color); }
private ColorVector RenderReflection(ColorVector currentColor, IntersectionInfo intersectionInfo, Ray ray, int depth) { if (RenderData.RenderReflection) { if (Scene.TryGetShape(intersectionInfo.ElementId, out var shape)) { if (shape.GetMaterial().KReflection > 0.0) { var reflectionRay = GetReflectionRay(intersectionInfo.Position, intersectionInfo.Normal, ray.Direction); var refl = TestIntersection(reflectionRay, shape.Id); var reflColor = refl.IsHit && refl.Distance > 0.0 ? RayTrace(refl, reflectionRay, depth + 1) : Scene.Background.Color; return(currentColor.Blend(reflColor, shape.GetMaterial().KReflection)); } } } return(currentColor); }
private ColorVector RenderRefraction(ColorVector currentColor, IntersectionInfo intersectionInfo, Ray ray, int depth) { if (RenderData.RenderRefraction) { if (Scene.TryGetShape(intersectionInfo.ElementId, out var shape)) { if (shape.GetMaterial().KTransparent > 0.0) { var refractionRay = GetRefractionRay(intersectionInfo.Position, intersectionInfo.Normal, ray.Direction, shape.GetMaterial().Refraction); var refr = shape.Intersect(refractionRay); var refractedColor = Scene.Background.Color; if (refr.IsHit) { if (Scene.TryGetShape(refr.ElementId, out var refrShape)) { var elemRefractionRay = GetRefractionRay(refr.Position, refr.Normal, refractionRay.Direction, refrShape.GetMaterial().Refraction); var secondRefr = TestIntersection(elemRefractionRay, shape.Id); if (secondRefr.IsHit && secondRefr.Distance > 0.0) { refractedColor = RayTrace(secondRefr, elemRefractionRay, depth + 1); } } } else { refractedColor = Scene.Background.Color; } return(currentColor.Blend(refractedColor, shape.GetMaterial().KTransparent)); } } } return(currentColor); }
private IntersectionInfo FindIntersectionNode(KdNode node, BoundingBox bbox, Ray ray) { if (node == null) { return(new IntersectionInfo()); } if (node.Plane == KdNodePlane.NoPlane) { // leaf node var bestInfo = new IntersectionInfo(); foreach (var shape in node.Shapes) { var info = shape.Intersect(ray); if (info.IsHit) { // if (bbox.IsPointInside(info.Position)) { if (info.Distance < bestInfo.Distance && info.Distance >= 0.0) { bestInfo = info; } } } } if (bestInfo.IsHit) { return(bestInfo); } else { return(new IntersectionInfo()); } } var(leftIsFront, frontBbox, backBbox) = SplitPlane(node, bbox, ray); var frontNode = leftIsFront ? node.Left : node.Right; var backNode = leftIsFront ? node.Right : node.Left; if (IsBoundingBoxIntersection(frontBbox, ray)) { var intInfo = FindIntersectionNode(frontNode, frontBbox, ray); if (intInfo.IsHit) { return(intInfo); } else { if (IsBoundingBoxIntersection(backBbox, ray)) { intInfo = FindIntersectionNode(backNode, backBbox, ray); return(intInfo.IsHit ? intInfo : new IntersectionInfo()); } else { return(new IntersectionInfo()); } } } else { return(new IntersectionInfo()); } }
private ColorVector CalculateColor(Ray ray, IntersectionInfo intInfo, double rayIntensity, int depth) { if (intInfo.IsHit && Scene.TryGetShape(intInfo.ElementId, out IShape shape)) { var material = shape.GetMaterial(); var objectColor = intInfo.Color; var ambientColor = new ColorVector(); var diffuseColor = new ColorVector(); var reflectedColor = new ColorVector(); var specularColor = new ColorVector(); var resultColor = new ColorVector(); double fogDensity = 0; if (Scene.HasFogDensity) { fogDensity = Scene.GetFogDensity(intInfo.Distance); } if (material.KAmbient > double.Epsilon) { ambientColor = Scene.Background.Color.Mix(objectColor); resultColor = resultColor.Mix(ambientColor); } if (material.KDiffuse > double.Epsilon) { diffuseColor = objectColor; if (Scene.HasLights) { diffuseColor = diffuseColor.Mix(GetLightingColor(intInfo.Position, intInfo.Normal)); } resultColor = resultColor.Blend(diffuseColor, material.KDiffuse); } if (material.KSpecular > double.Epsilon) { specularColor = Scene.Background.Color; if (Scene.HasLights) { var reflectedRay = ReflectRay(ray, intInfo.Normal); specularColor = GetSpecularColor(reflectedRay, material.Gloss); } resultColor = resultColor.Blend(specularColor, material.KSpecular); } if (material.KReflection > double.Epsilon) { // avoid deep recursion by tracing rays which have intensity greater than threshold // and avoid infinite recursion by limiting number of recursive calls if (rayIntensity > ThresholdRayIntensity && depth < MaxRayRecursionLevel) { var reflectedRay = ReflectRay(ray, intInfo.Normal); reflectedColor = TraceRecursive( reflectedRay, rayIntensity * material.KReflection * (1 - fogDensity), depth + 1); } else { reflectedColor = Scene.Background.Color; } resultColor = resultColor.Blend(reflectedColor, material.KReflection); } if (Scene.HasFogDensity) { resultColor = (Scene.Background.Color * fogDensity) + (resultColor * (1.0 - fogDensity)); } return(resultColor); } else { return(Scene.Background.Color); } }