Пример #1
0
        public static void DrawArea <T, M>(int id, int x0, int y0, int xf, int yf, Raytracer <DefaultRayPayload, T, M> raycaster, Texture2D texture, float4x4 viewMatrix, float4x4 projectionMatrix, Scene <T, M> scene, int step = 1) where T : struct where M : struct
        {
            for (int px = x0; px < xf; px += step)
            {
                for (int py = y0; py < yf; py += step)
                {
                    //int progress = (px * yf + py);
                    //if (progress % 100 == 0)
                    //{
                    //    Console.WriteLine($"{id}: " + progress * 100 / (xf * yf) + "%            ");
                    //}

                    RayDescription ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000);

                    DefaultRayPayload coloring = new DefaultRayPayload();

                    raycaster.Trace(scene, ray, ref coloring);
                    for (int i = 0; i < step; i++)
                    {
                        for (int j = 0; j < step; j++)
                        {
                            texture.Write(Math.Min(px + i, texture.Width - 1), Math.Min(py + j, texture.Height - 1), float4(coloring.Color, 1));
                        }
                    }
                }
            }
            Console.WriteLine($"Done {id}");
        }
Пример #2
0
        static void SimpleRaycast(Texture2D texture)
        {
            Raytracer <RayPayload, float3> raycaster = new Raytracer <RayPayload, float3>();

            // View and projection matrices
            float4x4 viewMatrix       = Transforms.LookAtLH(float3(2, 1f, 4), float3(0, 0, 0), float3(0, 1, 0));
            float4x4 projectionMatrix =
                Transforms.PerspectiveFovLH(pi_over_4, texture.Height / (float)texture.Width, 0.01f, 20);

            Scene <float3> scene = new Scene <float3>();

            CreateScene(scene);

            raycaster.OnClosestHit += delegate(IRaycastContext context, float3 attribute, ref RayPayload payload)
            {
                payload.Color = attribute;
            };

            for (float px = 0.5f; px < texture.Width; px++)
            {
                for (float py = 0.5f; py < texture.Height; py++)
                {
                    RayDescription ray = RayDescription.FromScreen(px, py, texture.Width, texture.Height,
                                                                   inverse(viewMatrix), inverse(projectionMatrix), 0, 1000);

                    RayPayload coloring = new RayPayload();

                    raycaster.Trace(scene, ray, ref coloring);

                    texture.Write((int)px, (int)py, float4(coloring.Color, 1));
                }
            }
        }
Пример #3
0
        public static void Draw <T, M>(Texture2D texture, Raytracer <DefaultRayPayload, T, M> raytracer, Scene <T, M> scene, float4x4 viewMatrix, float4x4 projectionMatrix, int rendStep = 1, int gridXDiv = 8, int gridYDiv = 8) where T : struct where M : struct
        {
            var start = new Stopwatch();

            start.Start();

            var tasks = new List <Task>();
            int id = 0, xStep = texture.Width / gridXDiv, yStep = texture.Height / gridYDiv;

            for (int i = 0; i *yStep < texture.Height; i++)
            {
                for (int j = 0; j *xStep < texture.Width; j++)
                {
                    int threadId = id, x0 = j * xStep, y0 = i * yStep, maxX = Math.Min((j + 1) * xStep, texture.Width), maxY = Math.Min((i + 1) * yStep, texture.Height);
                    tasks.Add(Task.Run(() => RenderUtils.DrawArea(threadId, x0, y0, maxX, maxY, raytracer, texture, viewMatrix, projectionMatrix, scene, rendStep)));
                    id++;
                }
            }
            Task.WaitAll(tasks.ToArray());
            start.Stop();
            Console.WriteLine($"Elapsed {start.ElapsedMilliseconds} milliseconds");
        }
Пример #4
0
        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));
                }
            }
        }
