diff options
Diffstat (limited to 'mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h')
| -rw-r--r-- | mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h | 846 |
1 files changed, 423 insertions, 423 deletions
diff --git a/mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h b/mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h index 66cc642a..2eb7bb3c 100644 --- a/mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h +++ b/mp/src/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h @@ -1,423 +1,423 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-#ifndef COMMON_VERTEXLITGENERIC_DX9_H_
-#define COMMON_VERTEXLITGENERIC_DX9_H_
-
-#include "common_ps_fxc.h"
-
-// We store four light colors and positions in an
-// array of three of these structures like so:
-//
-// x y z w
-// +------+------+------+------+
-// | L0.rgb | |
-// +------+------+------+ |
-// | L0.pos | L3 |
-// +------+------+------+ rgb |
-// | L1.rgb | |
-// +------+------+------+------+
-// | L1.pos | |
-// +------+------+------+ |
-// | L2.rgb | L3 |
-// +------+------+------+ pos |
-// | L2.pos | |
-// +------+------+------+------+
-//
-struct PixelShaderLightInfo
-{
- float4 color;
- float4 pos;
-};
-
-#define cOverbright 2.0f
-#define cOOOverbright 0.5f
-
-#define LIGHTTYPE_NONE 0
-#define LIGHTTYPE_SPOT 1
-#define LIGHTTYPE_POINT 2
-#define LIGHTTYPE_DIRECTIONAL 3
-
-// Better suited to Pixel shader models, 11 instructions in pixel shader
-// ... actually, now only 9: mul, cmp, cmp, mul, mad, mad, mad, mad, mad
-float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )
-{
- float3 linearColor, nSquared = worldNormal * worldNormal;
- float3 isNegative = ( worldNormal >= 0.0 ) ? 0 : nSquared;
- float3 isPositive = ( worldNormal >= 0.0 ) ? nSquared : 0;
- linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] +
- isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] +
- isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5];
- return linearColor;
-}
-
-// Better suited to Vertex shader models
-// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad)
-float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )
-{
- float3 nSquared = worldNormal * worldNormal;
- int3 isNegative = ( worldNormal < 0.0 );
- float3 linearColor;
- linearColor = nSquared.x * cAmbientCube[isNegative.x] +
- nSquared.y * cAmbientCube[isNegative.y+2] +
- nSquared.z * cAmbientCube[isNegative.z+4];
- return linearColor;
-}
-
-float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )
-{
- // Vertex shader cases
-#ifdef SHADER_MODEL_VS_1_0
- return VertexShaderAmbientLight( worldNormal, cAmbientCube );
-#elif SHADER_MODEL_VS_1_1
- return VertexShaderAmbientLight( worldNormal, cAmbientCube );
-#elif SHADER_MODEL_VS_2_0
- return VertexShaderAmbientLight( worldNormal, cAmbientCube );
-#elif SHADER_MODEL_VS_3_0
- return VertexShaderAmbientLight( worldNormal, cAmbientCube );
-#else
- // Pixel shader case
- return PixelShaderAmbientLight( worldNormal, cAmbientCube );
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Compute scalar diffuse term with various optional tweaks such as
-// Half Lambert and ambient occlusion
-//-----------------------------------------------------------------------------
-float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir,
- const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
- const bool bDoLightingWarp, in sampler lightWarpSampler )
-{
- float fResult;
-
- float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range)
-
- if ( bHalfLambert )
- {
- fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range
-
- if ( !bDoLightingWarp )
- {
- fResult *= fResult; // Square
- }
- }
- else
- {
- fResult = saturate( NDotL ); // Saturate pure Lambertian term
- }
-
- if ( bDoAmbientOcclusion )
- {
- // Raise to higher powers for darker AO values
-// float fAOPower = lerp( 4.0f, 1.0f, fAmbientOcclusion );
-// result *= pow( NDotL * 0.5 + 0.5, fAOPower );
- fResult *= fAmbientOcclusion;
- }
-
- float3 fOut = float3( fResult, fResult, fResult );
- if ( bDoLightingWarp )
- {
- fOut = 2.0f * tex1D( lightWarpSampler, fResult );
- }
-
- return fOut;
-}
-
-float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal,
- in sampler NormalizeSampler,
- const float3 vPosition, const float3 vColor, const bool bHalfLambert,
- const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
- const bool bDoLightingWarp, in sampler lightWarpSampler )
-{
-#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))
- float3 lightDir = normalize( vPosition - worldPos );
-#else
- float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos );
-#endif
- return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, bDoAmbientOcclusion, fAmbientOcclusion, bDoLightingWarp, lightWarpSampler );
-}
-
-float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex )
-{
- if ( nLightIndex == 3 )
- {
- // Unpack light 3 from w components...
- float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );
- return normalize( vLight3Pos - worldPos );
- }
- else
- {
- return normalize( cLightInfo[nLightIndex].pos - worldPos );
- }
-}
-
-float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex )
-{
- if ( nLightIndex == 3 )
- {
- // Unpack light 3 from w components...
- return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );
- }
- else
- {
- return cLightInfo[nLightIndex].color.rgb;
- }
-}
-
-
-void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent,
- const float3 vEyeDir, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
- const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel,
- const float3 color, const bool bDoRimLighting, const float fRimExponent,
-
- // Outputs
- out float3 specularLighting, out float3 rimLighting )
-{
- rimLighting = float3(0.0f, 0.0f, 0.0f);
-
- //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal
- float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal
- float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?)
- specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent
-
- // Optionally warp as function of scalar specular and fresnel
- if ( bDoSpecularWarp )
- specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }
-
- specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L
- specularLighting *= color; // Modulate with light color
-
- if ( bDoAmbientOcclusion ) // Optionally modulate with ambient occlusion
- specularLighting *= fAmbientOcclusion;
-
- if ( bDoRimLighting ) // Optionally do rim lighting
- {
- rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent
- rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L
- rimLighting *= color; // Modulate with light color
- }
-}
-
-// Traditional fresnel term approximation
-float Fresnel( const float3 vNormal, const float3 vEyeDir )
-{
- float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term
- return fresnel * fresnel; // Square for a more subtle look
-}
-
-// Traditional fresnel term approximation which uses 4th power (square twice)
-float Fresnel4( const float3 vNormal, const float3 vEyeDir )
-{
- float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term
- fresnel = fresnel * fresnel; // Square
- return fresnel * fresnel; // Square again for a more subtle look
-}
-
-
-//
-// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function
-// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between
-// low and mid while the 0.5 to 1 range blends between mid and high
-//
-// |
-// | . M . . . H
-// | .
-// L
-// |
-// +----------------
-// 0 1
-//
-float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges )
-{
- //float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel
- //if ( f > 0.5f )
- // result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values
- //else
- // result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values
-
- // note: vRanges is now encoded as ((mid-min)*2, mid, (max-mid)*2) to optimize math
- float f = saturate( 1 - dot( vNormal, vEyeDir ) );
- f = f*f - 0.5;
- return vRanges.y + (f >= 0.0 ? vRanges.z : vRanges.x) * f;
-}
-
-void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir,
- const float fAtten, const float3 vLightColor, const float3 vLightDir,
- const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
- const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,
- const bool bDoRimLighting, const float fRimExponent,
-
- // Outputs
- out float3 specularLighting, out float3 rimLighting )
-{
- // Compute Specular and rim terms
- SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent,
- vEyeDir, bDoAmbientOcclusion, fAmbientOcclusion,
- bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten,
- bDoRimLighting, fRimExponent, specularLighting, rimLighting );
-}
-
-float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal,
- const float3 staticLightingColor, const bool bStaticLight,
- const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],
- in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],
- const bool bHalfLambert, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
- const bool bDoLightingWarp, in sampler lightWarpSampler )
-{
- float3 linearColor = 0.0f;
-
- if ( bStaticLight )
- {
- // The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright
- // need to get it into
- // linear space so that we can do adds.
- linearColor += GammaToLinear( staticLightingColor * cOverbright );
- }
-
- if ( bAmbientLight )
- {
- float3 ambient = AmbientLight( worldNormal, cAmbientCube );
-
- if ( bDoAmbientOcclusion )
- ambient *= fAmbientOcclusion * fAmbientOcclusion; // Note squaring...
-
- linearColor += ambient;
- }
-
- if ( nNumLights > 0 )
- {
- linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler,
- cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert,
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoLightingWarp, lightWarpSampler );
- if ( nNumLights > 1 )
- {
- linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler,
- cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert,
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoLightingWarp, lightWarpSampler );
- if ( nNumLights > 2 )
- {
- linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler,
- cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert,
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoLightingWarp, lightWarpSampler );
- if ( nNumLights > 3 )
- {
- // Unpack the 4th light's data from tight constant packing
- float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );
- float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );
- linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler,
- vLight3Pos, vLight3Color, bHalfLambert,
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoLightingWarp, lightWarpSampler );
- }
- }
- }
- }
-
- return linearColor;
-}
-
-void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir,
- const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3],
- const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
- const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,
- const bool bDoRimLighting, const float fRimExponent,
-
- // Outputs
- out float3 specularLighting, out float3 rimLighting )
-{
- specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f );
- float3 localSpecularTerm, localRimTerm;
-
- if( nNumLights > 0 )
- {
- PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
- lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ),
- PixelShaderGetLightVector( worldPos, cLightInfo, 0 ),
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoSpecularWarp, specularWarpSampler, fFresnel,
- bDoRimLighting, fRimExponent,
- localSpecularTerm, localRimTerm );
-
- specularLighting += localSpecularTerm; // Accumulate specular and rim terms
- rimLighting += localRimTerm;
- }
-
- if( nNumLights > 1 )
- {
- PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
- lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ),
- PixelShaderGetLightVector( worldPos, cLightInfo, 1 ),
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoSpecularWarp, specularWarpSampler, fFresnel,
- bDoRimLighting, fRimExponent,
- localSpecularTerm, localRimTerm );
-
- specularLighting += localSpecularTerm; // Accumulate specular and rim terms
- rimLighting += localRimTerm;
- }
-
-
- if( nNumLights > 2 )
- {
- PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
- lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ),
- PixelShaderGetLightVector( worldPos, cLightInfo, 2 ),
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoSpecularWarp, specularWarpSampler, fFresnel,
- bDoRimLighting, fRimExponent,
- localSpecularTerm, localRimTerm );
-
- specularLighting += localSpecularTerm; // Accumulate specular and rim terms
- rimLighting += localRimTerm;
- }
-
- if( nNumLights > 3 )
- {
- PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
- lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ),
- PixelShaderGetLightVector( worldPos, cLightInfo, 3 ),
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoSpecularWarp, specularWarpSampler, fFresnel,
- bDoRimLighting, fRimExponent,
- localSpecularTerm, localRimTerm );
-
- specularLighting += localSpecularTerm; // Accumulate specular and rim terms
- rimLighting += localRimTerm;
- }
-
-}
-
-float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel )
-{
- float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal
-
- return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube );
-}
-
-// Called directly by newer shaders or through the following wrapper for older shaders
-float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal,
- const float3 staticLightingColor, const bool bStaticLight,
- const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],
- in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],
- const bool bHalfLambert,
-
- // New optional/experimental parameters
- const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
- const bool bDoLightingWarp, in sampler lightWarpSampler )
-{
- float3 linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor,
- bStaticLight, bAmbientLight, lightAtten,
- cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert,
- bDoAmbientOcclusion, fAmbientOcclusion,
- bDoLightingWarp, lightWarpSampler );
-
- // go ahead and clamp to the linear space equivalent of overbright 2 so that we match
- // everything else.
-// linearColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) );
-
- return linearColor;
-}
-
-#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_
+//========= Copyright Valve Corporation, All rights reserved. ============// +#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ +#define COMMON_VERTEXLITGENERIC_DX9_H_ + +#include "common_ps_fxc.h" + +// We store four light colors and positions in an +// array of three of these structures like so: +// +// x y z w +// +------+------+------+------+ +// | L0.rgb | | +// +------+------+------+ | +// | L0.pos | L3 | +// +------+------+------+ rgb | +// | L1.rgb | | +// +------+------+------+------+ +// | L1.pos | | +// +------+------+------+ | +// | L2.rgb | L3 | +// +------+------+------+ pos | +// | L2.pos | | +// +------+------+------+------+ +// +struct PixelShaderLightInfo +{ + float4 color; + float4 pos; +}; + +#define cOverbright 2.0f +#define cOOOverbright 0.5f + +#define LIGHTTYPE_NONE 0 +#define LIGHTTYPE_SPOT 1 +#define LIGHTTYPE_POINT 2 +#define LIGHTTYPE_DIRECTIONAL 3 + +// Better suited to Pixel shader models, 11 instructions in pixel shader +// ... actually, now only 9: mul, cmp, cmp, mul, mad, mad, mad, mad, mad +float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 linearColor, nSquared = worldNormal * worldNormal; + float3 isNegative = ( worldNormal >= 0.0 ) ? 0 : nSquared; + float3 isPositive = ( worldNormal >= 0.0 ) ? nSquared : 0; + linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] + + isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] + + isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5]; + return linearColor; +} + +// Better suited to Vertex shader models +// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad) +float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + float3 nSquared = worldNormal * worldNormal; + int3 isNegative = ( worldNormal < 0.0 ); + float3 linearColor; + linearColor = nSquared.x * cAmbientCube[isNegative.x] + + nSquared.y * cAmbientCube[isNegative.y+2] + + nSquared.z * cAmbientCube[isNegative.z+4]; + return linearColor; +} + +float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] ) +{ + // Vertex shader cases +#ifdef SHADER_MODEL_VS_1_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_1_1 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_2_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#elif SHADER_MODEL_VS_3_0 + return VertexShaderAmbientLight( worldNormal, cAmbientCube ); +#else + // Pixel shader case + return PixelShaderAmbientLight( worldNormal, cAmbientCube ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Compute scalar diffuse term with various optional tweaks such as +// Half Lambert and ambient occlusion +//----------------------------------------------------------------------------- +float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float fResult; + + float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range) + + if ( bHalfLambert ) + { + fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range + + if ( !bDoLightingWarp ) + { + fResult *= fResult; // Square + } + } + else + { + fResult = saturate( NDotL ); // Saturate pure Lambertian term + } + + if ( bDoAmbientOcclusion ) + { + // Raise to higher powers for darker AO values +// float fAOPower = lerp( 4.0f, 1.0f, fAmbientOcclusion ); +// result *= pow( NDotL * 0.5 + 0.5, fAOPower ); + fResult *= fAmbientOcclusion; + } + + float3 fOut = float3( fResult, fResult, fResult ); + if ( bDoLightingWarp ) + { + fOut = 2.0f * tex1D( lightWarpSampler, fResult ); + } + + return fOut; +} + +float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal, + in sampler NormalizeSampler, + const float3 vPosition, const float3 vColor, const bool bHalfLambert, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ +#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) + float3 lightDir = normalize( vPosition - worldPos ); +#else + float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos ); +#endif + return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, bDoAmbientOcclusion, fAmbientOcclusion, bDoLightingWarp, lightWarpSampler ); +} + +float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + return normalize( vLight3Pos - worldPos ); + } + else + { + return normalize( cLightInfo[nLightIndex].pos - worldPos ); + } +} + +float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex ) +{ + if ( nLightIndex == 3 ) + { + // Unpack light 3 from w components... + return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + } + else + { + return cLightInfo[nLightIndex].color.rgb; + } +} + + +void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, + const float3 vEyeDir, const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel, + const float3 color, const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + rimLighting = float3(0.0f, 0.0f, 0.0f); + + //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal + float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal + float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?) + specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent + + // Optionally warp as function of scalar specular and fresnel + if ( bDoSpecularWarp ) + specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel } + + specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + specularLighting *= color; // Modulate with light color + + if ( bDoAmbientOcclusion ) // Optionally modulate with ambient occlusion + specularLighting *= fAmbientOcclusion; + + if ( bDoRimLighting ) // Optionally do rim lighting + { + rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent + rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L + rimLighting *= color; // Modulate with light color + } +} + +// Traditional fresnel term approximation +float Fresnel( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + return fresnel * fresnel; // Square for a more subtle look +} + +// Traditional fresnel term approximation which uses 4th power (square twice) +float Fresnel4( const float3 vNormal, const float3 vEyeDir ) +{ + float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term + fresnel = fresnel * fresnel; // Square + return fresnel * fresnel; // Square again for a more subtle look +} + + +// +// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function +// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between +// low and mid while the 0.5 to 1 range blends between mid and high +// +// | +// | . M . . . H +// | . +// L +// | +// +---------------- +// 0 1 +// +float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges ) +{ + //float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel + //if ( f > 0.5f ) + // result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values + //else + // result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values + + // note: vRanges is now encoded as ((mid-min)*2, mid, (max-mid)*2) to optimize math + float f = saturate( 1 - dot( vNormal, vEyeDir ) ); + f = f*f - 0.5; + return vRanges.y + (f >= 0.0 ? vRanges.z : vRanges.x) * f; +} + +void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float fAtten, const float3 vLightColor, const float3 vLightDir, + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + // Compute Specular and rim terms + SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent, + vEyeDir, bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten, + bDoRimLighting, fRimExponent, specularLighting, rimLighting ); +} + +float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bHalfLambert, const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 linearColor = 0.0f; + + if ( bStaticLight ) + { + // The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright + // need to get it into + // linear space so that we can do adds. + linearColor += GammaToLinear( staticLightingColor * cOverbright ); + } + + if ( bAmbientLight ) + { + float3 ambient = AmbientLight( worldNormal, cAmbientCube ); + + if ( bDoAmbientOcclusion ) + ambient *= fAmbientOcclusion * fAmbientOcclusion; // Note squaring... + + linearColor += ambient; + } + + if ( nNumLights > 0 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler, + cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 1 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler, + cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 2 ) + { + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler, + cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + if ( nNumLights > 3 ) + { + // Unpack the 4th light's data from tight constant packing + float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w ); + float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w ); + linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler, + vLight3Pos, vLight3Color, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + } + } + } + } + + return linearColor; +} + +void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir, + const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel, + const bool bDoRimLighting, const float fRimExponent, + + // Outputs + out float3 specularLighting, out float3 rimLighting ) +{ + specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f ); + float3 localSpecularTerm, localRimTerm; + + if( nNumLights > 0 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 0 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 1 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 1 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + + if( nNumLights > 2 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 2 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + + if( nNumLights > 3 ) + { + PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir, + lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ), + PixelShaderGetLightVector( worldPos, cLightInfo, 3 ), + bDoAmbientOcclusion, fAmbientOcclusion, + bDoSpecularWarp, specularWarpSampler, fFresnel, + bDoRimLighting, fRimExponent, + localSpecularTerm, localRimTerm ); + + specularLighting += localSpecularTerm; // Accumulate specular and rim terms + rimLighting += localRimTerm; + } + +} + +float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel ) +{ + float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal + + return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube ); +} + +// Called directly by newer shaders or through the following wrapper for older shaders +float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal, + const float3 staticLightingColor, const bool bStaticLight, + const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6], + in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3], + const bool bHalfLambert, + + // New optional/experimental parameters + const bool bDoAmbientOcclusion, const float fAmbientOcclusion, + const bool bDoLightingWarp, in sampler lightWarpSampler ) +{ + float3 linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor, + bStaticLight, bAmbientLight, lightAtten, + cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert, + bDoAmbientOcclusion, fAmbientOcclusion, + bDoLightingWarp, lightWarpSampler ); + + // go ahead and clamp to the linear space equivalent of overbright 2 so that we match + // everything else. +// linearColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) ); + + return linearColor; +} + +#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_ |