コード例 #1
0
        private Vector EstimatePixelColor(int x, int y, Random rand)
        {
            Ray primaryRay = data.Camera.GetPrimaryRay(x, y);

            var eyePoint = this.intersectionFinder.GetIntersectionPoint(primaryRay);

            Vector pixelColor = new Vector(0, 0, 0);

            if (eyePoint != null)
            {
                if (eyePoint.IsLocatedOnLightSource)
                {
                    return(eyePoint.Emission);
                }

                //Direct Lighting
                var lightPoint = data.LightSource.GetRandomPointOnLightSource(rand);
                if (IsVisible(eyePoint.Position, lightPoint.Position))
                {
                    pixelColor += Vector.Mult(DiffuseBrdf.Evaluate(eyePoint), lightPoint.Color * GeometryTerm(eyePoint, lightPoint));
                }
            }

            return(pixelColor);
        }
コード例 #2
0
        private Vector EstimateColorWithPhotonmapping(int x, int y, Random rand, Photonmap photonmap)
        {
            Ray    primaryRay  = data.Camera.GetPrimaryRay(x, y);
            float  cosAtCamera = Vector.Dot(primaryRay.Direction, this.data.Camera.Forward);
            Vector pathWeight  = new Vector(1, 1, 1) * cosAtCamera;

            var eyePoint = this.intersectionFinder.GetIntersectionPoint(primaryRay);

            Vector pixelColor = new Vector(0, 0, 0);

            if (eyePoint != null)
            {
                if (eyePoint.IsLocatedOnLightSource)
                {
                    return(eyePoint.Emission);
                }

                pathWeight = Vector.Mult(pathWeight, DiffuseBrdf.Evaluate(eyePoint));

                //Direct Lighting
                var lightPoint = data.LightSource.GetRandomPointOnLightSource(rand);
                if (IsVisible(eyePoint.Position, lightPoint.Position))
                {
                    pixelColor += Vector.Mult(pathWeight, lightPoint.Color * GeometryTerm(eyePoint, lightPoint) / lightPoint.PdfA);
                }

                //Final Gathering
                Vector newDirection = DiffuseBrdf.SampleDirection(eyePoint.Normal, rand);
                pathWeight = pathWeight * Vector.Dot(eyePoint.Normal, newDirection) / DiffuseBrdf.PdfW(eyePoint.Normal, newDirection);
                var finalGatherPoint = this.intersectionFinder.GetIntersectionPoint(new Ray(eyePoint.Position, newDirection));

                if (finalGatherPoint != null)
                {
                    //100000 3000 1000
                    float searchRadius   = 0.00634257728f * 2;//0.0383904837f;//0.065260686f;
                    var   photons        = photonmap.SearchPhotons(finalGatherPoint, searchRadius);
                    float kernelFunction = 1.0f / (searchRadius * searchRadius * (float)Math.PI);
                    foreach (var photon in photons)
                    {
                        pixelColor += Vector.Mult(pathWeight, Vector.Mult(DiffuseBrdf.Evaluate(finalGatherPoint), photon.PathWeight) * kernelFunction);
                    }
                }
            }

            return(pixelColor);
        }
コード例 #3
0
        private Vector GetContributionFromLightSourceSampling(IntersectionPoint point, Random rand, Vector pathWeight)
        {
            //Sample Point on LightSource
            var    lightPoint       = data.LightSource.SampleRandomPointOnLightSource(rand);
            Vector directionToLight = (lightPoint.Position - point.Position).Normalize();

            //Shadow-Ray-Test: Test is the Point on Lightsource visible from 'point'?
            var   lightVisiblePoint = this.intersectionFinder.GetIntersectionPoint(new Ray(point.Position, directionToLight));
            float DistanceForPoint2PointVisibleCheck = 0.0001f; //Magic Number
            bool  isVisible = lightVisiblePoint != null && (lightVisiblePoint.Position - lightPoint.Position).Length() < DistanceForPoint2PointVisibleCheck;

            if (isVisible == false)
            {
                return(new Vector(0, 0, 0));                  //No contribution, if 'point' is located in shadow
            }
            //Pathcontribution from Lightsource-Sampling
            float  cosAtPoint     = Math.Max(0, Vector.Dot(point.Normal, directionToLight));
            float  cosAtLight     = Math.Max(0, Vector.Dot(lightPoint.Normal, -directionToLight));
            float  geometryFactor = cosAtPoint * cosAtLight / (lightPoint.Position - point.Position).SqrLength();
            float  pdfAFromLightSourceSampling   = data.LightSource.PdfA; //This is the PdfA for sampling the lightPoint on the Position lightPoint.Position
            Vector contributionFromLightSampling = Vector.Mult(pathWeight, DiffuseBrdf.Evaluate(point)) * geometryFactor * data.LightSource.EmissionPerArea / pdfAFromLightSourceSampling;

            //Get PdfA from Brdf-Sampling.
            float pdfW            = DiffuseBrdf.PdfW(point.Normal, directionToLight);
            float continuationPdf = Math.Min(1, point.Color.Max());

            //This is the PdfA, to hit the LightSource with Brdf-Sampling and hit the Lightsource on the Position lightPoint.Position
            //The Factor "cosAtLight / (lightPoint.Position - point.Position).SqrLength()" is the pdfW to PdfA-Conversionfactor.
            //This means, you project to Solid Angle Measure from the Brdf to the surface area measure on the Point on the Light
            float pdfAFromBrdfSampling = pdfW * continuationPdf * cosAtLight / (lightPoint.Position - point.Position).SqrLength();

            //Heare we have used LightSource-Sampling for the Creation of the Point on the LightSource. So we use pdfAFromLightSourceSampling in the numerator
            float misFactor = pdfAFromLightSourceSampling / (pdfAFromLightSourceSampling + pdfAFromBrdfSampling);

            contributionFromLightSampling *= misFactor;

            return(contributionFromLightSampling);
        }
