Exemplo n.º 1
0
            public Mesh(Scene _Owner, idTech5Map.Map.Entity _Entity) : base(_Owner, _Entity)
            {
                // BUild primitives and local space BBox
                m_Primitives    = new Primitive[_Entity.m_Model.m_Surfaces.Length];
                m_BBoxMin_Local = float.MaxValue * float3.One;
                m_BBoxMax_Local = -float.MaxValue * float3.One;

                int PrimitiveIndex = 0;

                foreach (idTech5Map.Model.Surface S in _Entity.m_Model.m_Surfaces)
                {
                    m_Primitives[PrimitiveIndex] = new Primitive(this, S);
                    m_BBoxMin_Local.Min(m_Primitives[PrimitiveIndex].m_BBoxMin);
                    m_BBoxMax_Local.Max(m_Primitives[PrimitiveIndex].m_BBoxMax);
                    PrimitiveIndex++;
                }

                // Convert BBox to world space
                m_BBoxMin_World = float.MaxValue * float3.One;
                m_BBoxMax_World = -float.MaxValue * float3.One;
                for (int CornerIndex = 0; CornerIndex < 8; CornerIndex++)
                {
                    float  X = (CornerIndex >> 0) & 1;
                    float  Y = (CornerIndex >> 0) & 1;
                    float  Z = (CornerIndex >> 0) & 1;
                    float3 D = m_BBoxMax_Local - m_BBoxMin_Local;

                    float3 lsCorner = m_BBoxMin_Local + new float3(X * D.x, Y * D.y, Z * D.z);
                    float3 wsCorner = (float3)(new float4(lsCorner, 1.0f) * m_Local2Parent);

                    m_BBoxMin_World.Min(wsCorner);
                    m_BBoxMax_World.Max(wsCorner);
                }
            }
Exemplo n.º 2
0
//      uint packR8G8B8A8( float4 value ) {
//          value = saturate( value );
//          return ( ( ( uint( value.x * 255.0 ) ) << 24 ) | ( ( uint( value.y * 255.0 ) ) << 16 ) | ( ( uint( value.z * 255.0 ) ) << 8 ) | ( uint( value.w * 255.0 ) ) );
//      }
//
//      float4 unpackR8G8B8A8( uint value ) {
//          return float4( ( value >> 24 ) & 0xFF, ( value >> 16 ) & 0xFF, ( value >> 8 ) & 0xFF, value & 0xFF ) / 255.0;
//      }
//
//      // RGBE (ward 1984)
//      uint packRGBE( float3 value ) {
//          const float sharedExp = ceil( ApproxLog2( max( max( value.r, value.g ), value.b ) ) );
//          return packR8G8B8A8( saturate( float4( value / ApproxExp2( sharedExp ), ( sharedExp + 128.0f ) / 255.0f ) ) );
//      }
//
//      float3 unpackRGBE( uint value ) {
//          const float4 rgbe = unpackR8G8B8A8( value );
//          return rgbe.rgb * ApproxExp2( rgbe.a * 255.0f - 128.0f );
//      }

        uint    EncodeRGBE(float3 _RGB)
        {
            float3 Sign = new float3(Math.Sign(_RGB.x), Math.Sign(_RGB.y), Math.Sign(_RGB.z));

            _RGB *= Sign;

            float maxRGB    = _RGB.Max();
            int   sharedExp = (int)Math.Ceiling(Math.Log(maxRGB) / Math.Log(2));

            sharedExp = Math.Max(0, Math.Min(31, sharedExp + EXPONENT_BIAS)) - EXPONENT_BIAS;


//          float	pow2 = (float) Math.Pow( 2.0f, sharedExp );
//          float3	reducedRGB = _RGB / pow2;
            float  invPow2    = (float)Math.Pow(2.0f, -sharedExp);
            float3 reducedRGB = _RGB * invPow2;

            reducedRGB.x = Math.Max(0.0f, Math.Min(1.0f, reducedRGB.x));
            reducedRGB.y = Math.Max(0.0f, Math.Min(1.0f, reducedRGB.y));
            reducedRGB.z = Math.Max(0.0f, Math.Min(1.0f, reducedRGB.z));

            byte R   = (byte)(255.0f * reducedRGB.x);
            byte G   = (byte)(255.0f * reducedRGB.y);
            byte B   = (byte)(255.0f * reducedRGB.z);
            byte exp = (byte)(EXPONENT_BIAS + sharedExp);

            exp |= (byte)((Sign.x < 0.0f ? 128 : 0) | (Sign.y < 0.0f ? 64 : 0) | (Sign.z < 0.0f ? 32 : 0));

            uint RGBE = (uint)((exp << 24) | (R << 16) | (G << 8) | B);

            return(RGBE);
        }
