Example #1
0
        private void    BuildQuad()
        {
            VertexPt4[] Vertices = new VertexPt4[] {
                new VertexPt4()
                {
                    Pt = new float4(-1, +1, 0, 1)
                },
                new VertexPt4()
                {
                    Pt = new float4(-1, -1, 0, 1)
                },
                new VertexPt4()
                {
                    Pt = new float4(+1, +1, 0, 1)
                },
                new VertexPt4()
                {
                    Pt = new float4(+1, -1, 0, 1)
                },
            };

            ByteBuffer VerticesBuffer = VertexPt4.FromArray(Vertices);

            Reg(m_Prim_Quad = new Primitive(m_Device, Vertices.Length, VerticesBuffer, null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.Pt4));
        }
Example #2
0
        private void    BuildQuad()
        {
            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);
        }
Example #3
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);
            }
        }
Example #4
0
		private void	BuildQuad()
		{
			VertexPt4[]	Vertices = new VertexPt4[] {
				new VertexPt4() { Pt = new float4( -1, +1, 0, 1 ) },
				new VertexPt4() { Pt = new float4( -1, -1, 0, 1 ) },
				new VertexPt4() { Pt = new float4( +1, +1, 0, 1 ) },
				new VertexPt4() { Pt = new float4( +1, -1, 0, 1 ) },
			};

			ByteBuffer	VerticesBuffer = VertexPt4.FromArray( Vertices );

			Reg( m_Prim_Quad = new Primitive( m_Device, Vertices.Length, VerticesBuffer, null, Primitive.TOPOLOGY.TRIANGLE_STRIP, VERTEX_FORMAT.Pt4 ) );
		}
        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);
            }
        }
