Пример #1
0
        public static void Kernel(Index2 index, ArrayView2D <Vector3> dataView, Scene scene, ArrayView <Geometry> sceneGeometry, ArrayView <Light> sceneLights, int seed)
        {
            Vector3 outputColor = Vector3.Zero;

            scene.SceneGeometry = sceneGeometry;
            scene.SceneLights   = sceneLights;
            //Models.Random random = new Models.Random((uint) (index.X * index.Y + seed));
            XorShift64Star random = new XorShift64Star((ulong)index.X + (ulong)scene.Camera.ScreenWidth * (ulong)index.Y + (ulong)seed);

            float xOffset = random.NextFloat();

            random.NextFloat();
            float yOffset = random.NextFloat();

            Ray ray = scene.Camera.GetRaySimple(index.X + (xOffset * 2f - 1f) * 0.5f, index.Y + (yOffset * 2f - 1f) * 0.5f);

            Intersection intersection = scene.TraceScene(ray);

            if (intersection.Hit)
            {
                outputColor = intersection.HitObject.Material.GetShaded(random, scene, intersection.HitPosition, ray.Direction, intersection.HitNormal);
            }
            else if (intersection.HitLight)
            {
                outputColor = intersection.HitLightObject.GetColor(ray.Direction);
            }

            dataView[index] += outputColor;
        }
Пример #2
0
        private static Vec3 RandomUnitVector(XorShift64Star rng)
        {
            float a = 2f * XMath.PI * rng.NextFloat();
            float z = (rng.NextFloat() * 2f) - 1f;
            float r = XMath.Sqrt(1f - z * z);

            return(new Vec3(r * XMath.Cos(a), r * XMath.Sin(a), z));
        }
Пример #3
0
        public static Vector3 PointOnHemisphere(this XorShift64Star random, Vector3 n)
        {
            float   azimuthal = random.NextFloat() * XMath.PI * 2f;
            float   z         = random.NextFloat();
            float   xyproj    = XMath.Sqrt(1 - z * z);
            Vector3 v         = new Vector3(xyproj * XMath.Cos(azimuthal), xyproj * XMath.Sin(azimuthal), z);

            if (Vector3.Dot(v, n) < 0)
            {
                return(v * -1);
            }
            else
            {
                return(v);
            }
        }
Пример #4
0
        public Vector3 GetReflection2(XorShift64Star random, Scene scene, Vector3 position, Vector3 direction,
                                      Vector3 normal)
        {
            float   roughness = 0.01f;
            Vector3 accu      = Vector3.Zero;

            for (int i = 0; i < 2; i++)
            {
                random.NextFloat();
                Vector3 microfacetNormal = Helper.GetGGXMicrofacet(random, roughness, normal);
                Vector3 reflectedDir     = Vector3.Reflect(direction, microfacetNormal);

                Ray          r            = new Ray(position + reflectedDir * 0.002f, reflectedDir);
                Intersection intersection = scene.TraceScene(r);
                if (!intersection.Hit)
                {
                    continue;
                }

                Material mat             = intersection.HitObject.Material;
                Vector3  reflectionColor = mat.GetShaded3(random, scene, intersection.HitPosition, reflectedDir,
                                                          intersection.HitNormal);

                accu += reflectionColor;
            }

            return(accu / 2f);
        }
Пример #5
0
        public Vector3 GetDirectReflection(XorShift64Star random, Scene scene, Vector3 position, Vector3 direction,
                                           Vector3 normal)
        {
            float roughness = 0.01f;

            Vector3 lightAccumulator = new Vector3();

            for (int i = 0; i < scene.SceneLights.Length; i++)
            {
                random.NextFloat();
                Light   l    = scene.SceneLights[i];
                Vector3 ldir = l.GetPoint(random) - position;
                ldir /= XMath.Sqrt(Vector3.Dot(ldir, ldir));

                Ray          r            = new Ray(position + ldir * 0.002f, ldir);
                Intersection intersection = scene.TraceScene(r);
                if (!intersection.HitLight)
                {
                    continue;
                }



                float probability = Helper.ggxNormalDistribution(Vector3.Dot(Vector3.Reflect(-ldir, normal), -direction), roughness);

                Vector3 reflectionColor = intersection.HitLightObject.GetColor(ldir);

                lightAccumulator += reflectionColor * probability;
            }

            return(lightAccumulator);
        }
Пример #6
0
        public static Vector3 GetGGXMicrofacet(XorShift64Star random, float roughness, Vector3 normal)
        {
            float rand1 = random.NextFloat();
            float rand2 = random.NextFloat();

            Vector3 B = GetPerpendicularVector(normal);
            Vector3 T = Vector3.Cross(B, normal);

            float a2        = roughness * roughness;
            float cosThetaH = XMath.Sqrt(XMath.Max(0f, (1f - rand1) / ((a2 - 1f) * rand1 + 1f)));
            float sinThetaH = XMath.Sqrt(XMath.Max(0f, 1f - cosThetaH * cosThetaH));
            float phiH      = rand2 * XMath.PI * 2f;

            return(T * (sinThetaH * XMath.Cos(phiH)) +
                   B * (sinThetaH * XMath.Sin(phiH)) +
                   normal * cosThetaH);
        }