Пример #5
0
        static void Pathtracing(Texture2D texture, int pass)
        {
            // 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 <PositionNormalCoordinate, Material> scene = new Scene <PositionNormalCoordinate, Material>();

            //CreateMeshScene(scene);
            CreateRaycastScene(scene);

            // Raycaster to trace rays and lit closest surfaces
            Raytracer <PTRayPayload, PositionNormalCoordinate, Material> raycaster = new Raytracer <PTRayPayload, PositionNormalCoordinate, Material>();

            raycaster.OnClosestHit += delegate(IRaycastContext context, PositionNormalCoordinate attribute, Material material, ref PTRayPayload payload)
            {
                // Move geometry attribute to world space
                attribute = attribute.Transform(context.FromGeometryToWorld);

                float3 V = -normalize(context.GlobalRay.Direction);

                attribute.Normal = normalize(attribute.Normal);

                if (material.BumpMap != null)
                {
                    float3 T, B;
                    createOrthoBasis(attribute.Normal, out T, out B);
                    float3 tangentBump = material.BumpMap.Sample(material.TextureSampler, attribute.Coordinates).xyz * 2 - 1;
                    float3 globalBump  = tangentBump.x * T + tangentBump.y * B + tangentBump.z * attribute.Normal;
                    attribute.Normal = globalBump;// normalize(attribute.Normal + globalBump * 5f);
                }

                ScatteredRay outgoing = material.Scatter(attribute, V);

                float lambertFactor = abs(dot(attribute.Normal, outgoing.Direction));

                payload.Color += payload.Importance * material.Emissive;

                // Recursive calls for indirect light due to reflections and refractions
                if (payload.Bounces > 0)
                {
                    float3 D           = outgoing.Direction;                                                  // recursive direction to check
                    float3 facedNormal = dot(D, attribute.Normal) > 0 ? attribute.Normal : -attribute.Normal; // normal respect to direction

                    RayDescription ray = new RayDescription {
                        Direction = D, Origin = attribute.Position + facedNormal * 0.001f, MinT = 0.0001f, MaxT = 10000
                    };

                    payload.Importance *= outgoing.Ratio * lambertFactor / outgoing.PDF;
                    payload.Bounces--;

                    raycaster.Trace(scene, ray, ref payload);
                }
            };
            raycaster.OnMiss += delegate(IRaycastContext context, ref PTRayPayload payload)
            {
                payload.Color = float3(0, 0, 0); // 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++)
                {
                    int progress = (px * texture.Height + py);
                    if (progress % 10000 == 0)
                    {
                        Console.Write("\r" + progress * 100 / (float)(texture.Width * texture.Height) + "%            ");
                    }

                    RayDescription ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000);

                    float4       accum    = texture.Read(px, py) * pass;
                    PTRayPayload coloring = new PTRayPayload();
                    coloring.Importance = float3(1, 1, 1);
                    coloring.Bounces    = 3;

                    raycaster.Trace(scene, ray, ref coloring);

                    texture.Write(px, py, float4((accum.xyz + coloring.Color) / (pass + 1), 1));
                }
            }
        }
Пример #6
0
        static void Raytracing(Texture2D texture)
        {
            // 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 <PositionNormalCoordinate, Material> scene = new Scene <PositionNormalCoordinate, Material>();

            //CreateMeshScene(scene);
            CreateRaycastScene(scene);

            // Raycaster to trace rays and check for shadow rays.
            Raytracer <ShadowRayPayload, PositionNormalCoordinate, Material> shadower = new Raytracer <ShadowRayPayload, PositionNormalCoordinate, Material>();

            shadower.OnAnyHit += delegate(IRaycastContext context, PositionNormalCoordinate attribute, Material material, ref ShadowRayPayload payload)
            {
                if (any(material.Emissive))
                {
                    return(HitResult.Discard); // Discard light sources during shadow test.
                }
                // 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 <MyRayPayload, PositionNormalCoordinate, Material> raycaster = new Raytracer <MyRayPayload, PositionNormalCoordinate, Material>();

            raycaster.OnClosestHit += delegate(IRaycastContext context, PositionNormalCoordinate attribute, Material material, ref MyRayPayload payload)
            {
                // Move geometry attribute to world space
                attribute = attribute.Transform(context.FromGeometryToWorld);

                float3 V = -normalize(context.GlobalRay.Direction);

                float3 L = (LightPosition - attribute.Position);
                float  d = length(L);
                L /= d; // normalize direction to light reusing distance to light

                attribute.Normal = normalize(attribute.Normal);

                if (material.BumpMap != null)
                {
                    float3 T, B;
                    createOrthoBasis(attribute.Normal, out T, out B);
                    float3 tangentBump = material.BumpMap.Sample(material.TextureSampler, attribute.Coordinates).xyz * 2 - 1;
                    float3 globalBump  = tangentBump.x * T + tangentBump.y * B + tangentBump.z * attribute.Normal;
                    //attribute.Normal = globalBump;
                    attribute.Normal = normalize(attribute.Normal + globalBump);
                }

                float lambertFactor = max(0, dot(attribute.Normal, L));

                // Check ray to light...
                ShadowRayPayload shadow = new ShadowRayPayload();
                shadower.Trace(scene,
                               RayDescription.FromDir(attribute.Position + attribute.Normal * 0.001f, // Move an epsilon away from the surface to avoid self-shadowing
                                                      L), ref shadow);

                float3 Intensity = (shadow.Shadowed ? 0.2f : 1.0f) * LightIntensity / (d * d);

                payload.Color = material.Emissive + material.EvalBRDF(attribute, V, L) * Intensity * lambertFactor; // direct light computation

                // Recursive calls for indirect light due to reflections and refractions
                if (payload.Bounces > 0)
                {
                    foreach (var impulse in material.GetBRDFImpulses(attribute, V))
                    {
                        float3 D           = impulse.Direction;                                                   // recursive direction to check
                        float3 facedNormal = dot(D, attribute.Normal) > 0 ? attribute.Normal : -attribute.Normal; // normal respect to direction

                        RayDescription ray = new RayDescription {
                            Direction = D, Origin = attribute.Position + facedNormal * 0.001f, MinT = 0.0001f, MaxT = 10000
                        };

                        MyRayPayload newPayload = new MyRayPayload
                        {
                            Bounces = payload.Bounces - 1
                        };

                        raycaster.Trace(scene, ray, ref newPayload);

                        payload.Color += newPayload.Color * impulse.Ratio;
                    }
                }
            };
            raycaster.OnMiss += delegate(IRaycastContext context, ref MyRayPayload payload)
            {
                payload.Color = float3(0, 0, 0); // 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++)
                {
                    int progress = (px * texture.Height + py);
                    if (progress % 1000 == 0)
                    {
                        Console.Write("\r" + progress * 100 / (float)(texture.Width * texture.Height) + "%            ");
                    }

                    RayDescription ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000);

                    MyRayPayload coloring = new MyRayPayload();
                    coloring.Bounces = 3;

                    raycaster.Trace(scene, ray, ref coloring);

                    texture.Write(px, py, float4(coloring.Color, 1));
                }
            }
        }
