static void LitRaycast(Texture2D texture) { // Scene Setup float3 CameraPosition = float3(3, 2f, 4); float3 LightPosition = float3(3, 5, -2); // View and projection matrices float4x4 viewMatrix = Transforms.LookAtLH(CameraPosition, float3(0, 1, 0), float3(0, 1, 0)); float4x4 projectionMatrix = Transforms.PerspectiveFovLH(pi_over_4, texture.Height / (float)texture.Width, 0.01f, 20); Scene <PositionNormal> scene = new Scene <PositionNormal>(); CreateScene(scene); // Raycaster to trace rays and check for shadow rays. Raytracer <ShadowRayPayload, PositionNormal> shadower = new Raytracer <ShadowRayPayload, PositionNormal>(); shadower.OnAnyHit += delegate(IRaycastContext context, PositionNormal attribute, ref ShadowRayPayload payload) { // If any object is found in ray-path to the light, the ray is shadowed. payload.Shadowed = true; // No neccessary to continue checking other objects return(HitResult.Stop); }; // Raycaster to trace rays and lit closest surfaces Raytracer <RayPayload, PositionNormal> raycaster = new Raytracer <RayPayload, PositionNormal>(); raycaster.OnClosestHit += delegate(IRaycastContext context, PositionNormal attribute, ref RayPayload payload) { // Move geometry attribute to world space attribute = attribute.Transform(context.FromGeometryToWorld); float3 V = normalize(CameraPosition - attribute.Position); float3 L = normalize(LightPosition - attribute.Position); float lambertFactor = max(0, dot(attribute.Normal, L)); // Check ray to light... ShadowRayPayload shadow = new ShadowRayPayload(); shadower.Trace(scene, RayDescription.FromTo( attribute.Position + attribute.Normal * 0.001f, // Move an epsilon away from the surface to avoid self-shadowing LightPosition), ref shadow); payload.Color = shadow.Shadowed ? float3(0, 0, 0) : float3(1, 1, 1) * lambertFactor; }; raycaster.OnMiss += delegate(IRaycastContext context, ref RayPayload payload) { payload.Color = float3(0, 0, 1); // Blue, as the sky. }; // Render all points of the screen for (int px = 0; px < texture.Width; px++) { for (int py = 0; py < texture.Height; py++) { RayDescription ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000); RayPayload coloring = new RayPayload(); raycaster.Trace(scene, ray, ref coloring); texture.Write(px, py, float4(coloring.Color, 1)); } } }
private static void RaycastingMesh(Texture2D texture, float3 cameraPosition, float3 lightPosition, float3 target) { // View and projection matrices var viewMatrix = Transforms.LookAtLH(cameraPosition, target, float3.up); var projectionMatrix = Transforms.PerspectiveFovLH(pi_over_4, texture.Height / (float)texture.Width, 0.01f, 20); var scene = new Scene <PositionNormal>(); CreateMeshScene(scene); // Raycaster to trace rays and check for shadow rays. var shadower = new Raytracer <ShadowRayPayload, PositionNormal>(); shadower.OnAnyHit += (IRaycastContext context, PositionNormal attribute, ref ShadowRayPayload payload) => { // If any object is found in ray-path to the light, the ray is shadowed. payload.Shadowed = true; // No necessary to continue checking other objects return(HitResult.Stop); }; // Raycaster to trace rays and lit closest surfaces var raycaster = new Raytracer <RayPayload, PositionNormal>(); raycaster.OnClosestHit += (IRaycastContext context, PositionNormal attribute, ref RayPayload payload) => { // Move geometry attribute to world space attribute = attribute.Transform(context.FromGeometryToWorld); var V = normalize(cameraPosition - attribute.Position); var L = normalize(lightPosition - attribute.Position); var lambertFactor = max(0, dot(attribute.Normal, L)); // Check ray to light... var shadow = new ShadowRayPayload(); shadower.Trace(scene, RayDescription.FromTo( attribute.Position + attribute.Normal * 0.001f, // Move an epsilon away from the surface to avoid self-shadowing lightPosition), ref shadow); payload.Color = shadow.Shadowed ? float3(0, 0, 0) : float3(1, 1, 1) * lambertFactor; }; raycaster.OnMiss += (IRaycastContext context, ref RayPayload payload) => { payload.Color = float3(0, 0, 1); // Blue, as the sky. }; // Render all points of the screen for (var px = 0; px < texture.Width; px++) { for (var py = 0; py < texture.Height; py++) { var progress = px * texture.Height + py; if (progress % 100 == 0) { Console.Write("\r" + progress * 100 / (float)(texture.Width * texture.Height) + "% "); } var ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000); var coloring = new RayPayload(); raycaster.Trace(scene, ray, ref coloring); texture.Write(px, py, float4(coloring.Color, 1)); } } Console.Write("\r" + 100 + "% "); }