Color TracePath(Ray ray, int depth) { if (depth >= MaxDepth) { return(Color.black); // Bounced enough times. } SceneRayHit hit = scene.RayCast(ray); if (hit == null) { return(Color.black); // Nothing was hit. } Profiler.BeginSample("GetComponent<MeshRenderer"); Profiler.EndSample(); Profiler.BeginSample("GetEmissionColor"); var emittance = hit.HitObj.Emittance; Profiler.EndSample(); // Pick a random direction from here and keep going. // This is NOT a cosine-weighted distribution! Profiler.BeginSample("RandomUnitVectorInHemisphere"); var direction = RandomUnitVectorInHemisphereOf(hit.normal); Profiler.EndSample(); Ray newRay = new Ray(hit.point, direction); // Recursively trace reflected light sources. Color incoming = TracePath(newRay, depth + 1); Profiler.BeginSample("LightCal"); // Probability of the newRay float p = 1 / (2 * M_PI); // Compute the BRDF for this ray (assuming Lambertian reflection) Profiler.BeginSample("Dot"); float cos_theta = Mathf.Max(0, Vector3.Dot(newRay.direction.normalized, hit.normal.normalized)); Profiler.EndSample(); Profiler.BeginSample("GetColor"); Color BRDF = hit.HitObj.reflectance / M_PI; Profiler.EndSample(); // Apply the Rendering Equation here. var finalColor = emittance + (BRDF * incoming * cos_theta / p); Profiler.EndSample(); return(finalColor); }
public SceneRayHit RayCast(Ray ray) { SceneRayHit hitObj = new SceneRayHit(); for (int i = 0; i < SceneObjects.Length; ++i) { RaycastHit hit; if (SceneObjects[i].RayCast(ray, out hit)) { if (hitObj.HitObj == null || hit.distance < hitObj.distance) { hitObj.HitObj = SceneObjects[i]; hitObj.normal = hit.normal; hitObj.point = hit.point; hitObj.distance = hit.distance; } } } return(hitObj.HitObj != null ? hitObj : null); }