private static void Main() { var materialIvory = new Material(new ColorF(0.4f, 0.4f, 0.3f), new Albedo(0.6f, 0.3f, 0.1f, 0f), 50f, 1f); var materialRed = new Material(new ColorF(0.3f, 0.1f, 0.1f), new Albedo(0.9f, 0.1f, 0.0f, 0f), 10f, 1f); var materialMirror = new Material(new ColorF(1.0f, 1.0f, 1.0f), new Albedo(0f, 10f, 0.8f, 0f), 1425f, 1f); var materialGlass = new Material( new ColorF(0.6f, 0.7f, 0.8f), new Albedo(0f, 0.5f, 0.1f, 0.8f), 125f, 1.5f); var scene = new List <IObject3D> { new Sphere(new Vector3(-3f, 0f, -16f), 2, materialIvory), new Sphere(new Vector3(-1f, -1.5f, -12f), 2, materialGlass), new Sphere(new Vector3(1.5f, -0.5f, -18f), 3, materialRed), new Sphere(new Vector3(7f, 5f, -18f), 4, materialMirror) }; var lightSources = new List <LightSource> { new LightSource(new Vector3(-20f, 20f, 20f), 1.5f), new LightSource(new Vector3(30f, 50f, -25f), 1.8f), new LightSource(new Vector3(30f, 20f, 30f), 1.7f) }; var renderEngine = new RenderEngine(Width, Height); var environmentMap = new ImageF(EnvMapPath); var frame = renderEngine.Render(Vector3.Zero, scene, lightSources, environmentMap); frame.SaveToFile(ResultFramePath); }
private ColorF CastRay( ref Vector3 origin, ref Vector3 projectionDirection, List <IObject3D> scene, List <LightSource> lightSources, ImageF environmentMap = null, int depth = 0) { RayIntersectionResult rayIntersectionResult; if (depth > RaycastDepth || !(rayIntersectionResult = SceneIntersect(ref origin, ref projectionDirection, scene)).IsIntersect) { return(environmentMap == null ? DefaultColor : GetColorFromEnvironmentMap(projectionDirection, environmentMap)); } CalculateLightIntensity( projectionDirection, scene, lightSources, rayIntersectionResult, out var diffuseLightIntensity, out var specularLightIntensity); var reflectionColor = GetReflectionColor( projectionDirection, scene, lightSources, environmentMap, depth, ref rayIntersectionResult); var refractionColor = GetRefractionColor( projectionDirection, scene, lightSources, environmentMap, depth, ref rayIntersectionResult); return(rayIntersectionResult.Material.DiffuseColor * diffuseLightIntensity * rayIntersectionResult.Material.Albedo.DiffuseKoef + ColorF.White * specularLightIntensity * rayIntersectionResult.Material.Albedo.SpecularKoef + reflectionColor * rayIntersectionResult.Material.Albedo.ReflectKoef + refractionColor * rayIntersectionResult.Material.Albedo.RefractKoef); }
private ColorF GetColorFromEnvironmentMap(Vector3 projectionDirection, ImageF environmentMap) { var x = (int)MathF.Max( 0f, MathF.Min( environmentMap.Width - 1, (int)((Math.Atan2(projectionDirection.Z, projectionDirection.X) / (2 * MathF.PI) + 0.5f) * environmentMap.Width))); var y = (int)MathF.Max( 0f, MathF.Min( environmentMap.Height - 1, (int)(MathF.Acos(projectionDirection.Y) / MathF.PI * environmentMap.Height))); return(environmentMap.Buffer[x][y]); }
public ImageF Render( Vector3 cameraPosition, List <IObject3D> scene, List <LightSource> lightSources, ImageF environmentMap = null) { var frame = new ImageF(FrameWidth, FrameHeight); Parallel.For( 0, FrameHeight, j => { for (var i = 0; i < FrameWidth; i++) { var x = (2 * (i + 1e-3f) / FrameWidth - 1) * MathF.Tanh(Fov / 2f) * (FrameWidth / (float)FrameHeight); var y = -(2 * (j + 1e-3f) / FrameHeight - 1) * MathF.Tanh(Fov / 2f); var projectionDirection = Vector3.Normalize(new Vector3(x, y, -1f)); frame.Buffer[i][j] = CastRay( ref cameraPosition, ref projectionDirection, scene, lightSources, environmentMap); } }); return(frame); }
private ColorF GetRefractionColor( Vector3 projectionDirection, List <IObject3D> scene, List <LightSource> lightSources, ImageF environmentMap, int depth, ref RayIntersectionResult rayIntersectionResult) { var refractDirection = Vector3.Normalize( Refract( projectionDirection, rayIntersectionResult.NormalVector, rayIntersectionResult.Material.RefractiveIndex)); var refractOrigin = Vector3.Dot(refractDirection, rayIntersectionResult.NormalVector) < 0 ? rayIntersectionResult.HitPoint - rayIntersectionResult.NormalVector * 1e-3f : rayIntersectionResult.HitPoint + rayIntersectionResult.NormalVector * 1e-3f; return(CastRay(ref refractOrigin, ref refractDirection, scene, lightSources, environmentMap, depth + 1)); }