Exemplo n.º 3
0
 public void             Combine(AABB a, AABB b)
 {
     m_Min = a.m_Min;
     m_Min.Min(b.m_Min);
     m_Max = a.m_Max;
     m_Max.Max(b.m_Max);
 }
Exemplo n.º 4
0
        // Evaluates the SH coefficients in the requested direction
        // Analytic method from http://www1.cs.columbia.edu/~ravir/papers/envmap/envmap.pdf eq. 3
        //
        void    EvaluateSHRadiance(ref float3 _direction, ref float3 _radiance)
        {
            const float f0 = 0.28209479177387814347403972578039f;                               // 0.5 / sqrt(PI);
            const float f1 = 0.48860251190291992158638462283835f;                               // 0.5 * sqrt(3/PI);
            const float f2 = 1.0925484305920790705433857058027f;                                // 0.5 * sqrt(15/PI);
            const float f3 = 0.31539156525252000603089369029571f;                               // 0.25 * sqrt(5.PI);

            float SH0 = f0;
            float SH1 = f1 * _direction.y;
            float SH2 = f1 * _direction.z;
            float SH3 = f1 * _direction.x;
            float SH4 = f2 * _direction.x * _direction.y;
            float SH5 = f2 * _direction.y * _direction.z;
            float SH6 = f3 * (3.0f * _direction.z * _direction.z - 1.0f);
            float SH7 = f2 * _direction.x * _direction.z;
            float SH8 = f2 * 0.5f * (_direction.x * _direction.x - _direction.y * _direction.y);

            float3[] _SH = m_rotatedLightSH;

            // Dot the SH together
            _radiance = SH0 * _SH[0]
                        + SH1 * _SH[1]
                        + SH2 * _SH[2]
                        + SH3 * _SH[3]
                        + SH4 * _SH[4]
                        + SH5 * _SH[5]
                        + SH6 * _SH[6]
                        + SH7 * _SH[7]
                        + SH8 * _SH[8];
            _radiance.Max(float3.Zero);
        }
