// STATIC: "BASETEXTURE" "0..1"
// STATIC: "CUBEMAP" "0..1"
// STATIC: "DIFFUSELIGHTING" "0..1"
// STATIC: "SELFILLUM" "0..1"
// STATIC: "NORMALMAPALPHAENVMAPMASK" "0..1"
// STATIC: "HALFLAMBERT" "0..1"
// STATIC: "FLASHLIGHT" "0..1"
// DYNAMIC: "LIGHT_COMBO" "0..21"
// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1"
// DYNAMIC: "FOGTYPE" "0..2"
// DYNAMIC: "FLASHLIGHTDEPTH" "0..0"
// This is because we don't support static lighting and bumpmapping
// SKIP: ( $LIGHT_COMBO == 1 || $LIGHT_COMBO > 11 )
// We don't use light combos when doing the flashlight, so force it to zero when using the flashlight.
// SKIP ( $FLASHLIGHT != 0 ) && ( $LIGHT_COMBO != 0 )
// We skip this because this combo blows ps_2_0 program length.
// SKIP: $CUBEMAP && $SELFILLUM && $WRITEWATERFOGTODESTALPHA
#include "common_vertexlitgeneric_dx9.h"
const HALF4 g_EnvmapTint : register( c0 );
const HALF4 g_DiffuseModulation : register( c1 );
#if !FLASHLIGHT
const HALF3 g_EnvmapContrast : register( c2 );
const HALF3 g_EnvmapSaturation : register( c3 );
#endif
const HALF4 g_SelfIllumTint : register( c4 );
const float3 cAmbientCube[6] : register( c5 );
// 3 register each - 6 register total
PixelShaderLightInfo cLightInfo[2] : register( c13 ); // through c18
const HALF4 g_WaterFogColor : register( c19 );
const HALF3 g_EyePos : register( c20 );
const HALF4 g_FogParams : register( c21 );
#define g_WaterZ g_FogParams.y
#define g_FogOORange g_FogParams.w
const float4 g_FlashlightAttenuationFactors : register( c22 );
const HALF3 g_FlashlightPos : register( c23 );
const float4x4 g_FlashlightWorldToTexture : register( c24 ); // through c27
static const int g_LightCombo = LIGHT_COMBO;
static const int g_StaticLightType = g_StaticLightTypeArray[g_LightCombo];
static const int g_AmbientLightType = g_AmbientLightTypeArray[g_LightCombo];
static const int g_LocalLightType0 = g_LocalLightType0Array[g_LightCombo];
static const int g_LocalLightType1 = g_LocalLightType1Array[g_LightCombo];
sampler BaseTextureSampler : register( s0 );
sampler EnvmapSampler : register( s1 );
sampler BumpmapSampler : register( s3 );
sampler EnvmapMaskSampler : register( s4 );
sampler NormalizeSampler : register( s5 );
sampler FlashlightSampler : register( s7 );
struct PS_INPUT
{
HALF4 baseTexCoord2_tangentSpaceVertToEyeVectorXY : TEXCOORD0;
// bump mapping and a separate envmap mask texture are mutually exclusive.
float3 color2 : TEXCOORD1;
float3 color1 : TEXCOORD2;
float4 worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ : TEXCOORD3;
float3x3 tangentSpaceTranspose : TEXCOORD4;
float4 worldPos_projPosZ : TEXCOORD7;
float4 fogFactorW : COLOR1;
};
HDR_PS_OUTPUT main( PS_INPUT i ) : COLOR
{
bool bBaseTexture = BASETEXTURE ? true : false;
bool bCubemap = CUBEMAP ? true : false;
bool bDiffuseLighting = DIFFUSELIGHTING ? true : false;
bool bSelfIllum = SELFILLUM ? true : false;
bool bNormalMapAlphaEnvmapMask = NORMALMAPALPHAENVMAPMASK ? true : false;
bool bHalfLambert = HALFLAMBERT ? true : false;
bool bFlashlight = (FLASHLIGHT!=0) ? true : false;
HALF4 baseColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f );
if( bBaseTexture )
{
baseColor = tex2D( BaseTextureSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy );
}
HALF3 specularFactor = 1.0f;
HALF4 normalTexel = tex2D( BumpmapSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy );
HALF3 tangentSpaceNormal = 2.0f * normalTexel - 1.0f;
if( bNormalMapAlphaEnvmapMask )
{
specularFactor = normalTexel.a;
}
HALF3 diffuseLighting = HALF3( 1.0f, 1.0f, 1.0f );
if( bDiffuseLighting )
{
float3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal );
worldSpaceNormal = NormalizeWithCubemap( NormalizeSampler, worldSpaceNormal );
float3 staticLightingColor = float3( 0.0f, 0.0f, 0.0f );
diffuseLighting = PixelShaderDoLighting( i.worldPos_projPosZ.xyz, worldSpaceNormal,
staticLightingColor, g_StaticLightType,
g_AmbientLightType, g_LocalLightType0,
g_LocalLightType1, 1.0f, i.color1,
i.color2, cAmbientCube, NormalizeSampler, cLightInfo, bHalfLambert );
}
HALF3 albedo = HALF3( 1.0f, 1.0f, 1.0f );
HALF alpha = 1.0f;
if( bBaseTexture )
{
albedo *= baseColor;
if ( !bSelfIllum )
{
alpha *= baseColor.a;
}
}
// If we only have specularity, assume that we want a black diffuse component, and
// get alpha from the envmapmask
if( !bBaseTexture && bCubemap )
{
diffuseLighting = HALF3( 0.0f, 0.0f, 0.0f );
if( bNormalMapAlphaEnvmapMask )
{
alpha *= specularFactor;
}
}
#if FLASHLIGHT
if( bFlashlight )
{
bool bDoShadow = (FLASHLIGHTDEPTH==1)?1:0;
float3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal );
diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos_projPosZ.xyz, worldSpaceNormal,
g_FlashlightWorldToTexture, g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w,
FlashlightSampler, EnvmapMaskSampler, bDoShadow );
}
#endif
// FIXME: This could be done per vertex!
diffuseLighting *= g_DiffuseModulation.rgb;
alpha *= g_DiffuseModulation.a;
HALF3 diffuseComponent = albedo * diffuseLighting;
if( bSelfIllum )
{
HALF3 selfIllumComponent = g_SelfIllumTint * albedo;
diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a );
}
HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f );
#if !FLASHLIGHT
if( bCubemap )
{
// If we've *only* specified a cubemap, blow off the diffuse component
if ( !bBaseTexture && !bDiffuseLighting && !bSelfIllum && !bFlashlight )
{
diffuseComponent = HALF3( 0.0f, 0.0f, 0.0f );
}
HALF3 worldSpaceNormal = mul( i.tangentSpaceTranspose, tangentSpaceNormal );
HALF3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, i.worldVertToEyeVectorXYZ_tangentSpaceVertToEyeVectorZ.xyz );
specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect );
specularLighting *= specularFactor;
specularLighting *= g_EnvmapTint;
HALF3 specularLightingSquared = specularLighting * specularLighting;
specularLighting = lerp( specularLighting, specularLightingSquared, g_EnvmapContrast );
HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) );
specularLighting = lerp( greyScale, specularLighting, g_EnvmapSaturation );
}
#endif
HALF3 result = diffuseComponent + specularLighting;
#if FOGTYPE == 2
float fogFactor = CalcWaterFogAlpha( g_WaterZ, g_EyePos.z, i.worldPos_projPosZ.z, i.worldPos_projPosZ.w, g_FogOORange );
result = lerp( result, g_WaterFogColor.xyz, fogFactor );
# if WRITEWATERFOGTODESTALPHA
alpha = fogFactor;
# endif
#endif
//FIXME: need to take dowaterfog into consideration
return LinearColorToHDROutput( float4( result, alpha ), i.fogFactorW.w );
}