Ejemplo n.º 1
0
        public void             InitializeCamera(float3 _position, float3 _target, float3 _up)
        {
            // Build the camera matrix
            float3 At = _target - _position;

            if (At.LengthSquared > 1e-2f)
            {
                // Normal case
                m_CameraTargetDistance = At.Length;
                At /= m_CameraTargetDistance;
            }
            else
            {
                // Special bad case
                m_CameraTargetDistance = 0.01f;
                At = new float3(0.0f, 0.0f, -1.0f);
            }

            float3 ortho = _up.Cross(At).Normalized;

            float4x4 cameraMat = float4x4.Identity;

            cameraMat[3] = new float4(_position, 1.0f);
            cameraMat[2] = new float4(At, 0.0f);
            cameraMat[0] = new float4(ortho, 0.0f);
            cameraMat[1] = new float4(At.Cross(ortho), 0.0f);

            CameraTransform = cameraMat;

            // Setup the normalized target distance
            m_NormalizedTargetDistance = NormalizeTargetDistance(m_CameraTargetDistance);
        }
Ejemplo n.º 2
0
        public void             InitializeCamera(float3 _Position, float3 _Target, float3 _Up)
        {
            // Build the camera matrix
            float3 At = _Target - _Position;

            if (At.LengthSquared > 1e-2f)
            {                   // Normal case
                m_CameraTargetDistance = At.Length;
                At /= m_CameraTargetDistance;
            }
            else
            {                   // Special bad case
                m_CameraTargetDistance = 0.01f;
                At = new float3(0.0f, 0.0f, -1.0f);
            }

            float3 Ortho = _Up.Cross(At).Normalized;

            float4x4 CameraMat = float4x4.Identity;

            CameraMat.r3 = new float4(_Position, 1.0f);
            CameraMat.r2 = new float4(At, 0.0f);
            CameraMat.r0 = new float4(Ortho, 0.0f);
            CameraMat.r1 = new float4(At.Cross(Ortho), 0.0f);

            CameraTransform = CameraMat;

            // Setup the normalized target distance
            m_NormalizedTargetDistance = NormalizeTargetDistance(m_CameraTargetDistance);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Initializes the collection of samples
        /// </summary>
        /// <param name="_Order">The order of the SH</param>
        /// <param name="_ThetaSamplesCount">The amount of samples on Theta (total samples count will be 2*N*N)</param>
        /// <param name="_Up">The vector to use as the Up direction (use [0,1,0] if not sure)</param>
        public void                     Initialize(int _Order, int _ThetaSamplesCount, float3 _Up)
        {
            m_Order             = _Order;
            m_ThetaSamplesCount = _ThetaSamplesCount;
            m_SamplesCount      = 2 * m_ThetaSamplesCount * m_ThetaSamplesCount;
            m_Random            = new Random(m_RandomSeed);

            // Compute the rotation matrix
            float3x3 Rotation = new float3x3();
            float3   Ortho    = float3.UnitY.Cross(_Up);
            float    fNorm    = Ortho.LengthSquared;

            if (fNorm < 1e-6f)
            {
                Rotation = float3x3.Identity;
            }
            else
            {
                Ortho      /= (float)Math.Sqrt(fNorm);
                Rotation.r0 = Ortho;
                Rotation.r1 = _Up;
                Rotation.r2 = Ortho.Cross(_Up);
            }

            // Initialize the SH samples
            m_SHSamples = new SHSample[m_SamplesCount];

            // Build the samples using stratified sampling
            int SampleIndex = 0;

            for (int ThetaIndex = 0; ThetaIndex < m_ThetaSamplesCount; ThetaIndex++)
            {
                for (int PhiIndex = 0; PhiIndex < 2 * m_ThetaSamplesCount; PhiIndex++)
                {
                    double fTheta = 2.0 * System.Math.Acos(System.Math.Sqrt(1.0 - (ThetaIndex + m_Random.NextDouble()) / m_ThetaSamplesCount));
                    double fPhi   = System.Math.PI * (PhiIndex + m_Random.NextDouble()) / m_ThetaSamplesCount;

                    // Compute direction, rotate it then cast it back to sphercial coordinates
                    float3 Direction = SphericalHarmonics.SHFunctions.SphericalToCartesian(fTheta, fPhi);
                    Direction *= Rotation;

                    SphericalHarmonics.SHFunctions.CartesianToSpherical(Direction, out fTheta, out fPhi);

                    // Fill up the new sample
                    m_SHSamples[SampleIndex]             = new SHSample((float)fPhi, (float)fTheta);
                    m_SHSamples[SampleIndex].m_SHFactors = new double[m_Order * m_Order];

                    // Build the SH Factors
                    SHFunctions.InitializeSHCoefficients(m_Order, fTheta, fPhi, m_SHSamples[SampleIndex].m_SHFactors);

                    SampleIndex++;
                }
            }
        }
Ejemplo n.º 4
0
        void    DrawArrow(float3 _start, float3 _end, float3 _ortho, float4 _color)
        {
            DrawLine(_start, _end, _ortho, -1.0f, _color);

            float3 dir  = _end - _start;
            float  size = dir.Length;

            dir /= size;

            size *= 0.1f;

            DrawPlane(_end - 0.5f * size * dir, _ortho, dir.Cross(_ortho), 0.0f, 0.5f * size, size, _color, false);
        }
Ejemplo n.º 5
0
            public CellPolygon(float3 _P, float3 _N)
            {
                m_P = _P;
                m_N = _N;
                m_T = (float3.UnitY.Cross(m_N)).Normalized;
                m_B = m_N.Cross(m_T);

                // Start with 4 vertices
                const float R = 10.0f;

                m_Vertices = new float3[] {
                    m_P + R * (-m_T + m_B),
                    m_P + R * (-m_T - m_B),
                    m_P + R * (m_T - m_B),
                    m_P + R * (m_T + m_B),
                };
            }
Ejemplo n.º 6
0
        /// <summary>
        /// Build the cube primitive
        /// </summary>
        void    BuildCube()
        {
            float3[] Normals = new float3[6] {
                -float3.UnitX,
                float3.UnitX,
                -float3.UnitY,
                float3.UnitY,
                -float3.UnitZ,
                float3.UnitZ,
            };

            float3[] Tangents = new float3[6] {
                float3.UnitZ,
                -float3.UnitZ,
                float3.UnitX,
                -float3.UnitX,
                -float3.UnitX,
                float3.UnitX,
            };

            VertexP3N3[] vertices = new VertexP3N3[6 * 4];
            uint[]       indices  = new uint[2 * 6 * 3];

            for (int FaceIndex = 0; FaceIndex < 6; FaceIndex++)
            {
                float3 N = Normals[FaceIndex];
                float3 T = Tangents[FaceIndex];
                float3 B = N.Cross(T);

                vertices[4 * FaceIndex + 0] = new VertexP3N3()
                {
                    P = N - T + B,
                    N = N,
//					T = T,
//					B = B,
//					UV = new float2( 0, 0 )
                };
                vertices[4 * FaceIndex + 1] = new VertexP3N3()
                {
                    P = N - T - B,
                    N = N,
//                  T = T,
//                  B = B,
//                  UV = new float2( 0, 1 )
                };
                vertices[4 * FaceIndex + 2] = new VertexP3N3()
                {
                    P = N + T - B,
                    N = N,
//                  T = T,
//                  B = B,
//                  UV = new float2( 1, 1 )
                };
                vertices[4 * FaceIndex + 3] = new VertexP3N3()
                {
                    P = N + T + B,
                    N = N,
//                  T = T,
//                  B = B,
//                  UV = new float2( 1, 0 )
                };

                indices[2 * 3 * FaceIndex + 0] = (uint)(4 * FaceIndex + 0);
                indices[2 * 3 * FaceIndex + 1] = (uint)(4 * FaceIndex + 1);
                indices[2 * 3 * FaceIndex + 2] = (uint)(4 * FaceIndex + 2);
                indices[2 * 3 * FaceIndex + 3] = (uint)(4 * FaceIndex + 0);
                indices[2 * 3 * FaceIndex + 4] = (uint)(4 * FaceIndex + 2);
                indices[2 * 3 * FaceIndex + 5] = (uint)(4 * FaceIndex + 3);
            }

            m_primitiveCube = new Primitive(m_device, (uint)vertices.Length, VertexP3N3.FromArray(vertices), indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3);

//          VertexP3N3[]	vertices = new VertexP3N3[4*6];
//          uint[]			indices = new uint[6*2*3];
//          for ( uint face=0; face < 6; face++ ) {
//              float3	N = (1 - 2 * (face & 1)) * new float3( (face >> 1) == 0 ? 1 : 0, (face >> 1) == 1 ? 1 : 0, (face >> 1) == 2 ? 1 : 0 );
//              float3	T = (1 - 2 * (face & 1)) * new float3( (face >> 1) == 1 ? 1 : 0, (face >> 1) == 2 ? 1 : 0, (face >> 1) == 0 ? 1 : 0 );
//              float3	B = T.Cross( N );
//
//              for ( uint v=0; v < 4; v++ ) {
//                  vertices[4*face+v].N = N;
//                  vertices[4*face+v].P = N + (2.0f*(v & 1)-1) * T + (2.0f*((v >> 1) & 1)-1) * B;
//              }
//
//              indices[3*(2*face+0)+0] = 4*face + 0;
//              indices[3*(2*face+0)+1] = 4*face + 1;
//              indices[3*(2*face+0)+2] = 4*face + 2;
//              indices[3*(2*face+1)+0] = 4*face + 2;
//              indices[3*(2*face+1)+1] = 4*face + 1;
//              indices[3*(2*face+1)+2] = 4*face + 3;
//          }
//
//          m_primitiveCube = new Primitive( m_device, 6*4, VertexP3N3.FromArray( vertices ), indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3 );
        }
Ejemplo n.º 7
0
        private void    BuildPrimitives()
        {
            {
                VertexPt4[] Vertices = new VertexPt4[4];
                Vertices[0] = new VertexPt4()
                {
                    Pt = new float4(-1, +1, 0, 1)
                };                                                                                      // Top-Left
                Vertices[1] = new VertexPt4()
                {
                    Pt = new float4(-1, -1, 0, 1)
                };                                                                                      // Bottom-Left
                Vertices[2] = new VertexPt4()
                {
                    Pt = new float4(+1, +1, 0, 1)
                };                                                                                      // Top-Right
                Vertices[3] = new VertexPt4()
                {
                    Pt = new float4(+1, -1, 0, 1)
                };                                                                                      // Bottom-Right

                ByteBuffer VerticesBuffer = VertexPt4.FromArray(Vertices);

                m_Prim_Quad = new Primitive(m_Device, Vertices.Length, VerticesBuffer, null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.Pt4);
            }

            {
                VertexP3N3G3B3T2[] Vertices = new VertexP3N3G3B3T2[4];
                Vertices[0] = new VertexP3N3G3B3T2()
                {
                    P = new float3(-1, +1, 0), N = new float3(0, 0, 1), T = new float3(1, 0, 0), B = new float3(0, 1, 0), UV = new float2(0, 0)
                };                                                                                                                                                                                              // Top-Left
                Vertices[1] = new VertexP3N3G3B3T2()
                {
                    P = new float3(-1, -1, 0), N = new float3(0, 0, 1), T = new float3(1, 0, 0), B = new float3(0, 1, 0), UV = new float2(0, 1)
                };                                                                                                                                                                                              // Bottom-Left
                Vertices[2] = new VertexP3N3G3B3T2()
                {
                    P = new float3(+1, +1, 0), N = new float3(0, 0, 1), T = new float3(1, 0, 0), B = new float3(0, 1, 0), UV = new float2(1, 0)
                };                                                                                                                                                                                              // Top-Right
                Vertices[3] = new VertexP3N3G3B3T2()
                {
                    P = new float3(+1, -1, 0), N = new float3(0, 0, 1), T = new float3(1, 0, 0), B = new float3(0, 1, 0), UV = new float2(1, 1)
                };                                                                                                                                                                                              // Bottom-Right

                ByteBuffer VerticesBuffer = VertexP3N3G3B3T2.FromArray(Vertices);

                m_Prim_Rectangle = new Primitive(m_Device, Vertices.Length, VerticesBuffer, null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.P3N3G3B3T2);
            }

            {                   // Build the sphere
                const int          W        = 41;
                const int          H        = 22;
                VertexP3N3G3B3T2[] Vertices = new VertexP3N3G3B3T2[W * H];
                for (int Y = 0; Y < H; Y++)
                {
                    double Theta    = Math.PI * Y / (H - 1);
                    float  CosTheta = (float)Math.Cos(Theta);
                    float  SinTheta = (float)Math.Sin(Theta);
                    for (int X = 0; X < W; X++)
                    {
                        double Phi    = 2.0 * Math.PI * X / (W - 1);
                        float  CosPhi = (float)Math.Cos(Phi);
                        float  SinPhi = (float)Math.Sin(Phi);

                        float3 N = new float3(SinTheta * SinPhi, CosTheta, SinTheta * CosPhi);
                        float3 T = new float3(CosPhi, 0.0f, -SinPhi);
                        float3 B = N.Cross(T);

                        Vertices[W * Y + X] = new VertexP3N3G3B3T2()
                        {
                            P  = N,
                            N  = N,
                            T  = T,
                            B  = B,
                            UV = new float2(2.0f * X / W, 1.0f * Y / H)
                        };
                    }
                }

                ByteBuffer VerticesBuffer = VertexP3N3G3B3T2.FromArray(Vertices);

                uint[] Indices    = new uint[(H - 1) * (2 * W + 2) - 2];
                int    IndexCount = 0;
                for (int Y = 0; Y < H - 1; Y++)
                {
                    for (int X = 0; X < W; X++)
                    {
                        Indices[IndexCount++] = (uint)((Y + 0) * W + X);
                        Indices[IndexCount++] = (uint)((Y + 1) * W + X);
                    }
                    if (Y < H - 2)
                    {
                        Indices[IndexCount++] = (uint)((Y + 1) * W - 1);
                        Indices[IndexCount++] = (uint)((Y + 1) * W + 0);
                    }
                }

                m_Prim_Sphere = new Primitive(m_Device, Vertices.Length, VerticesBuffer, Indices, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.P3N3G3B3T2);
            }

            {                   // Build the cube
                float3[] Normals = new float3[6] {
                    -float3.UnitX,
                    float3.UnitX,
                    -float3.UnitY,
                    float3.UnitY,
                    -float3.UnitZ,
                    float3.UnitZ,
                };

                float3[] Tangents = new float3[6] {
                    float3.UnitZ,
                    -float3.UnitZ,
                    float3.UnitX,
                    -float3.UnitX,
                    -float3.UnitX,
                    float3.UnitX,
                };

                VertexP3N3G3B3T2[] Vertices = new VertexP3N3G3B3T2[6 * 4];
                uint[]             Indices  = new uint[2 * 6 * 3];

                for (int FaceIndex = 0; FaceIndex < 6; FaceIndex++)
                {
                    float3 N = Normals[FaceIndex];
                    float3 T = Tangents[FaceIndex];
                    float3 B = N.Cross(T);

                    Vertices[4 * FaceIndex + 0] = new VertexP3N3G3B3T2()
                    {
                        P  = N - T + B,
                        N  = N,
                        T  = T,
                        B  = B,
                        UV = new float2(0, 0)
                    };
                    Vertices[4 * FaceIndex + 1] = new VertexP3N3G3B3T2()
                    {
                        P  = N - T - B,
                        N  = N,
                        T  = T,
                        B  = B,
                        UV = new float2(0, 1)
                    };
                    Vertices[4 * FaceIndex + 2] = new VertexP3N3G3B3T2()
                    {
                        P  = N + T - B,
                        N  = N,
                        T  = T,
                        B  = B,
                        UV = new float2(1, 1)
                    };
                    Vertices[4 * FaceIndex + 3] = new VertexP3N3G3B3T2()
                    {
                        P  = N + T + B,
                        N  = N,
                        T  = T,
                        B  = B,
                        UV = new float2(1, 0)
                    };

                    Indices[2 * 3 * FaceIndex + 0] = (uint)(4 * FaceIndex + 0);
                    Indices[2 * 3 * FaceIndex + 1] = (uint)(4 * FaceIndex + 1);
                    Indices[2 * 3 * FaceIndex + 2] = (uint)(4 * FaceIndex + 2);
                    Indices[2 * 3 * FaceIndex + 3] = (uint)(4 * FaceIndex + 0);
                    Indices[2 * 3 * FaceIndex + 4] = (uint)(4 * FaceIndex + 2);
                    Indices[2 * 3 * FaceIndex + 5] = (uint)(4 * FaceIndex + 3);
                }

                ByteBuffer VerticesBuffer = VertexP3N3G3B3T2.FromArray(Vertices);

                m_Prim_Cube = new Primitive(m_Device, Vertices.Length, VerticesBuffer, Indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3B3T2);
            }
        }
Ejemplo n.º 8
0
        void BuildPrimitives()
        {
            {	// Post-process quad
                List<VertexPt4>	Vertices = new List<VertexPt4>();
                Vertices.Add( new VertexPt4() { Pt=new float4( -1, +1, 0, 1 ) } );
                Vertices.Add( new VertexPt4() { Pt=new float4( -1, -1, 0, 1 ) } );
                Vertices.Add( new VertexPt4() { Pt=new float4( +1, +1, 0, 1 ) } );
                Vertices.Add( new VertexPt4() { Pt=new float4( +1, -1, 0, 1 ) } );
                m_Prim_Quad = new Primitive( m_Device, 4, VertexPt4.FromArray( Vertices.ToArray() ), null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.Pt4 );
            }

            {	// Sphere Primitive
                List<VertexP3N3G3T2>	Vertices = new List<VertexP3N3G3T2>();
                List<uint>				Indices = new List<uint>();

                const int		SUBDIVS_THETA = 80;
                const int		SUBDIVS_PHI = 160;
                for ( int Y=0; Y <= SUBDIVS_THETA; Y++ ) {
                    double	Theta = Y * Math.PI / SUBDIVS_THETA;
                    float	CosTheta = (float) Math.Cos( Theta );
                    float	SinTheta = (float) Math.Sin( Theta );
                    for ( int X=0; X <= SUBDIVS_PHI; X++ ) {
                        double	Phi = X * 2.0 * Math.PI / SUBDIVS_PHI;
                        float	CosPhi = (float) Math.Cos( Phi );
                        float	SinPhi = (float) Math.Sin( Phi );

                        float3	N = new float3( SinTheta*SinPhi, CosTheta, SinTheta*CosPhi );
                        float3	T = new float3( CosPhi, 0.0f, -SinPhi );
                        float2	UV = new float2( (float) X / SUBDIVS_PHI, (float) Y / SUBDIVS_THETA );
                        Vertices.Add( new VertexP3N3G3T2() { P=N, N=N, T=T, UV=UV } );
                    }
                }

                for ( int Y=0; Y < SUBDIVS_THETA; Y++ ) {
                    int	CurrentLineOffset = Y * (SUBDIVS_PHI+1);
                    int	NextLineOffset = (Y+1) * (SUBDIVS_PHI+1);
                    for ( int X=0; X <= SUBDIVS_PHI; X++ ) {
                        Indices.Add( (uint) (CurrentLineOffset + X) );
                        Indices.Add( (uint) (NextLineOffset + X) );
                    }
                    if ( Y < SUBDIVS_THETA-1 ) {
                        Indices.Add( (uint) (NextLineOffset - 1) );	// Degenerate triangle to end the line
                        Indices.Add( (uint) NextLineOffset );		// Degenerate triangle to start the next line
                    }
                }

                m_Prim_Sphere = new Primitive( m_Device, Vertices.Count, VertexP3N3G3T2.FromArray( Vertices.ToArray() ), Indices.ToArray(), Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.P3N3G3T2 );
            }

            {	// Build the cube
                float3[]	Normals = new float3[6] {
                    -float3.UnitX,
                    float3.UnitX,
                    -float3.UnitY,
                    float3.UnitY,
                    -float3.UnitZ,
                    float3.UnitZ,
                };

                float3[]	Tangents = new float3[6] {
                    float3.UnitZ,
                    -float3.UnitZ,
                    float3.UnitX,
                    -float3.UnitX,
                    -float3.UnitX,
                    float3.UnitX,
                };

                VertexP3N3G3T2[]	Vertices = new VertexP3N3G3T2[6*4];
                uint[]		Indices = new uint[2*6*3];

                for ( int FaceIndex=0; FaceIndex < 6; FaceIndex++ ) {
                    float3	N = Normals[FaceIndex];
                    float3	T = Tangents[FaceIndex];
                    float3	B = N.Cross( T );

                    Vertices[4*FaceIndex+0] = new VertexP3N3G3T2() {
                        P = N - T + B,
                        N = N,
                        T = T,
            //						B = B,
                        UV = new float2( 0, 0 )
                    };
                    Vertices[4*FaceIndex+1] = new VertexP3N3G3T2() {
                        P = N - T - B,
                        N = N,
                        T = T,
            //						B = B,
                        UV = new float2( 0, 1 )
                    };
                    Vertices[4*FaceIndex+2] = new VertexP3N3G3T2() {
                        P = N + T - B,
                        N = N,
                        T = T,
            //						B = B,
                        UV = new float2( 1, 1 )
                    };
                    Vertices[4*FaceIndex+3] = new VertexP3N3G3T2() {
                        P = N + T + B,
                        N = N,
                        T = T,
            //						B = B,
                        UV = new float2( 1, 0 )
                    };

                    Indices[2*3*FaceIndex+0] = (uint) (4*FaceIndex+0);
                    Indices[2*3*FaceIndex+1] = (uint) (4*FaceIndex+1);
                    Indices[2*3*FaceIndex+2] = (uint) (4*FaceIndex+2);
                    Indices[2*3*FaceIndex+3] = (uint) (4*FaceIndex+0);
                    Indices[2*3*FaceIndex+4] = (uint) (4*FaceIndex+2);
                    Indices[2*3*FaceIndex+5] = (uint) (4*FaceIndex+3);
                }

                ByteBuffer	VerticesBuffer = VertexP3N3G3T2.FromArray( Vertices );

                m_Prim_Cube = new Primitive( m_Device, Vertices.Length, VerticesBuffer, Indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3T2 );
            }
        }
Ejemplo n.º 9
0
        //
        float   DiskIrradiance(float3[] _tsQuadVertices)
        {
            // 1) Extract center position, tangent and bi-tangent axes
            float3 T  = 0.5f * (_tsQuadVertices[1] - _tsQuadVertices[2]);
            float3 B  = -0.5f * (_tsQuadVertices[3] - _tsQuadVertices[2]);
            float3 P0 = 0.5f * (_tsQuadVertices[0] + _tsQuadVertices[2]);                       // Half-way through the diagonal

            float sqRt = T.Dot(T);
            float sqRb = B.Dot(B);

            float3 N = T.Cross(B).Normalized;                   // @TODO: Optimize! Do we need to normalize anyway?

            // 2) Build frustum matrices
            // M transform P' = M * P into canonical frustum space
            float3x3 M;
            float    invDepth = 1.0f / P0.Dot(N);

            M.r0 = (T - P0.Dot(T) * invDepth * N) / sqRt;
            M.r1 = (B - P0.Dot(B) * invDepth * N) / sqRb;
            M.r2 = N * invDepth;

            // M^-1 transforms P = M^-1 * P' back into original space
            float3x3 invM = new float3x3();

            invM.r0.Set(T.x, B.x, P0.x);
            invM.r1.Set(T.y, B.y, P0.y);
            invM.r2.Set(T.z, B.z, P0.z);

            // Compute the determinant of M^-1 that will help us scale the resulting vector
            float det = invM.Determinant;

            det = Mathf.Sqrt(sqRt * sqRb) * P0.Dot(N);

            // 3) Compute the exact integral in the canonical space
            // We know the expression of the orthogonal vector at any point on the unit circle as:
            //
            //							| cos(theta)
            //	Tau(theta) = 1/sqrt(2)  | sin(theta)
            //							| 1
            //
            // We move the orientation so we always compute 2 symetrical integrals on a half circle
            //	then we only need to compute the X component integral as the Y components have opposite
            //	sign and simply cancel each other
            //
            // The integral we need to compute is thus:
            //
            //	X = Integral[-maxTheta,maxTheta]{ cos(theta) dtheta }
            //	X = 2 * sin(maxTheta)
            //
            // The Z component is straightforward Z = Integral[-maxTheta,maxTheta]{ dtheta } = 2 maxTheta
            //
            float cosMaxTheta = -1.0f;                                       // No clipping at the moment
            float maxTheta    = Mathf.Acos(Mathf.Clamp(cosMaxTheta, -1, 1)); // @TODO: Optimize! Use fast acos or something...

            float3 F = new float3(2 * Mathf.Sqrt(1 - cosMaxTheta * cosMaxTheta), 0, 2 * maxTheta) / (Mathf.Sqrt(2) * Mathf.TWOPI);

            float3 F2 = F / -det;

            return(F2.Length);

//			// 4) Transform back into LTC space using M^-1
//			float3	F2 = invM * F;	// @TODO: Optimize => simply return length(F2) = determinant of M^-1
//
//			// 5) Estimate scalar irradiance
////			return -1.0f / det;
////			return Mathf.Abs(F2.z);
//			return F2.Length;
        }
        Primitive       BuildSubdividedCube()
        {
            // Default example face where B is used to stored the triangle's center and
            float3 C0 = (new float3(-1.0f, 1.0f, 1.0f) + new float3(-1.0f, -1.0f, 1.0f) + new float3(1.0f, -1.0f, 1.0f)) / 3.0f;
            float3 C1 = (new float3(-1.0f, 1.0f, 1.0f) + new float3(1.0f, -1.0f, 1.0f) + new float3(1.0f, 1.0f, 1.0f)) / 3.0f;

            VertexP3N3G3B3T2[] defaultFace = new VertexP3N3G3B3T2[6] {
                // First triangle
                new VertexP3N3G3B3T2()
                {
                    P = new float3(-1.0f, 1.0f, 1.0f), N = new float3(BEND * -1.0f, BEND * 1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C0, UV = new float2(0, 0)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(-1.0f, -1.0f, 1.0f), N = new float3(BEND * -1.0f, BEND * -1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C0, UV = new float2(0, 1)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(1.0f, -1.0f, 1.0f), N = new float3(BEND * 1.0f, BEND * -1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C0, UV = new float2(1, 1)
                },

                // 2nd triangle
                new VertexP3N3G3B3T2()
                {
                    P = new float3(-1.0f, 1.0f, 1.0f), N = new float3(BEND * -1.0f, BEND * 1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C1, UV = new float2(0, 0)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(1.0f, -1.0f, 1.0f), N = new float3(BEND * 1.0f, BEND * -1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C1, UV = new float2(1, 1)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(1.0f, 1.0f, 1.0f), N = new float3(BEND * 1.0f, BEND * 1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C1, UV = new float2(1, 0)
                },
            };

            float3[] faceNormals = new float3[6] {
                -float3.UnitX,
                float3.UnitX,
                -float3.UnitY,
                float3.UnitY,
                -float3.UnitZ,
                float3.UnitZ,
            };
            float3[] faceTangents = new float3[6] {
                float3.UnitZ,
                -float3.UnitZ,
                float3.UnitX,
                float3.UnitX,
                -float3.UnitX,
                float3.UnitX,
            };

            Func <float3, float3, float3, float3, float3> lambdaTransform = (float3 _P, float3 _T, float3 _B, float3 _N) => _P.x * _T + _P.y * _B + _P.z * _N;

            List <VertexP3N3G3B3T2> vertices = new List <VertexP3N3G3B3T2>();
            List <uint>             indices  = new List <uint>();

            const uint SUBVIVS_COUNT = 5;

            VertexP3N3G3B3T2[] temp = new VertexP3N3G3B3T2[3];
//			for ( int faceIndex=3; faceIndex < 4; faceIndex++ ) {
            for (int faceIndex = 0; faceIndex < 6; faceIndex++)
            {
                float3 N = faceNormals[faceIndex];
                float3 T = faceTangents[faceIndex];
                float3 B = N.Cross(T);

                for (uint triIndex = 0; triIndex < 2; triIndex++)
                {
                    for (int i = 0; i < 3; i++)
                    {
                        VertexP3N3G3B3T2 V = defaultFace[3 * triIndex + i];
                        temp[i].P  = lambdaTransform(V.P, T, B, N);
                        temp[i].N  = lambdaTransform(V.N, T, B, N);
                        temp[i].T  = lambdaTransform(V.T, T, B, N);
                        temp[i].B  = lambdaTransform(V.B, T, B, N);
                        temp[i].UV = V.UV;
                    }

                    SubdivTriangle(temp, SUBVIVS_COUNT, vertices, indices);
                }
            }

            return(new Primitive(m_device, (uint)vertices.Count, VertexP3N3G3B3T2.FromArray(vertices.ToArray()), indices.ToArray(), Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3B3T2));
        }
        Primitive       BuildCube()
        {
            // Default example face where B is used to stored the triangle's center and
//          float3	C0 = (new float3( -1.0f,  1.0f, 1.0f ) + new float3( -1.0f, -1.0f, 1.0f ) + new float3(  1.0f, -1.0f, 1.0f )) / 3.0f;
//          float3	C1 = (new float3( -1.0f,  1.0f, 1.0f ) + new float3(  1.0f, -1.0f, 1.0f ) + new float3(  1.0f,  1.0f, 1.0f )) / 3.0f;

            float  R  = (float)Math.Sqrt(3.0f) / BEND;
            float3 C0 = new float3(R, 0, 0);
            float3 C1 = new float3(R, 0, 0);

            VertexP3N3G3B3T2[] defaultFace = new VertexP3N3G3B3T2[6] {
                // First triangle
                new VertexP3N3G3B3T2()
                {
                    P = new float3(-1.0f, 1.0f, 1.0f), N = new float3(BEND * -1.0f, BEND * 1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C0, UV = new float2(0, 0)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(-1.0f, -1.0f, 1.0f), N = new float3(BEND * -1.0f, BEND * -1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C0, UV = new float2(0, 1)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(1.0f, -1.0f, 1.0f), N = new float3(BEND * 1.0f, BEND * -1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C0, UV = new float2(1, 1)
                },

                // 2nd triangle
                new VertexP3N3G3B3T2()
                {
                    P = new float3(-1.0f, 1.0f, 1.0f), N = new float3(BEND * -1.0f, BEND * 1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C1, UV = new float2(0, 0)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(1.0f, -1.0f, 1.0f), N = new float3(BEND * 1.0f, BEND * -1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C1, UV = new float2(1, 1)
                },
                new VertexP3N3G3B3T2()
                {
                    P = new float3(1.0f, 1.0f, 1.0f), N = new float3(BEND * 1.0f, BEND * 1.0f, 1.0f).Normalized, T = new float3(0, 0, 1), B = C1, UV = new float2(1, 0)
                },
            };

            float3[] faceNormals = new float3[6] {
                -float3.UnitX,
                float3.UnitX,
                -float3.UnitY,
                float3.UnitY,
                -float3.UnitZ,
                float3.UnitZ,
            };
            float3[] faceTangents = new float3[6] {
                float3.UnitZ,
                -float3.UnitZ,
                float3.UnitX,
                float3.UnitX,
                -float3.UnitX,
                float3.UnitX,
            };

            Func <float3, float3, float3, float3, float3> lambdaTransform = (float3 _P, float3 _T, float3 _B, float3 _N) => _P.x * _T + _P.y * _B + _P.z * _N;

            VertexP3N3G3B3T2[] vertices = new VertexP3N3G3B3T2[6 * 2 * 3];
            for (int faceIndex = 0; faceIndex < 6; faceIndex++)
            {
                float3 N = faceNormals[faceIndex];
                float3 T = faceTangents[faceIndex];
                float3 B = N.Cross(T);

                for (int i = 0; i < 6; i++)
                {
                    VertexP3N3G3B3T2 V = defaultFace[i];
                    vertices[6 * faceIndex + i].P = lambdaTransform(V.P, T, B, N);
                    vertices[6 * faceIndex + i].N = lambdaTransform(V.N, T, B, N);
                    vertices[6 * faceIndex + i].T = lambdaTransform(V.T, T, B, N);
//					vertices[6*faceIndex+i].B = lambdaTransform( V.B, T, B, N );
                    vertices[6 * faceIndex + i].B  = V.B;
                    vertices[6 * faceIndex + i].UV = V.UV;
                }
            }
            uint[] indices = new uint[6 * 2 * 3] {
//              0, 1, 2, 0, 2, 3,
//              4, 5, 6, 4, 6, 7,
//              8, 9, 10, 8, 10, 11,
//              12, 13, 14, 12, 14, 15,
//              16, 17, 18, 16, 18, 19,
//              20, 21, 22, 20, 22, 23,
                0, 1, 2, 3, 4, 5,
                6, 7, 8, 9, 10, 11,
                12, 13, 14, 15, 16, 17,
                18, 19, 20, 21, 22, 23,
                24, 25, 26, 27, 28, 29,
                30, 31, 32, 33, 34, 35
            };

            return(new Primitive(m_device, (uint)vertices.Length, VertexP3N3G3B3T2.FromArray(vertices), indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3B3T2));
        }
        /// <summary>
        /// Computes the 2 radii of the surface tangent to a vertex given a set of neighbor vertices
        /// </summary>
        /// <param name="_P"></param>
        /// <param name="_N"></param>
        /// <param name="_neighbors"></param>
        /// <returns></returns>
        float2  ComputeTangentCurvatureRadii(float3 _P, float3 _N, float3 _T, float3[] _neighbors, bool _debugGraph)
        {
            // Compute the square distance between the local neighbors and the double curvature surface of equation f(x,y) = Rt * x² + Rb * y²
            Func <double, double, float3[], double> SquareDistance = (double _Rt, double _Rb, float3[] _Pns) => {
                double result = 0.0;
                foreach (float3 Pn in _Pns)
                {
                    double Fxy = _Rt * Pn.x * Pn.x + _Rb * Pn.y * Pn.y;
                    double Dz  = Fxy - Pn.z;
                    result += Dz * Dz;
//					result += Dz;
                }
                return(result);
            };

            // Transform neighbors into local space
            float3 B = _T.Cross(_N).Normalized;

            float3[] neighbors = new float3[_neighbors.Length];
            for (int neighborIndex = 0; neighborIndex < _neighbors.Length; neighborIndex++)
            {
                float3 D = _neighbors[neighborIndex] - _P;
                neighbors[neighborIndex].Set(D.Dot(_T), D.Dot(B), D.Dot(_N));
            }

            float2 rangeX = new float2(-100, 100), rangeY = new float2(-1000, 1000);
            float4 pipo = new float4(1, 0, 0, 1);

            if (_debugGraph)
            {
                graph.WritePixels((uint X, uint Y, ref float4 _color) => {
                    float R0         = rangeX.x + X * (rangeX.y - rangeX.x) / graph.Width;
                    float R1         = rangeY.y + Y * (rangeY.x - rangeY.y) / graph.Height;
                    float sqDistance = (float)SquareDistance(R0, R1, _neighbors);
                    float V          = Math.Abs(sqDistance / 200.0f);
                    _color.Set(V, V, V, 1);
                });
                graph.DrawLine(new float4(0, 0, 1, 1), new float2(0, 0.5f * graph.Height), new float2(graph.Width, 0.5f * graph.Height));
                graph.DrawLine(new float4(0, 0, 1, 1), new float2(0.5f * graph.Width, 0), new float2(0.5f * graph.Width, graph.Height));
            }

            const float  eps = 0.01f;
            const double tol = 1e-3;

            // Compute gradient descent
            double previousRt = -double.MaxValue;
            double previousRb = -double.MaxValue;
            double Rt = 0.0, Rb = 0.0;
            int    iterationsCount     = 0;
            double previousSqDistance  = double.MaxValue;
            double bestSqDistance      = double.MaxValue;
            double bestRt              = 0.0;
            double bestRb              = 0.0;
            double stepSize            = 10.0;
            int    bestIterationsCount = 0;

            while (Math.Abs(Rt) < 10000.0f && Math.Abs(Rb) < 10000.0f && iterationsCount < 1000)
            {
                // Compute gradient
                double sqDistance = SquareDistance(Rt, Rb, neighbors);                          // Central value
                if (Math.Abs(sqDistance - previousSqDistance) / sqDistance < tol)
                {
                    break;                      // Relative error is low enough
                }

                double sqDistance_dT = SquareDistance(Rt + eps, Rb, neighbors);
                double sqDistance_dB = SquareDistance(Rt, Rb + eps, neighbors);
//				double	sqDistance_dTdB = SquareDistance( Rt + eps, Rb + eps, neighbors );
                double grad_dT = (sqDistance_dT - sqDistance) / eps;
                double grad_dB = (sqDistance_dB - sqDistance) / eps;
//              double	grad_dTdB = (sqDistance_dTdB - sqDistance) / eps;
//                      grad_dT = 0.5 * (grad_dT + grad_dTdB);
//                      grad_dB = 0.5 * (grad_dB + grad_dTdB);

                // Compute intersection with secant Y=0
//              double	t_T = -sqDistance * (Math.Abs( grad_dT ) > 1e-6 ? 1.0 / grad_dT : (Math.Sign( grad_dT ) * 1e6));
//              double	t_B = -sqDistance * (Math.Abs( grad_dB ) > 1e-6 ? 1.0 / grad_dB : (Math.Sign( grad_dB ) * 1e6));
                double t_T = -stepSize * eps * grad_dT;
                double t_B = -stepSize * eps * grad_dB;
                if (t_T * t_T + t_B * t_B < tol * tol)
                {
                    break;
                }

                previousRt = Rt;
                previousRb = Rb;
                Rt        += t_T;
                Rb        += t_B;
                iterationsCount++;

                if (_debugGraph)
                {
                    graph.DrawLine(pipo, new float2(((float)previousRt - rangeX.x) * graph.Width / (rangeX.y - rangeX.x), ((float)previousRb - rangeY.y) * graph.Height / (rangeY.x - rangeY.y))
                                   , new float2(((float)Rt - rangeX.x) * graph.Width / (rangeX.y - rangeX.x), ((float)Rb - rangeY.y) * graph.Height / (rangeY.x - rangeY.y)));
                }

                // Keep best results
                previousSqDistance = sqDistance;
                if (sqDistance < bestSqDistance)
                {
                    bestSqDistance      = sqDistance;
                    bestRt              = previousRt;
                    bestRb              = previousRb;
                    bestIterationsCount = iterationsCount;
                }
            }

            Rt = Math.Max(-10000.0, Math.Min(10000.0, Rt));
            Rb = Math.Max(-10000.0, Math.Min(10000.0, Rb));

            if (_debugGraph)
            {
                panelOutputGraph.m_bitmap = graph.AsBitmap;
                panelOutputGraph.Refresh();
                labelResult.Text = "R = " + Rt.ToString("G4") + ", " + Rb.ToString("G4") + " (" + previousSqDistance.ToString("G4") + ") in " + iterationsCount + " iterations...\r\nBest = " + bestRt.ToString("G4") + ", " + bestRb.ToString("G4") + " (" + bestSqDistance.ToString("G4") + ") in " + bestIterationsCount + " iterations...";
            }

            return(new float2((float)Rt, (float)Rb));
        }
Ejemplo n.º 13
0
        private void    Generate_CPU(int _RaysCount)
        {
            try {
                tabControlGenerators.Enabled = false;

                // Half-life basis (Z points outside of the surface, as in normal maps)
                float3[] basis = new float3[] {
                    new float3((float)Math.Sqrt(2.0 / 3.0), 0.0f, (float)Math.Sqrt(1.0 / 3.0)),
                    new float3((float)-Math.Sqrt(1.0 / 6.0), (float)Math.Sqrt(1.0 / 2.0), (float)Math.Sqrt(1.0 / 3.0)),
                    new float3((float)-Math.Sqrt(1.0 / 6.0), (float)-Math.Sqrt(1.0 / 2.0), (float)Math.Sqrt(1.0 / 3.0)),
                };

//              // 1] Compute normal map
//              float3	dX = new float3();
//              float3	dY = new float3();
//              float3	N;
//              float			ddX = floatTrackbarControlPixelSize.Value;
//              float			ddH = floatTrackbarControlHeight.Value;
//              for ( int Y=0; Y < H; Y++ )
//              {
//                  int	Y0 = Math.Max( 0, Y-1 );
//                  int	Y1 = Math.Min( H-1, Y+1 );
//                  for ( int X=0; X < W; X++ )
//                  {
//                      int	X0 = Math.Max( 0, X-1 );
//                      int	X1 = Math.Min( W-1, X+1 );
//
//                      float	Hx0 = m_BitmapSource.ContentXYZ[X0,Y].y;
//                      float	Hx1 = m_BitmapSource.ContentXYZ[X1,Y].y;
//                      float	Hy0 = m_BitmapSource.ContentXYZ[X,Y0].y;
//                      float	Hy1 = m_BitmapSource.ContentXYZ[X,Y1].y;
//
//                      dX.Set( 2.0f * ddX, 0.0f, ddH * (Hx1 - Hx0) );
//                      dY.Set( 0.0f, 2.0f * ddX, ddH * (Hy1 - Hy0) );
//
//                      N = dX.Cross( dY ).Normalized;
//
//                      m_Normal[X,Y] = new float3(
//                          N.Dot( Basis[0] ),
//                          N.Dot( Basis[1] ),
//                          N.Dot( Basis[2] ) );
//                  }
//
//                  // Update and show progress
//                  UpdateProgress( m_Normal, Y, true );
//              }
//              UpdateProgress( m_Normal, H, true );

                float LobeExponent = 4.0f;                  //floatTrackbarControlLobeExponent.Value;

                float PixelSize_mm = 1000.0f / floatTrackbarControlPixelDensity.Value;

                float scale = 0.1f * PixelSize_mm / floatTrackbarControlHeight.Value;                   // Scale factor to apply to pixel distances so they're renormalized in [0,1], our "heights space"...
//						Scale *= floatTrackbarControlZFactor.Value;	// Cheat Z velocity so AO is amplified!

                // 2] Build local rays only once
                int raysCount = integerTrackbarControlRaysCount.Value;
                float3[,]       rays = new float3[3, raysCount];

                // Create orthonormal bases to orient the lobe
                float3 Xr = basis[0].Cross(float3.UnitZ).Normalized;                    // We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3 Yr = Xr.Cross(basis[0]);
                float3 Xg = basis[1].Cross(float3.UnitZ).Normalized;                    // We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3 Yg = Xg.Cross(basis[1]);
                float3 Xb = basis[2].Cross(float3.UnitZ).Normalized;                    // We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3 Yb = Xb.Cross(basis[2]);

                double Exponent = 1.0 / (1.0 + LobeExponent);
                for (int RayIndex = 0; RayIndex < raysCount; RayIndex++)
                {
//                  if ( false ) {
//                      double	Phi = 2.0 * Math.PI * WMath.SimpleRNG.GetUniform();
// //						double	Theta = Math.Acos( Math.Pow( WMath.SimpleRNG.GetUniform(), Exponent ) );
//                      double	Theta = Math.PI / 3.0 * WMath.SimpleRNG.GetUniform();
//
//                      float3	RayLocal = new float3(
//                          (float) (Math.Cos( Phi ) * Math.Sin( Theta )),
//                          (float) (Math.Sin( Phi ) * Math.Sin( Theta )),
//                          (float) Math.Cos( Theta ) );
//
//                      Rays[0,RayIndex] = RayLocal.x * Xr + RayLocal.y * Yr + RayLocal.z * Basis[0];
//                      Rays[1,RayIndex] = RayLocal.x * Xg + RayLocal.y * Yg + RayLocal.z * Basis[1];
//                      Rays[2,RayIndex] = RayLocal.x * Xb + RayLocal.y * Yb + RayLocal.z * Basis[2];
//                  } else
                    {
                        double Phi   = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0);
                        double Theta = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[0, RayIndex] = new float3(
                            (float)(Math.Cos(Phi) * Math.Sin(Theta)),
                            (float)(Math.Sin(Phi) * Math.Sin(Theta)),
                            (float)Math.Cos(Theta));

                        Phi               = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0 + 2.0);
                        Theta             = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[1, RayIndex] = new float3(
                            (float)(Math.Cos(Phi) * Math.Sin(Theta)),
                            (float)(Math.Sin(Phi) * Math.Sin(Theta)),
                            (float)Math.Cos(Theta));

                        Phi               = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0 + 4.0);
                        Theta             = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[2, RayIndex] = new float3(
                            (float)(Math.Cos(Phi) * Math.Sin(Theta)),
                            (float)(Math.Sin(Phi) * Math.Sin(Theta)),
                            (float)Math.Cos(Theta));
                    }

                    rays[0, RayIndex].z *= scale;
                    rays[1, RayIndex].z *= scale;
                    rays[2, RayIndex].z *= scale;
                }

                // 3] Compute directional occlusion
                float4[] scanline = new float4[W];
                float4   gammaRGB = float4.Zero;
                for (uint Y = 0; Y < H; Y++)
                {
                    for (uint X = 0; X < W; X++)
                    {
                        gammaRGB.x = ComputeAO(0, X, Y, scale, rays);
                        gammaRGB.y = ComputeAO(1, X, Y, scale, rays);
                        gammaRGB.z = ComputeAO(2, X, Y, scale, rays);
                        gammaRGB.w = (gammaRGB.x + gammaRGB.y + gammaRGB.z) / 3.0f;
                        m_sRGBProfile.GammaRGB2LinearRGB(gammaRGB, ref scanline[X]);
                    }
                    m_imageResult.WriteScanline(Y, scanline);

                    // Update and show progress
                    UpdateProgress(m_imageResult, Y, true);
                }
                UpdateProgress(m_imageResult, H, true);

//				m_BitmapResult.Save( "eye_generic_01_disp_hl2.png", ImageFormat.Png );
            }
            catch (Exception _e)
            {
                MessageBox("An error occurred during generation:\r\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                tabControlGenerators.Enabled = true;
            }
        }
Ejemplo n.º 14
0
        public double Eval( double[] _newParameters )
        {
            double	lobeTheta = _newParameters[0];
            double	lobeRoughness = _newParameters[1];
            double	lobeGlobalScale = _newParameters[2];
            double	lobeFlatten = _newParameters[3];
            double	maskingImportance = _newParameters[4];

            // Flattening is not linear when using the anisotropic lobe model!
            if ( m_lobeType == LOBE_TYPE.MODIFIED_PHONG_ANISOTROPIC )
                lobeFlatten = Math.Pow( 2.0, 4.0 * (lobeFlatten - 1.0));	// in [2e-4, 2e4], log space

            double	invLobeFlatten = 1.0 / lobeFlatten;

            // Compute constant masking term due to incoming direction
             			double	maskingIncoming = Masking( m_direction.z, lobeRoughness );		// Masking( incoming )

            // Compute lobe's reflection vector and tangent space using new parameters
            double	cosTheta = Math.Cos( lobeTheta );
            double	sinTheta = Math.Sin( lobeTheta );

            float3	lobe_normal = new float3( (float) (sinTheta * m_incomingDirection_CosPhi), (float) (sinTheta * m_incomingDirection_SinPhi), (float) cosTheta );
            float3	lobe_tangent = new float3( (float) -m_incomingDirection_SinPhi, (float) m_incomingDirection_CosPhi, 0.0f );	// Always lying in the X^Y plane
            float3	lobe_biTangent = lobe_normal.Cross( lobe_tangent );

            // Compute sum
            double	phi, theta, cosPhi, sinPhi;
            double	outgoingIntensity_Simulated, length;
            double	outgoingIntensity_Analytical, lobeIntensity;
            double	difference;
            float3	wsOutgoingDirection = float3.Zero;
            float3	wsOutgoingDirection2 = float3.Zero;
            float3	lsOutgoingDirection = float3.Zero;
            double	maskingOutGoing = 0.0;
            double	maskingShadowing;

            double	sum = 0.0;
            double	sum_Simulated = 0.0;
            double	sum_Analytical = 0.0;
            double	sqSum_Simulated = 0.0;
            double	sqSum_Analytical = 0.0;
            for ( int Y=0; Y < H; Y++ ) {

            // Formerly used wrong stuff!
            // 				// Y = theta bin index = 2.0 * LOBES_COUNT_THETA * pow2( sin( 0.5 * theta ) )
            // 				// We need theta:
            //				theta = 2.0 * Math.Asin( Math.Sqrt( 0.5 * Y / H ) );

                // Y = theta bin index = LOBES_COUNT_THETA * (1 - cos( theta ) )
            // 				// We need theta:
                theta = Math.Acos( 1.0 - (float) Y / H );
                cosTheta = Math.Cos( theta );
                sinTheta = Math.Sin( theta );

                for ( int X=0; X < W; X++ ) {

                    // X = phi bin index = LOBES_COUNT_PHI * X / (2PI)
                    // We need phi:
                    phi = 2.0 * Math.PI * X / W;
                    cosPhi = Math.Cos( phi );
                    sinPhi = Math.Sin( phi );

                    // Build simulated microfacet reflection direction in macro-surface space
                    outgoingIntensity_Simulated = m_histogramData[X,Y];
                    wsOutgoingDirection.Set( (float) (cosPhi * sinTheta), (float) (sinPhi * sinTheta), (float) cosTheta );

                    // Compute maksing term due to outgoing direction
                    maskingOutGoing = Masking( wsOutgoingDirection.z, lobeRoughness );		// Masking( outgoing )

                    // Compute projection of world space direction onto reflected direction
                    float	Vx = wsOutgoingDirection.Dot( lobe_tangent );
                    float	Vy = wsOutgoingDirection.Dot( lobe_biTangent );
                    float	Vz = wsOutgoingDirection.Dot( lobe_normal );

            //Vz = Math.Min( 0.99f, Vz );

                    float	cosTheta_M = Math.Max( 1e-6f, Vz );

                    // Compute the lobe intensity in local space
                    lobeIntensity = NDF( cosTheta_M, lobeRoughness );

                    maskingShadowing = 1.0 + maskingImportance * (maskingIncoming * maskingOutGoing - 1.0);	// = 1 when importance = 0, = masking when importance = 1
             					lobeIntensity *= maskingShadowing;	// * Masking terms

                    lobeIntensity *= lobeGlobalScale;

                    // Apply additional lobe scaling/flattening
                    length = m_flatteningEval( Vx, Vy, Vz, lobeFlatten, invLobeFlatten );

                    outgoingIntensity_Analytical = lobeIntensity * length;	// Lobe intensity was estimated in lobe space, account for scaling when converting back in world space

                    // Sum the difference between simulated intensity and lobe intensity
                    outgoingIntensity_Analytical *= m_oversizeFactor;	// Apply tolerance factor so we're always a bit smaller than the simulated lobe

                    if ( m_fitUsingCenterOfMass ) {
                        double	difference0 = outgoingIntensity_Simulated - outgoingIntensity_Analytical;

                        float3	wsLobePosition_Simulated = (float) outgoingIntensity_Simulated * wsOutgoingDirection;
                        float3	wsLobePosition_Analytical = (float) outgoingIntensity_Analytical * wsOutgoingDirection;
                        // Subtract center of mass
                        wsLobePosition_Simulated -= m_centerOfMass;
                        wsLobePosition_Analytical -= m_centerOfMass;
                        // Compute new intensities, relative to center of mass
                        outgoingIntensity_Simulated = wsLobePosition_Simulated.Length;
                        outgoingIntensity_Analytical = wsLobePosition_Analytical.Length;

                        double	difference1 = outgoingIntensity_Simulated - outgoingIntensity_Analytical;

                        difference = 0.5 * difference0 + 0.5 * difference1;

            //						difference *= (wsLobePosition_Simulated - wsLobePosition_Analytical).Length;
            //						difference += (wsLobePosition_Simulated - wsLobePosition_Analytical).Length;	// We also add the distance between lobe positions so it goes to the best of the 2 minima!

                    } else {
                        difference = outgoingIntensity_Simulated - outgoingIntensity_Analytical;
            //						difference = outgoingIntensity_Simulated / Math.Max( 1e-6, outgoingIntensity_Analytical ) - 1.0;
            //						difference = outgoingIntensity_Analytical / Math.Max( 1e-6, outgoingIntensity_Simulated ) - 1.0;
                    }

                    sum += difference * difference;

                    sum_Simulated += outgoingIntensity_Simulated;
                    sum_Analytical += outgoingIntensity_Analytical;
                    sqSum_Simulated += outgoingIntensity_Simulated*outgoingIntensity_Simulated;
                    sqSum_Analytical += outgoingIntensity_Analytical*outgoingIntensity_Analytical;
                }
            }
            sum /= W * H;	// Not very useful since BFGS won't care but I'm doing it anyway to have some sort of normalized sum, better for us humans

            return sum;
        }
Ejemplo n.º 15
0
        private void BuildPrimitives()
        {
            {
                VertexPt4[]	Vertices = new VertexPt4[4];
                Vertices[0] = new VertexPt4() { Pt = new float4( -1, +1, 0, 1 ) };	// Top-Left
                Vertices[1] = new VertexPt4() { Pt = new float4( -1, -1, 0, 1 ) };	// Bottom-Left
                Vertices[2] = new VertexPt4() { Pt = new float4( +1, +1, 0, 1 ) };	// Top-Right
                Vertices[3] = new VertexPt4() { Pt = new float4( +1, -1, 0, 1 ) };	// Bottom-Right

                ByteBuffer	VerticesBuffer = VertexPt4.FromArray( Vertices );

                m_Prim_Quad = new Primitive( m_Device, Vertices.Length, VerticesBuffer, null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.Pt4 );
            }

            {
                VertexP3N3G3B3T2[]	Vertices = new VertexP3N3G3B3T2[4];
                Vertices[0] = new VertexP3N3G3B3T2() { P = new float3( -1, +1, 0 ), N = new float3( 0, 0, 1 ), T = new float3( 1, 0, 0 ), B = new float3( 0, 1, 0 ), UV = new float2( 0, 0 ) };	// Top-Left
                Vertices[1] = new VertexP3N3G3B3T2() { P = new float3( -1, -1, 0 ), N = new float3( 0, 0, 1 ), T = new float3( 1, 0, 0 ), B = new float3( 0, 1, 0 ), UV = new float2( 0, 1 ) };	// Bottom-Left
                Vertices[2] = new VertexP3N3G3B3T2() { P = new float3( +1, +1, 0 ), N = new float3( 0, 0, 1 ), T = new float3( 1, 0, 0 ), B = new float3( 0, 1, 0 ), UV = new float2( 1, 0 ) };	// Top-Right
                Vertices[3] = new VertexP3N3G3B3T2() { P = new float3( +1, -1, 0 ), N = new float3( 0, 0, 1 ), T = new float3( 1, 0, 0 ), B = new float3( 0, 1, 0 ), UV = new float2( 1, 1 ) };	// Bottom-Right

                ByteBuffer	VerticesBuffer = VertexP3N3G3B3T2.FromArray( Vertices );

                m_Prim_Rectangle = new Primitive( m_Device, Vertices.Length, VerticesBuffer, null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.P3N3G3B3T2 );
            }

            {	// Build the sphere
                const int	W = 41;
                const int	H = 22;
                VertexP3N3G3B3T2[]	Vertices = new VertexP3N3G3B3T2[W*H];
                for ( int Y=0; Y < H; Y++ ) {
                    double	Theta = Math.PI * Y / (H-1);
                    float	CosTheta = (float) Math.Cos( Theta );
                    float	SinTheta = (float) Math.Sin( Theta );
                    for ( int X=0; X < W; X++ ) {
                        double	Phi = 2.0 * Math.PI * X / (W-1);
                        float	CosPhi = (float) Math.Cos( Phi );
                        float	SinPhi = (float) Math.Sin( Phi );

                        float3	N = new float3( SinTheta * SinPhi, CosTheta, SinTheta * CosPhi );
                        float3	T = new float3( CosPhi, 0.0f, -SinPhi );
                        float3	B = N.Cross( T );

                        Vertices[W*Y+X] = new VertexP3N3G3B3T2() {
                            P = N,
                            N = N,
                            T = T,
                            B = B,
                            UV = new float2( 2.0f * X / W, 1.0f * Y / H )
                        };
                    }
                }

                ByteBuffer	VerticesBuffer = VertexP3N3G3B3T2.FromArray( Vertices );

                uint[]		Indices = new uint[(H-1) * (2*W+2)-2];
                int			IndexCount = 0;
                for ( int Y=0; Y < H-1; Y++ ) {
                    for ( int X=0; X < W; X++ ) {
                        Indices[IndexCount++] = (uint) ((Y+0) * W + X);
                        Indices[IndexCount++] = (uint) ((Y+1) * W + X);
                    }
                    if ( Y < H-2 ) {
                        Indices[IndexCount++] = (uint) ((Y+1) * W - 1);
                        Indices[IndexCount++] = (uint) ((Y+1) * W + 0);
                    }
                }

                m_Prim_Sphere = new Primitive( m_Device, Vertices.Length, VerticesBuffer, Indices, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.P3N3G3B3T2 );
            }

            {	// Build the cube
                float3[]	Normals = new float3[6] {
                    -float3.UnitX,
                    float3.UnitX,
                    -float3.UnitY,
                    float3.UnitY,
                    -float3.UnitZ,
                    float3.UnitZ,
                };

                float3[]	Tangents = new float3[6] {
                    float3.UnitZ,
                    -float3.UnitZ,
                    float3.UnitX,
                    -float3.UnitX,
                    -float3.UnitX,
                    float3.UnitX,
                };

                VertexP3N3G3B3T2[]	Vertices = new VertexP3N3G3B3T2[6*4];
                uint[]		Indices = new uint[2*6*3];

                for ( int FaceIndex=0; FaceIndex < 6; FaceIndex++ ) {
                    float3	N = Normals[FaceIndex];
                    float3	T = Tangents[FaceIndex];
                    float3	B = N.Cross( T );

                    Vertices[4*FaceIndex+0] = new VertexP3N3G3B3T2() {
                        P = N - T + B,
                        N = N,
                        T = T,
                        B = B,
                        UV = new float2( 0, 0 )
                    };
                    Vertices[4*FaceIndex+1] = new VertexP3N3G3B3T2() {
                        P = N - T - B,
                        N = N,
                        T = T,
                        B = B,
                        UV = new float2( 0, 1 )
                    };
                    Vertices[4*FaceIndex+2] = new VertexP3N3G3B3T2() {
                        P = N + T - B,
                        N = N,
                        T = T,
                        B = B,
                        UV = new float2( 1, 1 )
                    };
                    Vertices[4*FaceIndex+3] = new VertexP3N3G3B3T2() {
                        P = N + T + B,
                        N = N,
                        T = T,
                        B = B,
                        UV = new float2( 1, 0 )
                    };

                    Indices[2*3*FaceIndex+0] = (uint) (4*FaceIndex+0);
                    Indices[2*3*FaceIndex+1] = (uint) (4*FaceIndex+1);
                    Indices[2*3*FaceIndex+2] = (uint) (4*FaceIndex+2);
                    Indices[2*3*FaceIndex+3] = (uint) (4*FaceIndex+0);
                    Indices[2*3*FaceIndex+4] = (uint) (4*FaceIndex+2);
                    Indices[2*3*FaceIndex+5] = (uint) (4*FaceIndex+3);
                }

                ByteBuffer	VerticesBuffer = VertexP3N3G3B3T2.FromArray( Vertices );

                m_Prim_Cube = new Primitive( m_Device, Vertices.Length, VerticesBuffer, Indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3B3T2 );
            }
        }
Ejemplo n.º 16
0
        public double Eval(double[] _newParameters)
        {
            double lobeTheta         = _newParameters[0];
            double lobeRoughness     = _newParameters[1];
            double lobeGlobalScale   = _newParameters[2];
            double lobeFlatten       = _newParameters[3];
            double maskingImportance = _newParameters[4];


            // Flattening is not linear when using the anisotropic lobe model!
            if (m_lobeType == LOBE_TYPE.MODIFIED_PHONG_ANISOTROPIC)
            {
                lobeFlatten = Math.Pow(2.0, 4.0 * (lobeFlatten - 1.0));                         // in [2e-4, 2e4], log space
            }
            double invLobeFlatten = 1.0 / lobeFlatten;

            // Compute constant masking term due to incoming direction
            double maskingIncoming = Masking(m_direction.z, lobeRoughness);                             // Masking( incoming )

            // Compute lobe's reflection vector and tangent space using new parameters
            double cosTheta = Math.Cos(lobeTheta);
            double sinTheta = Math.Sin(lobeTheta);

            float3 lobe_normal    = new float3((float)(sinTheta * m_incomingDirection_CosPhi), (float)(sinTheta * m_incomingDirection_SinPhi), (float)cosTheta);
            float3 lobe_tangent   = new float3((float)-m_incomingDirection_SinPhi, (float)m_incomingDirection_CosPhi, 0.0f);                    // Always lying in the X^Y plane
            float3 lobe_biTangent = lobe_normal.Cross(lobe_tangent);

            // Compute sum
            double phi, theta, cosPhi, sinPhi;
            double outgoingIntensity_Simulated, length;
            double outgoingIntensity_Analytical, lobeIntensity;
            double difference;
            float3 wsOutgoingDirection  = float3.Zero;
            float3 wsOutgoingDirection2 = float3.Zero;
            float3 lsOutgoingDirection  = float3.Zero;
            double maskingOutGoing      = 0.0;
            double maskingShadowing;

            double sum              = 0.0;
            double sum_Simulated    = 0.0;
            double sum_Analytical   = 0.0;
            double sqSum_Simulated  = 0.0;
            double sqSum_Analytical = 0.0;

            for (int Y = 0; Y < H; Y++)
            {
// Formerly used wrong stuff!
//              // Y = theta bin index = 2.0 * LOBES_COUNT_THETA * pow2( sin( 0.5 * theta ) )
//              // We need theta:
//				theta = 2.0 * Math.Asin( Math.Sqrt( 0.5 * Y / H ) );

                // Y = theta bin index = LOBES_COUNT_THETA * (1 - cos( theta ) )
//              // We need theta:
                theta    = Math.Acos(1.0 - (float)Y / H);
                cosTheta = Math.Cos(theta);
                sinTheta = Math.Sin(theta);

                for (int X = 0; X < W; X++)
                {
                    // X = phi bin index = LOBES_COUNT_PHI * X / (2PI)
                    // We need phi:
                    phi    = 2.0 * Math.PI * X / W;
                    cosPhi = Math.Cos(phi);
                    sinPhi = Math.Sin(phi);

                    // Build simulated microfacet reflection direction in macro-surface space
                    outgoingIntensity_Simulated = m_histogramData[X, Y];
                    wsOutgoingDirection.Set((float)(cosPhi * sinTheta), (float)(sinPhi * sinTheta), (float)cosTheta);

                    // Compute maksing term due to outgoing direction
                    maskingOutGoing = Masking(wsOutgoingDirection.z, lobeRoughness);                                    // Masking( outgoing )

                    // Compute projection of world space direction onto reflected direction
                    float Vx = wsOutgoingDirection.Dot(lobe_tangent);
                    float Vy = wsOutgoingDirection.Dot(lobe_biTangent);
                    float Vz = wsOutgoingDirection.Dot(lobe_normal);

//Vz = Math.Min( 0.99f, Vz );

                    float cosTheta_M = Math.Max(1e-6f, Vz);

                    // Compute the lobe intensity in local space
                    lobeIntensity = NDF(cosTheta_M, lobeRoughness);

                    maskingShadowing = 1.0 + maskingImportance * (maskingIncoming * maskingOutGoing - 1.0); // = 1 when importance = 0, = masking when importance = 1
                    lobeIntensity   *= maskingShadowing;                                                    // * Masking terms

                    lobeIntensity *= lobeGlobalScale;

                    // Apply additional lobe scaling/flattening
                    length = m_flatteningEval(Vx, Vy, Vz, lobeFlatten, invLobeFlatten);

                    outgoingIntensity_Analytical = lobeIntensity * length;                      // Lobe intensity was estimated in lobe space, account for scaling when converting back in world space

                    // Sum the difference between simulated intensity and lobe intensity
                    outgoingIntensity_Analytical *= m_oversizeFactor;                           // Apply tolerance factor so we're always a bit smaller than the simulated lobe


                    if (m_fitUsingCenterOfMass)
                    {
                        double difference0 = outgoingIntensity_Simulated - outgoingIntensity_Analytical;

                        float3 wsLobePosition_Simulated  = (float)outgoingIntensity_Simulated * wsOutgoingDirection;
                        float3 wsLobePosition_Analytical = (float)outgoingIntensity_Analytical * wsOutgoingDirection;
                        // Subtract center of mass
                        wsLobePosition_Simulated  -= m_centerOfMass;
                        wsLobePosition_Analytical -= m_centerOfMass;
                        // Compute new intensities, relative to center of mass
                        outgoingIntensity_Simulated  = wsLobePosition_Simulated.Length;
                        outgoingIntensity_Analytical = wsLobePosition_Analytical.Length;

                        double difference1 = outgoingIntensity_Simulated - outgoingIntensity_Analytical;

                        difference = 0.5 * difference0 + 0.5 * difference1;

//						difference *= (wsLobePosition_Simulated - wsLobePosition_Analytical).Length;
//						difference += (wsLobePosition_Simulated - wsLobePosition_Analytical).Length;	// We also add the distance between lobe positions so it goes to the best of the 2 minima!
                    }
                    else
                    {
                        difference = outgoingIntensity_Simulated - outgoingIntensity_Analytical;
//						difference = outgoingIntensity_Simulated / Math.Max( 1e-6, outgoingIntensity_Analytical ) - 1.0;
//						difference = outgoingIntensity_Analytical / Math.Max( 1e-6, outgoingIntensity_Simulated ) - 1.0;
                    }


                    sum += difference * difference;

                    sum_Simulated    += outgoingIntensity_Simulated;
                    sum_Analytical   += outgoingIntensity_Analytical;
                    sqSum_Simulated  += outgoingIntensity_Simulated * outgoingIntensity_Simulated;
                    sqSum_Analytical += outgoingIntensity_Analytical * outgoingIntensity_Analytical;
                }
            }
            sum /= W * H;               // Not very useful since BFGS won't care but I'm doing it anyway to have some sort of normalized sum, better for us humans

            return(sum);
        }
Ejemplo n.º 17
0
        public void InitializeCamera( float3 _Position, float3 _Target, float3 _Up )
        {
            // Build the camera matrix
            float3	At = _Target - _Position;
            if ( At.LengthSquared > 1e-2f )
            {	// Normal case
                m_CameraTargetDistance = At.Length;
                At /= m_CameraTargetDistance;
            }
            else
            {	// Special bad case
                m_CameraTargetDistance = 0.01f;
                At = new float3( 0.0f, 0.0f, -1.0f );
            }

            float3		Ortho = _Up.Cross( At ).Normalized;

            float4x4	CameraMat = float4x4.Identity;
                        CameraMat.r3 = new float4( _Position, 1.0f );
                        CameraMat.r2 = new float4( At, 0.0f );
                        CameraMat.r0 = new float4( Ortho, 0.0f );
                        CameraMat.r1 = new float4( At.Cross( Ortho ), 0.0f );

            CameraTransform = CameraMat;

            // Setup the normalized target distance
            m_NormalizedTargetDistance = NormalizeTargetDistance( m_CameraTargetDistance );
        }
        Primitive       BuildTorus()
        {
            List <VertexP3N3G3B3T2> vertices = new List <VertexP3N3G3B3T2>();
            List <uint>             indices  = new List <uint>();

            // Build vertices
            VertexP3N3G3B3T2 V = new VertexP3N3G3B3T2();

            for (uint i = 0; i < SUBDIVS0; i++)
            {
                float  a0 = 2.0f * (float)Math.PI * i / SUBDIVS0;
                float3 X  = new float3((float)Math.Cos(a0), (float)Math.Sin(a0), 0.0f);
                float3 Y  = new float3(-X.y, X.x, 0.0f);
                float3 Z  = X.Cross(Y);
                float3 C  = RADIUS0 * X;                        // Center of little ring, around large ring

                for (uint j = 0; j < SUBDIVS1; j++)
                {
                    float  a1  = 2.0f * (float)Math.PI * j / SUBDIVS1;
                    float3 lsN = new float3((float)Math.Cos(a1), (float)Math.Sin(a1), 0.0f);
//					float3	lsN2 = new float3( -lsN.y, lsN.x, 0.0f );
                    float3 N = lsN.x * X + lsN.y * Z;
//					float3	N2 = lsN2.x * X + lsN2.y * Z;

                    V.P  = C + RADIUS1 * N;
                    V.N  = N;
                    V.T  = Y;
                    V.UV = new float2(4.0f * i / SUBDIVS0, 1.0f * j / SUBDIVS1);

                    vertices.Add(V);
                }
            }

            // Build indices and curvature
            uint[,]                 neighborIndices = new uint[3, 3];
            float3[]      neighbors    = new float3[8];
            List <float2> curvatures   = new List <float2>();
            float2        minCurvature = new float2(float.MaxValue, float.MaxValue);
            float2        maxCurvature = new float2(-float.MaxValue, -float.MaxValue);
            float2        avgCurvature = float2.Zero;
            int           count        = 0;

            for (uint i = 0; i < SUBDIVS0; i++)
            {
                uint Pi = (i + SUBDIVS0 - 1) % SUBDIVS0;
                uint Ni = (i + 1) % SUBDIVS0;

                uint ringCurrent  = SUBDIVS1 * i;
                uint ringPrevious = SUBDIVS1 * Pi;
                uint ringNext     = SUBDIVS1 * Ni;

                for (uint j = 0; j < SUBDIVS1; j++)
                {
                    uint Pj = (j + SUBDIVS1 - 1) % SUBDIVS1;
                    uint Nj = (j + 1) % SUBDIVS1;

                    neighborIndices[0, 0] = ringPrevious + Pj;
                    neighborIndices[0, 1] = ringPrevious + j;
                    neighborIndices[0, 2] = ringPrevious + Nj;
                    neighborIndices[1, 0] = ringCurrent + Pj;
                    neighborIndices[1, 1] = ringCurrent + j;
                    neighborIndices[1, 2] = ringCurrent + Nj;
                    neighborIndices[2, 0] = ringNext + Pj;
                    neighborIndices[2, 1] = ringNext + j;
                    neighborIndices[2, 2] = ringNext + Nj;

                    // Build 2 triangles
                    indices.Add(neighborIndices[1, 2]);
                    indices.Add(neighborIndices[1, 1]);
                    indices.Add(neighborIndices[2, 1]);
                    indices.Add(neighborIndices[1, 2]);
                    indices.Add(neighborIndices[2, 1]);
                    indices.Add(neighborIndices[2, 2]);

                    // Compute central vertex's curvature
                    VertexP3N3G3B3T2 centerVertex = vertices[(int)neighborIndices[1, 1]];
                    neighbors[0] = vertices[(int)neighborIndices[0, 0]].P;
                    neighbors[1] = vertices[(int)neighborIndices[1, 0]].P;
                    neighbors[2] = vertices[(int)neighborIndices[2, 0]].P;
                    neighbors[3] = vertices[(int)neighborIndices[0, 1]].P;
//					neighbors[] = vertices[(int) neighborIndices[1,1]].P;
                    neighbors[4] = vertices[(int)neighborIndices[2, 1]].P;
                    neighbors[5] = vertices[(int)neighborIndices[0, 2]].P;
                    neighbors[6] = vertices[(int)neighborIndices[1, 2]].P;
                    neighbors[7] = vertices[(int)neighborIndices[2, 2]].P;

                    // Single curvature
//                  float	curvature = ComputeTangentSphereRadius( centerVertex.P, centerVertex.N, neighbors, false );
//                  centerVertex.B.x = curvature;

                    // Double curvature
                    float2 curvature = ComputeTangentCurvatureRadii(centerVertex.P, centerVertex.N, centerVertex.T, neighbors, false);
                    centerVertex.B.x = curvature.x;
                    centerVertex.B.y = curvature.y;

                    vertices[(int)neighborIndices[1, 1]] = centerVertex;

                    curvatures.Add(curvature);
                    minCurvature.Min(curvature);
                    maxCurvature.Max(curvature);
                    avgCurvature += curvature;
                    count++;
                }
            }
            avgCurvature /= count;

            labelMeshInfo.Text = "Curvature Avg. = " + avgCurvature + " - Min = " + minCurvature + " - Max = " + maxCurvature;

            return(new Primitive(m_device, (uint)vertices.Count, VertexP3N3G3B3T2.FromArray(vertices.ToArray()), indices.ToArray(), Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3B3T2));
        }
Ejemplo n.º 19
0
        void    BuildPrimitives()
        {
            {                   // Post-process quad
                List <VertexPt4> Vertices = new List <VertexPt4>();
                Vertices.Add(new VertexPt4()
                {
                    Pt = new float4(-1, +1, 0, 1)
                });
                Vertices.Add(new VertexPt4()
                {
                    Pt = new float4(-1, -1, 0, 1)
                });
                Vertices.Add(new VertexPt4()
                {
                    Pt = new float4(+1, +1, 0, 1)
                });
                Vertices.Add(new VertexPt4()
                {
                    Pt = new float4(+1, -1, 0, 1)
                });
                m_Prim_Quad = new Primitive(m_Device, 4, VertexPt4.FromArray(Vertices.ToArray()), null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.Pt4);
            }

            {                   // Sphere Primitive
                List <VertexP3N3G3T2> Vertices = new List <VertexP3N3G3T2>();
                List <uint>           Indices  = new List <uint>();

                const int SUBDIVS_THETA = 80;
                const int SUBDIVS_PHI   = 160;
                for (int Y = 0; Y <= SUBDIVS_THETA; Y++)
                {
                    double Theta    = Y * Math.PI / SUBDIVS_THETA;
                    float  CosTheta = (float)Math.Cos(Theta);
                    float  SinTheta = (float)Math.Sin(Theta);
                    for (int X = 0; X <= SUBDIVS_PHI; X++)
                    {
                        double Phi    = X * 2.0 * Math.PI / SUBDIVS_PHI;
                        float  CosPhi = (float)Math.Cos(Phi);
                        float  SinPhi = (float)Math.Sin(Phi);

                        float3 N  = new float3(SinTheta * SinPhi, CosTheta, SinTheta * CosPhi);
                        float3 T  = new float3(CosPhi, 0.0f, -SinPhi);
                        float2 UV = new float2((float)X / SUBDIVS_PHI, (float)Y / SUBDIVS_THETA);
                        Vertices.Add(new VertexP3N3G3T2()
                        {
                            P = N, N = N, T = T, UV = UV
                        });
                    }
                }

                for (int Y = 0; Y < SUBDIVS_THETA; Y++)
                {
                    int CurrentLineOffset = Y * (SUBDIVS_PHI + 1);
                    int NextLineOffset    = (Y + 1) * (SUBDIVS_PHI + 1);
                    for (int X = 0; X <= SUBDIVS_PHI; X++)
                    {
                        Indices.Add((uint)(CurrentLineOffset + X));
                        Indices.Add((uint)(NextLineOffset + X));
                    }
                    if (Y < SUBDIVS_THETA - 1)
                    {
                        Indices.Add((uint)(NextLineOffset - 1));                                // Degenerate triangle to end the line
                        Indices.Add((uint)NextLineOffset);                                      // Degenerate triangle to start the next line
                    }
                }

                m_Prim_Sphere = new Primitive(m_Device, Vertices.Count, VertexP3N3G3T2.FromArray(Vertices.ToArray()), Indices.ToArray(), Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.P3N3G3T2);
            }

            {                   // Build the cube
                float3[] Normals = new float3[6] {
                    -float3.UnitX,
                    float3.UnitX,
                    -float3.UnitY,
                    float3.UnitY,
                    -float3.UnitZ,
                    float3.UnitZ,
                };

                float3[] Tangents = new float3[6] {
                    float3.UnitZ,
                    -float3.UnitZ,
                    float3.UnitX,
                    -float3.UnitX,
                    -float3.UnitX,
                    float3.UnitX,
                };

                VertexP3N3G3T2[] Vertices = new VertexP3N3G3T2[6 * 4];
                uint[]           Indices  = new uint[2 * 6 * 3];

                for (int FaceIndex = 0; FaceIndex < 6; FaceIndex++)
                {
                    float3 N = Normals[FaceIndex];
                    float3 T = Tangents[FaceIndex];
                    float3 B = N.Cross(T);

                    Vertices[4 * FaceIndex + 0] = new VertexP3N3G3T2()
                    {
                        P = N - T + B,
                        N = N,
                        T = T,
//						B = B,
                        UV = new float2(0, 0)
                    };
                    Vertices[4 * FaceIndex + 1] = new VertexP3N3G3T2()
                    {
                        P = N - T - B,
                        N = N,
                        T = T,
//						B = B,
                        UV = new float2(0, 1)
                    };
                    Vertices[4 * FaceIndex + 2] = new VertexP3N3G3T2()
                    {
                        P = N + T - B,
                        N = N,
                        T = T,
//						B = B,
                        UV = new float2(1, 1)
                    };
                    Vertices[4 * FaceIndex + 3] = new VertexP3N3G3T2()
                    {
                        P = N + T + B,
                        N = N,
                        T = T,
//						B = B,
                        UV = new float2(1, 0)
                    };

                    Indices[2 * 3 * FaceIndex + 0] = (uint)(4 * FaceIndex + 0);
                    Indices[2 * 3 * FaceIndex + 1] = (uint)(4 * FaceIndex + 1);
                    Indices[2 * 3 * FaceIndex + 2] = (uint)(4 * FaceIndex + 2);
                    Indices[2 * 3 * FaceIndex + 3] = (uint)(4 * FaceIndex + 0);
                    Indices[2 * 3 * FaceIndex + 4] = (uint)(4 * FaceIndex + 2);
                    Indices[2 * 3 * FaceIndex + 5] = (uint)(4 * FaceIndex + 3);
                }

                ByteBuffer VerticesBuffer = VertexP3N3G3T2.FromArray(Vertices);

                m_Prim_Cube = new Primitive(m_Device, Vertices.Length, VerticesBuffer, Indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3T2);
            }
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Builds the surface texture from an actual image file
        /// </summary>
        /// <param name="_textureFileName"></param>
        /// <param name="_pixelSize">Size of a pixel, assuming the maximum height is 1</param>
        public unsafe void BuildSurfaceFromTexture( string _textureFileName, float _pixelSize )
        {
            if ( m_Tex_Heightfield != null )
                m_Tex_Heightfield.Dispose();	// We will create a new one so dispose of the old one...

            // Read the bitmap
            int			W, H;
            float4[,]	Content = null;
            using ( Bitmap BM = Bitmap.FromFile( _textureFileName ) as Bitmap ) {
                W = BM.Width;
                H = BM.Height;
                Content = new float4[W,H];

                BitmapData	LockedBitmap = BM.LockBits( new Rectangle( 0, 0, W, H ), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb );

                byte	R, G, B, A;
                for ( int Y=0; Y < H; Y++ ) {
                    byte*	pScanline = (byte*) LockedBitmap.Scan0.ToPointer() + Y*LockedBitmap.Stride;
                    for ( int X=0; X < W; X++ ) {

                        // Read in shitty order
                        B = *pScanline++;
                        G = *pScanline++;
                        R = *pScanline++;
                        A = *pScanline++;

            // Use this if you really need RGBA data
            //						Content[X,Y].Set( R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f );

            // But assuming it's a height field, we only store one component into alpha
                        Content[X,Y].Set( 0, 0, 0, R / 255.0f );	// Use Red as height
                    }
                }
                BM.UnlockBits( LockedBitmap );
            }

            // Build normal (shitty version)
            float	Hx0, Hx1, Hy0, Hy1;
            float3	dNx = new float3( 2.0f * _pixelSize, 0, 0 );
            float3	dNy = new float3( 0, 2.0f * _pixelSize, 0 );
            float3	N;
            for ( int Y=0; Y < H; Y++ ) {
                int	pY = (Y+H-1) % H;
                int	nY = (Y+1) % H;
                for ( int X=0; X < W; X++ ) {
                    int	pX = (X+W-1) % W;
                    int	nX = (X+1) % W;

                    Hx0 = Content[pX,Y].w;
                    Hx1 = Content[nX,Y].w;
                    Hy0 = Content[X,pY].w;
                    Hy1 = Content[X,nY].w;

                    dNx.z = Hx1 - Hx0;
                    dNy.z = Hy0 - Hy1;	// Assuming +Y is upward

                    N = dNx.Cross( dNy );
                    N = N.Normalized;

                    Content[X,Y].x = N.x;
                    Content[X,Y].y = N.y;
                    Content[X,Y].z = N.z;
                }
            }

            // Build the texture from the array
            PixelsBuffer	Buf = new PixelsBuffer( W*H*16 );
            using ( BinaryWriter Writer = Buf.OpenStreamWrite() )
                for ( int Y=0; Y < H; Y++ )
                    for ( int X=0; X < W; X++ ) {
                        float4	pixel = Content[X,Y];
                        Writer.Write( pixel.x );
                        Writer.Write( pixel.y );
                        Writer.Write( pixel.z );
                        Writer.Write( pixel.w );
                    }
            Buf.CloseStream();

            m_Tex_Heightfield = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, new PixelsBuffer[] { Buf } );
        }
Ejemplo n.º 21
0
            public CellPolygon( float3 _P, float3 _N )
            {
                m_P = _P;
                m_N = _N;
                m_T = (float3.UnitY.Cross( m_N )).Normalized;
                m_B = m_N.Cross( m_T );

                // Start with 4 vertices
                const float	R = 10.0f;
                m_Vertices = new float3[] {
                    m_P + R * (-m_T + m_B),
                    m_P + R * (-m_T - m_B),
                    m_P + R * ( m_T - m_B),
                    m_P + R * ( m_T + m_B),
                };
            }
Ejemplo n.º 22
0
        public void             Compute(uint _X, uint _Y)
        {
            float2 __Position     = new float2(0.5f + _X, 0.5f + _Y);
            float2 UV             = __Position / m_resolution;
            uint   pixelPositionX = (uint)Mathf.Floor(__Position.x);
            uint   pixelPositionY = (uint)Mathf.Floor(__Position.y);
            float  noise          = 0.0f;    //_tex_blueNoise[pixelPosition & 0x3F];


//PerformIntegrationTest();


            // Setup camera ray
            float3 csView     = BuildCameraRay(UV);
            float  Z2Distance = csView.Length;

            csView /= Z2Distance;
            float3 wsView = (new float4(csView, 0.0f) * m_camera2World).xyz;

            // Read back depth, normal & central radiance value from last frame
            float Z = FetchDepth(__Position, 0.0f);

            Z -= 1e-2f;                 // Prevent acnea by offseting the central depth closer

//			float	distance = Z * Z2Distance;
            float3 wsNormal = m_arrayNormal[0][pixelPositionX, pixelPositionY].xyz.Normalized;

            // Read back last frame's radiance value that we always can use as a default for neighbor areas
            float3 centralRadiance = m_arrayIrradiance[0][pixelPositionX, pixelPositionY].xyz;

            // Compute local camera-space
            float3 wsPos   = m_camera2World[3].xyz + Z * Z2Distance * wsView;
            float3 wsRight = wsView.Cross(m_camera2World[1].xyz).Normalized;
            float3 wsUp    = wsRight.Cross(wsView);
            float3 wsAt    = -wsView;

            float4x4 localCamera2World = new float4x4(new float4(wsRight, 0), new float4(wsUp, 0), new float4(wsAt, 0), new float4(wsPos, 1));

            // Compute local camera-space normal
            float3 N = new float3(wsNormal.Dot(wsRight), wsNormal.Dot(wsUp), wsNormal.Dot(wsAt));

            N.z = Math.Max(1e-4f, N.z);                                 // Make sure it's never 0!

//			float3	T, B;
//			BuildOrthonormalBasis( N, T, B );

            // Compute screen radius of gather sphere
            float screenSize_m        = 2.0f * Z * TAN_HALF_FOV;        // Vertical size of the screen in meters when extended to distance Z
            float sphereRadius_pixels = m_resolution.y * m_gatherSphereMaxRadius_m / screenSize_m;

            sphereRadius_pixels = Mathf.Min(GATHER_SPHERE_MAX_RADIUS_P, sphereRadius_pixels);                                                           // Prevent it to grow larger than our fixed limit
            float radiusStepSize_pixels = Mathf.Max(1.0f, sphereRadius_pixels / MAX_SAMPLES);                                                           // This gives us our radial step size in pixels
            uint  samplesCount          = Mathf.Clamp((uint)Mathf.Ceiling(sphereRadius_pixels / radiusStepSize_pixels), 1, MAX_SAMPLES);                // Reduce samples count if possible
            float radiusStepSize_meters = sphereRadius_pixels * screenSize_m / (samplesCount * m_resolution.y);                                         // This gives us our radial step size in meters

            // Start gathering radiance and bent normal by subdividing the screen-space disk around our pixel into Z slices
            float4 GATHER_DEBUG        = float4.Zero;
            float3 sumIrradiance       = float3.Zero;
            float3 csAverageBentNormal = float3.Zero;
//          float	averageConeAngle = 0.0f;
//          float	varianceConeAngle = 0.0f;
            float sumAO = 0.0f;

            for (uint angleIndex = 0; angleIndex < MAX_ANGLES; angleIndex++)
            {
                float phi = (angleIndex + noise) * Mathf.PI / MAX_ANGLES;

//phi = 0.0f;

                float2 csDirection;
                csDirection.x = Mathf.Cos(phi);
                csDirection.y = Mathf.Sin(phi);

                // Gather irradiance and average cone direction for that slice
                float3 csBentNormal;
                float2 coneAngles;
                float  AO;
                sumIrradiance += GatherIrradiance(csDirection, localCamera2World, N, radiusStepSize_meters, samplesCount, Z, centralRadiance, out csBentNormal, out coneAngles, out AO, ref GATHER_DEBUG);

// if ( AO < -0.01f || AO > 1.01f )
//  throw new Exception( "MERDE!" );

                csAverageBentNormal += csBentNormal;
                sumAO += AO;

//              // We're using running variance computation from https://www.johndcook.com/blog/standard_deviation/
//              //	Avg(N) = Avg(N-1) + [V(N) - Avg(N-1)] / N
//              //	S(N) = S(N-1) + [V(N) - Avg(N-1)] * [V(N) - Avg(N)]
//              // And variance = S(finalN) / (finalN-1)
//              //
//              float	previousAverageConeAngle = averageConeAngle;
//              averageConeAngle += (coneAngles.x - averageConeAngle) / (2*angleIndex+1);
//              varianceConeAngle += (coneAngles.x - previousAverageConeAngle) * (coneAngles.x - averageConeAngle);
//
//              previousAverageConeAngle = averageConeAngle;
//              averageConeAngle += (coneAngles.y - averageConeAngle) / (2*angleIndex+2);
//              varianceConeAngle += (coneAngles.y - previousAverageConeAngle) * (coneAngles.y - averageConeAngle);
            }

            // Finalize bent cone & irradiance
            csAverageBentNormal = csAverageBentNormal.Normalized;

//csAverageBentNormal *= Mathf.PI / MAX_ANGLES;

            sumIrradiance *= Mathf.PI / MAX_ANGLES;

//          varianceConeAngle /= 2.0f*MAX_ANGLES - 1.0f;
//          float	stdDeviation = Mathf.Sqrt( varianceConeAngle );

            sumAO /= 2.0f * MAX_ANGLES;
//if ( sumAO < 0.0f || sumAO > 1.0f )
//	throw new Exception( "MERDE!" );

            float averageConeAngle  = Mathf.Acos(1.0f - sumAO);
            float varianceConeAngle = 0.0f;                     // Unfortunately, we don't have a proper value for the variance anymore... :'(
            float stdDeviation      = Mathf.Sqrt(varianceConeAngle);

            sumIrradiance.Max(float3.Zero);

            //////////////////////////////////////////////////////////////////////////
            // Finalize results
            m_sumIrradiance = new float4(sumIrradiance, 0);
            m_bentCone      = new float4(Mathf.Max(0.01f, Mathf.Cos(averageConeAngle)) * csAverageBentNormal, 1.0f - stdDeviation / (0.5f * Mathf.PI));


            float3 DEBUG_VALUE = new float3(1, 0, 1);

            DEBUG_VALUE = csAverageBentNormal;
            DEBUG_VALUE = csAverageBentNormal.x * wsRight - csAverageBentNormal.y * wsUp - csAverageBentNormal.z * wsAt; // World-space normal
//DEBUG_VALUE = cos( averageConeAngle );
//DEBUG_VALUE = dot( ssAverageBentNormal, N );
//DEBUG_VALUE = 0.01 * Z;
//DEBUG_VALUE = sphereRadius_pixels / GATHER_SPHERE_MAX_RADIUS_P;
//DEBUG_VALUE = 0.1 * (radiusStepSize_pixels-1);
//DEBUG_VALUE = 0.5 * float(samplesCount) / MAX_SAMPLES;
//DEBUG_VALUE = varianceConeAngle;
//DEBUG_VALUE = stdDeviation;
//DEBUG_VALUE = float3( GATHER_DEBUG.xy, 0 );
//DEBUG_VALUE = float3( GATHER_DEBUG.zw, 0 );
            DEBUG_VALUE = GATHER_DEBUG.xyz;
//DEBUG_VALUE = N;
//m_bentCone = float4( DEBUG_VALUE, 1 );

            //////////////////////////////////////////////////////////////////////////
            // Finalize bent code debug info
            m_wsConePosition  = wsPos;
            m_wsConeDirection = csAverageBentNormal.x * wsRight + csAverageBentNormal.y * wsUp + csAverageBentNormal.z * wsAt;
//m_wsConeDirection = wsNormal;
            m_averageConeAngle = averageConeAngle;
            m_stdDeviation     = stdDeviation;
        }