Example #1
0
        public static void Render(RenderSettings settings, Camera camera)
        {
            if (settings.traceMethod == TraceMethod.PhotonTracing)
            {
                if (Config.RENDER_PHOTON_MAP)
                {
                    screen.UpdateSurface(PhotonMapping.PhotonMapRender(settings, camera));
                    return;
                }
            }

            Bitmap bitmap = new Bitmap(settings.width, settings.height);

            for (int j = 0; j < settings.height; ++j)
            {
                for (int i = 0; i < settings.width; ++i)
                {
                    Vector3 colorVector = settings.backgroundColor;

                    float vx = i / (float)settings.width;
                    float vy = j / (float)settings.height;

                    Ray ray = camera.RayThroughScreen(vx, vy);

                    switch (settings.traceMethod)
                    {
                    case TraceMethod.WhittedRayTracing:
                    {
                        colorVector = RayTracer.Trace(settings.maxDepth, settings.scene, ray, settings.backgroundColor);
                        break;
                    }

                    case TraceMethod.PathTracing:
                    {
                        int sampleCount = Config.PATH_TRACING_SAMPLES;

                        //TODO: Unsure if this should be here or if I should start random sampling loop from 0 instead of 1
                        colorVector = PathTracer.Trace(settings.maxDepth, settings.scene, ray, settings.backgroundColor);

                        for (int k = 1; k < sampleCount; k++)
                        {
                            var offsetXMin = -(0.5f / settings.width);
                            var offsetXMax = (0.5f / settings.width);
                            var offsetYMin = -(0.5f / settings.height);
                            var offsetYMax = (0.5f / settings.height);

                            var x = vx + MathHelper.RandomRange(offsetXMin, offsetXMax);
                            var y = vy + MathHelper.RandomRange(offsetYMin, offsetYMax);

                            ray = camera.RayThroughScreen(x, y);

                            colorVector += PathTracer.Trace(settings.maxDepth, settings.scene, ray, settings.backgroundColor);
                        }

                        colorVector /= sampleCount;
                        break;
                    }

                    case TraceMethod.PhotonTracing:
                    {
                        colorVector = PhotonTracer.Trace(settings.maxDepth, settings.scene, ray, settings.backgroundColor);
                        break;
                    }
                    }

                    if (settings.showUI)
                    {
                        //Render UI
                        Vector3?uiColor = RenderUI(settings, i, j);

                        if (uiColor.HasValue)
                        {
                            colorVector += uiColor.Value;
                        }
                    }

                    float red   = MathHelper.Clamp(colorVector.X, 0.0f, 1.0f);
                    float green = MathHelper.Clamp(colorVector.Y, 0.0f, 1.0f);
                    float blue  = MathHelper.Clamp(colorVector.Z, 0.0f, 1.0f);

                    Color color = Color.FromArgb(255, (int)(red * 255), (int)(green * 255), (int)(blue * 255));
                    bitmap.SetPixel(i, j, color);
                }
            }

            screen.UpdateSurface(bitmap);
        }