コード例 #4
0
        private ConnectionData TryToConnectPointWithCamera(IntersectionPoint point, Vector pathWeight, int lightPathsPerIteration)
        {
            Vector2D pixelPosition = GetPixelPositionForScenePoint(point.Position);

            if (pixelPosition != null)
            {
                //GeometryTerm
                Vector cameraToLightPointDirection = (point.Position - data.Camera.Position).Normalize();
                float  cosAtCamera     = Vector.Dot(cameraToLightPointDirection, data.Camera.Forward);
                float  cosAtPoint      = Vector.Dot(-cameraToLightPointDirection, point.Normal);
                float  geomertryFaktor = (cosAtCamera * cosAtPoint) / (point.Position - data.Camera.Position).SqrLength();

                //Brdf (Inputdirection is Direction from preceeding point to 'point' and Outgoingdirection is direction from 'point' to Camera-Point
                //In this case its a Diffuse Brdf and no Input- or Outputdirection is needed
                Vector brdf = DiffuseBrdf.Evaluate(point);

                //If you use Pathtracing and don't divide the Pathweight with the PdfW from the Camera, then you implicite multiply the Pathweight with (1 / CameraPdfW)
                //To get with Lightracing the same Results as with Pathtracing, you have to multipli the PathWeight with the cameraPdfW, which is also called PixelFilter
                float cameraPdfW = data.Camera.PdfWForPrimaryRayDirectionSampling(cameraToLightPointDirection); //cameraPdfW == PixelFilter

                Vector pathContribution = Vector.Mult(pathWeight, brdf) * geomertryFaktor / lightPathsPerIteration * cameraPdfW;

                int x = (int)pixelPosition.X;
                int y = (int)pixelPosition.Y;
                if (x >= 0 && x < width && y >= 0 && y < height)
                {
                    return(new ConnectionData()
                    {
                        PixelX = x,
                        PixelY = y,
                        PathContribution = pathContribution,
                    });
                }
            }

            return(null);
        }
コード例 #5
0
        private Vector EstimateColorWithPathtracing(int x, int y, Random rand)
        {
            Ray    primaryRay  = data.Camera.GetPrimaryRay(x, y);
            float  cosAtCamera = Vector.Dot(primaryRay.Direction, this.data.Camera.Forward);
            Vector pathWeight  = new Vector(1, 1, 1) * cosAtCamera;

            Ray ray = primaryRay;

            int maxPathLength = 5;

            for (int i = 0; i < maxPathLength; i++)
            {
                var point = this.intersectionFinder.GetIntersectionPoint(ray);
                if (point == null)
                {
                    return(new Vector(0, 0, 0));
                }

                if (point.IsLocatedOnLightSource && Vector.Dot(point.Normal, -ray.Direction) > 0)
                {
                    pathWeight = Vector.Mult(pathWeight, point.Emission);
                    return(pathWeight);
                }

                //Abbruch mit Russia Rollete
                float continuationPdf = Math.Min(1, point.Color.Max());
                if (rand.NextDouble() >= continuationPdf)
                {
                    return(new Vector(0, 0, 0)); // Absorbation
                }
                Vector newDirection = DiffuseBrdf.SampleDirection(point.Normal, rand);
                pathWeight = Vector.Mult(pathWeight * Vector.Dot(point.Normal, newDirection) / DiffuseBrdf.PdfW(point.Normal, newDirection), DiffuseBrdf.Evaluate(point)) / continuationPdf;
                ray        = new Ray(point.Position, newDirection);
            }

            return(new Vector(0, 0, 0));
        }
