Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="job"></param>
        private unsafe void RenderJob(RenderingJob job)
        {
            var threadColor = GetThreadColor();
            var pixelColor  = (ColorRGB *)job.OutputOffset;

            var widthIterator  = job.Camera.PixelWidthIterator;
            var heightIterator = job.Camera.PixelHeightIterator;
            var imageOrigin    = job.Camera.ImageOrigin;
            var cameraPosition = job.Camera.Position;

            var jobOffsetPosition = job.OffsetPosition;
            var jobSize           = job.Size;

            var ray = new Ray();

            var threadDebugging = ThreadDebugging;

            if (!threadDebugging)
            {
                threadColor = ColorRGB.White;
            }

            var jobColorBuffer      = job.ColorBuffer;
            var jobColorBufferIndex = 0;
            var cornerSize          = 8;

            var jobDebugging = JobDebugging;

            if (jobDebugging)
            {
                #region paint margin as white rectangle

                //jobColorBuffer = new ColorRGB[jobSize.X * 2 + (jobSize.Y - 2) * 2];

                //// bottom line
                //for (var jobx = 0; jobx < jobSize.X; jobx++, pixelColor++)
                //    (*pixelColor) = marginColor;
                //pixelColor += job.NextOutputLineOffset;

                //// left and right margin
                //for (var joby = 1; joby < jobSize.Y - 1; joby++, pixelColor += job.NextOutputLineOffset + 1)
                //{
                //    (*pixelColor) = marginColor;
                //    pixelColor += (jobSize.X - 1);
                //    (*pixelColor) = marginColor;
                //}

                //// top line
                //for (var jobx = 0; jobx < jobSize.X; jobx++, pixelColor++)
                //    (*pixelColor) = marginColor;

                #endregion

                #region paint corners of job

                // bottom parts of corners
                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++)
                {
                    (*pixelColor) = threadColor;
                }
                pixelColor += jobSize.X - cornerSize * 2;

                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++)
                {
                    (*pixelColor) = threadColor;
                }
                pixelColor += job.NextOutputLineOffset;

                // bottom left and right parts of corners
                for (var joby = 1; joby < cornerSize; joby++, pixelColor += job.NextOutputLineOffset + 1)
                {
                    (*pixelColor) = threadColor;
                    pixelColor   += (jobSize.X - 1);
                    (*pixelColor) = threadColor;
                }

                // top left and right parts of corners
                pixelColor += ((job.NextOutputLineOffset + 1) + (jobSize.X - 1)) * (jobSize.Y - cornerSize * 2);
                for (var joby = 1; joby < cornerSize; joby++, pixelColor += job.NextOutputLineOffset + 1)
                {
                    (*pixelColor) = threadColor;
                    pixelColor   += (jobSize.X - 1);
                    (*pixelColor) = threadColor;
                }

                // top parts of corners
                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++)
                {
                    (*pixelColor) = threadColor;
                }
                pixelColor += jobSize.X - cornerSize * 2;

                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++)
                {
                    (*pixelColor) = threadColor;
                }
                pixelColor += job.NextOutputLineOffset;

                #endregion

                pixelColor = (ColorRGB *)job.OutputOffset;
            }

            //  .
            // /|\
            //  |
            for (var joby = 0; joby < jobSize.Y; joby++, pixelColor += job.NextOutputLineOffset)
            {
                //    \
                // -----
                //    /
                for (var jobx = 0; jobx < jobSize.X; jobx++, pixelColor++)
                {
                    // create ray for pixel at [x,y]
                    ray.Prepare(cameraPosition, ((widthIterator * (jobx + jobOffsetPosition.X) + heightIterator * (joby + jobOffsetPosition.Y) + imageOrigin) - cameraPosition).Normalize());
                    //ray.Pixel.X = jobx + job.OffsetPosition.X;
                    //ray.Pixel.Y = joby + job.OffsetPosition.Y;

                    // trace scene
                    RayTracer.Trace(ray);

                    if (threadDebugging)
                    {
                        ray.Color *= threadColor;
                    }

                    if (jobDebugging)
                    {
                        #region paint margin with real colors

                        //if (jobx == 0 || jobx == jobSize.X - 1 || joby == 0 || joby == jobSize.Y - 1)
                        //{
                        //    jobColorBuffer[colorBufferIndex] = ray.Color;
                        //    colorBufferIndex++;
                        //    continue;
                        //}

                        #endregion

                        #region corner colors

                        if (((joby == 0 || joby == jobSize.Y - 1) && (jobx < cornerSize || jobx >= jobSize.X - cornerSize)) || ((jobx == 0 || jobx == jobSize.X - 1) && (joby < cornerSize || joby >= jobSize.Y - cornerSize)))
                        {
                            jobColorBuffer[jobColorBufferIndex] = ray.Color;
                            jobColorBufferIndex++;
                            continue;
                        }

                        #endregion
                    }

                    (*pixelColor) = ray.Color;
                }
            }

            if (jobDebugging)
            {
                pixelColor          = (ColorRGB *)job.OutputOffset;
                jobColorBufferIndex = 0;

                #region paint margin with real colors

                //// bottom line
                //for (var jobx = 0; jobx < jobSize.X; jobx++, pixelColor++, colorBufferIndex++)
                //    (*pixelColor) = jobColorBuffer[colorBufferIndex];
                //pixelColor += job.NextOutputLineOffset;

                //// left and right margin
                //for (var joby = 1; joby < jobSize.Y - 1; joby++, pixelColor += job.NextOutputLineOffset + 1)
                //{
                //    (*pixelColor) = jobColorBuffer[colorBufferIndex];
                //    colorBufferIndex++;

                //    pixelColor += (jobSize.X - 1);

                //    (*pixelColor) = jobColorBuffer[colorBufferIndex];
                //    colorBufferIndex++;
                //}

                //// top line
                //for (var jobx = 0; jobx < jobSize.X; jobx++, pixelColor++, colorBufferIndex++)
                //    (*pixelColor) = jobColorBuffer[colorBufferIndex];

                #endregion

                #region paint corners of job

                // bottom parts of corners
                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++, jobColorBufferIndex++)
                {
                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                }
                pixelColor += jobSize.X - cornerSize * 2;

                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++, jobColorBufferIndex++)
                {
                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                }
                pixelColor += job.NextOutputLineOffset;

                // bottom left and right parts of corners
                for (var joby = 1; joby < cornerSize; joby++, pixelColor += job.NextOutputLineOffset + 1)
                {
                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                    jobColorBufferIndex++;

                    pixelColor += (jobSize.X - 1);

                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                    jobColorBufferIndex++;
                }

                // top left and right parts of corners
                pixelColor += ((job.NextOutputLineOffset + 1) + (jobSize.X - 1)) * (jobSize.Y - cornerSize * 2);
                for (var joby = 1; joby < cornerSize; joby++, pixelColor += job.NextOutputLineOffset + 1)
                {
                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                    jobColorBufferIndex++;

                    pixelColor += (jobSize.X - 1);

                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                    jobColorBufferIndex++;
                }

                // top parts of corners
                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++, jobColorBufferIndex++)
                {
                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                }
                pixelColor += jobSize.X - cornerSize * 2;

                for (var jobx = 0; jobx < cornerSize; jobx++, pixelColor++, jobColorBufferIndex++)
                {
                    (*pixelColor) = jobColorBuffer[jobColorBufferIndex];
                }
                pixelColor += job.NextOutputLineOffset;

                #endregion
            }

            if (threadDebugging)
            {
                var invThreaColor = threadColor.Inv();
                pixelColor = (ColorRGB *)job.OutputOffset;
                for (var joby = 0; joby < jobSize.Y; joby++, pixelColor += job.NextOutputLineOffset)
                {
                    for (var jobx = 0; jobx < jobSize.X; jobx++, pixelColor++)
                    {
                        (*pixelColor) = (*pixelColor) * invThreaColor;
                    }
                }
            }
        }
