private Color RenderRay(RayData rayData) { float depth = 0; for (int step = 0; step < MaxMarchingSteps; step++) { Vector3 samplePoint = rayData.EyePosition + depth * rayData.RayDirection; float distance = SphereSDF(samplePoint); if (distance < rayData.Epsilon) { // Since our sphere located in the center of the world we can easlity get normal of // the point where we touching sphere by simple normalization Vector3 normal = samplePoint.normalized; // TODO: implement Specualr and Ambient sampling Color color = GetDiffuseColor(normal, rayData.LightingRig, hitPoint: samplePoint); return(color); } depth += distance; // Make sure we are not going too far from sphere if (depth > _distanceToSphere * 2) { break; } } return(Color.black); }
// TODO: implement split texture rendering for Diffuse, Alpha & Specular (now supported only Combined) // TODO: implement viriable view position (now supported only along Z axis) public override void Render(MatCapSnapshot matCapSnapshot, LightingRig lightingRig, CameraRuntimeRef cameraRef) { Texture2D combined = matCapSnapshot.Combined; Color[] pixels = combined.GetPixels(); // Min distance to sphere caluclated according to texel size float epsilon = GetEpsilon(combined.width, combined.height); // Pixels layed out left to right, bottom to top for (int row = combined.height - 1; row >= 0; row--) { for (int col = 0; col < combined.width; col++) { var rayData = new RayData(); rayData.RayDirection = GetRayDirection(combined.width, col, combined.height, row, cameraRef); rayData.LightingRig = lightingRig; rayData.EyePosition = new Vector3(0, 0, -_distanceToSphere); rayData.Epsilon = epsilon; // TODO: use new Unity data oriented desing with ECS and Burst // This task could be parallelized int index = row * combined.width + col; pixels[index] = RenderRay(rayData); } } combined.SetPixels(pixels); combined.Apply(); }