Exemplo n.º 5
0
        void TestSHRGBEEncoding()
        {
            float3[] coeffs = null;

            System.IO.FileInfo coeffsFileName = new System.IO.FileInfo("SHCoeffs.sh3");
            using (System.IO.FileStream S = coeffsFileName.OpenRead())
                using (System.IO.BinaryReader R = new System.IO.BinaryReader(S)) {
                    uint coeffsCount = R.ReadUInt32();
                    coeffs = new float3[coeffsCount * 9];
                    for (int i = 0; i < 9 * coeffsCount; i++)
                    {
                        coeffs[i] = new float3(R.ReadSingle(), R.ReadSingle(), R.ReadSingle());

// The exponent bias allows us to support up to 512 in luminance!
//coeffs[i] *= 5.0f;
                    }
                }

            uint   test1_packed   = EncodeRGBE(new float3(1, 0, 1.5f));
            float3 test1_unpacked = DecodeRGBE(test1_packed);

//			float3	coeffMin = new float3( float.MaxValue, float.MaxValue, float.MaxValue );
            float3 coeffMax    = new float3(-float.MaxValue, -float.MaxValue, -float.MaxValue);
            float3 coeffMinAbs = new float3(float.MaxValue, float.MaxValue, float.MaxValue);
            int    coeffsWithDifferentSignsInRGBCount = 0;

            for (int i = 0; i < coeffs.Length; i++)
            {
                float3 coeff    = coeffs[i];
                float3 absCoeff = new float3(Math.Abs(coeff.x), Math.Abs(coeff.y), Math.Abs(coeff.z));

                if (coeff.x * coeff.y < 0.0f || coeff.x * coeff.z < 0.0f || coeff.y * coeff.z < 0.0f)
                {
                    coeffsWithDifferentSignsInRGBCount++;
                }

//				coeffMin.Min( coeff );
                coeffMax.Max(absCoeff);
                if (absCoeff.x > 0.0f)
                {
                    coeffMinAbs.x = Math.Min(coeffMinAbs.x, absCoeff.x);
                }
                if (absCoeff.y > 0.0f)
                {
                    coeffMinAbs.y = Math.Min(coeffMinAbs.y, absCoeff.y);
                }
                if (absCoeff.z > 0.0f)
                {
                    coeffMinAbs.z = Math.Min(coeffMinAbs.z, absCoeff.z);
                }
            }

            double expMin = Math.Min(Math.Min(Math.Log(coeffMinAbs.x) / Math.Log(2), Math.Log(coeffMinAbs.y) / Math.Log(2)), Math.Log(coeffMinAbs.z) / Math.Log(2));
            double expMax = Math.Max(Math.Max(Math.Log(coeffMax.x) / Math.Log(2), Math.Log(coeffMax.y) / Math.Log(2)), Math.Log(coeffMax.z) / Math.Log(2));

            // Measure discrepancies after RGBE encoding
//          float3	errorAbsMin = new float3( +float.MaxValue, +float.MaxValue, +float.MaxValue );
//          float3	errorAbsMax = new float3( -float.MaxValue, -float.MaxValue, -float.MaxValue );
            float3 errorRelMin = new float3(+float.MaxValue, +float.MaxValue, +float.MaxValue);
            float3 errorRelMax = new float3(-float.MaxValue, -float.MaxValue, -float.MaxValue);
            int    minExponent = +int.MaxValue, maxExponent = -int.MaxValue;
            int    largeRelativeErrorsCount = 0;

            for (int i = 0; i < coeffs.Length; i++)
            {
                float3 originalRGB = coeffs[i];
                uint   RGBE        = EncodeRGBE(originalRGB);
                float3 decodedRGB  = DecodeRGBE(RGBE);

                // Compute absolute error
//              float3	delta = decodedRGB - originalRGB;
//              float3	distanceFromOriginal = new float3( Math.Abs( delta.x ), Math.Abs( delta.y ), Math.Abs( delta.z ) );
//              errorAbsMin.Min( distanceFromOriginal );
//              errorAbsMax.Max( distanceFromOriginal );

                // Compute relative error
                float3 errorRel = new float3(Math.Abs(originalRGB.x) > 0.0f ? Math.Abs(decodedRGB.x / originalRGB.x - 1.0f) : 0.0f, Math.Abs(originalRGB.y) > 0.0f ? Math.Abs(decodedRGB.y / originalRGB.y - 1.0f) : 0.0f, Math.Abs(originalRGB.z) > 0.0f ? Math.Abs(decodedRGB.z / originalRGB.z - 1.0f) : 0.0f);

                // Scale the relative error by the magnitude of each component as compared to the maximum component
                // This way, if we happen to have a "large" relative error on a component that is super small compared to the component with maximum amplitude then we can safely drop that small component (it's insignificant compared to the largest contribution)
                float  maxComponent   = Math.Max(Math.Max(Math.Abs(originalRGB.x), Math.Abs(originalRGB.y)), Math.Abs(originalRGB.z));
                float3 magnitudeScale = maxComponent > 0.0f ? new float3(Math.Abs(originalRGB.x) / maxComponent, Math.Abs(originalRGB.y) / maxComponent, Math.Abs(originalRGB.z) / maxComponent) : float3.Zero;
                errorRel *= magnitudeScale;

                // Don't account for dernomalization
//              if ( decodedRGB.x == 0.0 && originalRGB.x != 0.0f ) errorRel.x = 0.0f;
//              if ( decodedRGB.y == 0.0 && originalRGB.y != 0.0f ) errorRel.y = 0.0f;
//              if ( decodedRGB.z == 0.0 && originalRGB.z != 0.0f ) errorRel.z = 0.0f;

                const float errorThreshold = 0.2f;
                if (Math.Abs(errorRel.x) > errorThreshold || Math.Abs(errorRel.y) > errorThreshold || Math.Abs(errorRel.z) > errorThreshold)
                {
                    largeRelativeErrorsCount++;
                }
                errorRelMin.Min(errorRel);
                errorRelMax.Max(errorRel);

                int exp = (int)((RGBE >> 24) & 31) - EXPONENT_BIAS;
                minExponent = Math.Min(minExponent, exp);
                maxExponent = Math.Max(maxExponent, exp);
            }
        }
