/// <summary> /// Method that check is a light ray originated in Point point reaches the Point observerPoint. /// Needed for the point light renderer. /// </summary> /// <param name="point">point where the ray originates</param> /// <param name="observerPoint">the point the ray should reach</param> /// <returns></returns> public bool isPointVisible(Point point, Point observerPoint) { Vec direction = point - observerPoint; float directionNorm = direction.getNorm(); Ray ray = new Ray(observerPoint, direction, tm: ((float) 1e-2 / directionNorm), tM: 1.0f); foreach (var shape in shapes) { if (shape.quickRayIntersection(ray)) return false; } return true; }
public override Color computeRadiance(Ray ray) { HitRecord? hitRecord = this.world.rayIntersection(ray); if (hitRecord == null) return this.backgroundColor; Material hitMaterial = hitRecord?.shape?.material!; Color resultColor = this.ambientColor; foreach (PointLight curLight in world.lightSources) { if (this.world.isPointVisible(curLight.position, (Point)hitRecord?.worldPoint!)) { Vec distanceVec = (Point)hitRecord?.worldPoint! - curLight.position; float distance = distanceVec.getNorm(); Vec inDir = distanceVec * (1f / distance); float cosTheta = MathF.Max(0f, Utility.NormalizedDot(-ray.dir, (Vec)hitRecord?.normal.toVec()!)); float distanceFactor; if (curLight.linearRadius > 0) distanceFactor = (curLight.linearRadius / distance) * (curLight.linearRadius / distance); else distanceFactor = 1f; Color emittedColor = (Color)hitMaterial?.emittedRadiance.getColor(hitRecord.Value.surfacePoint)!; Color brdfColor = (Color)hitMaterial?.brdf.Eval( (Normal)hitRecord?.normal!, inDir, -ray.dir, (Vec2D)hitRecord?.surfacePoint!)!; resultColor += (emittedColor + brdfColor) * curLight.color * cosTheta * distanceFactor; } } return resultColor; }