Пример #7
0
        static void RaycastingMeshTexture(Texture2D texture, Material mat)
        {
            // Scene Setup
            float3 CameraPosition = float3(3, 2f, 4);
            float3 LightPosition  = float3(3, 5, -2);
            float3 LightIntensity = float3(1, 1, 1) * 100;

            // 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 <PositionNormalCoordinate, Material> scene = new Scene <PositionNormalCoordinate, Material>();

            CreateMeshScene(scene);
            //CreateRaycastScene(scene, mat);

            // Raycaster to trace rays and check for shadow rays.
            Raytracer <ShadowRayPayload, PositionNormalCoordinate, Material> shadower = new Raytracer <ShadowRayPayload, PositionNormalCoordinate, Material>();

            shadower.OnAnyHit += delegate(IRaycastContext context, PositionNormalCoordinate attribute, Material material, 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 <MyRayPayload, PositionNormalCoordinate, Material> raycaster = new Raytracer <MyRayPayload, PositionNormalCoordinate, Material>();

            raycaster.OnClosestHit += delegate(IRaycastContext context, PositionNormalCoordinate attribute, Material material, ref MyRayPayload payload)
            {
                // Move geometry attribute to world space
                attribute = attribute.Transform(context.FromGeometryToWorld);

                float3 V = normalize(CameraPosition - attribute.Position);
                float3 L = (LightPosition - attribute.Position);
                float  d = length(L);
                L /= d; // normalize direction to light reusing distance to light

                attribute.Normal = normalize(attribute.Normal);

                float lambertFactor = max(0, dot(attribute.Normal, L));

                // Check ray to light...
                ShadowRayPayload shadow = new ShadowRayPayload();
                shadower.Trace(scene,
                               RayDescription.FromDir(attribute.Position + attribute.Normal * 0.001f, // Move an epsilon away from the surface to avoid self-shadowing
                                                      L), ref shadow);

                float3 Intensity = (shadow.Shadowed ? 0.2f : 1.0f) * LightIntensity / (d * d);

                payload.Color = material.EvalBRDF(attribute, V, L) * Intensity * lambertFactor;
            };
            raycaster.OnMiss += delegate(IRaycastContext context, ref MyRayPayload payload)
            {
                payload.Color = float3(0, 0, 0); // 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++)
                {
                    int progress = (px * texture.Height + py);
                    if (progress % 1000 == 0)
                    {
                        Console.Write("\r" + progress * 100 / (float)(texture.Width * texture.Height) + "%            ");
                    }

                    RayDescription ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000);

                    MyRayPayload coloring = new MyRayPayload();

                    raycaster.Trace(scene, ray, ref coloring);

                    texture.Write(px, py, float4(coloring.Color, 1));
                }
            }
        }