Exemplo n.º 6
0
                public Primitive(Mesh _Owner, FBX.Scene.Nodes.Mesh.Primitive _Primitive)
                {
                    m_Owner = _Owner;

                    m_MaterialID = (ushort)_Primitive.MaterialParms.ID;

                    m_Faces    = new Face[_Primitive.FacesCount];
                    m_Vertices = new Vertex[_Primitive.VerticesCount];

                    // Retrieve streams
                    FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE[] Usages =
                    {
                        FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.POSITION,
                        FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.NORMAL,
                        FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TANGENT,
                        FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.BITANGENT,
                        FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TEXCOORDS,
                    };
                    FBX.Scene.Nodes.Mesh.Primitive.VertexStream[][] Streams = new FBX.Scene.Nodes.Mesh.Primitive.VertexStream[Usages.Length][];
                    for (int UsageIndex = 0; UsageIndex < Usages.Length; UsageIndex++)
                    {
                        Streams[UsageIndex] = _Primitive.FindStreamsByUsage(Usages[UsageIndex]);
                        if (Streams[UsageIndex].Length == 0)
                        {
                            throw new Exception("No stream for usage " + Usages[UsageIndex] + "! Can't complete target vertex format!");
                        }
                    }

                    // Build local space bounding box
                    float3 Temp = new float3();

                    WMath.Vector[] VertexPositions = Streams[0][0].Content as WMath.Vector[];
                    foreach (WMath.Vector VertexPosition in VertexPositions)
                    {
                        Temp.FromVector3(VertexPosition);
                        m_BBoxMin.Min(Temp);
                        m_BBoxMax.Max(Temp);
                    }

                    // Build faces
                    int FaceIndex = 0;

                    foreach (FBX.Scene.Nodes.Mesh.Primitive.Face F in _Primitive.Faces)
                    {
                        m_Faces[FaceIndex].V0 = F.V0;
                        m_Faces[FaceIndex].V1 = F.V1;
                        m_Faces[FaceIndex].V2 = F.V2;
                        FaceIndex++;
                    }

                    // Build vertices
                    for (int VertexIndex = 0; VertexIndex < m_Vertices.Length; VertexIndex++)
                    {
                        for (int UsageIndex = 0; UsageIndex < Usages.Length; UsageIndex++)
                        {
                            FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE Usage = Usages[UsageIndex];
                            switch (Usage)
                            {
                            case FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.POSITION:
                            {
                                float3[] Stream = Streams[UsageIndex][0].Content as float3[];
                                m_Vertices[VertexIndex].P = Stream[VertexIndex];
                                break;
                            }

                            case FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.NORMAL:
                            {
                                float3[] Stream = Streams[UsageIndex][0].Content as float3[];
                                m_Vertices[VertexIndex].N = Stream[VertexIndex];
                                break;
                            }

                            case FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TANGENT:
                            {
                                float3[] Stream = Streams[UsageIndex][0].Content as float3[];
                                m_Vertices[VertexIndex].G = Stream[VertexIndex];
                                break;
                            }

                            case FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.BITANGENT:
                            {
                                float3[] Stream = Streams[UsageIndex][0].Content as float3[];
                                m_Vertices[VertexIndex].B = Stream[VertexIndex];
                                break;
                            }

                            case FBX.Scene.Nodes.Mesh.Primitive.VertexStream.USAGE.TEXCOORDS:
                            {
                                float2[] Stream = Streams[UsageIndex][0].Content as float2[];
                                m_Vertices[VertexIndex].T = Stream[VertexIndex];
                                break;
                            }
                            }
                        }
                    }
                }
