private double ComputeLightIntensity(ILight light, Vector3d intersectionPoint, Vector3d normal, Vector3d viewDirection, double specularExponent) { if (light is AmbientLight) { return(light.Intensity); } Vector3d oppositeLightDirection; double maxDistance; switch (light) { case DirectionalLight directionalLight: oppositeLightDirection = -directionalLight.Direction; maxDistance = double.PositiveInfinity; break; case PointLight pointLight: oppositeLightDirection = pointLight.Position - intersectionPoint; maxDistance = 1d; break; default: throw new NotSupportedException($"Cannot handle light of type {light.GetType().Name}"); } // shadow Ray shadowRay = new Ray(intersectionPoint, oppositeLightDirection); bool hasShadow = shadowRay.HasIntersection(_scene.Objects, RayTracer.Delta, maxDistance); if (hasShadow) { return(0d); } double intensity = 0d; // diffuse double nl = normal * oppositeLightDirection; if (nl > 0d) { intensity += light.Intensity * nl / (normal.Length * intersectionPoint.Length); } // specular if (specularExponent < 0d) { return(intensity); } Vector3d lightReflection = oppositeLightDirection.Reflect(normal); double rv = lightReflection * viewDirection; if (rv > 0d) { intensity += light.Intensity * Math.Pow(rv / (lightReflection.Length * viewDirection.Length), specularExponent); } return(intensity); }