Example #2
0
        public static Vector3 Trace(int depth, Scene scene, Ray ray, Vector3 backgroundColor)
        {
            if (depth == Game.settings.maxDepth)
            {
                Game.numPrimaryRays++;
            }

            float distance       = 0.0f;
            int?  indexOfNearest = null;

            if (Config.USE_BVH)
            {
                List <int> meshIndices = scene.bvh.Traverse(ray);

                if (meshIndices.Count > 0)
                {
                    Game.numRayTests += meshIndices.Count;

                    NearestIntersection(scene, meshIndices, ray, out distance, out indexOfNearest);

                    if (indexOfNearest.HasValue)
                    {
                        indexOfNearest = meshIndices[indexOfNearest.Value];
                    }
                }
            }
            else
            {
                Game.numRayTests += scene.meshes.Count;

                NearestIntersection(scene.meshes, ray, out distance, out indexOfNearest);
            }

            if (indexOfNearest.HasValue)
            {
                Game.numRayIntersections++;

                int      index    = indexOfNearest.Value;
                Material material = scene.materials[index];
                Mesh     mesh     = scene.meshes[index];

                var intersection = ray.At(distance);
                var normal       = mesh.Normal(intersection);

                Vector3 color = material.Color(mesh, ray, distance, intersection);

                var reflection = material.reflection;
                var refraction = material.refraction;
                var ior        = material.ior;

                var diffuse = 1.0f - reflection - refraction;

                var result = Vector3.Zero;

                //Photon map
                if (diffuse > 0.0f)
                {
                    result = diffuse * PhotonMapping.GatherPhotonEnergy(intersection, normal, index);
                }

                if (mesh.isSkyboxMesh)
                {
                    return(material.Color(mesh, ray, distance, intersection));
                }

                if (depth > 1)
                {
                    bool    outside = Vector3.Dot(ray.direction, normal) < 0.0f;
                    Vector3 bias    = Renderer.EPSILON * normal;

                    switch (material.materialType)
                    {
                    case MaterialType.Diffuse:
                    {
                        result = color * result;
                        break;
                    }

                    case MaterialType.Reflection:
                    {
                        Vector3 reflectionRayOrigin = outside ? intersection + bias : intersection - bias;
                        Vector3 reflectionDirection = Renderer.Reflect(ray.direction, normal).Normalized();
                        Ray     reflectionRay       = new Ray(reflectionRayOrigin, reflectionDirection);

                        Vector3 reflectionColor = Trace(depth - 1, scene, reflectionRay, backgroundColor);
                        result += reflection * reflectionColor;

                        result = color * result;
                        break;
                    }

                    case MaterialType.Reflection_Refraction:
                    {
                        Vector3 refractionColor = new Vector3(0.0f);

                        float kr = Renderer.Fresnel(ray.direction, normal, ior);

                        //Compute refraction if it is not a case of total internal reflection
                        if (kr < 1.0f)
                        {
                            Vector3 refractionRayOrigin = outside ? intersection - bias : intersection + bias;
                            Vector3 refractionDirection = Renderer.Refract(ray.direction, normal, ior).Normalized();
                            Ray     refractionRay       = new Ray(refractionRayOrigin, refractionDirection);

                            refractionColor = Trace(depth - 1, scene, refractionRay, backgroundColor);
                        }

                        Vector3 reflectionDirection = Renderer.Reflect(ray.direction, normal).Normalized();
                        Vector3 reflectionRayOrigin = outside ? intersection + bias : intersection - bias;
                        Ray     reflectionRay       = new Ray(reflectionRayOrigin, reflectionDirection);

                        Vector3 reflectionColor = Trace(depth - 1, scene, reflectionRay, backgroundColor);
                        result += (reflectionColor * kr + refractionColor * (1.0f - kr)) * reflection;

                        result = color * result;
                        break;
                    }
                    }
                }

                if (material.selected)
                {
                    //Outline
                    float outlineSize = 0.01f;

                    switch (mesh.shape)
                    {
                    case Shape.Plane:
                    {
                        if (mesh.TextureCoords(intersection).X < outlineSize || mesh.TextureCoords(intersection).X > 1.0f - outlineSize ||
                            mesh.TextureCoords(intersection).Y < outlineSize || mesh.TextureCoords(intersection).Y > 1.0f - outlineSize)
                        {
                            result = Vector3.One;
                        }

                        break;
                    }

                    case Shape.Sphere:
                    {
                        float kr = Renderer.Fresnel(ray.direction, normal, 0.95f);
                        result = Vector3.One * kr + result * (1.0f - kr);

                        break;
                    }
                    }
                }

                return(result);
            }

            return(backgroundColor);
        }
Example #3
0
 private static void InitializePhotonMap()
 {
     PhotonMapping.InitializePhotonMap(settings);
 }