Exemplo n.º 7
0
 public void             Combine(AABB _Other)
 {
     m_Min.Min(_Other.m_Min);
     m_Max.Max(_Other.m_Max);
 }
Exemplo n.º 8
0
        void TestSHRGBEEncoding()
        {
            float3[]	coeffs = null;

            System.IO.FileInfo	coeffsFileName = new System.IO.FileInfo( "SHCoeffs.sh3" );
            using ( System.IO.FileStream S = coeffsFileName.OpenRead() )
                using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) {
                    uint	coeffsCount = R.ReadUInt32();
                    coeffs = new float3[coeffsCount * 9];
                    for ( int i=0; i < 9*coeffsCount; i++ ) {
                        coeffs[i] = new float3( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() );

            // The exponent bias allows us to support up to 512 in luminance!
            //coeffs[i] *= 5.0f;

                    }
                }

            uint	test1_packed = EncodeRGBE( new float3( 1, 0, 1.5f ) );
            float3	test1_unpacked = DecodeRGBE( test1_packed );

            //			float3	coeffMin = new float3( float.MaxValue, float.MaxValue, float.MaxValue );
            float3	coeffMax = new float3( -float.MaxValue, -float.MaxValue, -float.MaxValue );
            float3	coeffMinAbs = new float3( float.MaxValue, float.MaxValue, float.MaxValue );
            int		coeffsWithDifferentSignsInRGBCount = 0;
            for ( int i=0; i < coeffs.Length; i++ ) {
                float3	coeff = coeffs[i];
                float3	absCoeff = new float3( Math.Abs( coeff.x ), Math.Abs( coeff.y ), Math.Abs( coeff.z ) );

                if ( coeff.x * coeff.y < 0.0f || coeff.x * coeff.z < 0.0f || coeff.y * coeff.z < 0.0f )
                    coeffsWithDifferentSignsInRGBCount++;

            //				coeffMin.Min( coeff );
                coeffMax.Max( absCoeff );
                if ( absCoeff.x > 0.0f ) coeffMinAbs.x = Math.Min( coeffMinAbs.x, absCoeff.x );
                if ( absCoeff.y > 0.0f ) coeffMinAbs.y = Math.Min( coeffMinAbs.y, absCoeff.y );
                if ( absCoeff.z > 0.0f ) coeffMinAbs.z = Math.Min( coeffMinAbs.z, absCoeff.z );
            }

            double	expMin = Math.Min( Math.Min( Math.Log( coeffMinAbs.x ) / Math.Log(2), Math.Log( coeffMinAbs.y ) / Math.Log(2) ), Math.Log( coeffMinAbs.z ) / Math.Log(2) );
            double	expMax = Math.Max( Math.Max( Math.Log( coeffMax.x ) / Math.Log(2), Math.Log( coeffMax.y ) / Math.Log(2) ), Math.Log( coeffMax.z ) / Math.Log(2) );

            // Measure discrepancies after RGBE encoding
            // 			float3	errorAbsMin = new float3( +float.MaxValue, +float.MaxValue, +float.MaxValue );
            // 			float3	errorAbsMax = new float3( -float.MaxValue, -float.MaxValue, -float.MaxValue );
            float3	errorRelMin = new float3( +float.MaxValue, +float.MaxValue, +float.MaxValue );
            float3	errorRelMax = new float3( -float.MaxValue, -float.MaxValue, -float.MaxValue );
            int		minExponent = +int.MaxValue, maxExponent = -int.MaxValue;
            int		largeRelativeErrorsCount = 0;
            for ( int i=0; i < coeffs.Length; i++ ) {
                float3	originalRGB = coeffs[i];
                uint	RGBE = EncodeRGBE( originalRGB );
                float3	decodedRGB = DecodeRGBE( RGBE );

                // Compute absolute error
            // 				float3	delta = decodedRGB - originalRGB;
            // 				float3	distanceFromOriginal = new float3( Math.Abs( delta.x ), Math.Abs( delta.y ), Math.Abs( delta.z ) );
            // 				errorAbsMin.Min( distanceFromOriginal );
            // 				errorAbsMax.Max( distanceFromOriginal );

                // Compute relative error
                float3	errorRel = new float3( Math.Abs( originalRGB.x ) > 0.0f ? Math.Abs( decodedRGB.x / originalRGB.x - 1.0f ) : 0.0f, Math.Abs( originalRGB.y ) > 0.0f ? Math.Abs( decodedRGB.y / originalRGB.y - 1.0f ) : 0.0f, Math.Abs( originalRGB.z ) > 0.0f ? Math.Abs( decodedRGB.z / originalRGB.z - 1.0f ) : 0.0f );

                // Scale the relative error by the magnitude of each component as compared to the maximum component
                // This way, if we happen to have a "large" relative error on a component that is super small compared to the component with maximum amplitude then we can safely drop that small component (it's insignificant compared to the largest contribution)
                float	maxComponent = Math.Max( Math.Max( Math.Abs( originalRGB.x ), Math.Abs( originalRGB.y ) ), Math.Abs( originalRGB.z ) );
                float3	magnitudeScale = maxComponent > 0.0f ? new float3( Math.Abs( originalRGB.x ) / maxComponent, Math.Abs( originalRGB.y ) / maxComponent, Math.Abs( originalRGB.z ) / maxComponent ) : float3.Zero;
                errorRel *= magnitudeScale;

                // Don't account for dernomalization
            // 				if ( decodedRGB.x == 0.0 && originalRGB.x != 0.0f ) errorRel.x = 0.0f;
            // 				if ( decodedRGB.y == 0.0 && originalRGB.y != 0.0f ) errorRel.y = 0.0f;
            // 				if ( decodedRGB.z == 0.0 && originalRGB.z != 0.0f ) errorRel.z = 0.0f;

                const float	errorThreshold = 0.2f;
                if ( Math.Abs( errorRel.x ) > errorThreshold || Math.Abs( errorRel.y ) > errorThreshold || Math.Abs( errorRel.z ) > errorThreshold )
                    largeRelativeErrorsCount++;
                errorRelMin.Min( errorRel );
                errorRelMax.Max( errorRel );

                int		exp = (int) ((RGBE >> 24) & 31) - EXPONENT_BIAS;
                minExponent = Math.Min( minExponent, exp );
                maxExponent = Math.Max( maxExponent, exp );
            }
        }
