summaryrefslogtreecommitdiff
path: root/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h
diff options
context:
space:
mode:
Diffstat (limited to 'materialsystem/stdshaders/common_vertexlitgeneric_dx9.h')
-rw-r--r--materialsystem/stdshaders/common_vertexlitgeneric_dx9.h423
1 files changed, 423 insertions, 0 deletions
diff --git a/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h b/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h
new file mode 100644
index 0000000..2eb7bb3
--- /dev/null
+++ b/materialsystem/stdshaders/common_vertexlitgeneric_dx9.h
@@ -0,0 +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_