示例#1
0
    private static HitRecord GetTriangleHit(Ray r, dWorldBuffer world, dGPUMesh mesh, float nearerThan)
    {
        Triangle t = new Triangle();
        float    currentNearestDist = nearerThan;
        int      NcurrentIndex      = -1;
        int      material           = 0;
        float    Ndet = 0;

        for (int i = 0; i < mesh.triangleCount; i++)
        {
            t = mesh.GetTriangle(i, world);
            Vec3  tuVec = t.uVector();
            Vec3  tvVec = t.vVector();
            Vec3  pVec  = Vec3.cross(r.b, tvVec);
            float det   = Vec3.dot(tuVec, pVec);

            if (XMath.Abs(det) < nearerThan)
            {
                float invDet = 1.0f / det;
                Vec3  tVec   = r.a - t.Vert0;
                float u      = Vec3.dot(tVec, pVec) * invDet;
                Vec3  qVec   = Vec3.cross(tVec, tuVec);
                float v      = Vec3.dot(r.b, qVec) * invDet;

                if (u > 0 && u <= 1.0f && v > 0 && u + v <= 1.0f)
                {
                    float temp = Vec3.dot(tvVec, qVec) * invDet;
                    if (temp < currentNearestDist)
                    {
                        currentNearestDist = temp;
                        NcurrentIndex      = i;
                        Ndet     = det;
                        material = t.MaterialID;
                    }
                }
            }
        }

        if (NcurrentIndex == -1)
        {
            return(new HitRecord(float.MaxValue, new Vec3(), new Vec3(), false, -1, -1));
        }
        else
        {
            if (Ndet < 0)
            {
                return(new HitRecord(currentNearestDist, r.pointAtParameter(currentNearestDist), -t.faceNormal(), true, material, NcurrentIndex));
            }
            else
            {
                return(new HitRecord(currentNearestDist, r.pointAtParameter(currentNearestDist), t.faceNormal(), false, material, NcurrentIndex));
            }
        }
    }
示例#2
0
    public Triangle GetTriangle(int index, dWorldBuffer world)
    {
        int triangleIndex     = index * 3;
        int vertexStartIndex0 = world.triangles[triangleIndex] * 3;
        int vertexStartIndex1 = world.triangles[triangleIndex + 1] * 3;
        int vertexStartIndex2 = world.triangles[triangleIndex + 2] * 3;

        Vec3 Vert0 = new Vec3(world.verticies[vertexStartIndex0], world.verticies[vertexStartIndex0 + 1], world.verticies[vertexStartIndex0 + 2]) + position;
        Vec3 Vert1 = new Vec3(world.verticies[vertexStartIndex1], world.verticies[vertexStartIndex1 + 1], world.verticies[vertexStartIndex1 + 2]) + position;
        Vec3 Vert2 = new Vec3(world.verticies[vertexStartIndex2], world.verticies[vertexStartIndex2 + 1], world.verticies[vertexStartIndex2 + 2]) + position;

        return(new Triangle(Vert0, Vert1, Vert2, world.triangleMaterials[index]));
    }
示例#3
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);
        }
示例#4
0
        private static HitRecord GetWorldHit(Ray r, dWorldBuffer world, float minT)
        {
            HitRecord rec    = GetSphereHit(r, world.spheres, minT);
            HitRecord vRec   = world.VoxelChunk.hit(r, minT, rec.t);
            HitRecord triRec = GetMeshHit(r, world, vRec.t);

            if (rec.t < vRec.t && rec.t < triRec.t)
            {
                return(rec);
            }
            else if (vRec.t < rec.t && vRec.t < triRec.t)
            {
                return(vRec);
            }
            else
            {
                return(triRec);
            }
        }
示例#5
0
        private static HitRecord GetMeshHit(Ray r, dWorldBuffer world, float nearerThan)
        {
            float     dist = nearerThan;
            HitRecord rec  = new HitRecord(float.MaxValue, new Vec3(), new Vec3(), false, -1, -1);

            for (int i = 0; i < world.meshes.Length; i++)
            {
                if (world.meshes[i].aabb.hit(r, nearerThan, dist))
                {
                    HitRecord meshHit = GetTriangleHit(r, world, world.meshes[i], dist);
                    if (meshHit.t < dist)
                    {
                        dist = meshHit.t;
                        rec  = meshHit;
                    }
                }
            }

            return(rec);
        }
示例#6
0
    public static void PerPixelRayIntersectionMethod(Index2 pixel, CanvasData data, dWorldBuffer world, Camera camera)
    {
        int x = pixel.X;
        int y = pixel.Y;

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

        HitRecord hit = default;

        hit.t = float.MaxValue;

        for (int i = 0; i < world.meshes.Length; i++)
        {
            if (world.meshes[i].aabb.hit(ray, 0.001f, hit.t))
            {
                HitRecord meshHit = GetTriangleHit(ray, world, world.meshes[i], hit.t);
                if (meshHit.drawableID != -1)
                {
                    hit = meshHit;
                    data.setColor(pixel, getDebugColor(meshHit.drawableID));
                }
            }
        }
    }
示例#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;
        }