Exemplo n.º 9
0
        // 		uint packR8G8B8A8( float4 value ) {
        // 			value = saturate( value );
        // 			return ( ( ( uint( value.x * 255.0 ) ) << 24 ) | ( ( uint( value.y * 255.0 ) ) << 16 ) | ( ( uint( value.z * 255.0 ) ) << 8 ) | ( uint( value.w * 255.0 ) ) );
        // 		}
        //
        // 		float4 unpackR8G8B8A8( uint value ) {
        // 			return float4( ( value >> 24 ) & 0xFF, ( value >> 16 ) & 0xFF, ( value >> 8 ) & 0xFF, value & 0xFF ) / 255.0;
        // 		}
        //
        // 		// RGBE (ward 1984)
        // 		uint packRGBE( float3 value ) {
        // 			const float sharedExp = ceil( ApproxLog2( max( max( value.r, value.g ), value.b ) ) );
        // 			return packR8G8B8A8( saturate( float4( value / ApproxExp2( sharedExp ), ( sharedExp + 128.0f ) / 255.0f ) ) );
        // 		}
        //
        // 		float3 unpackRGBE( uint value ) {
        // 			const float4 rgbe = unpackR8G8B8A8( value );
        // 			return rgbe.rgb * ApproxExp2( rgbe.a * 255.0f - 128.0f );
        // 		}
        uint EncodeRGBE( float3 _RGB )
        {
            float3	Sign = new float3( Math.Sign( _RGB.x ), Math.Sign( _RGB.y ), Math.Sign( _RGB.z ) );
            _RGB *= Sign;

            float	maxRGB = _RGB.Max();
            int		sharedExp = (int) Math.Ceiling( Math.Log( maxRGB ) / Math.Log(2) );

            sharedExp = Math.Max( 0, Math.Min( 31, sharedExp + EXPONENT_BIAS ) ) - EXPONENT_BIAS;

            // 			float	pow2 = (float) Math.Pow( 2.0f, sharedExp );
            // 			float3	reducedRGB = _RGB / pow2;
            float	invPow2 = (float) Math.Pow( 2.0f, -sharedExp );
            float3	reducedRGB = _RGB * invPow2;
                    reducedRGB.x = Math.Max( 0.0f, Math.Min( 1.0f, reducedRGB.x ) );
                    reducedRGB.y = Math.Max( 0.0f, Math.Min( 1.0f, reducedRGB.y ) );
                    reducedRGB.z = Math.Max( 0.0f, Math.Min( 1.0f, reducedRGB.z ) );

            byte	R = (byte) (255.0f * reducedRGB.x);
            byte	G = (byte) (255.0f * reducedRGB.y);
            byte	B = (byte) (255.0f * reducedRGB.z);
            byte	exp = (byte) (EXPONENT_BIAS + sharedExp);
                    exp |= (byte) ((Sign.x < 0.0f ? 128 : 0) | (Sign.y < 0.0f ? 64 : 0) | (Sign.z < 0.0f ? 32 : 0));

            uint	RGBE = (uint) ((exp << 24) | (R << 16) | (G << 8) | B);
            return RGBE;
        }