Пример #7
0
        public static void RenderKernel(Index2 id,
                                        dFramebuffer framebuffer,
                                        dWorldBuffer world,
                                        Camera camera, int rngOffset)
        {
            int x = id.X;
            int y = id.Y;

            int index = ((y * camera.width) + x);

            //there is probably a better way to do this, but it seems to work. seed = the tick * a large prime xor (index + 1) * even larger prime
            XorShift64Star rng = new XorShift64Star((((ulong)(rngOffset + 1) * 3727177) ^ ((ulong)(index + 1) * 113013596393)));
            //XorShift64Star rng = new XorShift64Star();

            Ray ray = camera.GetRay(x + rng.NextFloat(), y + rng.NextFloat());

            ColorRay(index, ray, framebuffer, world, rng, camera);
        }
Пример #8
0
        public Vector3 GetIndirectDiffuse2(XorShift64Star random, Scene scene, Vector3 position, Vector3 normal)
        {
            Vector3 lightAccumulator = new Vector3();
            int     samples          = 4;

            for (int i = 0; i < samples; i++)
            {
                float   azimuthal = random.NextFloat() * XMath.PI * 2f;
                float   z         = random.NextFloat();
                float   xyproj    = XMath.Sqrt(1 - z * z);
                Vector3 dir       = new Vector3(xyproj * XMath.Cos(azimuthal), xyproj * XMath.Sin(azimuthal), z);
                if (Vector3.Dot(dir, normal) < 0)
                {
                    dir *= -1;
                }
                Ray          ray          = new Ray(position + dir * 0.002f, dir);
                Intersection intersection = scene.TraceScene(ray);
                if (!intersection.Hit && !intersection.HitLight)
                {
                    lightAccumulator += Vector3.Multiply(scene.SkylightColor * scene.SkylightBrightness * Vector3.Dot(dir, normal), DiffuseColor) * Diffuse;
                    continue;
                }
                else if (!intersection.Hit || intersection.HitLight)
                {
                    continue;
                }
                Material hitMaterial = intersection.HitObject.Material;
                Vector3  lightC      = hitMaterial.GetShaded3(random, scene, intersection.HitPosition, dir, intersection.HitNormal);
                lightC           *= Vector3.Dot(dir, normal);
                lightAccumulator += Vector3.Multiply(lightC, DiffuseColor) * Diffuse;
            }

            lightAccumulator /= (float)samples;

            return(lightAccumulator);
        }
Пример #9
0
        private static ScatterRecord Scatter(Ray r, HitRecord rec, XorShift64Star rng, ArrayView <MaterialData> materials, float minT)
        {
            MaterialData material = materials[rec.materialID];
            Ray          ray;
            Vec3         outward_normal;
            Vec3         refracted;
            Vec3         reflected;
            float        ni_over_nt;
            float        cosine;

            if (material.type == 0) //Diffuse
            {
                refracted = rec.p + rec.normal + RandomUnitVector(rng);
                return(new ScatterRecord(rec.materialID, new Ray(rec.p, refracted - rec.p), material.color, false));
            }
            else if (material.type == 1) // dielectric
            {
                if (Vec3.dot(r.b, rec.normal) > minT)
                {
                    outward_normal = -rec.normal;
                    ni_over_nt     = material.ref_idx;
                    cosine         = Vec3.dot(r.b, rec.normal);
                    cosine         = XMath.Sqrt(1.0f - material.ref_idx * material.ref_idx * (1f - cosine * cosine));
                }
                else
                {
                    outward_normal = rec.normal;
                    ni_over_nt     = 1.0f / material.ref_idx;
                    cosine         = -Vec3.dot(r.b, rec.normal);
                }

                //moved the refract code here because I need the if (discriminant > 0) check
                float dt           = Vec3.dot(r.b, outward_normal);
                float discriminant = 1.0f - ni_over_nt * ni_over_nt * (1f - dt * dt);

                if (discriminant > minT)
                {
                    if (rng.NextFloat() < schlick(cosine, material.ref_idx))
                    {
                        return(new ScatterRecord(rec.materialID, new Ray(rec.p, Vec3.reflect(rec.normal, r.b)), material.color, true));
                    }
                    else
                    {
                        return(new ScatterRecord(rec.materialID, new Ray(rec.p, ni_over_nt * (r.b - (outward_normal * dt)) - outward_normal * XMath.Sqrt(discriminant)), material.color, true));
                    }
                }
                else
                {
                    return(new ScatterRecord(rec.materialID, new Ray(rec.p, Vec3.reflect(rec.normal, r.b)), material.color, true));
                }
            }
            else if (material.type == 2) //Metal
            {
                reflected = Vec3.reflect(rec.normal, r.b);
                if (material.reflectionConeAngleRadians > minT)
                {
                    ray = new Ray(rec.p, reflected + (material.reflectionConeAngleRadians * RandomUnitVector(rng)));
                }
                else
                {
                    ray = new Ray(rec.p, reflected);
                }

                if ((Vec3.dot(ray.b, rec.normal) > minT))
                {
                    return(new ScatterRecord(rec.materialID, ray, material.color, true));
                }
            }
            else if (material.type == 3) //Lights
            {
                refracted = rec.p + rec.normal;
                return(new ScatterRecord(rec.materialID, new Ray(rec.p, refracted - rec.p), material.color, false));
            }

            return(new ScatterRecord(-1, r, new Vec3(), true));
        }