コード例 #6
0
        private List <Photon> TracePhoton(Random rand)
        {
            var    lightPoint = this.lightSource.GetRandomPointOnLightSource(rand);
            Vector direction  = DiffuseBrdf.SampleDirection(lightPoint.Normal, rand);
            float  pdfW       = DiffuseBrdf.PdfW(lightPoint.Normal, direction);
            float  lambda     = Vector.Dot(lightPoint.Normal, direction);
            Vector pathWeight = lightPoint.Color * lambda / (lightPoint.PdfA * pdfW);
            Ray    ray        = new Ray(lightPoint.Position, direction);
            //PhotonType type = PhotonType.None;

            int maxPathLength = 5;

            List <Photon> photons = new List <Photon>();

            for (int i = 0; i < maxPathLength; i++)
            {
                var point = this.intersectionFinder.GetIntersectionPoint(ray);
                if (point == null)
                {
                    return(photons);
                }

                photons.Add(new Photon(point.Position, point.Normal, pathWeight / this.photonCount, ray.Direction));

                //Abbruch mit Russia Rollete
                float continuationPdf = Math.Min(1, point.Color.Max());
                if (rand.NextDouble() >= continuationPdf)
                {
                    return(photons); // Absorbation
                }
                Vector newDirection = DiffuseBrdf.SampleDirection(point.Normal, rand);
                pathWeight = Vector.Mult(pathWeight * Vector.Dot(point.Normal, newDirection) / DiffuseBrdf.PdfW(point.Normal, newDirection), DiffuseBrdf.Evaluate(point)) / continuationPdf;
                ray        = new Ray(point.Position, newDirection);
            }

            return(photons);
        }
コード例 #7
0
        private Vector GetPixelColorFromPhotonmap(int x, int y, Photonmap photonmap)
        {
            Ray    primaryRay  = data.Camera.GetPrimaryRay(x, y);
            float  cosAtCamera = Vector.Dot(primaryRay.Direction, this.data.Camera.Forward);
            Vector pathWeight  = new Vector(1, 1, 1) * cosAtCamera;

            var eyePoint = this.intersectionFinder.GetIntersectionPoint(primaryRay);

            Vector pixelColor = new Vector(0, 0, 0);

            if (eyePoint != null)
            {
                //100000 3000 1000
                float searchRadius   = 0.00634257728f * 2;//0.0383904837f;//0.065260686f;
                var   photons        = photonmap.SearchPhotons(eyePoint, searchRadius);
                float kernelFunction = 1.0f / (searchRadius * searchRadius * (float)Math.PI);
                foreach (var photon in photons)
                {
                    pixelColor += Vector.Mult(pathWeight, Vector.Mult(DiffuseBrdf.Evaluate(eyePoint), photon.PathWeight) * kernelFunction);
                }
            }

            return(pixelColor);
        }
コード例 #8
0
        private Vector[,] EstimateFrameWithLightracing(int width, int height, Random rand)
        {
            int lightPathsPerIteration = width * height;
            int maxPathLength          = 5;

            Vector[,] frame = new Vector[width, height];

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    frame[x, y] = new Vector(0, 0, 0);
                }
            }

            for (int j = 0; j < lightPathsPerIteration; j++)
            {
                //Sample Position on Lightsource
                var point = data.LightSource.SampleRandomPointOnLightSource(rand);

                //Pathweight
                Vector pathWeight = new Vector(1, 1, 1) * data.LightSource.EmissionPerArea / data.LightSource.PdfA;

                //Connect Point on Lightsource with Camera
                var c = TryToConnectPointWithCamera(point, pathWeight, lightPathsPerIteration);
                if (c != null)
                {
                    frame[c.PixelX, c.PixelY] += c.PathContribution;
                }

                //Sample Direction from Point on LightSource into scene. Use the diffuse Brdf
                Vector direction = DiffuseBrdf.SampleDirection(point.Normal, rand); //Direct vom Point on Light into some point in scene
                float  pdfW      = DiffuseBrdf.PdfW(point.Normal, direction);       //PDF with Respect to Solid Angle from 'direction'

                //New Pathweight after sampling direction
                float cosAtPoint = Math.Max(0, Vector.Dot(point.Normal, direction));
                pathWeight *= cosAtPoint / pdfW;

                Ray ray = new Ray(point.Position, direction);

                for (int k = 1; k < maxPathLength; k++)
                {
                    //Get next intersectionpoint with scene starting from old point-Position
                    point = this.intersectionFinder.GetIntersectionPoint(ray);
                    if (point == null)
                    {
                        break;                //Break Light-Path-Creation
                    }
                    //Connect Point in scene with Camera
                    c = TryToConnectPointWithCamera(point, pathWeight, lightPathsPerIteration);
                    if (c != null)
                    {
                        frame[c.PixelX, c.PixelY] += c.PathContribution;
                    }

                    //The Lightsource dosn't reflect light
                    if (point.IsLocatedOnLightSource)
                    {
                        break;
                    }

                    //Break with Russia Rollete
                    float continuationPdf = Math.Min(1, point.Color.Max());
                    if (rand.NextDouble() >= continuationPdf)
                    {
                        break; // Absorbation
                    }
                    //Go ahead with lighttracing after connection with camera
                    direction  = DiffuseBrdf.SampleDirection(point.Normal, rand);
                    pdfW       = DiffuseBrdf.PdfW(point.Normal, direction);
                    cosAtPoint = Math.Max(0, Vector.Dot(point.Normal, direction));
                    pathWeight = Vector.Mult(pathWeight, DiffuseBrdf.Evaluate(point)) * cosAtPoint / (pdfW * continuationPdf);
                    ray        = new Ray(point.Position, direction);
                }
            }

            return(frame);
        }