Example #6
0
/*

// 				float	Theta = 0.5 * _UV.x * PI;
// 				float3	ToLight = float3( sin( Theta ), 0, cos( Theta ) );
// 				float3	ToView = float3( -sin( Theta ), 0, cos( Theta ) );
// 
// 				float	Albedo = 0.0;
// 				const int	THETA_COUNT = 64; // * $alwaysOne; // warning X4008: floating point division by zero
// 				const float	dTheta = HALFPI / THETA_COUNT;
// 				const float	dPhi = PI / THETA_COUNT;
// 				for ( int i=0; i < THETA_COUNT; i++ )
// 				{
// 					Theta = HALFPI * (0.5 + i) / THETA_COUNT;
// 					for ( int j=0; j < THETA_COUNT; j++ )
// 					{
// 						float	Phi = PI * j / THETA_COUNT;
// 
// 						ToView = float3( sin( Theta ) * cos( Phi ), sin( Theta ) * sin( Phi ), cos( Theta ) );
// 
// 						float3	Half = normalize( ToLight + ToView );
// 
// 						// "True" and expensive evaluation of the Ward BRDF
// 						float	alpha = Roughness;
// 
// 						float	CosDelta = Half.z;	// dot( Half, _wsNormal );
// 						float	delta = acos( CosDelta );
// 						float	CosThetaL = ToLight.z;
// 						float	SinThetaL = sqrt( 1.0 - CosThetaL*CosThetaL );
// 						float	PhiL = atan2( ToLight.y, ToLight.x );
// 						float	CosThetaV = ToView.z;
// 						float	SinThetaV = sqrt( 1.0 - CosThetaV*CosThetaV );
// 						float	PhiV = atan2( ToView.y, ToView.x );
// 
// 						float	BRDF = 1.0 / square(alpha) * exp( -square( tan( delta ) / alpha ) ) * 2.0 * (1.0 + CosThetaL*CosThetaV + SinThetaL*SinThetaV*cos( PhiV - PhiL )) / pow4( CosThetaL + CosThetaV );
// 
// 						Albedo += BRDF * cos( Theta ) * sin( Theta ) * dTheta * dPhi;
// 					}
// 				}
// 
// 				Albedo *= 2.0;		// Since we integrate on half a hemisphere...
// 				Albedo *= INVPI;	// Since we forgot that in the main loop
// 
 
// ==========================================================================
// arkDebugBRDFAlbedo
// 
// 	Displays the true and theoretical BRDF albedos
// 
// ==========================================================================
//
renderProg PostFX/Debug/WardBRDFAlbedo {
	newstyle
	
	hlsl_prefix {

		#include <ward>
		
		// Displays the BRDF albedo in 2 small screen insets showing how the albedo varies with roughness
		// The albedo is computed by integrating the BRDF over an entire hemisphere of view directions for a 
		//	single light direction that varies with U in [0,1] corresponding to Theta_Light in [0,PI/2].
		//
		// The goal here is to demonstrate the albedo is correctly bounded (i.e. never > 1).
		// The especially important part is when the light is at grazing angles (i.e. U -> 1)
		//
		// Just call this function in the finalizer post-process, providing the screen UVs and the final color
		//
		void	DEBUG_DisplayWardBRDFAlbedo( float2 _UV, inout float3 _Color )
		{
			float	Roughness = lerp( 0.01, 1.0, 0.5 * (1.0 + sin( $time.x )) );	// Roughness is varying with time here...

			if ( _UV.x < 0.2 && _UV.y > 0.8 )
			{	// This version integrates the "true" BRDF
				// The formula comes from eq. (15) from http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.169.9908&rep=rep1&type=pdf
				//
				_UV.x /= 0.2;
				_UV.y = (_UV.y - 0.8) / 0.2;

				float	Theta = 0.5 * _UV.x * PI;
				float3	ToLight = float3( sin( Theta ), 0, cos( Theta ) );
				float3	ToView = float3( -sin( Theta ), 0, cos( Theta ) );

				float	Albedo = 0.0;
				const int	THETA_COUNT = 64; // * $alwaysOne; // warning X4008: floating point division by zero
				const float	dTheta = HALFPI / THETA_COUNT;
				const float	dPhi = PI / THETA_COUNT;
				for ( int i=0; i < THETA_COUNT; i++ )
				{
					Theta = HALFPI * (0.5 + i) / THETA_COUNT;
					for ( int j=0; j < THETA_COUNT; j++ )
					{
						float	Phi = PI * j / THETA_COUNT;

						ToView = float3( sin( Theta ) * cos( Phi ), sin( Theta ) * sin( Phi ), cos( Theta ) );

						float3	Half = normalize( ToLight + ToView );

						// "True" and expensive evaluation of the Ward BRDF
						float	alpha = Roughness;

						float	CosDelta = Half.z;	// dot( Half, _wsNormal );
						float	delta = acos( CosDelta );
						float	CosThetaL = ToLight.z;
						float	SinThetaL = sqrt( 1.0 - CosThetaL*CosThetaL );
						float	PhiL = atan2( ToLight.y, ToLight.x );
						float	CosThetaV = ToView.z;
						float	SinThetaV = sqrt( 1.0 - CosThetaV*CosThetaV );
						float	PhiV = atan2( ToView.y, ToView.x );

						float	BRDF = 1.0 / square(alpha) * exp( -square( tan( delta ) / alpha ) ) * 2.0 * (1.0 + CosThetaL*CosThetaV + SinThetaL*SinThetaV*cos( PhiV - PhiL )) / pow4( CosThetaL + CosThetaV );

						Albedo += BRDF * cos( Theta ) * sin( Theta ) * dTheta * dPhi;
					}
				}

				Albedo *= 2.0;		// Since we integrate on half a hemisphere...
				Albedo *= INVPI;	// Since we forgot that in the main loop

				_Color = 1.0 - _UV.y < 0.8 * Albedo ? 1 : 0;

				if ( _UV.x < 0.01 )
					_Color = Roughness;
			}
			else if ( _UV.x > 0.25 && _UV.x < 0.45 && _UV.y > 0.8 )
			{	// And this version uses our implementation of the Ward BRDF
				// The formula comes from eq. (23) of the same paper.
				// Both renderings should be equal and albedo should NEVER be > 1!
				//
				_UV.x = (_UV.x - 0.25) / 0.2;
				_UV.y = (_UV.y - 0.8) / 0.2;

				WardContext	ctx;
				CreateWardContext( ctx, Roughness, 0.0, 0.0, float3( 1, 0, 0 ), float3( 0, 1, 0 ) );

				float	Theta = 0.5 * _UV.x * PI;
				float3	ToLight = float3( sin( Theta ), 0, cos( Theta ) );
				float3	ToView = float3( -sin( Theta ), 0, cos( Theta ) );

				float	Albedo = 0.0;
				const int	THETA_COUNT = 64; // * $alwaysOne;	// Allows to prevent unrolling and lenghty shader compilation!
				const float	dTheta = HALFPI / THETA_COUNT;
				const float	dPhi = PI / THETA_COUNT;
				for ( int i=0; i < THETA_COUNT; i++ )
				{
					Theta = HALFPI * (0.5 + i) / THETA_COUNT;
					for ( int j=0; j < THETA_COUNT; j++ )
					{
						float	Phi = PI * j / THETA_COUNT;

						ToView = float3( sin( Theta ) * cos( Phi ), sin( Theta ) * sin( Phi ), cos( Theta ) );
 						Albedo += ctx.ComputeWardTerm( float3( 0, 0, 1 ), ToLight, ToView ) * cos( Theta ) * sin( Theta ) * dTheta * dPhi;
					}
				}

				Albedo *= 2.0;		// Since we integrate on half a hemisphere...
				Albedo *= INVPI;	// Since we forgot that in the main loop

				_Color = (1.0 - _UV.y < 0.8 * Albedo ? 1 : 0) * float3( 1, 0, 0 );

				if ( _UV.x < 0.01 )
					_Color = Roughness;
			}
		}
	}
}

 * /


/*

		struct WardContext
		{
			float3	anisoTangentDivRoughness;
			float3	anisoBitangentDivRoughness;
			float	specularNormalization;
			float	isotropicRoughness;				// Original normalized isotropic roughness
//			float	diffuseRoughness;				// ARKANE: bmayaux (2013-10-14) Disney diffuse roughness Fresnel term
		
			// Computes the Ward normal distribution
			//	_wsNormal, surface normal
			//	_wsToLight, world space light vector
			//	_wsView, world space view vector
			//	
			float	ComputeWardTerm( float3 _wsNormal, float3 _wsToLight, float3 _wsView )
			{
				float3	Half = _wsToLight + _wsView; 
//				Half = normalize(Half); // not normalized on purpose, HdotH would be 1 if normalized, nonsense
			
				float	HdotN = dot( Half, _wsNormal );
						HdotN = max( 1e-4f, HdotN );
				float	invHdotN_2 = 1.0 / square( HdotN );
				float	invHdotN_4 = square( invHdotN_2 );
			
				float	HdotT = dot( Half, anisoTangentDivRoughness );
				float	HdotB = dot( Half, anisoBitangentDivRoughness );
				float	HdotH = dot( Half, Half );
			
				float	exponent = -invHdotN_2 * (square( HdotT ) + square( HdotB ));

 				return specularNormalization * exp( exponent ) * HdotH * invHdotN_4;
			}
		};

		void	CreateWardContext( out WardContext wardContext, float _Roughness, float _Anisotropy, float _AnisotropyAngle, float3 _Tangent, float3 _BiTangent )
		{
			// Tweak roughness so the user feels it's a linear parameter
			float	Roughness = _Roughness * _Roughness;	// Roughness squared seems to give a nice linear feel...
															// People at Disney seem to agree with me! (cf ยง5.4 http://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v2.pdf)

			// Keep an average normalized roughness value for other people who require it (e.g. IBL)
			wardContext.isotropicRoughness = Roughness;

			// Build anisotropic roughness along tangent/bitangent
			float2	anisotropicRoughness = float2( Roughness, Roughness * saturate( 1.0 - _Anisotropy ) );

			anisotropicRoughness = max( 0.01, anisotropicRoughness );	// Make sure we don't go below 0.01 otherwise specularity is unnatural for our poor lights (only IBL with many samples would solve that!)

			// Tangent/Ax, Bitangent/Ay
			float2	sinCosAnisotropy;
			sincos( _AnisotropyAngle, sinCosAnisotropy.x, sinCosAnisotropy.y );

			float2	invRoughness = 1.0 / (1e-5 + anisotropicRoughness);
			wardContext.anisoTangentDivRoughness = (sinCosAnisotropy.y * _Tangent + sinCosAnisotropy.x * _BiTangent) * invRoughness.x;
			wardContext.anisoBitangentDivRoughness = (sinCosAnisotropy.y * _BiTangent - sinCosAnisotropy.x * _Tangent) * invRoughness.y;

			wardContext.specularNormalization = INVPI * invRoughness.x * invRoughness.y;

// ARKANE: bmayaux (2014-02-05) Sheen is not tied to roughness anymore (for better or for worse?) so it doesn't need to be tied to Ward anymore either!
// 			// ARKANE: bmayaux (2013-10-14) Disney diffuse roughness Fresnel term
// 			// Diffuse roughness starts increasing for ward roughness > 0.35 and reaches 1 for ward roughness = 0.85
// 			//	this to make sure only very diffuse and rough objects have a sheen...
// //			wardContext.diffuseRoughness = _Sheen * saturate( 2.0 * _Roughness - 0.7 );
// 			wardContext.diffuseRoughness = _Sheen;	// Use direct sheen value, at the risk of making it strange on smooth materials...
		}

*/

		#endregion

		#region Primitives

		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 );
			}
		}
Example #7
0
        private void BuildQuad()
        {
            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 );
        }