Exemplo n.º 10
0
 public void Combine( AABB a, AABB b )
 {
     m_Min = a.m_Min;
     m_Min.Min( b.m_Min );
     m_Max = a.m_Max;
     m_Max.Max( b.m_Max );
 }
Exemplo n.º 11
0
            public Mesh( Scene _Owner, idTech5Map.Map.Entity _Entity )
                : base(_Owner, _Entity)
            {
                // BUild primitives and local space BBox
                m_Primitives = new Primitive[_Entity.m_Model.m_Surfaces.Length];
                m_BBoxMin_Local = float.MaxValue * float3.One;
                m_BBoxMax_Local = -float.MaxValue * float3.One;

                int	PrimitiveIndex = 0;
                foreach ( idTech5Map.Model.Surface S in _Entity.m_Model.m_Surfaces ) {
                    m_Primitives[PrimitiveIndex] = new Primitive( this, S );
                    m_BBoxMin_Local.Min( m_Primitives[PrimitiveIndex].m_BBoxMin );
                    m_BBoxMax_Local.Max( m_Primitives[PrimitiveIndex].m_BBoxMax );
                    PrimitiveIndex++;
                }

                // Convert BBox to world space
                m_BBoxMin_World = float.MaxValue * float3.One;
                m_BBoxMax_World = -float.MaxValue * float3.One;
                for ( int CornerIndex=0; CornerIndex < 8; CornerIndex++ ) {
                    float	X = (CornerIndex >> 0) & 1;
                    float	Y = (CornerIndex >> 0) & 1;
                    float	Z = (CornerIndex >> 0) & 1;
                    float3	D = m_BBoxMax_Local - m_BBoxMin_Local;

                    float3	lsCorner = m_BBoxMin_Local + new float3( X * D.x, Y * D.y, Z * D.z );
                    float3	wsCorner = (float3) (new float4( lsCorner, 1.0f ) * m_Local2Parent);

                    m_BBoxMin_World.Min( wsCorner );
                    m_BBoxMax_World.Max( wsCorner );
                }
            }
Exemplo n.º 12
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;
        }