Пример #1
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);
        }
Пример #2
0
        public Vector3 GetShaded2(XorShift64Star random, Scene scene, Vector3 position, Vector3 direction, Vector3 normal)
        {
            Vector3 shaded = new Vector3();

            float fresnel = Helper.Schlick(normal, direction, 1f, ReflectionIOR);

            if (Diffuse > 0)
            {
                shaded += GetDirectDiffuse(random, scene, position, normal) * (1f - fresnel);
                shaded += GetIndirectDiffuse2(random, scene, position, normal) * (1f - fresnel);
            }

            if (Reflectivity > 0)
            {
                shaded += GetReflection2(random, scene, position, direction, normal) * fresnel;
            }


            shaded += GetEmissive(direction, normal);

            return(shaded);
        }
Пример #3
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);
        }
Пример #4
0
        public Vector3 GetDirectDiffuse(XorShift64Star random, Scene scene, Vector3 position, Vector3 normal)
        {
            Vector3 lightAccumulator = new Vector3();

            for (int i = 0; i < scene.SceneLights.Length; i++)
            {
                Light   l   = scene.SceneLights[i];
                Vector3 dir = Vector3.Normalize(l.GetPoint(random) - position);
                if (Vector3.Dot(normal, dir) <= 0)
                {
                    continue;
                }
                Ray          r            = new Ray(position + dir * 0.002f, dir);
                Intersection intersection = scene.TraceScene(r);
                if (!intersection.HitLight)
                {
                    continue;
                }
                Vector3 lightC = l.GetColor(dir) * Vector3.Dot(dir, normal) * l.GetAttenuation(intersection.IntersectionLength, dir);
                lightAccumulator += Vector3.Multiply(lightC, DiffuseColor * Diffuse);
            }

            return(lightAccumulator);
        }
Пример #5
0
 public Vector3 GetIndirectDiffuse3(XorShift64Star random, Scene scene, Vector3 position, Vector3 normal)
 {
     return(GetDirectDiffuse(random, scene, position, normal));
 }
 public PseudorandomNumberGeneratorsBenchmark()
 {
     linearCongruentialRandomNumberGenerator = new LinearCongruentialRandomNumberGenerator();
     xOrShift64Star   = new XorShift64Star();
     xOrShift1024Star = new XorShift1024Star();
 }
Пример #7
0
        private static void ColorRay(int index,
                                     Ray ray,
                                     dFramebuffer framebuffer,
                                     dWorldBuffer world,
                                     XorShift64Star rng, Camera camera)
        {
            Vec3 attenuation = new Vec3(1f, 1f, 1f);
            Vec3 lighting    = new Vec3();

            Ray  working             = ray;
            bool attenuationHasValue = false;

            float minT = 0.1f;

            for (int i = 0; i < camera.maxBounces; i++)
            {
                HitRecord rec = GetWorldHit(working, world, minT);

                if (rec.materialID == -1)
                {
                    if (i == 0 || attenuationHasValue)
                    {
                        framebuffer.DrawableIDBuffer[index] = -2;
                    }

                    float t = 0.5f * (working.b.y + 1.0f);
                    attenuation *= (1.0f - t) * new Vec3(1.0f, 1.0f, 1.0f) + t * new Vec3(0.5f, 0.7f, 1.0f);
                    break;
                }
                else
                {
                    if (i == 0)
                    {
                        framebuffer.ZBuffer[index]          = rec.t;
                        framebuffer.DrawableIDBuffer[index] = rec.drawableID;
                    }

                    ScatterRecord sRec = Scatter(working, rec, rng, world.materials, minT);
                    if (sRec.materialID != -1)
                    {
                        attenuationHasValue = sRec.mirrorSkyLightingFix;
                        attenuation        *= sRec.attenuation;
                        working             = sRec.scatterRay;
                    }
                    else
                    {
                        framebuffer.DrawableIDBuffer[index] = -1;
                        break;
                    }
                }

                for (int j = 0; j < world.lightSphereIDs.Length; j++)
                {
                    Sphere    s         = world.spheres[world.lightSphereIDs[j]];
                    Vec3      lightDir  = s.center - rec.p;
                    HitRecord shadowRec = GetWorldHit(new Ray(rec.p, lightDir), world, minT);

                    if (shadowRec.materialID != -1 && (shadowRec.p - rec.p).length() > lightDir.length() - (s.radius * 1.1f)) // the second part of this IF could probably be much more efficent
                    {
                        MaterialData material = world.materials[shadowRec.materialID];
                        if (material.type != 1)
                        {
                            lightDir  = Vec3.unitVector(lightDir);
                            lighting += material.color * XMath.Max(0.0f, Vec3.dot(lightDir, rec.normal));
                            lighting *= XMath.Pow(XMath.Max(0.0f, Vec3.dot(-Vec3.reflect(rec.normal, -lightDir), ray.b)), material.reflectivity) * material.color;
                        }
                    }
                }
            }

            int rIndex = index * 3;
            int gIndex = rIndex + 1;
            int bIndex = rIndex + 2;

            framebuffer.ColorFrameBuffer[rIndex] = attenuation.x;
            framebuffer.ColorFrameBuffer[gIndex] = attenuation.y;
            framebuffer.ColorFrameBuffer[bIndex] = attenuation.z;

            framebuffer.LightingFrameBuffer[rIndex] = lighting.x;
            framebuffer.LightingFrameBuffer[gIndex] = lighting.y;
            framebuffer.LightingFrameBuffer[bIndex] = lighting.z;
        }
Пример #8
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));
        }
Пример #9
0
 //Applies a random detune value based on the current randomness parameter and the max specified detune level.
 public void ApplyDetuneRandomness()
 {
     detune_current = Tools.Lerp(_detune, 1.0, (XorShift64Star.NextDouble()) * detune_randomness);
 }