コード例 #9
0
        private Vector EstimateColorWithPathtracingWithNextEventEstimation(int x, int y, Random rand)
        {
            //This is the sum from all Pathcontributions from all Pathlenghts up to maxPathLength
            //This means Contribution(C L) + Contribution(C D L) + Contribution(C D D L) + Contribution(C D D D L) + Contribution(C D D D D L)
            //For Each Pathlength-Step, the Contribution from Brdf-Sampling and Lightsource-Sampling is added but only one from this two Sampling-Methods
            //will create a Contribution != 0. If you hit the Lightsource, then you only get the BrdfSampling-Contribution. The LightSource-Sampling-Contribution
            //will be zero because if your running point is on the light and the light don't reflect any light, then you don't can create any more Lightpoints
            //If you are on a Point in the Scene (Not Lightsoure) then only the Contribution from Lightsource-Sampling can be greater zero. The Brdf-Sampling
            //Contribution (Pathtracing) will be zero.
            Vector contributionSum = new Vector(0, 0, 0);

            Ray    primaryRay  = data.Camera.GetPrimaryRay(x, y);
            float  cosAtCamera = Vector.Dot(primaryRay.Direction, this.data.Camera.Forward);
            Vector pathWeight  = new Vector(1, 1, 1) * cosAtCamera;

            Ray   ray  = primaryRay;
            float pdfW = data.Camera.PdfWForPrimaryRayDirectionSampling(ray.Direction); //This will store the PdfW and Contination Pdf, which was used for Brdf-Sampling

            int maxPathLength = 5;

            for (int i = 0; i < maxPathLength; i++)
            {
                IntersectionPoint point = this.intersectionFinder.GetIntersectionPoint(ray);
                if (point == null)
                {
                    break;                //Ray leave the scene
                }
                //Try to add Contribution from Brdf-Sampling (This Brdf-Sampling is also called Pathtracing because you do this for every Pathpoint)
                if (point.IsLocatedOnLightSource && Vector.Dot(point.Normal, -ray.Direction) > 0)
                {
                    //This is the PdfA on the LightPoint, if you would use LightSource-Sampling, to reach from lastPoint(ray.Origin) to current point 'point'
                    float pdfAFromLightSourceSampling = data.LightSource.PdfA;

                    //This is the PdfA on the LightPoint, which you get from BrdfSampling to reach rom lastPoint(ray.Origin) to current point 'point'
                    float pdfAFromBrdfSampling = pdfW * Vector.Dot(point.Normal, -ray.Direction) / (ray.Origin - point.Position).SqrLength();

                    //We have used Brdf-Sampling. So the pdfAFromBrdfSampling is in the numerator
                    float  misFactor = pdfAFromBrdfSampling / (pdfAFromLightSourceSampling + pdfAFromBrdfSampling);
                    Vector contributionFromBrdfSampling = Vector.Mult(pathWeight, point.Emission) * misFactor;

                    contributionSum += contributionFromBrdfSampling;

                    break; //The light don't reflect any light. So stop here with Pathtracing
                }

                //Try to add Contribution from Lightsource-Sampling (This is the Next Event Estimation-Sampling)
                contributionSum += GetContributionFromLightSourceSampling(point, rand, pathWeight);

                //Stop with Russia Rollete
                float continuationPdf = Math.Min(1, point.Color.Max());
                if (rand.NextDouble() >= continuationPdf)
                {
                    break; // Absorbation
                }
                //Sample Direction and try to hit to lightSource
                Vector direction = DiffuseBrdf.SampleDirection(point.Normal, rand);
                pdfW = DiffuseBrdf.PdfW(point.Normal, direction) * continuationPdf;
                float cosAtPoint = Math.Max(0, Vector.Dot(point.Normal, direction));

                pathWeight = Vector.Mult(pathWeight, DiffuseBrdf.Evaluate(point)) * cosAtPoint / pdfW; //New Pathweight after Brdf-Sampling
                ray        = new Ray(point.Position, direction);
            }

            return(contributionSum);
        }