Exemplo n.º 2
0
        public void Calculate()
        {
            // главный цикл по лучам
            for (var iteration = 0; iteration < NRays; iteration++)
            {
                // определяем источник
                var light = this.RouletteLight();

                // розыгрыш луча от источника
                var ray = light.RandomRay();

                //ray = new LightRay( light.Position, new Vector( -0f, -0f, -1.0f, true ), new Spectrum( 1f ) );

                var wMinFact = ray.Illuminance.ValueMax * WMin;

                // основной блуждания луча
                int rayIteration = 0;
                while (ray.Illuminance.ValueMax > wMinFact && rayIteration < 8)
                {
                    rayIteration++;

                    // ищем пересечение с элементом сцены
                    var intersection = RayTracer.Trace(ray.From, ray.Direction, Constants.Epsilon);
                    while (intersection != null && intersection.Face.Material.Reflectance == null)
                    {
                        if (intersection.Face.Material.Mirror != null)
                        {
                            var mirrorRay = Vector.Reflect(ray.Direction, intersection.Face.Normal);
                            mirrorRay.Normalize();
                            ray.From      = intersection.Point;
                            ray.Direction = mirrorRay;
                            intersection  = this.RayTracer.Trace(ray.From, ray.Direction, Constants.Epsilon);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }
                    if (intersection == null)
                    {
                        break;
                    }

                    //RayDebugStaticCollection.Add( new Ray( ray.From, intersection.Point ), Color.Blue );
                    //this.Log.Message( string.Format( "Ray.From = {0}, Ray.To = {1}", ray.From, intersection.Point ) );

                    var intersectionNormal      = intersection.Face.Normal;
                    var intesectionPointOcclude = intersection.Point + intersectionNormal * Constants.Epsilon;

                    // для всех расчетных точек производимы вычисления
                    foreach (var obj in Scene.Objects)
                    {
                        foreach (var vertex in obj.Vertices)
                        {
                            var renderPointNormal = vertex.Face.Normal;

                            if (vertex.Face == intersection.Face)
                            {
                                continue;
                            }

                            var dnormals = intersection.Face.Normal - renderPointNormal;
                            if (Math.Abs(dnormals.X) < Constants.Epsilon && Math.Abs(dnormals.Y) < Constants.Epsilon && Math.Abs(dnormals.Z) < Constants.Epsilon)
                            {
                                continue;
                            }


                            var mr = (new Vector(intersection.Point, vertex.Point).Reflect(vertex.Face.Normal));
                            //RayDebugStaticCollection.Add( new Ray( intersection.Point, vertex.Point ), Color.Green );
                            //RayDebugStaticCollection.Add( new Ray( vertex.Point,mr  ), Color.Red );

                            //if (point.Obj.Name == "Box2")
                            //{
                            //    point.Illuminance = new Spectrum(1f, 0, 0);
                            //    continue;
                            //}

                            //if ( Vector.Dot( intersectionNormal, renderPointNormal ) > Constants.Epsilon )
                            //{
                            //    vertex.CounterVisibleNormals++;
                            //    continue;
                            //}


                            var pointOcclude = vertex.Point;

                            // направление от точки до точки рендеринга
                            var r2 = Point3D.LenghtSquared(intesectionPointOcclude, pointOcclude);

                            var coreDirection = new Vector(intesectionPointOcclude, pointOcclude, true);
                            //var occludeRayLength = (float)Math.Sqrt( r2 ) - Constants.Epsilon;

                            //r2 = Point3D.LenghtSquared(intesectionPointOcclude, point.Position );
                            var occludeRayLength = (float)Math.Sqrt(r2) - Constants.Epsilon;


                            if (this.RayTracer.Occluded(intesectionPointOcclude, coreDirection, 0, occludeRayLength))
                            {
                                //vertex.CounterOccluded++;
                                continue;
                            }



                            //if ( this.RayTracer.Occluded( intersection.Point, coreDirection, Constants.Epsilon, occludeRayLength ) )
                            //    continue;

                            var cos1 = (Vector.Dot(coreDirection, intersectionNormal));
                            var cos2 = Math.Abs(Vector.Dot(coreDirection, renderPointNormal));

                            /*
                             * if ( cos1 < Constants.Epsilon2 )
                             *  vertex.CounterRaysCos1Zero++;
                             * if ( cos2 < Constants.Epsilon )
                             *  vertex.CounterRaysCos2Zero++;
                             */

                            cos1 = Math.Abs(cos1);
                            cos2 = Math.Abs(cos2);

                            var sigma1 = intersection.Face.Material.Reflectance.BRDF(ray.Direction, intersectionNormal, coreDirection);

                            if (sigma1.ValueMax > 0)
                            {
                                cos1 = Math.Abs(cos1);
                            }

                            var kernel1 = sigma1 * cos1 * cos2 / r2;
                            //var kernel1 = intersection.Face.Material.BRDF( ray.Direction, intersection.Face.Normal,
                            //    core1Direction );

                            //var kernel1 = new Spectrum( sigma1 );

                            //kernel1.Multiplication( cos1 * cos2 / r2 );

                            // Ядро 2. Переход из суб. точки в искомое направление
                            for (int i = 0; i < vertex.IlluminanceAngles.Directions.Count; i++)
                            {
                                var sigma2 = vertex.Face.Material.Reflectance.BRDF(coreDirection, renderPointNormal, vertex.IlluminanceAngles.Directions[i]);

                                var kernel2 = sigma2;
                                var q       = ray.Illuminance * kernel1 * kernel2;
                                if (float.IsNaN(q.R) || float.IsNaN(q.G) || float.IsNaN(q.B))
                                {
                                    q = new Spectrum( );
                                }

                                vertex.IlluminanceIndirect[i] += q;
                            }
                        }
                    }

                    var newDirection = intersection.Face.Material.Reflectance.RandomReflectedDirection(ray.Direction,
                                                                                                       intersectionNormal);
                    var brdf = intersection.Face.Material.Reflectance.BRDF(ray.Direction, intersectionNormal, newDirection);

                    ray = new LightRay(intersection.Point, newDirection, ray.Illuminance * brdf);

                    /*
                     * if (rayIteration == 1)
                     *  ray = new LightRay(ray.From, new Vector(1f, 0, 1f), ray.Illuminance);
                     * else if ( rayIteration == 2 )
                     *  ray = new LightRay( ray.From, new Vector( -0.85f, 1.5f, 1.5f, true ), ray.Illuminance );
                     *
                     * */
                }

                if (iteration % 10 == 0)
                {
                    Log.Message(string.Format("Render {0} rays", iteration), 1);
                }
            }


            const float XXXX = 0.25f;
            const float norm = 4 * Constants.PI * XXXX;

            foreach (var obj in Scene.Objects)
            {
                foreach (var vertex in obj.Vertices)
                {
                    for (int i = 0; i < vertex.IlluminanceAngles.Directions.Count; i++)
                    {
                        vertex.IlluminanceIndirect[i] *= (norm / (NRays * Constants.PI * Constants.PI));
                    }
                }
            }
        }