Пример #8
0
        public static void RaytracePassDrawArea <T>(int id, int x0, int y0, int xf, int yf, Raytracer <MyRTRayPayload, T, MyMaterial <T> > raycaster, Texture2D texture, float4x4 viewMatrix, float4x4 projectionMatrix, Scene <T, MyMaterial <T> > scene, int step = 1) where T : struct, IVertex <T>, INormalVertex <T>, ICoordinatesVertex <T>, IColorable, ITransformable <T>
        {
            for (int px = x0; px < xf; px += step)
            {
                for (int py = y0; py < yf; py += step)
                {
                    RayDescription ray = RayDescription.FromScreen(px + 0.5f, py + 0.5f, texture.Width, texture.Height, inverse(viewMatrix), inverse(projectionMatrix), 0, 1000);

                    MyRTRayPayload coloring = new MyRTRayPayload();
                    coloring.Bounces = 3;

                    raycaster.Trace(scene, ray, ref coloring);

                    for (int i = 0; i < step; i++)
                    {
                        for (int j = 0; j < step; j++)
                        {
                            texture.Write(Math.Min(px + i, texture.Width - 1), Math.Min(py + j, texture.Height - 1), float4(coloring.Color, 1));
                        }
                    }
                }
            }
            Console.WriteLine($"Done {id}");
        }
Пример #9
0
        public static void RayTrace <T>(Texture2D texture, Scene <T, MyMaterial <T> > scene, Raytracer <MyRTRayPayload, T, MyMaterial <T> > raycaster, float4x4 viewMatrix, float4x4 projectionMatrix, int rendStep = 1, int gridXDiv = 8, int gridYDiv = 8) where T : struct, IVertex <T>, INormalVertex <T>, ICoordinatesVertex <T>, IColorable, ITransformable <T>
        {
            var start = new Stopwatch();

            start.Start();

            var tasks = new List <Task>();
            int id = 0, xStep = texture.Width / gridXDiv, yStep = texture.Height / gridYDiv;

            for (int i = 0; i *yStep < texture.Height; i++)
            {
                for (int j = 0; j *xStep < texture.Width; j++)
                {
                    int threadId = id, x0 = j * xStep, y0 = i * yStep, maxX = Math.Min((j + 1) * xStep, texture.Width), maxY = Math.Min((i + 1) * yStep, texture.Height);
                    tasks.Add(Task.Run(() => RenderUtils.RaytracePassDrawArea(threadId, x0, y0, maxX, maxY, raycaster, texture, viewMatrix, projectionMatrix, scene, rendStep)));
                    id++;
                }
            }
            Task.WaitAll(tasks.ToArray());
            start.Stop();
            Console.WriteLine($"Elapsed {start.ElapsedMilliseconds} milliseconds");
        }
Пример #10
0
        public static void PathTrace <T>(Texture2D texture, Scene <T, MyMaterial <T> > scene, Raytracer <MyPTRayPayload, T, MyMaterial <T> > raycaster, float4x4 viewMatrix, float4x4 projectionMatrix, int maxPass, int rendStep = 1, int gridXDiv = 8, int gridYDiv = 8, int initPass = 0) where T : struct, IVertex <T>, INormalVertex <T>, ICoordinatesVertex <T>, IColorable, ITransformable <T>
        {
            var pathTimer = new Stopwatch();
            var passTimer = new Stopwatch();

            pathTimer.Start();

            int id = 0, xStep = texture.Width / gridXDiv, yStep = texture.Height / gridYDiv;
            int pass = initPass;

            while (pass < maxPass)
            {
                var tasks = new List <Task>();
                passTimer.Restart();
                for (int i = 0; i *yStep < texture.Height; i++)
                {
                    for (int j = 0; j *xStep < texture.Width; j++)
                    {
                        int threadId = id, x0 = j * xStep, y0 = i * yStep, maxX = Math.Min((j + 1) * xStep, texture.Width), maxY = Math.Min((i + 1) * yStep, texture.Height);
                        tasks.Add(Task.Run(() => RenderUtils.PathtracePassDrawArea(threadId, x0, y0, maxX, maxY, raycaster, texture, viewMatrix, projectionMatrix, scene, pass, rendStep)));
                        id++;
                    }
                }
                Task.WaitAll(tasks.ToArray());
                texture.Save("test.rbm");
                texture.SaveToBmp("test.bmp");
                Console.WriteLine($"Pass {pass} completed in {passTimer.ElapsedMilliseconds / 1000} seconds. {DateTime.Now}");
                pass++;
            }
            pathTimer.Stop();
            Console.WriteLine($"Elapsed {pathTimer.ElapsedMilliseconds / 1000} seconds. {DateTime.Now}");
        }