diff --git a/include_files/depthpass.lua b/include_files/depthpass.lua index 72da0ad..812a0af 100644 --- a/include_files/depthpass.lua +++ b/include_files/depthpass.lua @@ -1,4 +1,3 @@ - local depthWriteMat = CreateMaterial( "egsm/depthmat", "DepthWrite", { ["$no_fullbright"] = "1", ["$color_depth"] = "1", @@ -63,10 +62,8 @@ local function PreDrawEffectsHK() BeginDepthPass() rClear(0,0,0,0) - PopRenderTarget() rClear(0,0,0,0) - PopRenderTarget() rClear(0,0,0,0) @@ -106,4 +103,4 @@ function shaderlib.__INIT() render.DrawBox( zero_vec, angle_zero, max, min, color_white ) cam.End3D() end) -end +end \ No newline at end of file diff --git a/source/common_flashlight_fxc.h.inc b/source/common_flashlight_fxc.h.inc index f5ac6c1..21e07ce 100644 --- a/source/common_flashlight_fxc.h.inc +++ b/source/common_flashlight_fxc.h.inc @@ -1 +1 @@ -const char common_flashlight_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""//\n""\n""// Purpose: Common pixel shader code specific to flashlights\n""\n""//\n""\n""// $NoKeywords: $\n""\n""//\n""\n""//=============================================================================//\n""\n""#ifndef COMMON_FLASHLIGHT_FXC_H_\n""\n""#define COMMON_FLASHLIGHT_FXC_H_\n""\n""\n""#include \"common_ps_fxc.h\"\n""\n""\n""\n""// JasonM - TODO: remove this simpleton version\n""\n""float DoShadow( sampler DepthSampler, float4 texCoord )\n""\n""{\n""\n"" const float g_flShadowBias = 0.0005f;\n""\n"" float2 uoffset = float2( 0.5f/512.f, 0.0f );\n""\n"" float2 voffset = float2( 0.0f, 0.5f/512.f );\n""\n"" float3 projTexCoord = texCoord.xyz / texCoord.w;\n""\n"" float4 flashlightDepth = float4( tex2D( DepthSampler, projTexCoord + uoffset + voffset ).x,\n""\n"" tex2D( DepthSampler, projTexCoord + uoffset - voffset ).x,\n""\n"" tex2D( DepthSampler, projTexCoord - uoffset + voffset ).x,\n""\n"" tex2D( DepthSampler, projTexCoord - uoffset - voffset ).x );\n""\n""\n""# if ( defined( REVERSE_DEPTH_ON_X360 ) )\n""\n"" {\n""\n"" flashlightDepth = 1.0f - flashlightDepth;\n""\n"" }\n""\n""# endif\n""\n""\n"" float shadowed = 0.0f;\n""\n"" float z = texCoord.z/texCoord.w;\n""\n"" float4 dz = float4(z,z,z,z) - (flashlightDepth + float4( g_flShadowBias, g_flShadowBias, g_flShadowBias, g_flShadowBias));\n""\n"" float4 shadow = float4(0.25f,0.25f,0.25f,0.25f);\n""\n""\n"" if( dz.x <= 0.0f )\n""\n"" shadowed += shadow.x;\n""\n"" if( dz.y <= 0.0f )\n""\n"" shadowed += shadow.y;\n""\n"" if( dz.z <= 0.0f )\n""\n"" shadowed += shadow.z;\n""\n"" if( dz.w <= 0.0f )\n""\n"" shadowed += shadow.w;\n""\n""\n"" return shadowed;\n""\n""}\n""\n""\n""\n""float DoShadowNvidiaRAWZOneTap( sampler DepthSampler, const float4 shadowMapPos )\n""\n""{\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n""\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n""\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n""\n"" float fDepth = dot(tex2D(DepthSampler, shadowMapCenter).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n""\n""\n"" return fDepth > objDepth;\n""\n""}\n""\n""\n""\n""float DoShadowNvidiaRAWZ( sampler DepthSampler, const float4 shadowMapPos )\n""\n""{\n""\n"" float fE = 1.0f / 512.0f; // Epsilon\n""\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n""\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n""\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n""\n"" float4 vDepths;\n""\n"" vDepths.x = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n""\n"" vDepths.y = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n""\n"" vDepths.z = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n""\n"" vDepths.w = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n""\n""\n"" return dot(vDepths > objDepth.xxxx, float4(0.25, 0.25, 0.25, 0.25));\n""\n""}\n""\n""\n""\n""float DoShadowNvidiaCheap( sampler DepthSampler, const float4 shadowMapPos )\n""\n""{\n""\n"" float fTexelEpsilon = 1.0f / 1024.0f;\n""\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n""\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n""\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n""\n"" float4 vTaps;\n""\n"" vTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x;\n""\n"" vTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x;\n""\n"" vTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x;\n""\n"" vTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x;\n""\n""\n"" return dot(vTaps, float4(0.25, 0.25, 0.25, 0.25));\n""\n""}\n""\n""\n""float DoShadowNvidiaPCF3x3Box( sampler DepthSampler, const float4 shadowMapPos )\n""\n""{\n""\n"" float fTexelEpsilon = 1.0f / 1024.0f;\n""\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n""\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n""\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n""\n"" float4 vOneTaps;\n""\n"" vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x;\n""\n"" vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x;\n""\n"" vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x;\n""\n"" vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x;\n""\n"" float flOneTaps = dot( vOneTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f));\n""\n""\n"" float4 vTwoTaps;\n""\n"" vTwoTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, 0 ), objDepth, 1 ) ).x;\n""\n"" vTwoTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, 0 ), objDepth, 1 ) ).x;\n""\n"" vTwoTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x;\n""\n"" vTwoTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x;\n""\n"" float flTwoTaps = dot( vTwoTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f));\n""\n""\n"" float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (1.0f / 9.0f);\n""\n""\n"" // Sum all 9 Taps\n""\n"" return flOneTaps + flTwoTaps + flCenterTap;\n""\n""}\n""\n""\n""\n""//\n""\n""// 1 4 7 4 1\n""\n""// 4 20 33 20 4\n""\n""// 7 33 55 33 7\n""\n""// 4 20 33 20 4\n""\n""// 1 4 7 4 1\n""\n""//\n""\n""float DoShadowNvidiaPCF5x5Gaussian( sampler DepthSampler, const float4 shadowMapPos )\n""\n""{\n""\n"" float fEpsilon = 1.0f / 512.0f;\n""\n"" float fTwoEpsilon = 2.0f * fEpsilon;\n""\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n""\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n""\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n""\n"" float4 vOneTaps;\n""\n"" vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" float flOneTaps = dot( vOneTaps, float4(1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f));\n""\n""\n"" float4 vSevenTaps;\n""\n"" vSevenTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, 0 ), objDepth, 1 ) ).x;\n""\n"" vSevenTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, 0 ), objDepth, 1 ) ).x;\n""\n"" vSevenTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vSevenTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" float flSevenTaps = dot( vSevenTaps, float4( 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f ) );\n""\n""\n"" float4 vFourTapsA, vFourTapsB;\n""\n"" vFourTapsA.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n""\n"" vFourTapsA.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vFourTapsA.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vFourTapsA.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n""\n"" vFourTapsB.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n""\n"" vFourTapsB.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vFourTapsB.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n""\n"" vFourTapsB.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n""\n"" float flFourTapsA = dot( vFourTapsA, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) );\n""\n"" float flFourTapsB = dot( vFourTapsB, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) );\n""\n""\n"" float4 v20Taps;\n""\n"" v20Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n""\n"" v20Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n""\n"" v20Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n""\n"" v20Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n""\n"" float fl20Taps = dot( v20Taps, float4(20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f));\n""\n""\n"" float4 v33Taps;\n""\n"" v33Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, 0 ), objDepth, 1 ) ).x;\n""\n"" v33Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, 0 ), objDepth, 1 ) ).x;\n""\n"" v33Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x;\n""\n"" v33Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x;\n""\n"" float fl33Taps = dot( v33Taps, float4(33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f));\n""\n""\n"" float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (55.0f / 331.0f);\n""\n""\n"" // Sum all 25 Taps\n""\n"" return flOneTaps + flSevenTaps + +flFourTapsA + flFourTapsB + fl20Taps + fl33Taps + flCenterTap;\n""\n""}\n""\n""\n""\n""float DoShadowATICheap( sampler DepthSampler, const float4 shadowMapPos )\n""\n""{\n""\n"" float2 shadowMapCenter = shadowMapPos.xy/shadowMapPos.w;\n""\n"" float objDepth = shadowMapPos.z / shadowMapPos.w;\n""\n"" float fSampleDepth = tex2D( DepthSampler, shadowMapCenter ).x;\n""\n""\n"" objDepth = min( objDepth, 0.99999 ); //HACKHACK: On 360, surfaces at or past the far flashlight plane have an abrupt cutoff. This is temp until a smooth falloff is implemented\n""\n""\n"" return fSampleDepth > objDepth;\n""\n""}\n""\n""\n""\n""// Poisson disc, randomly rotated at different UVs\n""\n""float DoShadowPoisson16Sample( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks, bool bNvidiaHardwarePCF, bool bFetch4 )\n""\n""{\n""\n"" float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ),\n""\n"" float2( 0.8806f, 0.3430f ),\n""\n"" float2( -0.0041f, -0.6197f ),\n""\n"" float2( 0.0472f, 0.4964f ),\n""\n"" float2( -0.3730f, 0.0874f ),\n""\n"" float2( -0.9217f, -0.3177f ),\n""\n"" float2( -0.6289f, 0.7388f ),\n""\n"" float2( 0.5744f, -0.7741f ) };\n""\n""\n"" float flScaleOverMapSize = vShadowTweaks.x * 2; // Tweak parameters to shader\n""\n"" float2 vNoiseOffset = vShadowTweaks.zw;\n""\n"" float4 vLightDepths = 0, accum = 0.0f;\n""\n"" float2 rotOffset = 0;\n""\n""\n"" float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter\n""\n"" float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space\n""\n""\n"" // 2D Rotation Matrix setup\n""\n"" float3 RMatTop = 0, RMatBottom = 0;\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n""\n"" RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5) + vNoiseOffset) * 2.0 - 1.0;\n""\n"" RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple\n""\n""#endif\n""\n""\n"" RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution\n""\n"" RMatBottom *= flScaleOverMapSize;\n""\n""\n"" RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below\n""\n"" RMatBottom.z = shadowMapCenter.y;\n""\n"" \n""\n"" float fResult = 0.0f;\n""\n""\n"" if ( bNvidiaHardwarePCF )\n""\n"" {\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z;\n""\n"" vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z;\n""\n"" vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z;\n""\n"" vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z;\n""\n"" vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z;\n""\n"" vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z;\n""\n"" vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z;\n""\n"" vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z;\n""\n"" vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n""\n"" fResult = dot( vLightDepths, float4( 0.25, 0.25, 0.25, 0.25) );\n""\n"" }\n""\n"" else if ( bFetch4 )\n""\n"" {\n""\n""/*\n""\n""\n""TODO: Fix this contact hardening stuff\n""\n""\n"" float flNumCloserSamples = 1;\n""\n"" float flAccumulatedCloserSamples = objDepth;\n""\n"" float4 vBlockerDepths;\n""\n""\n"" // First, search for blockers\n""\n"" for( int j=0; j<8; j++ )\n""\n"" {\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[j].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[j].xy) + RMatBottom.z;\n""\n"" vBlockerDepths = tex2D( DepthSampler, rotOffset.xy );\n""\n""\n"" // Which samples are closer than the pixel we're rendering?\n""\n"" float4 vCloserSamples = (vBlockerDepths < objDepth.xxxx ); // Binary comparison results\n""\n"" flNumCloserSamples += dot( vCloserSamples, float4(1, 1, 1, 1) ); // How many samples are closer than receiver?\n""\n"" flAccumulatedCloserSamples += dot (vCloserSamples, vBlockerDepths ); // Total depths from samples closer than receiver\n""\n"" }\n""\n""\n"" float flBlockerDepth = flAccumulatedCloserSamples / flNumCloserSamples;\n""\n"" float flContactHardeningScale = (objDepth - flBlockerDepth) / flBlockerDepth;\n""\n""\n"" // Scale the kernel\n""\n"" RMatTop.xy *= flContactHardeningScale;\n""\n"" RMatBottom.xy *= flContactHardeningScale;\n""\n""*/\n""\n""\n"" for( int i=0; i<8; i++ )\n""\n"" {\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[i].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[i].xy) + RMatBottom.z;\n""\n"" vLightDepths = tex2D( DepthSampler, rotOffset.xy );\n""\n"" accum += (vLightDepths > objDepth.xxxx);\n""\n"" }\n""\n""\n"" fResult = dot( accum, float4( 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f) );\n""\n"" }\n""\n"" else // ATI vanilla hardware shadow mapping\n""\n"" {\n""\n"" for( int i=0; i<2; i++ )\n""\n"" {\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+0].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+0].xy) + RMatBottom.z;\n""\n"" vLightDepths.x = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+1].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+1].xy) + RMatBottom.z;\n""\n"" vLightDepths.y = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+2].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+2].xy) + RMatBottom.z;\n""\n"" vLightDepths.z = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+3].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+3].xy) + RMatBottom.z;\n""\n"" vLightDepths.w = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n""\n"" accum += (vLightDepths > objDepth.xxxx);\n""\n"" }\n""\n""\n"" fResult = dot( accum, float4( 0.125, 0.125, 0.125, 0.125) );\n""\n"" }\n""\n""\n"" return fResult;\n""\n""}\n""\n""\n""#if defined( _X360 )\n""\n""\n""// Poisson disc, randomly rotated at different UVs\n""\n""float DoShadow360Simple( sampler DepthSampler, const float3 vProjCoords )\n""\n""{\n""\n"" float fLOD;\n""\n"" float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter\n""\n"" float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space\n""\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n""\n"" objDepth = 1.0f - objDepth;\n""\n""#endif \n""\n""\n"" float4 vSampledDepths, vWeights;\n""\n""\n"" asm {\n""\n"" getCompTexLOD2D fLOD.x, shadowMapCenter.xy, DepthSampler, AnisoFilter=max16to1\n""\n"" setTexLOD fLOD.x\n""\n""\n"" tfetch2D vSampledDepths.x___, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths._x__, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths.__x_, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths.___x, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n""\n"" getWeights2D vWeights, shadowMapCenter.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true\n""\n"" };\n""\n""\n"" vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y );\n""\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n""\n"" float4 vCompare = (vSampledDepths < objDepth.xxxx);\n""\n""#else\n""\n"" float4 vCompare = (vSampledDepths > objDepth.xxxx);\n""\n""#endif\n""\n""\n"" return dot( vCompare, vWeights );\n""\n""}\n""\n""\n""\n""float Do360PCFFetch( sampler DepthSampler, float2 tc, float objDepth )\n""\n""{\n""\n"" float fLOD;\n""\n"" float4 vSampledDepths, vWeights;\n""\n""\n"" asm {\n""\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n""\n"" setTexLOD fLOD.x\n""\n""\n"" tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n""\n"" getWeights2D vWeights, tc.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true\n""\n"" };\n""\n""\n"" vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y );\n""\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n""\n"" float4 vCompare = (vSampledDepths < objDepth.xxxx);\n""\n""#else\n""\n"" float4 vCompare = (vSampledDepths > objDepth.xxxx);\n""\n""#endif\n""\n""\n"" return dot( vCompare, vWeights );\n""\n""}\n""\n""\n""\n""\n""float Do360NearestFetch( sampler DepthSampler, float2 tc, float objDepth )\n""\n""{\n""\n"" float fLOD;\n""\n"" float4 vSampledDepth;\n""\n""\n"" asm {\n""\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n""\n"" setTexLOD fLOD.x\n""\n""\n"" tfetch2D vSampledDepth.x___, tc, DepthSampler, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" };\n""\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n""\n"" return (vSampledDepth.x < objDepth.x);\n""\n""#else\n""\n"" return (vSampledDepth.x > objDepth.x);\n""\n""#endif\n""\n""\n""}\n""\n""\n""\n""float AmountShadowed_8Tap_360( sampler DepthSampler, float2 tc, float objDepth )\n""\n""{\n""\n"" float fLOD;\n""\n"" float4 vSampledDepthsA, vSampledDepthsB;\n""\n""\n"" // Optimal 8 rooks pattern to get an idea about whether we're at a penumbra or not\n""\n"" // From [Kallio07] \"Scanline Edge-Flag Algorithm for Antialiasing\" \n""\n"" //\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | | | | | | o | | |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | o | | | | | | | |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | | | | o | | | | |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | | | | | | | o | |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | | o | | | | | | |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | | | | | o | | | |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | | | | | | | | o |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" // | | | o | | | | | |\n""\n"" // +---+---+---+---+---+---+---+---+\n""\n"" //\n""\n"" asm {\n""\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n""\n"" setTexLOD fLOD.x\n""\n""\n"" tfetch2D vSampledDepthsA.x___, tc, DepthSampler, OffsetX = -2.0, OffsetY = -1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepthsA._x__, tc, DepthSampler, OffsetX = -1.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepthsA.__x_, tc, DepthSampler, OffsetX = -1.0, OffsetY = 2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepthsA.___x, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n""\n"" tfetch2D vSampledDepthsB.x___, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepthsB._x__, tc, DepthSampler, OffsetX = 1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepthsB.__x_, tc, DepthSampler, OffsetX = 1.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepthsB.___x, tc, DepthSampler, OffsetX = 2.0, OffsetY = 1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" };\n""\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n""\n"" float4 vCompareA = (vSampledDepthsA < objDepth.xxxx);\n""\n"" float4 vCompareB = (vSampledDepthsB < objDepth.xxxx);\n""\n""#else\n""\n"" float4 vCompareA = (vSampledDepthsA > objDepth.xxxx);\n""\n"" float4 vCompareB = (vSampledDepthsB > objDepth.xxxx);\n""\n""#endif\n""\n""\n"" return dot( vCompareA, float4(0.125,0.125,0.125,0.125) ) + dot( vCompareB, float4(0.125,0.125,0.125,0.125) );\n""\n""}\n""\n""\n""\n""float AmountShadowed_4Tap_360( sampler DepthSampler, float2 tc, float objDepth )\n""\n""{\n""\n"" float fLOD;\n""\n"" float4 vSampledDepths;\n""\n""\n"" // Rotated grid pattern to get an idea about whether we're at a penumbra or not\n""\n"" asm {\n""\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n""\n"" setTexLOD fLOD.x\n""\n""\n"" tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -1.0, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 1.0, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" };\n""\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n""\n"" float4 vCompare = (vSampledDepths < objDepth.xxxx);\n""\n""#else\n""\n"" float4 vCompare = (vSampledDepths > objDepth.xxxx);\n""\n""#endif\n""\n""\n"" return dot( vCompare, float4(0.25,0.25,0.25,0.25) );\n""\n""}\n""\n""\n""// Poisson disc, randomly rotated at different UVs\n""\n""float DoShadowPoisson360( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks )\n""\n""{\n""\n"" float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ),\n""\n"" float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ),\n""\n"" float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ),\n""\n"" float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) };\n""\n""\n"" float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter\n""\n"" float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space\n""\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n""\n"" objDepth = 1.0f - objDepth;\n""\n""#endif\n""\n""\n"" float fAmountShadowed = AmountShadowed_4Tap_360( DepthSampler, shadowMapCenter, objDepth );\n""\n""\n"" if ( fAmountShadowed >= 1.0f ) // Fully in light\n""\n"" {\n""\n"" return 1.0f;\n""\n"" }\n""\n"" else // Do the expensive filtering since we're at least partially shadowed\n""\n"" {\n""\n"" float flScaleOverMapSize = 1.7f / 512.0f; // Tweak parameters to shader\n""\n""\n"" // 2D Rotation Matrix setup\n""\n"" float3 RMatTop = 0, RMatBottom = 0;\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n""\n"" RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5)) * 2.0 - 1.0;\n""\n"" RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple\n""\n""#endif\n""\n""\n"" RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution\n""\n"" RMatBottom *= flScaleOverMapSize;\n""\n"" RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below\n""\n"" RMatBottom.z = shadowMapCenter.y;\n""\n"" float2 rotOffset = float2(0,0);\n""\n"" float4 vAccum = 0;\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z;\n""\n"" vAccum.x = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z;\n""\n"" vAccum.y = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z;\n""\n"" vAccum.z = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z;\n""\n"" vAccum.w = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z;\n""\n"" vAccum.x += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z;\n""\n"" vAccum.y += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z;\n""\n"" vAccum.z += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z;\n""\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z;\n""\n"" vAccum.w += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n""\n"" return dot( vAccum, float4( 0.25, 0.25, 0.25, 0.25) );\n""\n"" }\n""\n""}\n""\n""\n""#endif // _X360\n""\n""\n""\n""float DoFlashlightShadow( sampler DepthSampler, sampler RandomRotationSampler, float3 vProjCoords, float2 vScreenPos, int nShadowLevel, float4 vShadowTweaks, bool bAllowHighQuality )\n""\n""{\n""\n"" float flShadow = 1.0f;\n""\n""\n""#if !defined( _X360 ) //PC\n""\n"" if( nShadowLevel == NVIDIA_PCF_POISSON )\n""\n"" flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, true, false );\n""\n"" else if( nShadowLevel == ATI_NOPCF )\n""\n"" flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, false );\n""\n"" else if( nShadowLevel == ATI_NO_PCF_FETCH4 )\n""\n"" flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, true );\n""\n""\n"" return flShadow;\n""\n""#else\n""\n""\n"" // Compile-time switch for shaders which allow high quality modes on 360\n""\n"" if ( bAllowHighQuality )\n""\n"" {\n""\n"" // Static control flow switch for shadow quality. Some non-interactive sequences use the high quality path\n""\n"" if ( g_bHighQualityShadows )\n""\n"" {\n""\n"" flShadow = DoShadowPoisson360( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" flShadow = DoShadow360Simple( DepthSampler, vProjCoords );\n""\n"" }\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" flShadow = DoShadow360Simple( DepthSampler, vProjCoords );\n""\n"" }\n""\n""\n"" return flShadow;\n""\n""\n""#endif\n""\n""}\n""\n""\n""float3 SpecularLight( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent,\n""\n"" const float3 vEyeDir, const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel )\n""\n""{\n""\n"" float3 result = float3(0.0f, 0.0f, 0.0f);\n""\n""\n"" //float3 vReflect = reflect( -vEyeDir, vWorldNormal );\n""\n"" float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal\n""\n"" float3 vSpecular = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?)\n""\n"" vSpecular = pow( vSpecular.x, fSpecularExponent ); // Raise to specular power\n""\n""\n"" // Optionally warp as function of scalar specular and fresnel\n""\n"" if ( bDoSpecularWarp )\n""\n"" vSpecular *= tex2D( specularWarpSampler, float2(vSpecular.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }\n""\n""\n"" return vSpecular;\n""\n""}\n""\n""\n""void DoSpecularFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, \n""\n"" float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, sampler RandomRotationSampler,\n""\n"" int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, const float2 vScreenPos, const float fSpecularExponent, const float3 vEyeDir,\n""\n"" const bool bDoSpecularWarp, sampler specularWarpSampler, float fFresnel, float4 vShadowTweaks,\n""\n""\n"" // Outputs of this shader...separate shadowed diffuse and specular from the flashlight\n""\n"" out float3 diffuseLighting, out float3 specularLighting )\n""\n""{\n""\n"" float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w;\n""\n"" float3 flashlightColor = float3(1,1,1);\n""\n""\n""#if ( defined( _X360 ) )\n""\n""\n"" float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f );\n""\n"" float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f );\n""\n""\n"" [branch]\n""\n"" if ( dot(ltz + gto, float3(1,1,1)) > 0 )\n""\n"" {\n""\n"" clip(-1);\n""\n"" diffuseLighting = specularLighting = float3(0,0,0);\n""\n"" return;\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""\n""\n"" [branch]\n""\n"" if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 )\n""\n"" {\n""\n"" clip(-1);\n""\n"" diffuseLighting = specularLighting = float3(0,0,0);\n""\n"" return;\n""\n"" }\n""\n"" }\n""\n""#else\n""\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""\n""#endif\n""\n""\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n""\n"" flashlightColor *= cFlashlightColor.xyz; // Flashlight color\n""\n""#endif\n""\n""\n"" float3 delta = flashlightPos - worldPos;\n""\n"" float3 L = normalize( delta );\n""\n"" float distSquared = dot( delta, delta );\n""\n"" float dist = sqrt( distSquared );\n""\n""\n"" float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f );\n""\n""\n"" // Attenuation for light and to fade out shadow over distance\n""\n"" float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) );\n""\n""\n"" // Shadowing and coloring terms\n""\n""#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))\n""\n"" if ( bDoShadows )\n""\n"" {\n""\n"" float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality );\n""\n"" float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated\n""\n"" flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation\n""\n"" flashlightColor *= flShadow; // Shadow term\n""\n"" }\n""\n""#endif\n""\n""\n"" diffuseLighting = fAtten;\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n""\n"" diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) + flFlashlightNoLambertValue ); // Lambertian term\n""\n""#else\n""\n"" diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) ); // Lambertian (not Half-Lambert) term\n""\n""#endif\n""\n"" diffuseLighting *= flashlightColor;\n""\n"" diffuseLighting *= endFalloffFactor;\n""\n""\n"" // Specular term (masked by diffuse)\n""\n"" specularLighting = diffuseLighting * SpecularLight ( worldNormal, L, fSpecularExponent, vEyeDir, bDoSpecularWarp, specularWarpSampler, fFresnel );\n""\n""}\n""\n""\n""// Diffuse only version\n""\n""float3 DoFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, \n""\n"" float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler,\n""\n"" sampler RandomRotationSampler, int nShadowLevel, bool bDoShadows, bool bAllowHighQuality,\n""\n"" const float2 vScreenPos, bool bClip, float4 vShadowTweaks = float4(3/1024.0f, 0.0005f, 0.0f, 0.0f), bool bHasNormal = true )\n""\n""{\n""\n"" float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w;\n""\n"" float3 flashlightColor = float3(1,1,1);\n""\n""\n""#if ( defined( _X360 ) )\n""\n""\n"" float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f );\n""\n"" float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f );\n""\n""\n"" [branch]\n""\n"" if ( dot(ltz + gto, float3(1,1,1)) > 0 )\n""\n"" {\n""\n"" if ( bClip )\n""\n"" {\n""\n"" clip(-1);\n""\n"" }\n""\n"" return float3(0,0,0);\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""\n""\n"" [branch]\n""\n"" if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 )\n""\n"" {\n""\n"" if ( bClip )\n""\n"" {\n""\n"" clip(-1);\n""\n"" }\n""\n"" return float3(0,0,0);\n""\n"" }\n""\n"" }\n""\n""#else\n""\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""\n""#endif\n""\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n""\n"" flashlightColor *= cFlashlightColor.xyz; // Flashlight color\n""\n""#endif\n""\n""\n"" float3 delta = flashlightPos - worldPos;\n""\n"" float3 L = normalize( delta );\n""\n"" float distSquared = dot( delta, delta );\n""\n"" float dist = sqrt( distSquared );\n""\n""\n"" float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f );\n""\n""\n"" // Attenuation for light and to fade out shadow over distance\n""\n"" float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) );\n""\n""\n"" // Shadowing and coloring terms\n""\n""#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))\n""\n"" if ( bDoShadows )\n""\n"" {\n""\n"" float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality );\n""\n"" float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated\n""\n"" flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation\n""\n"" flashlightColor *= flShadow; // Shadow term\n""\n"" }\n""\n""#endif\n""\n""\n"" float3 diffuseLighting = fAtten;\n""\n""\n"" float flLDotWorldNormal;\n""\n"" if ( bHasNormal )\n""\n"" {\n""\n"" flLDotWorldNormal = dot( L.xyz, worldNormal.xyz );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" flLDotWorldNormal = 1.0f;\n""\n"" }\n""\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n""\n"" diffuseLighting *= saturate( flLDotWorldNormal + flFlashlightNoLambertValue ); // Lambertian term\n""\n""#else\n""\n"" diffuseLighting *= saturate( flLDotWorldNormal ); // Lambertian (not Half-Lambert) term\n""\n""#endif\n""\n""\n"" diffuseLighting *= flashlightColor;\n""\n"" diffuseLighting *= endFalloffFactor;\n""\n""\n"" return diffuseLighting;\n""\n""}\n""\n""\n""#endif //#ifndef COMMON_FLASHLIGHT_FXC_H_\n""\n""\n"; \ No newline at end of file +const char common_flashlight_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""//\n""// Purpose: Common pixel shader code specific to flashlights\n""//\n""// $NoKeywords: $\n""//\n""//=============================================================================//\n""#ifndef COMMON_FLASHLIGHT_FXC_H_\n""#define COMMON_FLASHLIGHT_FXC_H_\n""\n""#include \"common_ps_fxc.h\"\n""\n""\n""// JasonM - TODO: remove this simpleton version\n""float DoShadow( sampler DepthSampler, float4 texCoord )\n""{\n"" const float g_flShadowBias = 0.0005f;\n"" float2 uoffset = float2( 0.5f/512.f, 0.0f );\n"" float2 voffset = float2( 0.0f, 0.5f/512.f );\n"" float3 projTexCoord = texCoord.xyz / texCoord.w;\n"" float4 flashlightDepth = float4( tex2D( DepthSampler, projTexCoord + uoffset + voffset ).x,\n"" tex2D( DepthSampler, projTexCoord + uoffset - voffset ).x,\n"" tex2D( DepthSampler, projTexCoord - uoffset + voffset ).x,\n"" tex2D( DepthSampler, projTexCoord - uoffset - voffset ).x );\n""\n""# if ( defined( REVERSE_DEPTH_ON_X360 ) )\n"" {\n"" flashlightDepth = 1.0f - flashlightDepth;\n"" }\n""# endif\n""\n"" float shadowed = 0.0f;\n"" float z = texCoord.z/texCoord.w;\n"" float4 dz = float4(z,z,z,z) - (flashlightDepth + float4( g_flShadowBias, g_flShadowBias, g_flShadowBias, g_flShadowBias));\n"" float4 shadow = float4(0.25f,0.25f,0.25f,0.25f);\n""\n"" if( dz.x <= 0.0f )\n"" shadowed += shadow.x;\n"" if( dz.y <= 0.0f )\n"" shadowed += shadow.y;\n"" if( dz.z <= 0.0f )\n"" shadowed += shadow.z;\n"" if( dz.w <= 0.0f )\n"" shadowed += shadow.w;\n""\n"" return shadowed;\n""}\n""\n""\n""float DoShadowNvidiaRAWZOneTap( sampler DepthSampler, const float4 shadowMapPos )\n""{\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n"" float fDepth = dot(tex2D(DepthSampler, shadowMapCenter).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n""\n"" return fDepth > objDepth;\n""}\n""\n""\n""float DoShadowNvidiaRAWZ( sampler DepthSampler, const float4 shadowMapPos )\n""{\n"" float fE = 1.0f / 512.0f; // Epsilon\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n"" float4 vDepths;\n"" vDepths.x = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n"" vDepths.y = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n"" vDepths.z = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n"" vDepths.w = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));\n""\n"" return dot(vDepths > objDepth.xxxx, float4(0.25, 0.25, 0.25, 0.25));\n""}\n""\n""\n""float DoShadowNvidiaCheap( sampler DepthSampler, const float4 shadowMapPos )\n""{\n"" float fTexelEpsilon = 1.0f / 1024.0f;\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n"" float4 vTaps;\n"" vTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x;\n"" vTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x;\n"" vTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x;\n"" vTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x;\n""\n"" return dot(vTaps, float4(0.25, 0.25, 0.25, 0.25));\n""}\n""\n""float DoShadowNvidiaPCF3x3Box( sampler DepthSampler, const float4 shadowMapPos )\n""{\n"" float fTexelEpsilon = 1.0f / 1024.0f;\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n"" float4 vOneTaps;\n"" vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x;\n"" vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x;\n"" vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x;\n"" vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x;\n"" float flOneTaps = dot( vOneTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f));\n""\n"" float4 vTwoTaps;\n"" vTwoTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, 0 ), objDepth, 1 ) ).x;\n"" vTwoTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, 0 ), objDepth, 1 ) ).x;\n"" vTwoTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x;\n"" vTwoTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x;\n"" float flTwoTaps = dot( vTwoTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f));\n""\n"" float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (1.0f / 9.0f);\n""\n"" // Sum all 9 Taps\n"" return flOneTaps + flTwoTaps + flCenterTap;\n""}\n""\n""\n""//\n""// 1 4 7 4 1\n""// 4 20 33 20 4\n""// 7 33 55 33 7\n""// 4 20 33 20 4\n""// 1 4 7 4 1\n""//\n""float DoShadowNvidiaPCF5x5Gaussian( sampler DepthSampler, const float4 shadowMapPos )\n""{\n"" float fEpsilon = 1.0f / 512.0f;\n"" float fTwoEpsilon = 2.0f * fEpsilon;\n""\n"" float ooW = 1.0f / shadowMapPos.w; // 1 / w\n"" float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once\n""\n"" float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter\n"" float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space\n""\n"" float4 vOneTaps;\n"" vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n"" float flOneTaps = dot( vOneTaps, float4(1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f));\n""\n"" float4 vSevenTaps;\n"" vSevenTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, 0 ), objDepth, 1 ) ).x;\n"" vSevenTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, 0 ), objDepth, 1 ) ).x;\n"" vSevenTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vSevenTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x;\n"" float flSevenTaps = dot( vSevenTaps, float4( 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f ) );\n""\n"" float4 vFourTapsA, vFourTapsB;\n"" vFourTapsA.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n"" vFourTapsA.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vFourTapsA.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vFourTapsA.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n"" vFourTapsB.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n"" vFourTapsB.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vFourTapsB.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;\n"" vFourTapsB.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n"" float flFourTapsA = dot( vFourTapsA, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) );\n"" float flFourTapsB = dot( vFourTapsB, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) );\n""\n"" float4 v20Taps;\n"" v20Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n"" v20Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fEpsilon ), objDepth, 1 ) ).x;\n"" v20Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n"" v20Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fEpsilon ), objDepth, 1 ) ).x;\n"" float fl20Taps = dot( v20Taps, float4(20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f));\n""\n"" float4 v33Taps;\n"" v33Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, 0 ), objDepth, 1 ) ).x;\n"" v33Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, 0 ), objDepth, 1 ) ).x;\n"" v33Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x;\n"" v33Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x;\n"" float fl33Taps = dot( v33Taps, float4(33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f));\n""\n"" float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (55.0f / 331.0f);\n""\n"" // Sum all 25 Taps\n"" return flOneTaps + flSevenTaps + +flFourTapsA + flFourTapsB + fl20Taps + fl33Taps + flCenterTap;\n""}\n""\n""\n""float DoShadowATICheap( sampler DepthSampler, const float4 shadowMapPos )\n""{\n"" float2 shadowMapCenter = shadowMapPos.xy/shadowMapPos.w;\n"" float objDepth = shadowMapPos.z / shadowMapPos.w;\n"" float fSampleDepth = tex2D( DepthSampler, shadowMapCenter ).x;\n""\n"" objDepth = min( objDepth, 0.99999 ); //HACKHACK: On 360, surfaces at or past the far flashlight plane have an abrupt cutoff. This is temp until a smooth falloff is implemented\n""\n"" return fSampleDepth > objDepth;\n""}\n""\n""\n""// Poisson disc, randomly rotated at different UVs\n""float DoShadowPoisson16Sample( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks, bool bNvidiaHardwarePCF, bool bFetch4 )\n""{\n"" float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ),\n"" float2( 0.8806f, 0.3430f ),\n"" float2( -0.0041f, -0.6197f ),\n"" float2( 0.0472f, 0.4964f ),\n"" float2( -0.3730f, 0.0874f ),\n"" float2( -0.9217f, -0.3177f ),\n"" float2( -0.6289f, 0.7388f ),\n"" float2( 0.5744f, -0.7741f ) };\n""\n"" float flScaleOverMapSize = vShadowTweaks.x * 2; // Tweak parameters to shader\n"" float2 vNoiseOffset = vShadowTweaks.zw;\n"" float4 vLightDepths = 0, accum = 0.0f;\n"" float2 rotOffset = 0;\n""\n"" float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter\n"" float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space\n""\n"" // 2D Rotation Matrix setup\n"" float3 RMatTop = 0, RMatBottom = 0;\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n"" RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5) + vNoiseOffset) * 2.0 - 1.0;\n"" RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple\n""#endif\n""\n"" RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution\n"" RMatBottom *= flScaleOverMapSize;\n""\n"" RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below\n"" RMatBottom.z = shadowMapCenter.y;\n"" \n"" float fResult = 0.0f;\n""\n"" if ( bNvidiaHardwarePCF )\n"" {\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z;\n"" vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z;\n"" vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z;\n"" vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z;\n"" vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z;\n"" vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z;\n"" vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z;\n"" vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z;\n"" vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;\n""\n"" fResult = dot( vLightDepths, float4( 0.25, 0.25, 0.25, 0.25) );\n"" }\n"" else if ( bFetch4 )\n"" {\n""/*\n""\n""TODO: Fix this contact hardening stuff\n""\n"" float flNumCloserSamples = 1;\n"" float flAccumulatedCloserSamples = objDepth;\n"" float4 vBlockerDepths;\n""\n"" // First, search for blockers\n"" for( int j=0; j<8; j++ )\n"" {\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[j].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[j].xy) + RMatBottom.z;\n"" vBlockerDepths = tex2D( DepthSampler, rotOffset.xy );\n""\n"" // Which samples are closer than the pixel we're rendering?\n"" float4 vCloserSamples = (vBlockerDepths < objDepth.xxxx ); // Binary comparison results\n"" flNumCloserSamples += dot( vCloserSamples, float4(1, 1, 1, 1) ); // How many samples are closer than receiver?\n"" flAccumulatedCloserSamples += dot (vCloserSamples, vBlockerDepths ); // Total depths from samples closer than receiver\n"" }\n""\n"" float flBlockerDepth = flAccumulatedCloserSamples / flNumCloserSamples;\n"" float flContactHardeningScale = (objDepth - flBlockerDepth) / flBlockerDepth;\n""\n"" // Scale the kernel\n"" RMatTop.xy *= flContactHardeningScale;\n"" RMatBottom.xy *= flContactHardeningScale;\n""*/\n""\n"" for( int i=0; i<8; i++ )\n"" {\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[i].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[i].xy) + RMatBottom.z;\n"" vLightDepths = tex2D( DepthSampler, rotOffset.xy );\n"" accum += (vLightDepths > objDepth.xxxx);\n"" }\n""\n"" fResult = dot( accum, float4( 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f) );\n"" }\n"" else // ATI vanilla hardware shadow mapping\n"" {\n"" for( int i=0; i<2; i++ )\n"" {\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+0].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+0].xy) + RMatBottom.z;\n"" vLightDepths.x = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+1].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+1].xy) + RMatBottom.z;\n"" vLightDepths.y = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+2].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+2].xy) + RMatBottom.z;\n"" vLightDepths.z = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+3].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+3].xy) + RMatBottom.z;\n"" vLightDepths.w = tex2D( DepthSampler, rotOffset.xy ).x;\n""\n"" accum += (vLightDepths > objDepth.xxxx);\n"" }\n""\n"" fResult = dot( accum, float4( 0.125, 0.125, 0.125, 0.125) );\n"" }\n""\n"" return fResult;\n""}\n""\n""#if defined( _X360 )\n""\n""// Poisson disc, randomly rotated at different UVs\n""float DoShadow360Simple( sampler DepthSampler, const float3 vProjCoords )\n""{\n"" float fLOD;\n"" float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter\n"" float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n"" objDepth = 1.0f - objDepth;\n""#endif \n""\n"" float4 vSampledDepths, vWeights;\n""\n"" asm {\n"" getCompTexLOD2D fLOD.x, shadowMapCenter.xy, DepthSampler, AnisoFilter=max16to1\n"" setTexLOD fLOD.x\n""\n"" tfetch2D vSampledDepths.x___, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths._x__, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths.__x_, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths.___x, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" getWeights2D vWeights, shadowMapCenter.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true\n"" };\n""\n"" vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y );\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n"" float4 vCompare = (vSampledDepths < objDepth.xxxx);\n""#else\n"" float4 vCompare = (vSampledDepths > objDepth.xxxx);\n""#endif\n""\n"" return dot( vCompare, vWeights );\n""}\n""\n""\n""float Do360PCFFetch( sampler DepthSampler, float2 tc, float objDepth )\n""{\n"" float fLOD;\n"" float4 vSampledDepths, vWeights;\n""\n"" asm {\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n"" setTexLOD fLOD.x\n""\n"" tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" getWeights2D vWeights, tc.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true\n"" };\n""\n"" vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y );\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n"" float4 vCompare = (vSampledDepths < objDepth.xxxx);\n""#else\n"" float4 vCompare = (vSampledDepths > objDepth.xxxx);\n""#endif\n""\n"" return dot( vCompare, vWeights );\n""}\n""\n""\n""\n""float Do360NearestFetch( sampler DepthSampler, float2 tc, float objDepth )\n""{\n"" float fLOD;\n"" float4 vSampledDepth;\n""\n"" asm {\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n"" setTexLOD fLOD.x\n""\n"" tfetch2D vSampledDepth.x___, tc, DepthSampler, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" };\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n"" return (vSampledDepth.x < objDepth.x);\n""#else\n"" return (vSampledDepth.x > objDepth.x);\n""#endif\n""\n""}\n""\n""\n""float AmountShadowed_8Tap_360( sampler DepthSampler, float2 tc, float objDepth )\n""{\n"" float fLOD;\n"" float4 vSampledDepthsA, vSampledDepthsB;\n""\n"" // Optimal 8 rooks pattern to get an idea about whether we're at a penumbra or not\n"" // From [Kallio07] \"Scanline Edge-Flag Algorithm for Antialiasing\" \n"" //\n"" // +---+---+---+---+---+---+---+---+\n"" // | | | | | | o | | |\n"" // +---+---+---+---+---+---+---+---+\n"" // | o | | | | | | | |\n"" // +---+---+---+---+---+---+---+---+\n"" // | | | | o | | | | |\n"" // +---+---+---+---+---+---+---+---+\n"" // | | | | | | | o | |\n"" // +---+---+---+---+---+---+---+---+\n"" // | | o | | | | | | |\n"" // +---+---+---+---+---+---+---+---+\n"" // | | | | | o | | | |\n"" // +---+---+---+---+---+---+---+---+\n"" // | | | | | | | | o |\n"" // +---+---+---+---+---+---+---+---+\n"" // | | | o | | | | | |\n"" // +---+---+---+---+---+---+---+---+\n"" //\n"" asm {\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n"" setTexLOD fLOD.x\n""\n"" tfetch2D vSampledDepthsA.x___, tc, DepthSampler, OffsetX = -2.0, OffsetY = -1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepthsA._x__, tc, DepthSampler, OffsetX = -1.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepthsA.__x_, tc, DepthSampler, OffsetX = -1.0, OffsetY = 2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepthsA.___x, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n""\n"" tfetch2D vSampledDepthsB.x___, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepthsB._x__, tc, DepthSampler, OffsetX = 1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepthsB.__x_, tc, DepthSampler, OffsetX = 1.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepthsB.___x, tc, DepthSampler, OffsetX = 2.0, OffsetY = 1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" };\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n"" float4 vCompareA = (vSampledDepthsA < objDepth.xxxx);\n"" float4 vCompareB = (vSampledDepthsB < objDepth.xxxx);\n""#else\n"" float4 vCompareA = (vSampledDepthsA > objDepth.xxxx);\n"" float4 vCompareB = (vSampledDepthsB > objDepth.xxxx);\n""#endif\n""\n"" return dot( vCompareA, float4(0.125,0.125,0.125,0.125) ) + dot( vCompareB, float4(0.125,0.125,0.125,0.125) );\n""}\n""\n""\n""float AmountShadowed_4Tap_360( sampler DepthSampler, float2 tc, float objDepth )\n""{\n"" float fLOD;\n"" float4 vSampledDepths;\n""\n"" // Rotated grid pattern to get an idea about whether we're at a penumbra or not\n"" asm {\n"" getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1\n"" setTexLOD fLOD.x\n""\n"" tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -1.0, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 1.0, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point\n"" };\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n"" float4 vCompare = (vSampledDepths < objDepth.xxxx);\n""#else\n"" float4 vCompare = (vSampledDepths > objDepth.xxxx);\n""#endif\n""\n"" return dot( vCompare, float4(0.25,0.25,0.25,0.25) );\n""}\n""\n""// Poisson disc, randomly rotated at different UVs\n""float DoShadowPoisson360( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks )\n""{\n"" float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ),\n"" float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ),\n"" float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ),\n"" float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) };\n""\n"" float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter\n"" float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space\n""\n""#if defined( REVERSE_DEPTH_ON_X360 )\n"" objDepth = 1.0f - objDepth;\n""#endif\n""\n"" float fAmountShadowed = AmountShadowed_4Tap_360( DepthSampler, shadowMapCenter, objDepth );\n""\n"" if ( fAmountShadowed >= 1.0f ) // Fully in light\n"" {\n"" return 1.0f;\n"" }\n"" else // Do the expensive filtering since we're at least partially shadowed\n"" {\n"" float flScaleOverMapSize = 1.7f / 512.0f; // Tweak parameters to shader\n""\n"" // 2D Rotation Matrix setup\n"" float3 RMatTop = 0, RMatBottom = 0;\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n"" RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5)) * 2.0 - 1.0;\n"" RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple\n""#endif\n""\n"" RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution\n"" RMatBottom *= flScaleOverMapSize;\n"" RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below\n"" RMatBottom.z = shadowMapCenter.y;\n"" float2 rotOffset = float2(0,0);\n"" float4 vAccum = 0;\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z;\n"" vAccum.x = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z;\n"" vAccum.y = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z;\n"" vAccum.z = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z;\n"" vAccum.w = Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z;\n"" vAccum.x += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z;\n"" vAccum.y += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z;\n"" vAccum.z += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z;\n"" rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z;\n"" vAccum.w += Do360NearestFetch( DepthSampler, rotOffset, objDepth );\n""\n"" return dot( vAccum, float4( 0.25, 0.25, 0.25, 0.25) );\n"" }\n""}\n""\n""#endif // _X360\n""\n""\n""float DoFlashlightShadow( sampler DepthSampler, sampler RandomRotationSampler, float3 vProjCoords, float2 vScreenPos, int nShadowLevel, float4 vShadowTweaks, bool bAllowHighQuality )\n""{\n"" float flShadow = 1.0f;\n""\n""#if !defined( _X360 ) //PC\n"" if( nShadowLevel == NVIDIA_PCF_POISSON )\n"" flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, true, false );\n"" else if( nShadowLevel == ATI_NOPCF )\n"" flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, false );\n"" else if( nShadowLevel == ATI_NO_PCF_FETCH4 )\n"" flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, true );\n""\n"" return flShadow;\n""#else\n""\n"" // Compile-time switch for shaders which allow high quality modes on 360\n"" if ( bAllowHighQuality )\n"" {\n"" // Static control flow switch for shadow quality. Some non-interactive sequences use the high quality path\n"" if ( g_bHighQualityShadows )\n"" {\n"" flShadow = DoShadowPoisson360( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks );\n"" }\n"" else\n"" {\n"" flShadow = DoShadow360Simple( DepthSampler, vProjCoords );\n"" }\n"" }\n"" else\n"" {\n"" flShadow = DoShadow360Simple( DepthSampler, vProjCoords );\n"" }\n""\n"" return flShadow;\n""\n""#endif\n""}\n""\n""float3 SpecularLight( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent,\n"" const float3 vEyeDir, const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel )\n""{\n"" float3 result = float3(0.0f, 0.0f, 0.0f);\n""\n"" //float3 vReflect = reflect( -vEyeDir, vWorldNormal );\n"" float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal\n"" float3 vSpecular = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?)\n"" vSpecular = pow( vSpecular.x, fSpecularExponent ); // Raise to specular power\n""\n"" // Optionally warp as function of scalar specular and fresnel\n"" if ( bDoSpecularWarp )\n"" vSpecular *= tex2D( specularWarpSampler, float2(vSpecular.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }\n""\n"" return vSpecular;\n""}\n""\n""void DoSpecularFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, \n"" float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, sampler RandomRotationSampler,\n"" int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, const float2 vScreenPos, const float fSpecularExponent, const float3 vEyeDir,\n"" const bool bDoSpecularWarp, sampler specularWarpSampler, float fFresnel, float4 vShadowTweaks,\n""\n"" // Outputs of this shader...separate shadowed diffuse and specular from the flashlight\n"" out float3 diffuseLighting, out float3 specularLighting )\n""{\n"" float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w;\n"" float3 flashlightColor = float3(1,1,1);\n""\n""#if ( defined( _X360 ) )\n""\n"" float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f );\n"" float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f );\n""\n"" [branch]\n"" if ( dot(ltz + gto, float3(1,1,1)) > 0 )\n"" {\n"" clip(-1);\n"" diffuseLighting = specularLighting = float3(0,0,0);\n"" return;\n"" }\n"" else\n"" {\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""\n"" [branch]\n"" if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 )\n"" {\n"" clip(-1);\n"" diffuseLighting = specularLighting = float3(0,0,0);\n"" return;\n"" }\n"" }\n""#else\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""#endif\n""\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n"" flashlightColor *= cFlashlightColor.xyz; // Flashlight color\n""#endif\n""\n"" float3 delta = flashlightPos - worldPos;\n"" float3 L = normalize( delta );\n"" float distSquared = dot( delta, delta );\n"" float dist = sqrt( distSquared );\n""\n"" float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f );\n""\n"" // Attenuation for light and to fade out shadow over distance\n"" float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) );\n""\n"" // Shadowing and coloring terms\n""#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))\n"" if ( bDoShadows )\n"" {\n"" float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality );\n"" float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated\n"" flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation\n"" flashlightColor *= flShadow; // Shadow term\n"" }\n""#endif\n""\n"" diffuseLighting = fAtten;\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n"" diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) + flFlashlightNoLambertValue ); // Lambertian term\n""#else\n"" diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) ); // Lambertian (not Half-Lambert) term\n""#endif\n"" diffuseLighting *= flashlightColor;\n"" diffuseLighting *= endFalloffFactor;\n""\n"" // Specular term (masked by diffuse)\n"" specularLighting = diffuseLighting * SpecularLight ( worldNormal, L, fSpecularExponent, vEyeDir, bDoSpecularWarp, specularWarpSampler, fFresnel );\n""}\n""\n""// Diffuse only version\n""float3 DoFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal, \n"" float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler,\n"" sampler RandomRotationSampler, int nShadowLevel, bool bDoShadows, bool bAllowHighQuality,\n"" const float2 vScreenPos, bool bClip, float4 vShadowTweaks = float4(3/1024.0f, 0.0005f, 0.0f, 0.0f), bool bHasNormal = true )\n""{\n"" float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w;\n"" float3 flashlightColor = float3(1,1,1);\n""\n""#if ( defined( _X360 ) )\n""\n"" float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f );\n"" float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f );\n""\n"" [branch]\n"" if ( dot(ltz + gto, float3(1,1,1)) > 0 )\n"" {\n"" if ( bClip )\n"" {\n"" clip(-1);\n"" }\n"" return float3(0,0,0);\n"" }\n"" else\n"" {\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""\n"" [branch]\n"" if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 )\n"" {\n"" if ( bClip )\n"" {\n"" clip(-1);\n"" }\n"" return float3(0,0,0);\n"" }\n"" }\n""#else\n"" flashlightColor = tex2D( FlashlightSampler, vProjCoords );\n""#endif\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n"" flashlightColor *= cFlashlightColor.xyz; // Flashlight color\n""#endif\n""\n"" float3 delta = flashlightPos - worldPos;\n"" float3 L = normalize( delta );\n"" float distSquared = dot( delta, delta );\n"" float dist = sqrt( distSquared );\n""\n"" float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f );\n""\n"" // Attenuation for light and to fade out shadow over distance\n"" float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) );\n""\n"" // Shadowing and coloring terms\n""#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))\n"" if ( bDoShadows )\n"" {\n"" float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality );\n"" float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated\n"" flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation\n"" flashlightColor *= flShadow; // Shadow term\n"" }\n""#endif\n""\n"" float3 diffuseLighting = fAtten;\n""\n"" float flLDotWorldNormal;\n"" if ( bHasNormal )\n"" {\n"" flLDotWorldNormal = dot( L.xyz, worldNormal.xyz );\n"" }\n"" else\n"" {\n"" flLDotWorldNormal = 1.0f;\n"" }\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n"" diffuseLighting *= saturate( flLDotWorldNormal + flFlashlightNoLambertValue ); // Lambertian term\n""#else\n"" diffuseLighting *= saturate( flLDotWorldNormal ); // Lambertian (not Half-Lambert) term\n""#endif\n""\n"" diffuseLighting *= flashlightColor;\n"" diffuseLighting *= endFalloffFactor;\n""\n"" return diffuseLighting;\n""}\n""\n""#endif //#ifndef COMMON_FLASHLIGHT_FXC_H_\n""\n"; \ No newline at end of file diff --git a/source/common_fxc.h.inc b/source/common_fxc.h.inc index 7daacb1..ebdef97 100644 --- a/source/common_fxc.h.inc +++ b/source/common_fxc.h.inc @@ -1 +1 @@ -const char common_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""//\n""\n""// Purpose: \n""\n""//\n""\n""// $NoKeywords: $\n""\n""//\n""\n""//=============================================================================//\n""\n""#ifndef COMMON_FXC_H_\n""\n""#define COMMON_FXC_H_\n""\n""\n""#include \"common_pragmas.h\"\n""\n""#include \"common_hlsl_cpp_consts.h\"\n""\n""\n""#ifdef NV3X\n""\n""# define HALF half\n""\n""# define HALF2 half2\n""\n""# define HALF3 half3\n""\n""# define HALF4 half4\n""\n""# define HALF3x3 half3x3\n""\n""# define HALF3x4 half3x4\n""\n""# define HALF4x3 half4x3\n""\n""# define HALF_CONSTANT( _constant ) ((HALF)_constant)\n""\n""#else\n""\n""# define HALF float\n""\n""# define HALF2 float2\n""\n""# define HALF3 float3\n""\n""# define HALF4 float4\n""\n""# define HALF3x3 float3x3\n""\n""# define HALF3x4 float3x4\n""\n""# define HALF4x3 float4x3\n""\n""# define HALF_CONSTANT( _constant ) _constant\n""\n""#endif\n""\n""\n""// This is where all common code for both vertex and pixel shaders.\n""\n""#define OO_SQRT_3 0.57735025882720947f\n""\n""static const HALF3 bumpBasis[3] = {\n""\n"" HALF3( 0.81649661064147949f, 0.0f, OO_SQRT_3 ),\n""\n"" HALF3( -0.40824833512306213f, 0.70710676908493042f, OO_SQRT_3 ),\n""\n"" HALF3( -0.40824821591377258f, -0.7071068286895752f, OO_SQRT_3 )\n""\n""};\n""\n""static const HALF3 bumpBasisTranspose[3] = {\n""\n"" HALF3( 0.81649661064147949f, -0.40824833512306213f, -0.40824833512306213f ),\n""\n"" HALF3( 0.0f, 0.70710676908493042f, -0.7071068286895752f ),\n""\n"" HALF3( OO_SQRT_3, OO_SQRT_3, OO_SQRT_3 )\n""\n""};\n""\n""\n""#if defined( _X360 )\n""\n""#define REVERSE_DEPTH_ON_X360 //uncomment to use D3DFMT_D24FS8 with an inverted depth viewport for better performance. Keep this in sync with the same named #define in public/shaderapi/shareddefs.h\n""\n""//Note that the reversal happens in the viewport. So ONLY reading back from a depth texture should be affected. Projected math is unaffected.\n""\n""#endif\n""\n""\n""HALF3 CalcReflectionVectorNormalized( HALF3 normal, HALF3 eyeVector )\n""\n""{\n""\n"" // FIXME: might be better of normalizing with a normalizing cube map and\n""\n"" // get rid of the dot( normal, normal )\n""\n"" // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v\n""\n"" return 2.0 * ( dot( normal, eyeVector ) / dot( normal, normal ) ) * normal - eyeVector;\n""\n""}\n""\n""\n""HALF3 CalcReflectionVectorUnnormalized( HALF3 normal, HALF3 eyeVector )\n""\n""{\n""\n"" // FIXME: might be better of normalizing with a normalizing cube map and\n""\n"" // get rid of the dot( normal, normal )\n""\n"" // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v\n""\n"" // multiply all values through by N.N. uniformly scaling reflection vector won't affect result\n""\n"" // since it is used in a cubemap lookup\n""\n"" return (2.0*(dot( normal, eyeVector ))*normal) - (dot( normal, normal )*eyeVector);\n""\n""}\n""\n""\n""float3 HuePreservingColorClamp( float3 c )\n""\n""{\n""\n"" // Get the max of all of the color components and a specified maximum amount\n""\n"" float maximum = max( max( c.x, c.y ), max( c.z, 1.0f ) );\n""\n""\n"" return (c / maximum);\n""\n""}\n""\n""\n""HALF3 HuePreservingColorClamp( HALF3 c, HALF maxVal )\n""\n""{\n""\n"" // Get the max of all of the color components and a specified maximum amount\n""\n"" float maximum = max( max( c.x, c.y ), max( c.z, maxVal ) );\n""\n"" return (c * ( maxVal / maximum ) );\n""\n""}\n""\n""\n""#if (AA_CLAMP==1)\n""\n""HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) \n""\n""{\n""\n"" HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;\n""\n"" result += Lightmap3Coord;\n""\n"" return result;\n""\n""}\n""\n""\n""void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,\n""\n"" out HALF2 bumpCoord1,\n""\n"" out HALF2 bumpCoord2,\n""\n"" out HALF2 bumpCoord3 ) \n""\n""{\n""\n"" HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;\n""\n"" result += Lightmap3Coord;\n""\n"" bumpCoord1 = result + HALF2(Lightmap1and2Coord.z, 0);\n""\n"" bumpCoord2 = result + 2*HALF2(Lightmap1and2Coord.z, 0);\n""\n"" bumpCoord3 = result + 3*HALF2(Lightmap1and2Coord.z, 0);\n""\n""}\n""\n""#else\n""\n""HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) \n""\n""{\n""\n"" return Lightmap1and2Coord.xy;\n""\n""}\n""\n""\n""void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,\n""\n"" out HALF2 bumpCoord1,\n""\n"" out HALF2 bumpCoord2,\n""\n"" out HALF2 bumpCoord3 ) \n""\n""{\n""\n"" bumpCoord1 = Lightmap1and2Coord.xy;\n""\n"" bumpCoord2 = Lightmap1and2Coord.wz; // reversed order!!!\n""\n"" bumpCoord3 = Lightmap3Coord.xy;\n""\n""}\n""\n""#endif\n""\n""\n""// Versions of matrix multiply functions which force HLSL compiler to explictly use DOTs, \n""\n""// not giving it the option of using MAD expansion. In a perfect world, the compiler would\n""\n""// always pick the best strategy, and these shouldn't be needed.. but.. well.. umm..\n""\n""//\n""\n""// lorenmcq\n""\n""\n""float3 mul3x3(float3 v, float3x3 m)\n""\n""{\n""\n""#if !defined( _X360 )\n""\n"" return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));\n""\n""#else\n""\n"" // xbox360 fxc.exe (new back end) borks with transposes, generates bad code\n""\n"" return mul( v, m );\n""\n""#endif\n""\n""}\n""\n""\n""float3 mul4x3(float4 v, float4x3 m)\n""\n""{\n""\n""#if !defined( _X360 )\n""\n"" return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));\n""\n""#else\n""\n"" // xbox360 fxc.exe (new back end) borks with transposes, generates bad code\n""\n"" return mul( v, m );\n""\n""#endif\n""\n""}\n""\n""\n""float3 DecompressHDR( float4 input )\n""\n""{\n""\n"" return input.rgb * input.a * MAX_HDR_OVERBRIGHT;\n""\n""}\n""\n""\n""float4 CompressHDR( float3 input )\n""\n""{\n""\n"" // FIXME: want to use min so that we clamp to white, but what happens if we \n""\n"" // have an albedo component that's less than 1/MAX_HDR_OVERBRIGHT?\n""\n"" // float fMax = max( max( color.r, color.g ), color.b );\n""\n"" float4 output;\n""\n"" float fMax = min( min( input.r, input.g ), input.b );\n""\n"" if( fMax > 1.0f )\n""\n"" {\n""\n"" float oofMax = 1.0f / fMax;\n""\n"" output.rgb = oofMax * input.rgb;\n""\n"" output.a = min( fMax / MAX_HDR_OVERBRIGHT, 1.0f );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" output.rgb = input.rgb;\n""\n"" output.a = 0.0f;\n""\n"" }\n""\n"" return output;\n""\n""}\n""\n""\n""\n""float3 LinearToGamma( const float3 f3linear )\n""\n""{\n""\n"" return pow( f3linear, 1.0f / 2.2f );\n""\n""}\n""\n""\n""float4 LinearToGamma( const float4 f4linear )\n""\n""{\n""\n"" return float4( pow( f4linear.xyz, 1.0f / 2.2f ), f4linear.w );\n""\n""}\n""\n""\n""float LinearToGamma( const float f1linear )\n""\n""{\n""\n"" return pow( f1linear, 1.0f / 2.2f );\n""\n""}\n""\n""\n""float3 GammaToLinear( const float3 gamma )\n""\n""{\n""\n"" return pow( gamma, 2.2f );\n""\n""}\n""\n""\n""float4 GammaToLinear( const float4 gamma )\n""\n""{\n""\n"" return float4( pow( gamma.xyz, 2.2f ), gamma.w );\n""\n""}\n""\n""\n""float GammaToLinear( const float gamma )\n""\n""{\n""\n"" return pow( gamma, 2.2f );\n""\n""}\n""\n""\n""// These two functions use the actual sRGB math\n""\n""float SrgbGammaToLinear( float flSrgbGammaValue )\n""\n""{\n""\n"" float x = saturate( flSrgbGammaValue );\n""\n"" return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) );\n""\n""}\n""\n""\n""float SrgbLinearToGamma( float flLinearValue )\n""\n""{\n""\n"" float x = saturate( flLinearValue );\n""\n"" return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f;\n""\n""}\n""\n""\n""// These twofunctions use the XBox 360's exact piecewise linear algorithm\n""\n""float X360GammaToLinear( float fl360GammaValue )\n""\n""{\n""\n"" float flLinearValue;\n""\n""\n"" fl360GammaValue = saturate( fl360GammaValue );\n""\n"" if ( fl360GammaValue < ( 96.0f / 255.0f ) )\n""\n"" {\n""\n"" if ( fl360GammaValue < ( 64.0f / 255.0f ) )\n""\n"" {\n""\n"" flLinearValue = fl360GammaValue * 255.0f;\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f;\n""\n"" flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) );\n""\n"" }\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" if( fl360GammaValue < ( 192.0f / 255.0f ) )\n""\n"" {\n""\n"" flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f;\n""\n"" flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f;\n""\n"" flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) );\n""\n"" }\n""\n"" }\n""\n""\n"" flLinearValue *= 1.0f / 1023.0f;\n""\n""\n"" flLinearValue = saturate( flLinearValue );\n""\n"" return flLinearValue;\n""\n""}\n""\n""\n""float X360LinearToGamma( float flLinearValue )\n""\n""{\n""\n"" float fl360GammaValue;\n""\n""\n"" flLinearValue = saturate( flLinearValue );\n""\n"" if ( flLinearValue < ( 128.0f / 1023.0f ) )\n""\n"" {\n""\n"" if ( flLinearValue < ( 64.0f / 1023.0f ) )\n""\n"" {\n""\n"" fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f );\n""\n"" }\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" if ( flLinearValue < ( 512.0f / 1023.0f ) )\n""\n"" {\n""\n"" fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016\n""\n"" if ( fl360GammaValue > 1.0f )\n""\n"" {\n""\n"" fl360GammaValue = 1.0f;\n""\n"" }\n""\n"" }\n""\n"" }\n""\n""\n"" fl360GammaValue = saturate( fl360GammaValue );\n""\n"" return fl360GammaValue;\n""\n""}\n""\n""\n""float SrgbGammaTo360Gamma( float flSrgbGammaValue )\n""\n""{\n""\n"" float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue );\n""\n"" float fl360GammaValue = X360LinearToGamma( flLinearValue );\n""\n"" return fl360GammaValue;\n""\n""}\n""\n""\n""float3 Vec3WorldToTangent( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""\n""{\n""\n"" float3 vTangentVector;\n""\n"" vTangentVector.x = dot( iWorldVector.xyz, iWorldTangent.xyz );\n""\n"" vTangentVector.y = dot( iWorldVector.xyz, iWorldBinormal.xyz );\n""\n"" vTangentVector.z = dot( iWorldVector.xyz, iWorldNormal.xyz );\n""\n"" return vTangentVector.xyz; // Return without normalizing\n""\n""}\n""\n""\n""float3 Vec3WorldToTangentNormalized( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""\n""{\n""\n"" return normalize( Vec3WorldToTangent( iWorldVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );\n""\n""}\n""\n""\n""float3 Vec3TangentToWorld( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""\n""{\n""\n"" float3 vWorldVector;\n""\n"" vWorldVector.xyz = iTangentVector.x * iWorldTangent.xyz;\n""\n"" vWorldVector.xyz += iTangentVector.y * iWorldBinormal.xyz;\n""\n"" vWorldVector.xyz += iTangentVector.z * iWorldNormal.xyz;\n""\n"" return vWorldVector.xyz; // Return without normalizing\n""\n""}\n""\n""\n""float3 Vec3TangentToWorldNormalized( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""\n""{\n""\n"" return normalize( Vec3TangentToWorld( iTangentVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );\n""\n""}\n""\n""\n""#endif //#ifndef COMMON_FXC_H_\n""\n""\n"; \ No newline at end of file +const char common_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""//\n""// Purpose: \n""//\n""// $NoKeywords: $\n""//\n""//=============================================================================//\n""#ifndef COMMON_FXC_H_\n""#define COMMON_FXC_H_\n""\n""#include \"common_pragmas.h\"\n""#include \"common_hlsl_cpp_consts.h\"\n""\n""#ifdef NV3X\n""# define HALF half\n""# define HALF2 half2\n""# define HALF3 half3\n""# define HALF4 half4\n""# define HALF3x3 half3x3\n""# define HALF3x4 half3x4\n""# define HALF4x3 half4x3\n""# define HALF_CONSTANT( _constant ) ((HALF)_constant)\n""#else\n""# define HALF float\n""# define HALF2 float2\n""# define HALF3 float3\n""# define HALF4 float4\n""# define HALF3x3 float3x3\n""# define HALF3x4 float3x4\n""# define HALF4x3 float4x3\n""# define HALF_CONSTANT( _constant ) _constant\n""#endif\n""\n""// This is where all common code for both vertex and pixel shaders.\n""#define OO_SQRT_3 0.57735025882720947f\n""static const HALF3 bumpBasis[3] = {\n"" HALF3( 0.81649661064147949f, 0.0f, OO_SQRT_3 ),\n"" HALF3( -0.40824833512306213f, 0.70710676908493042f, OO_SQRT_3 ),\n"" HALF3( -0.40824821591377258f, -0.7071068286895752f, OO_SQRT_3 )\n""};\n""static const HALF3 bumpBasisTranspose[3] = {\n"" HALF3( 0.81649661064147949f, -0.40824833512306213f, -0.40824833512306213f ),\n"" HALF3( 0.0f, 0.70710676908493042f, -0.7071068286895752f ),\n"" HALF3( OO_SQRT_3, OO_SQRT_3, OO_SQRT_3 )\n""};\n""\n""#if defined( _X360 )\n""#define REVERSE_DEPTH_ON_X360 //uncomment to use D3DFMT_D24FS8 with an inverted depth viewport for better performance. Keep this in sync with the same named #define in public/shaderapi/shareddefs.h\n""//Note that the reversal happens in the viewport. So ONLY reading back from a depth texture should be affected. Projected math is unaffected.\n""#endif\n""\n""HALF3 CalcReflectionVectorNormalized( HALF3 normal, HALF3 eyeVector )\n""{\n"" // FIXME: might be better of normalizing with a normalizing cube map and\n"" // get rid of the dot( normal, normal )\n"" // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v\n"" return 2.0 * ( dot( normal, eyeVector ) / dot( normal, normal ) ) * normal - eyeVector;\n""}\n""\n""HALF3 CalcReflectionVectorUnnormalized( HALF3 normal, HALF3 eyeVector )\n""{\n"" // FIXME: might be better of normalizing with a normalizing cube map and\n"" // get rid of the dot( normal, normal )\n"" // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v\n"" // multiply all values through by N.N. uniformly scaling reflection vector won't affect result\n"" // since it is used in a cubemap lookup\n"" return (2.0*(dot( normal, eyeVector ))*normal) - (dot( normal, normal )*eyeVector);\n""}\n""\n""float3 HuePreservingColorClamp( float3 c )\n""{\n"" // Get the max of all of the color components and a specified maximum amount\n"" float maximum = max( max( c.x, c.y ), max( c.z, 1.0f ) );\n""\n"" return (c / maximum);\n""}\n""\n""HALF3 HuePreservingColorClamp( HALF3 c, HALF maxVal )\n""{\n"" // Get the max of all of the color components and a specified maximum amount\n"" float maximum = max( max( c.x, c.y ), max( c.z, maxVal ) );\n"" return (c * ( maxVal / maximum ) );\n""}\n""\n""#if (AA_CLAMP==1)\n""HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) \n""{\n"" HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;\n"" result += Lightmap3Coord;\n"" return result;\n""}\n""\n""void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,\n"" out HALF2 bumpCoord1,\n"" out HALF2 bumpCoord2,\n"" out HALF2 bumpCoord3 ) \n""{\n"" HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;\n"" result += Lightmap3Coord;\n"" bumpCoord1 = result + HALF2(Lightmap1and2Coord.z, 0);\n"" bumpCoord2 = result + 2*HALF2(Lightmap1and2Coord.z, 0);\n"" bumpCoord3 = result + 3*HALF2(Lightmap1and2Coord.z, 0);\n""}\n""#else\n""HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord ) \n""{\n"" return Lightmap1and2Coord.xy;\n""}\n""\n""void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,\n"" out HALF2 bumpCoord1,\n"" out HALF2 bumpCoord2,\n"" out HALF2 bumpCoord3 ) \n""{\n"" bumpCoord1 = Lightmap1and2Coord.xy;\n"" bumpCoord2 = Lightmap1and2Coord.wz; // reversed order!!!\n"" bumpCoord3 = Lightmap3Coord.xy;\n""}\n""#endif\n""\n""// Versions of matrix multiply functions which force HLSL compiler to explictly use DOTs, \n""// not giving it the option of using MAD expansion. In a perfect world, the compiler would\n""// always pick the best strategy, and these shouldn't be needed.. but.. well.. umm..\n""//\n""// lorenmcq\n""\n""float3 mul3x3(float3 v, float3x3 m)\n""{\n""#if !defined( _X360 )\n"" return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));\n""#else\n"" // xbox360 fxc.exe (new back end) borks with transposes, generates bad code\n"" return mul( v, m );\n""#endif\n""}\n""\n""float3 mul4x3(float4 v, float4x3 m)\n""{\n""#if !defined( _X360 )\n"" return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));\n""#else\n"" // xbox360 fxc.exe (new back end) borks with transposes, generates bad code\n"" return mul( v, m );\n""#endif\n""}\n""\n""float3 DecompressHDR( float4 input )\n""{\n"" return input.rgb * input.a * MAX_HDR_OVERBRIGHT;\n""}\n""\n""float4 CompressHDR( float3 input )\n""{\n"" // FIXME: want to use min so that we clamp to white, but what happens if we \n"" // have an albedo component that's less than 1/MAX_HDR_OVERBRIGHT?\n"" // float fMax = max( max( color.r, color.g ), color.b );\n"" float4 output;\n"" float fMax = min( min( input.r, input.g ), input.b );\n"" if( fMax > 1.0f )\n"" {\n"" float oofMax = 1.0f / fMax;\n"" output.rgb = oofMax * input.rgb;\n"" output.a = min( fMax / MAX_HDR_OVERBRIGHT, 1.0f );\n"" }\n"" else\n"" {\n"" output.rgb = input.rgb;\n"" output.a = 0.0f;\n"" }\n"" return output;\n""}\n""\n""\n""float3 LinearToGamma( const float3 f3linear )\n""{\n"" return pow( f3linear, 1.0f / 2.2f );\n""}\n""\n""float4 LinearToGamma( const float4 f4linear )\n""{\n"" return float4( pow( f4linear.xyz, 1.0f / 2.2f ), f4linear.w );\n""}\n""\n""float LinearToGamma( const float f1linear )\n""{\n"" return pow( f1linear, 1.0f / 2.2f );\n""}\n""\n""float3 GammaToLinear( const float3 gamma )\n""{\n"" return pow( gamma, 2.2f );\n""}\n""\n""float4 GammaToLinear( const float4 gamma )\n""{\n"" return float4( pow( gamma.xyz, 2.2f ), gamma.w );\n""}\n""\n""float GammaToLinear( const float gamma )\n""{\n"" return pow( gamma, 2.2f );\n""}\n""\n""// These two functions use the actual sRGB math\n""float SrgbGammaToLinear( float flSrgbGammaValue )\n""{\n"" float x = saturate( flSrgbGammaValue );\n"" return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) );\n""}\n""\n""float SrgbLinearToGamma( float flLinearValue )\n""{\n"" float x = saturate( flLinearValue );\n"" return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f;\n""}\n""\n""// These twofunctions use the XBox 360's exact piecewise linear algorithm\n""float X360GammaToLinear( float fl360GammaValue )\n""{\n"" float flLinearValue;\n""\n"" fl360GammaValue = saturate( fl360GammaValue );\n"" if ( fl360GammaValue < ( 96.0f / 255.0f ) )\n"" {\n"" if ( fl360GammaValue < ( 64.0f / 255.0f ) )\n"" {\n"" flLinearValue = fl360GammaValue * 255.0f;\n"" }\n"" else\n"" {\n"" flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f;\n"" flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) );\n"" }\n"" }\n"" else\n"" {\n"" if( fl360GammaValue < ( 192.0f / 255.0f ) )\n"" {\n"" flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f;\n"" flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) );\n"" }\n"" else\n"" {\n"" flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f;\n"" flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) );\n"" }\n"" }\n""\n"" flLinearValue *= 1.0f / 1023.0f;\n""\n"" flLinearValue = saturate( flLinearValue );\n"" return flLinearValue;\n""}\n""\n""float X360LinearToGamma( float flLinearValue )\n""{\n"" float fl360GammaValue;\n""\n"" flLinearValue = saturate( flLinearValue );\n"" if ( flLinearValue < ( 128.0f / 1023.0f ) )\n"" {\n"" if ( flLinearValue < ( 64.0f / 1023.0f ) )\n"" {\n"" fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) );\n"" }\n"" else\n"" {\n"" fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f );\n"" }\n"" }\n"" else\n"" {\n"" if ( flLinearValue < ( 512.0f / 1023.0f ) )\n"" {\n"" fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f );\n"" }\n"" else\n"" {\n"" fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016\n"" if ( fl360GammaValue > 1.0f )\n"" {\n"" fl360GammaValue = 1.0f;\n"" }\n"" }\n"" }\n""\n"" fl360GammaValue = saturate( fl360GammaValue );\n"" return fl360GammaValue;\n""}\n""\n""float SrgbGammaTo360Gamma( float flSrgbGammaValue )\n""{\n"" float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue );\n"" float fl360GammaValue = X360LinearToGamma( flLinearValue );\n"" return fl360GammaValue;\n""}\n""\n""float3 Vec3WorldToTangent( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""{\n"" float3 vTangentVector;\n"" vTangentVector.x = dot( iWorldVector.xyz, iWorldTangent.xyz );\n"" vTangentVector.y = dot( iWorldVector.xyz, iWorldBinormal.xyz );\n"" vTangentVector.z = dot( iWorldVector.xyz, iWorldNormal.xyz );\n"" return vTangentVector.xyz; // Return without normalizing\n""}\n""\n""float3 Vec3WorldToTangentNormalized( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""{\n"" return normalize( Vec3WorldToTangent( iWorldVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );\n""}\n""\n""float3 Vec3TangentToWorld( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""{\n"" float3 vWorldVector;\n"" vWorldVector.xyz = iTangentVector.x * iWorldTangent.xyz;\n"" vWorldVector.xyz += iTangentVector.y * iWorldBinormal.xyz;\n"" vWorldVector.xyz += iTangentVector.z * iWorldNormal.xyz;\n"" return vWorldVector.xyz; // Return without normalizing\n""}\n""\n""float3 Vec3TangentToWorldNormalized( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )\n""{\n"" return normalize( Vec3TangentToWorld( iTangentVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );\n""}\n""\n""#endif //#ifndef COMMON_FXC_H_\n""\n"; \ No newline at end of file diff --git a/source/common_hlsl_cpp_consts.h.inc b/source/common_hlsl_cpp_consts.h.inc index c98c802..25441fe 100644 --- a/source/common_hlsl_cpp_consts.h.inc +++ b/source/common_hlsl_cpp_consts.h.inc @@ -1 +1 @@ -const char common_hlsl_cpp_consts_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""//\n""\n""// Purpose: \n""\n""//\n""\n""// $NoKeywords: $\n""\n""//\n""\n""//=============================================================================//\n""\n""#ifndef COMMON_HLSL_CONSTS_H_\n""\n""#define COMMON_HLSL_CONSTS_H_\n""\n""\n""#ifdef NV3X\n""\n"" #define PSHADER_VECT_SCALE 20.0\n""\n"" #define VSHADER_VECT_SCALE (1.0 / (PSHADER_VECT_SCALE) )\n""\n""#else\n""\n"" #define PSHADER_VECT_SCALE 1.0\n""\n"" #define VSHADER_VECT_SCALE 1.0\n""\n""#endif\n""\n""\n""// GR - HDR luminance maps to 0..n range\n""\n""// IMPORTANT: Keep the same value as in materialsystem_global.h\n""\n""// HDRFIXME: Make this a pixel shader constant?\n""\n""#define MAX_HDR_OVERBRIGHT 16.0f\n""\n""\n""#define LINEAR_FOG_COLOR 29\n""\n""#define TONE_MAPPING_SCALE_PSH_CONSTANT 30\n""\n""\n""#endif //#ifndef COMMON_HLSL_CONSTS_H_\n""\n""\n"; \ No newline at end of file +const char common_hlsl_cpp_consts_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""//\n""// Purpose: \n""//\n""// $NoKeywords: $\n""//\n""//=============================================================================//\n""#ifndef COMMON_HLSL_CONSTS_H_\n""#define COMMON_HLSL_CONSTS_H_\n""\n""#ifdef NV3X\n"" #define PSHADER_VECT_SCALE 20.0\n"" #define VSHADER_VECT_SCALE (1.0 / (PSHADER_VECT_SCALE) )\n""#else\n"" #define PSHADER_VECT_SCALE 1.0\n"" #define VSHADER_VECT_SCALE 1.0\n""#endif\n""\n""// GR - HDR luminance maps to 0..n range\n""// IMPORTANT: Keep the same value as in materialsystem_global.h\n""// HDRFIXME: Make this a pixel shader constant?\n""#define MAX_HDR_OVERBRIGHT 16.0f\n""\n""#define LINEAR_FOG_COLOR 29\n""#define TONE_MAPPING_SCALE_PSH_CONSTANT 30\n""\n""#endif //#ifndef COMMON_HLSL_CONSTS_H_\n""\n"; \ No newline at end of file diff --git a/source/common_pragmas.h.inc b/source/common_pragmas.h.inc index 64988f7..e934a1c 100644 --- a/source/common_pragmas.h.inc +++ b/source/common_pragmas.h.inc @@ -1 +1 @@ -const char common_pragmas_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""//\n""\n""// Purpose: Common shader compiler pragmas\n""\n""//\n""\n""// $NoKeywords: $\n""\n""//\n""\n""//=============================================================================//\n""\n""#ifndef COMMON_PRAGMAS_H_\n""\n""#define COMMON_PRAGMAS_H_\n""\n""\n""//\n""\n""// Validated shader models:\n""\n""//\n""\n""// SHADER_MODEL_VS_1_1\n""\n""// SHADER_MODEL_VS_2_0\n""\n""// SHADER_MODEL_VS_3_0\n""\n""//\n""\n""// SHADER_MODEL_PS_1_1\n""\n""// SHADER_MODEL_PS_1_4\n""\n""// SHADER_MODEL_PS_2_0\n""\n""// SHADER_MODEL_PS_2_B\n""\n""// SHADER_MODEL_PS_3_0\n""\n""//\n""\n""//\n""\n""//\n""\n""// Platforms:\n""\n""//\n""\n""// PC\n""\n""// _X360\n""\n""//\n""\n""\n""// Special pragmas silencing common warnings\n""\n""#pragma warning ( disable : 3557 ) // warning X3557: Loop only executes for N iteration(s), forcing loop to unroll\n""\n""#pragma warning ( disable : 3595 ) // warning X3595: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused\n""\n""#pragma warning ( disable : 3596 ) // warning X3596: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused\n""\n""#pragma warning ( disable : 4702 ) // warning X4702: complement opportunity missed because input result WAS clamped from 0 to 1\n""\n""\n""#endif //#ifndef COMMON_PRAGMAS_H_\n""\n""\n"; \ No newline at end of file +const char common_pragmas_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""//\n""// Purpose: Common shader compiler pragmas\n""//\n""// $NoKeywords: $\n""//\n""//=============================================================================//\n""#ifndef COMMON_PRAGMAS_H_\n""#define COMMON_PRAGMAS_H_\n""\n""//\n""// Validated shader models:\n""//\n""// SHADER_MODEL_VS_1_1\n""// SHADER_MODEL_VS_2_0\n""// SHADER_MODEL_VS_3_0\n""//\n""// SHADER_MODEL_PS_1_1\n""// SHADER_MODEL_PS_1_4\n""// SHADER_MODEL_PS_2_0\n""// SHADER_MODEL_PS_2_B\n""// SHADER_MODEL_PS_3_0\n""//\n""//\n""//\n""// Platforms:\n""//\n""// PC\n""// _X360\n""//\n""\n""// Special pragmas silencing common warnings\n""#pragma warning ( disable : 3557 ) // warning X3557: Loop only executes for N iteration(s), forcing loop to unroll\n""#pragma warning ( disable : 3595 ) // warning X3595: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused\n""#pragma warning ( disable : 3596 ) // warning X3596: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused\n""#pragma warning ( disable : 4702 ) // warning X4702: complement opportunity missed because input result WAS clamped from 0 to 1\n""\n""#endif //#ifndef COMMON_PRAGMAS_H_\n""\n"; \ No newline at end of file diff --git a/source/common_ps_fxc.h.inc b/source/common_ps_fxc.h.inc index bb2d9e0..c85aa40 100644 --- a/source/common_ps_fxc.h.inc +++ b/source/common_ps_fxc.h.inc @@ -1 +1 @@ -const char common_ps_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""//\n""\n""// Purpose: Common pixel shader code\n""\n""//\n""\n""// $NoKeywords: $\n""\n""//\n""\n""//=============================================================================//\n""\n""#ifndef COMMON_PS_FXC_H_\n""\n""#define COMMON_PS_FXC_H_\n""\n""\n""#include \"common_fxc.h\"\n""\n""\n""// Put global skip commands here. . make sure and check that the appropriate vars are defined\n""\n""// so these aren't used on the wrong shaders!\n""\n""\n""// --------------------------------------------------------------------------------\n""\n""// HDR should never be enabled if we don't aren't running in float or integer HDR mode.\n""\n""// SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED\n""\n""// --------------------------------------------------------------------------------\n""\n""// We don't ever write water fog to dest alpha if we aren't doing water fog.\n""\n""// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA\n""\n""// --------------------------------------------------------------------------------\n""\n""// We don't need fog in the pixel shader if we aren't in float fog mode2\n""\n""// NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0\n""\n""// --------------------------------------------------------------------------------\n""\n""// We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer.\n""\n""// SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0\n""\n""// --------------------------------------------------------------------------------\n""\n""// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW.\n""\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT\n""\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST\n""\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH\n""\n""// --------------------------------------------------------------------------------\n""\n""// Ditch flashlight depth when flashlight is disabled\n""\n""// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW\n""\n""// --------------------------------------------------------------------------------\n""\n""\n""// System defined pixel shader constants\n""\n""\n""#if defined( _X360 )\n""\n""const bool g_bHighQualityShadows : register( b0 );\n""\n""#endif\n""\n""\n""// NOTE: w == 1.0f / (Dest alpha compressed depth range).\n""\n""const float4 g_LinearFogColor : register( c29 );\n""\n""#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w)\n""\n""\n""// Linear and gamma light scale values\n""\n""const float4 cLightScale : register( c30 );\n""\n""#define LINEAR_LIGHT_SCALE (cLightScale.x)\n""\n""#define LIGHT_MAP_SCALE (cLightScale.y)\n""\n""#define ENV_MAP_SCALE (cLightScale.z)\n""\n""#define GAMMA_LIGHT_SCALE (cLightScale.w)\n""\n""\n""// Flashlight constants\n""\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n""\n"" const float4 cFlashlightColor : register( c28 );\n""\n"" const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused\n""\n"" #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0\n""\n""#endif\n""\n""\n""#define HDR_INPUT_MAP_SCALE 16.0f\n""\n""\n""#define TONEMAP_SCALE_NONE 0\n""\n""#define TONEMAP_SCALE_LINEAR 1\n""\n""#define TONEMAP_SCALE_GAMMA 2\n""\n""\n""#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader\n""\n""#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits)\n""\n""#define PIXEL_FOG_TYPE_HEIGHT 1\n""\n""\n""// If you change these, make the corresponding change in hardwareconfig.cpp\n""\n""#define NVIDIA_PCF_POISSON 0\n""\n""#define ATI_NOPCF 1\n""\n""#define ATI_NO_PCF_FETCH4 2\n""\n""\n""struct LPREVIEW_PS_OUT\n""\n""{\n""\n"" float4 color : COLOR0;\n""\n"" float4 normal : COLOR1;\n""\n"" float4 position : COLOR2;\n""\n"" float4 flags : COLOR3;\n""\n""};\n""\n""\n""/*\n""\n""// unused\n""\n""HALF Luminance( HALF3 color )\n""\n""{\n""\n"" return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) );\n""\n""}\n""\n""*/\n""\n""\n""/*\n""\n""// unused\n""\n""HALF LuminanceScaled( HALF3 color )\n""\n""{\n""\n"" return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) );\n""\n""}\n""\n""*/\n""\n""\n""/*\n""\n""// unused\n""\n""HALF AvgColor( HALF3 color )\n""\n""{\n""\n"" return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) );\n""\n""}\n""\n""*/\n""\n""\n""/*\n""\n""// unused\n""\n""HALF4 DiffuseBump( sampler lightmapSampler,\n""\n"" float2 lightmapTexCoord1,\n""\n"" float2 lightmapTexCoord2,\n""\n"" float2 lightmapTexCoord3,\n""\n"" HALF3 normal )\n""\n""{\n""\n"" HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 );\n""\n"" HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 );\n""\n"" HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 );\n""\n""\n"" HALF3 diffuseLighting;\n""\n"" diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 +\n""\n"" saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 +\n""\n"" saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3;\n""\n""\n"" return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) );\n""\n""}\n""\n""*/\n""\n""\n""\n""/*\n""\n""// unused\n""\n""HALF Fresnel( HALF3 normal,\n""\n"" HALF3 eye,\n""\n"" HALF2 scaleBias )\n""\n""{\n""\n"" HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye );\n""\n"" fresnel = pow( fresnel, HALF_CONSTANT(5.0f) );\n""\n""\n"" return fresnel * scaleBias.x + scaleBias.y;\n""\n""}\n""\n""*/\n""\n""\n""/*\n""\n""// unused\n""\n""HALF4 GetNormal( sampler normalSampler,\n""\n"" float2 normalTexCoord )\n""\n""{\n""\n"" HALF4 normal = tex2D( normalSampler, normalTexCoord );\n""\n"" normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f);\n""\n""\n"" return normal;\n""\n""}\n""\n""*/\n""\n""\n""// Needs to match NormalDecodeMode_t enum in imaterialsystem.h\n""\n""#define NORM_DECODE_NONE 0\n""\n""#define NORM_DECODE_ATI2N 1\n""\n""#define NORM_DECODE_ATI2N_ALPHA 2\n""\n""\n""float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler )\n""\n""{\n""\n"" float4 normalTexel = tex2D( NormalSampler, tc );\n""\n"" float4 result;\n""\n""\n"" if ( nDecompressionMode == NORM_DECODE_NONE )\n""\n"" {\n""\n"" result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a );\n""\n"" }\n""\n"" else if ( nDecompressionMode == NORM_DECODE_ATI2N )\n""\n"" {\n""\n"" result.xy = normalTexel.xy * 2.0f - 1.0f;\n""\n"" result.z = sqrt( 1.0f - dot(result.xy, result.xy) );\n""\n"" result.a = 1.0f;\n""\n"" }\n""\n"" else // ATI2N plus ATI1N for alpha\n""\n"" {\n""\n"" result.xy = normalTexel.xy * 2.0f - 1.0f;\n""\n"" result.z = sqrt( 1.0f - dot(result.xy, result.xy) );\n""\n"" result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel\n""\n"" }\n""\n""\n"" return result;\n""\n""}\n""\n""\n""float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode )\n""\n""{\n""\n"" return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler );\n""\n""}\n""\n""\n""\n""HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input )\n""\n""{\n""\n""// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f;\n""\n"" return texCUBE( normalizeSampler, input );\n""\n""}\n""\n""\n""/*\n""\n""HALF4 EnvReflect( sampler envmapSampler,\n""\n"" sampler normalizeSampler,\n""\n"" HALF3 normal,\n""\n"" float3 eye,\n""\n"" HALF2 fresnelScaleBias )\n""\n""{\n""\n"" HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye );\n""\n"" HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias );\n""\n"" HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye );\n""\n"" return texCUBE( envmapSampler, reflect );\n""\n""}\n""\n""*/\n""\n""\n""float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange )\n""\n""{\n""\n""// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp\n""\n"" float flDepthFromWater = flWaterZ - flWorldPosZ;\n""\n""\n"" // if flDepthFromWater < 0, then set it to 0\n""\n"" // This is the equivalent of moving the vert to the water surface if it's above the water surface\n""\n"" // We'll do this with the saturate at the end instead.\n""\n""// flDepthFromWater = max( 0.0f, flDepthFromWater );\n""\n""\n"" // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer\n""\n"" // to the vert is actually underwater.\n""\n"" float flDepthFromEye = flEyePosZ - flWorldPosZ;\n""\n"" float f = saturate(flDepthFromWater * (1.0/flDepthFromEye));\n""\n""\n"" // $tmp.w is now the distance that we see through water.\n""\n"" return saturate(f * flProjPosZ * flFogOORange);\n""\n""}\n""\n""\n""float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange )\n""\n""{\n""\n""#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n""\n"" return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) );\n""\n""#else\n""\n"" return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots.\n""\n""#endif\n""\n""}\n""\n""\n""float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )\n""\n""{\n""\n"" float retVal;\n""\n"" if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )\n""\n"" {\n""\n"" retVal = 0.0f;\n""\n"" }\n""\n"" if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters\n""\n"" {\n""\n"" retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w );\n""\n"" }\n""\n"" else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog\n""\n"" {\n""\n"" retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w );\n""\n"" }\n""\n""\n"" return retVal;\n""\n""}\n""\n""\n""//g_FogParams not defined by default, but this is the same layout for every shader that does define it\n""\n""#define g_fPixelFogType g_ShaderControls.x\n""\n""#define g_fWriteDepthToAlpha g_ShaderControls.y\n""\n""#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z\n""\n""#define g_fVertexAlpha g_ShaderControls.w\n""\n""\n""#define g_FogEndOverRange g_FogParams.x\n""\n""#define g_WaterZ g_FogParams.y\n""\n""#define g_FogMaxDensity g_FogParams.z\n""\n""#define g_FogOORange g_FogParams.w\n""\n""\n""float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE )\n""\n""{\n""\n"" if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b\n""\n"" {\n""\n""# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n""\n"" pixelFogFactor = saturate( pixelFogFactor );\n""\n"" return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog\n""\n""# else\n""\n"" return vShaderColor;\n""\n""# endif\n""\n"" }\n""\n"" else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )\n""\n"" {\n""\n"" return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );\n""\n"" }\n""\n"" return vShaderColor;\n""\n""}\n""\n""\n""\n""#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) )\n""\n""sampler1D GammaTableSampler : register( s15 );\n""\n""\n""float3 SRGBOutput( const float3 vShaderColor )\n""\n""{ \n""\n"" //On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15.\n""\n"" float3 result;\n""\n"" result.r = tex1D( GammaTableSampler, vShaderColor.r ).r;\n""\n"" result.g = tex1D( GammaTableSampler, vShaderColor.g ).r;\n""\n"" result.b = tex1D( GammaTableSampler, vShaderColor.b ).r;\n""\n"" return result; \n""\n""}\n""\n""\n""#else\n""\n""\n""float3 SRGBOutput( const float3 vShaderColor )\n""\n""{\n""\n"" return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader\n""\n""}\n""\n""\n""#endif\n""\n""\n""\n""float SoftParticleDepth( float flDepth )\n""\n""{\n""\n"" return flDepth * OO_DESTALPHA_DEPTH_RANGE;\n""\n""}\n""\n""\n""\n""float DepthToDestAlpha( const float flProjZ )\n""\n""{\n""\n""#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n""\n"" return SoftParticleDepth( flProjZ );\n""\n""#else\n""\n"" return 1.0f;\n""\n""#endif\n""\n""}\n""\n""\n""\n""float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f )\n""\n""{\n""\n"" float4 result;\n""\n"" if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )\n""\n"" {\n""\n"" result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE;\n""\n"" }\n""\n"" else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )\n""\n"" {\n""\n"" result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE;\n""\n"" }\n""\n"" else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE )\n""\n"" {\n""\n"" result.rgb = vShaderColor.rgb;\n""\n"" }\n""\n"" \n""\n"" if( bWriteDepthToDestAlpha )\n""\n"" result.a = DepthToDestAlpha( flProjZ );\n""\n"" else\n""\n"" result.a = vShaderColor.a;\n""\n""\n"" result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE );\n""\n"" \n""\n""#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n""\n"" result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion\n""\n""#endif\n""\n""\n"" return result;\n""\n""}\n""\n""\n""LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE )\n""\n""{\n""\n"" LPREVIEW_PS_OUT result;\n""\n"" result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE );\n""\n"" result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb );\n""\n"" result.normal.a = vShaderColor.normal.a;\n""\n""\n"" result.position.rgb = SRGBOutput( vShaderColor.position.rgb );\n""\n"" result.position.a = vShaderColor.position.a;\n""\n""\n"" result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb ); \n""\n"" result.flags.a = vShaderColor.flags.a;\n""\n""\n"" return result;\n""\n""}\n""\n""\n""\n""\n""\n""float RemapValClamped( float val, float A, float B, float C, float D)\n""\n""{\n""\n"" float cVal = (val - A) / (B - A);\n""\n"" cVal = saturate( cVal );\n""\n""\n"" return C + (D - C) * cVal;\n""\n""}\n""\n""\n""\n""//===================================================================================//\n""\n""// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI)\n""\n""//===================================================================================//\n""\n""// INPUT:\n""\n""// inTexCoord: \n""\n""// the texcoord for the height/displacement map before parallaxing\n""\n""//\n""\n""// vParallax:\n""\n""// Compute initial parallax displacement direction:\n""\n""// float2 vParallaxDirection = normalize( vViewTS.xy );\n""\n""// float fLength = length( vViewTS );\n""\n""// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z; \n""\n""// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight;\n""\n""//\n""\n""// vNormal:\n""\n""// tangent space normal\n""\n""//\n""\n""// vViewW: \n""\n""// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition );\n""\n""//\n""\n""// OUTPUT:\n""\n""// the new texcoord after parallaxing\n""\n""float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal, \n""\n"" float3 vViewW, sampler HeightMapSampler )\n""\n""{\n""\n"" const int nMinSamples = 8;\n""\n"" const int nMaxSamples = 50;\n""\n""\n"" // Normalize the incoming view vector to avoid artifacts:\n""\n""// vView = normalize( vView );\n""\n"" vViewW = normalize( vViewW );\n""\n""// vLight = normalize( vLight );\n""\n"" \n""\n"" // Change the number of samples per ray depending on the viewing angle\n""\n"" // for the surface. Oblique angles require smaller step sizes to achieve \n""\n"" // more accurate precision \n""\n"" int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) );\n""\n"" \n""\n"" float4 cResultColor = float4( 0, 0, 0, 1 );\n""\n"" \n""\n"" //===============================================//\n""\n"" // Parallax occlusion mapping offset computation //\n""\n"" //===============================================// \n""\n"" float fCurrHeight = 0.0;\n""\n"" float fStepSize = 1.0 / (float) nNumSteps;\n""\n"" float fPrevHeight = 1.0;\n""\n"" float fNextHeight = 0.0;\n""\n""\n"" int nStepIndex = 0;\n""\n""// bool bCondition = true;\n""\n"" \n""\n"" float2 dx = ddx( inTexCoord );\n""\n"" float2 dy = ddy( inTexCoord );\n""\n"" \n""\n"" float2 vTexOffsetPerStep = fStepSize * vParallax;\n""\n"" \n""\n"" float2 vTexCurrentOffset = inTexCoord;\n""\n"" float fCurrentBound = 1.0;\n""\n"" \n""\n"" float x = 0;\n""\n"" float y = 0;\n""\n"" float xh = 0;\n""\n"" float yh = 0; \n""\n"" \n""\n"" float2 texOffset2 = 0;\n""\n"" \n""\n"" bool bCondition = true;\n""\n"" while ( bCondition == true && nStepIndex < nNumSteps ) \n""\n"" {\n""\n"" vTexCurrentOffset -= vTexOffsetPerStep;\n""\n"" \n""\n"" fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r;\n""\n"" \n""\n"" fCurrentBound -= fStepSize;\n""\n"" \n""\n"" if ( fCurrHeight > fCurrentBound ) \n""\n"" { \n""\n"" x = fCurrentBound; \n""\n"" y = fCurrentBound + fStepSize; \n""\n"" xh = fCurrHeight;\n""\n"" yh = fPrevHeight;\n""\n"" \n""\n"" texOffset2 = vTexCurrentOffset - vTexOffsetPerStep;\n""\n"" \n""\n"" bCondition = false;\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" nStepIndex++;\n""\n"" fPrevHeight = fCurrHeight;\n""\n"" }\n""\n"" \n""\n"" } // End of while ( bCondition == true && nStepIndex > -1 )#else\n""\n""\n"" fCurrentBound -= fStepSize;\n""\n"" \n""\n"" float fParallaxAmount;\n""\n"" float numerator = (x * (y - yh) - y * (x - xh));\n""\n"" float denomenator = ((y - yh) - (x - xh));\n""\n"" // avoid NaN generation\n""\n"" if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) )\n""\n"" {\n""\n"" fParallaxAmount = 0.0f;\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" fParallaxAmount = numerator / denomenator;\n""\n"" }\n""\n""\n"" float2 vParallaxOffset = vParallax * (1 - fParallaxAmount );\n""\n""\n"" // Sample the height at the next possible step:\n""\n"" fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r;\n""\n"" \n""\n"" // Original offset:\n""\n"" float2 texSampleBase = inTexCoord - vParallaxOffset;\n""\n""\n"" return texSampleBase;\n""\n""\n""#if 0\n""\n"" cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight );\n""\n"" \n""\n"" float fBound = 1.0 - fStepSize * nStepIndex;\n""\n"" if ( fNextHeight < fCurrentBound )\n""\n""// if( 0 )\n""\n"" {\n""\n"" //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor )\n""\n"" //cResultColor.rgb = float3(1,0,0);\n""\n"" DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n""\n"" DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n""\n"" DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n""\n"" DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n""\n""\n"" cResultColor.rgb /= 5;\n""\n""// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f );\n""\n"" } // End of if ( fNextHeight < fCurrentBound )\n""\n"" \n""\n""#if DOSHADOWS\n""\n"" {\n""\n"" //============================================//\n""\n"" // Soft shadow and self-occlusion computation //\n""\n"" //============================================//\n""\n"" // Compute the blurry shadows (note that this computation takes into \n""\n"" // account self-occlusion for shadow computation):\n""\n"" float sh0 = tex2D( sNormalMap, texSampleBase).w;\n""\n"" float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening;\n""\n"" float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening;\n""\n"" float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening;\n""\n"" float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening;\n""\n"" float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening;\n""\n"" float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening;\n""\n"" float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening;\n""\n"" \n""\n"" // Compute the actual shadow strength:\n""\n"" float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 );\n""\n""\n"" cResultColor.rgb *= fShadow * 0.6 + 0.4;\n""\n"" }\n""\n""#endif\n""\n"" \n""\n"" return cResultColor;\n""\n""#endif\n""\n""}\n""\n""\n""\n""//======================================//\n""\n""// HSL Color space conversion routines //\n""\n""//======================================//\n""\n""\n""#define HUE 0\n""\n""#define SATURATION 1\n""\n""#define LIGHTNESS 2\n""\n""\n""// Convert from RGB to HSL color space\n""\n""float4 RGBtoHSL( float4 inColor )\n""\n""{\n""\n"" float h, s;\n""\n"" float flMax = max( inColor.r, max( inColor.g, inColor.b ) );\n""\n"" float flMin = min( inColor.r, min( inColor.g, inColor.b ) );\n""\n"" \n""\n"" float l = (flMax + flMin) / 2.0f;\n""\n"" \n""\n"" if (flMax == flMin) // achromatic case\n""\n"" {\n""\n"" s = h = 0;\n""\n"" }\n""\n"" else // chromatic case\n""\n"" {\n""\n"" // Next, calculate the hue\n""\n"" float delta = flMax - flMin;\n""\n"" \n""\n"" // First, calculate the saturation\n""\n"" if (l < 0.5f) // If we're in the lower hexcone\n""\n"" {\n""\n"" s = delta/(flMax + flMin);\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" s = delta/(2 - flMax - flMin);\n""\n"" }\n""\n"" \n""\n"" if ( inColor.r == flMax )\n""\n"" {\n""\n"" h = (inColor.g - inColor.b)/delta; // color between yellow and magenta\n""\n"" }\n""\n"" else if ( inColor.g == flMax )\n""\n"" {\n""\n"" h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow\n""\n"" }\n""\n"" else // blue must be max\n""\n"" {\n""\n"" h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan\n""\n"" }\n""\n"" \n""\n"" h *= 60.0f;\n""\n"" \n""\n"" if (h < 0.0f)\n""\n"" {\n""\n"" h += 360.0f;\n""\n"" }\n""\n"" \n""\n"" h /= 360.0f; \n""\n"" }\n""\n""\n"" return float4 (h, s, l, 1.0f);\n""\n""}\n""\n""\n""float HueToRGB( float v1, float v2, float vH )\n""\n""{\n""\n"" float fResult = v1;\n""\n"" \n""\n"" vH = fmod (vH + 1.0f, 1.0f);\n""\n""\n"" if ( ( 6.0f * vH ) < 1.0f )\n""\n"" {\n""\n"" fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH );\n""\n"" }\n""\n"" else if ( ( 2.0f * vH ) < 1.0f )\n""\n"" {\n""\n"" fResult = ( v2 );\n""\n"" }\n""\n"" else if ( ( 3.0f * vH ) < 2.0f )\n""\n"" {\n""\n"" fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f );\n""\n"" }\n""\n""\n"" return fResult;\n""\n""}\n""\n""\n""// Convert from HSL to RGB color space\n""\n""float4 HSLtoRGB( float4 hsl )\n""\n""{\n""\n"" float r, g, b;\n""\n"" float h = hsl[HUE];\n""\n"" float s = hsl[SATURATION];\n""\n"" float l = hsl[LIGHTNESS];\n""\n""\n"" if ( s == 0 )\n""\n"" {\n""\n"" r = g = b = l;\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" float v1, v2;\n""\n"" \n""\n"" if ( l < 0.5f )\n""\n"" v2 = l * ( 1.0f + s );\n""\n"" else\n""\n"" v2 = ( l + s ) - ( s * l );\n""\n""\n"" v1 = 2 * l - v2;\n""\n""\n"" r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) );\n""\n"" g = HueToRGB( v1, v2, h );\n""\n"" b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) );\n""\n"" }\n""\n"" \n""\n"" return float4( r, g, b, 1.0f );\n""\n""}\n""\n""\n""\n""// texture combining modes for combining base and detail/basetexture2\n""\n""#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode\n""\n""#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend\n""\n""#define TCOMBINE_DETAIL_OVER_BASE 2\n""\n""#define TCOMBINE_FADE 3 // straight fade between base and detail.\n""\n""#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail\n""\n""#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting\n""\n""#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6\n""\n""#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail\n""\n""#define TCOMBINE_MULTIPLY 8\n""\n""#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base\n""\n""#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump\n""\n""#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11\n""\n""\n""float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode,\n""\n"" float fBlendFactor )\n""\n""{\n""\n"" if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS)\n""\n"" {\n""\n"" float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a);\n""\n"" baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor);\n""\n"" }\n""\n"" if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2)\n""\n"" baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor);\n""\n"" if ( combine_mode == TCOMBINE_RGB_ADDITIVE )\n""\n"" baseColor.rgb += fBlendFactor * detailColor.rgb;\n""\n"" if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE )\n""\n"" {\n""\n"" float fblend=fBlendFactor * detailColor.a;\n""\n"" baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend);\n""\n"" }\n""\n"" if ( combine_mode == TCOMBINE_FADE )\n""\n"" {\n""\n"" baseColor = lerp( baseColor, detailColor, fBlendFactor);\n""\n"" }\n""\n"" if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL )\n""\n"" {\n""\n"" float fblend=fBlendFactor * (1-baseColor.a);\n""\n"" baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend );\n""\n"" baseColor.a = detailColor.a;\n""\n"" }\n""\n"" if ( combine_mode == TCOMBINE_MULTIPLY )\n""\n"" {\n""\n"" baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor);\n""\n"" }\n""\n""\n"" if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA )\n""\n"" {\n""\n"" baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor );\n""\n"" }\n""\n"" if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP )\n""\n"" {\n""\n"" baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 );\n""\n"" }\n""\n"" return baseColor;\n""\n""}\n""\n""\n""float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x)\n""\n""{\n""\n"" return f1+(f2-f1)*(x-i1)/(i2-i1);\n""\n""}\n""\n""\n""float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode,\n""\n"" float fBlendFactor )\n""\n""{\n""\n"" if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM )\n""\n"" lit_baseColor += fBlendFactor * detailColor.rgb;\n""\n"" if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE )\n""\n"" {\n""\n"" // fade in an unusual way - instead of fading out color, remap an increasing band of it from\n""\n"" // 0..1\n""\n"" //if (fBlendFactor > 0.5)\n""\n"" // lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) );\n""\n"" //else\n""\n"" // lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5);\n""\n""\n"" float f = fBlendFactor - 0.5;\n""\n"" float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor;\n""\n"" float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult;\n""\n"" lit_baseColor += saturate(fMult * detailColor.rgb + fAdd);\n""\n"" }\n""\n"" return lit_baseColor;\n""\n""}\n""\n""\n""//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader\n""\n""float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants )\n""\n""{\n""\n""# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b\n""\n"" {\n""\n"" float flFeatheredAlpha;\n""\n"" float2 flDepths;\n""\n""#define flSceneDepth flDepths.x\n""\n""#define flSpriteDepth flDepths.y\n""\n""\n""# if ( defined( _X360 ) )\n""\n"" {\n""\n"" //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors\n""\n"" asm {\n""\n"" tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point\n""\n"" };\n""\n""\n""# if( !defined( REVERSE_DEPTH_ON_X360 ) )\n""\n"" flSceneDepth = 1.0f - flSceneDepth;\n""\n""# endif\n""\n""\n"" //get the sprite depth into the same range as the texture depth\n""\n"" flSpriteDepth = fProjZ / fProjW;\n""\n""\n"" //unproject to get at the pre-projection z. This value is much more linear than depth\n""\n"" flDepths = vDepthBlendConstants.z / flDepths;\n""\n"" flDepths = vDepthBlendConstants.y - flDepths;\n""\n""\n"" flFeatheredAlpha = flSceneDepth - flSpriteDepth;\n""\n"" flFeatheredAlpha *= vDepthBlendConstants.x;\n""\n"" flFeatheredAlpha = saturate( flFeatheredAlpha );\n""\n"" }\n""\n""# else\n""\n"" {\n""\n"" flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer\n""\n"" flSpriteDepth = SoftParticleDepth( fProjZ );\n""\n""\n"" flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x;\n""\n"" flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering.\n""\n"" flFeatheredAlpha = saturate( flFeatheredAlpha );\n""\n"" }\n""\n""# endif\n""\n""\n""#undef flSceneDepth\n""\n""#undef flSpriteDepth\n""\n""\n"" return flFeatheredAlpha;\n""\n"" }\n""\n""# else\n""\n"" {\n""\n"" return 1.0f;\n""\n"" }\n""\n""# endif\n""\n""}\n""\n""\n""#endif //#ifndef COMMON_PS_FXC_H_\n""\n""\n"; \ No newline at end of file +const char common_ps_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""//\n""// Purpose: Common pixel shader code\n""//\n""// $NoKeywords: $\n""//\n""//=============================================================================//\n""#ifndef COMMON_PS_FXC_H_\n""#define COMMON_PS_FXC_H_\n""\n""#include \"common_fxc.h\"\n""\n""// Put global skip commands here. . make sure and check that the appropriate vars are defined\n""// so these aren't used on the wrong shaders!\n""\n""// --------------------------------------------------------------------------------\n""// HDR should never be enabled if we don't aren't running in float or integer HDR mode.\n""// SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED\n""// --------------------------------------------------------------------------------\n""// We don't ever write water fog to dest alpha if we aren't doing water fog.\n""// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA\n""// --------------------------------------------------------------------------------\n""// We don't need fog in the pixel shader if we aren't in float fog mode2\n""// NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0\n""// --------------------------------------------------------------------------------\n""// We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer.\n""// SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0\n""// --------------------------------------------------------------------------------\n""// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW.\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH\n""// --------------------------------------------------------------------------------\n""// Ditch flashlight depth when flashlight is disabled\n""// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW\n""// --------------------------------------------------------------------------------\n""\n""// System defined pixel shader constants\n""\n""#if defined( _X360 )\n""const bool g_bHighQualityShadows : register( b0 );\n""#endif\n""\n""// NOTE: w == 1.0f / (Dest alpha compressed depth range).\n""const float4 g_LinearFogColor : register( c29 );\n""#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w)\n""\n""// Linear and gamma light scale values\n""const float4 cLightScale : register( c30 );\n""#define LINEAR_LIGHT_SCALE (cLightScale.x)\n""#define LIGHT_MAP_SCALE (cLightScale.y)\n""#define ENV_MAP_SCALE (cLightScale.z)\n""#define GAMMA_LIGHT_SCALE (cLightScale.w)\n""\n""// Flashlight constants\n""#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)\n"" const float4 cFlashlightColor : register( c28 );\n"" const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused\n"" #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0\n""#endif\n""\n""#define HDR_INPUT_MAP_SCALE 16.0f\n""\n""#define TONEMAP_SCALE_NONE 0\n""#define TONEMAP_SCALE_LINEAR 1\n""#define TONEMAP_SCALE_GAMMA 2\n""\n""#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader\n""#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits)\n""#define PIXEL_FOG_TYPE_HEIGHT 1\n""\n""// If you change these, make the corresponding change in hardwareconfig.cpp\n""#define NVIDIA_PCF_POISSON 0\n""#define ATI_NOPCF 1\n""#define ATI_NO_PCF_FETCH4 2\n""\n""struct LPREVIEW_PS_OUT\n""{\n"" float4 color : COLOR0;\n"" float4 normal : COLOR1;\n"" float4 position : COLOR2;\n"" float4 flags : COLOR3;\n""};\n""\n""/*\n""// unused\n""HALF Luminance( HALF3 color )\n""{\n"" return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) );\n""}\n""*/\n""\n""/*\n""// unused\n""HALF LuminanceScaled( HALF3 color )\n""{\n"" return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) );\n""}\n""*/\n""\n""/*\n""// unused\n""HALF AvgColor( HALF3 color )\n""{\n"" return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) );\n""}\n""*/\n""\n""/*\n""// unused\n""HALF4 DiffuseBump( sampler lightmapSampler,\n"" float2 lightmapTexCoord1,\n"" float2 lightmapTexCoord2,\n"" float2 lightmapTexCoord3,\n"" HALF3 normal )\n""{\n"" HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 );\n"" HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 );\n"" HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 );\n""\n"" HALF3 diffuseLighting;\n"" diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 +\n"" saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 +\n"" saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3;\n""\n"" return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) );\n""}\n""*/\n""\n""\n""/*\n""// unused\n""HALF Fresnel( HALF3 normal,\n"" HALF3 eye,\n"" HALF2 scaleBias )\n""{\n"" HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye );\n"" fresnel = pow( fresnel, HALF_CONSTANT(5.0f) );\n""\n"" return fresnel * scaleBias.x + scaleBias.y;\n""}\n""*/\n""\n""/*\n""// unused\n""HALF4 GetNormal( sampler normalSampler,\n"" float2 normalTexCoord )\n""{\n"" HALF4 normal = tex2D( normalSampler, normalTexCoord );\n"" normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f);\n""\n"" return normal;\n""}\n""*/\n""\n""// Needs to match NormalDecodeMode_t enum in imaterialsystem.h\n""#define NORM_DECODE_NONE 0\n""#define NORM_DECODE_ATI2N 1\n""#define NORM_DECODE_ATI2N_ALPHA 2\n""\n""float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler )\n""{\n"" float4 normalTexel = tex2D( NormalSampler, tc );\n"" float4 result;\n""\n"" if ( nDecompressionMode == NORM_DECODE_NONE )\n"" {\n"" result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a );\n"" }\n"" else if ( nDecompressionMode == NORM_DECODE_ATI2N )\n"" {\n"" result.xy = normalTexel.xy * 2.0f - 1.0f;\n"" result.z = sqrt( 1.0f - dot(result.xy, result.xy) );\n"" result.a = 1.0f;\n"" }\n"" else // ATI2N plus ATI1N for alpha\n"" {\n"" result.xy = normalTexel.xy * 2.0f - 1.0f;\n"" result.z = sqrt( 1.0f - dot(result.xy, result.xy) );\n"" result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel\n"" }\n""\n"" return result;\n""}\n""\n""float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode )\n""{\n"" return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler );\n""}\n""\n""\n""HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input )\n""{\n""// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f;\n"" return texCUBE( normalizeSampler, input );\n""}\n""\n""/*\n""HALF4 EnvReflect( sampler envmapSampler,\n"" sampler normalizeSampler,\n"" HALF3 normal,\n"" float3 eye,\n"" HALF2 fresnelScaleBias )\n""{\n"" HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye );\n"" HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias );\n"" HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye );\n"" return texCUBE( envmapSampler, reflect );\n""}\n""*/\n""\n""float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange )\n""{\n""// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp\n"" float flDepthFromWater = flWaterZ - flWorldPosZ;\n""\n"" // if flDepthFromWater < 0, then set it to 0\n"" // This is the equivalent of moving the vert to the water surface if it's above the water surface\n"" // We'll do this with the saturate at the end instead.\n""// flDepthFromWater = max( 0.0f, flDepthFromWater );\n""\n"" // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer\n"" // to the vert is actually underwater.\n"" float flDepthFromEye = flEyePosZ - flWorldPosZ;\n"" float f = saturate(flDepthFromWater * (1.0/flDepthFromEye));\n""\n"" // $tmp.w is now the distance that we see through water.\n"" return saturate(f * flProjPosZ * flFogOORange);\n""}\n""\n""float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange )\n""{\n""#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n"" return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) );\n""#else\n"" return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots.\n""#endif\n""}\n""\n""float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )\n""{\n"" float retVal;\n"" if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )\n"" {\n"" retVal = 0.0f;\n"" }\n"" if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters\n"" {\n"" retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w );\n"" }\n"" else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog\n"" {\n"" retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w );\n"" }\n""\n"" return retVal;\n""}\n""\n""//g_FogParams not defined by default, but this is the same layout for every shader that does define it\n""#define g_fPixelFogType g_ShaderControls.x\n""#define g_fWriteDepthToAlpha g_ShaderControls.y\n""#define g_fWriteWaterFogToDestAlpha g_ShaderControls.z\n""#define g_fVertexAlpha g_ShaderControls.w\n""\n""#define g_FogEndOverRange g_FogParams.x\n""#define g_WaterZ g_FogParams.y\n""#define g_FogMaxDensity g_FogParams.z\n""#define g_FogOORange g_FogParams.w\n""\n""float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE )\n""{\n"" if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b\n"" {\n""# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n"" pixelFogFactor = saturate( pixelFogFactor );\n"" return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog\n""# else\n"" return vShaderColor;\n""# endif\n"" }\n"" else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )\n"" {\n"" return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );\n"" }\n"" return vShaderColor;\n""}\n""\n""\n""#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) )\n""sampler1D GammaTableSampler : register( s15 );\n""\n""float3 SRGBOutput( const float3 vShaderColor )\n""{ \n"" //On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15.\n"" float3 result;\n"" result.r = tex1D( GammaTableSampler, vShaderColor.r ).r;\n"" result.g = tex1D( GammaTableSampler, vShaderColor.g ).r;\n"" result.b = tex1D( GammaTableSampler, vShaderColor.b ).r;\n"" return result; \n""}\n""\n""#else\n""\n""float3 SRGBOutput( const float3 vShaderColor )\n""{\n"" return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader\n""}\n""\n""#endif\n""\n""\n""float SoftParticleDepth( float flDepth )\n""{\n"" return flDepth * OO_DESTALPHA_DEPTH_RANGE;\n""}\n""\n""\n""float DepthToDestAlpha( const float flProjZ )\n""{\n""#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n"" return SoftParticleDepth( flProjZ );\n""#else\n"" return 1.0f;\n""#endif\n""}\n""\n""\n""float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f )\n""{\n"" float4 result;\n"" if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )\n"" {\n"" result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE;\n"" }\n"" else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )\n"" {\n"" result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE;\n"" }\n"" else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE )\n"" {\n"" result.rgb = vShaderColor.rgb;\n"" }\n"" \n"" if( bWriteDepthToDestAlpha )\n"" result.a = DepthToDestAlpha( flProjZ );\n"" else\n"" result.a = vShaderColor.a;\n""\n"" result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE );\n"" \n""#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b\n"" result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion\n""#endif\n""\n"" return result;\n""}\n""\n""LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE )\n""{\n"" LPREVIEW_PS_OUT result;\n"" result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE );\n"" result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb );\n"" result.normal.a = vShaderColor.normal.a;\n""\n"" result.position.rgb = SRGBOutput( vShaderColor.position.rgb );\n"" result.position.a = vShaderColor.position.a;\n""\n"" result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb ); \n"" result.flags.a = vShaderColor.flags.a;\n""\n"" return result;\n""}\n""\n""\n""\n""\n""float RemapValClamped( float val, float A, float B, float C, float D)\n""{\n"" float cVal = (val - A) / (B - A);\n"" cVal = saturate( cVal );\n""\n"" return C + (D - C) * cVal;\n""}\n""\n""\n""//===================================================================================//\n""// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI)\n""//===================================================================================//\n""// INPUT:\n""// inTexCoord: \n""// the texcoord for the height/displacement map before parallaxing\n""//\n""// vParallax:\n""// Compute initial parallax displacement direction:\n""// float2 vParallaxDirection = normalize( vViewTS.xy );\n""// float fLength = length( vViewTS );\n""// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z; \n""// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight;\n""//\n""// vNormal:\n""// tangent space normal\n""//\n""// vViewW: \n""// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition );\n""//\n""// OUTPUT:\n""// the new texcoord after parallaxing\n""float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal, \n"" float3 vViewW, sampler HeightMapSampler )\n""{\n"" const int nMinSamples = 8;\n"" const int nMaxSamples = 50;\n""\n"" // Normalize the incoming view vector to avoid artifacts:\n""// vView = normalize( vView );\n"" vViewW = normalize( vViewW );\n""// vLight = normalize( vLight );\n"" \n"" // Change the number of samples per ray depending on the viewing angle\n"" // for the surface. Oblique angles require smaller step sizes to achieve \n"" // more accurate precision \n"" int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) );\n"" \n"" float4 cResultColor = float4( 0, 0, 0, 1 );\n"" \n"" //===============================================//\n"" // Parallax occlusion mapping offset computation //\n"" //===============================================// \n"" float fCurrHeight = 0.0;\n"" float fStepSize = 1.0 / (float) nNumSteps;\n"" float fPrevHeight = 1.0;\n"" float fNextHeight = 0.0;\n""\n"" int nStepIndex = 0;\n""// bool bCondition = true;\n"" \n"" float2 dx = ddx( inTexCoord );\n"" float2 dy = ddy( inTexCoord );\n"" \n"" float2 vTexOffsetPerStep = fStepSize * vParallax;\n"" \n"" float2 vTexCurrentOffset = inTexCoord;\n"" float fCurrentBound = 1.0;\n"" \n"" float x = 0;\n"" float y = 0;\n"" float xh = 0;\n"" float yh = 0; \n"" \n"" float2 texOffset2 = 0;\n"" \n"" bool bCondition = true;\n"" while ( bCondition == true && nStepIndex < nNumSteps ) \n"" {\n"" vTexCurrentOffset -= vTexOffsetPerStep;\n"" \n"" fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r;\n"" \n"" fCurrentBound -= fStepSize;\n"" \n"" if ( fCurrHeight > fCurrentBound ) \n"" { \n"" x = fCurrentBound; \n"" y = fCurrentBound + fStepSize; \n"" xh = fCurrHeight;\n"" yh = fPrevHeight;\n"" \n"" texOffset2 = vTexCurrentOffset - vTexOffsetPerStep;\n"" \n"" bCondition = false;\n"" }\n"" else\n"" {\n"" nStepIndex++;\n"" fPrevHeight = fCurrHeight;\n"" }\n"" \n"" } // End of while ( bCondition == true && nStepIndex > -1 )#else\n""\n"" fCurrentBound -= fStepSize;\n"" \n"" float fParallaxAmount;\n"" float numerator = (x * (y - yh) - y * (x - xh));\n"" float denomenator = ((y - yh) - (x - xh));\n"" // avoid NaN generation\n"" if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) )\n"" {\n"" fParallaxAmount = 0.0f;\n"" }\n"" else\n"" {\n"" fParallaxAmount = numerator / denomenator;\n"" }\n""\n"" float2 vParallaxOffset = vParallax * (1 - fParallaxAmount );\n""\n"" // Sample the height at the next possible step:\n"" fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r;\n"" \n"" // Original offset:\n"" float2 texSampleBase = inTexCoord - vParallaxOffset;\n""\n"" return texSampleBase;\n""\n""#if 0\n"" cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight );\n"" \n"" float fBound = 1.0 - fStepSize * nStepIndex;\n"" if ( fNextHeight < fCurrentBound )\n""// if( 0 )\n"" {\n"" //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor )\n"" //cResultColor.rgb = float3(1,0,0);\n"" DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n"" DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n"" DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n"" DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );\n""\n"" cResultColor.rgb /= 5;\n""// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f );\n"" } // End of if ( fNextHeight < fCurrentBound )\n"" \n""#if DOSHADOWS\n"" {\n"" //============================================//\n"" // Soft shadow and self-occlusion computation //\n"" //============================================//\n"" // Compute the blurry shadows (note that this computation takes into \n"" // account self-occlusion for shadow computation):\n"" float sh0 = tex2D( sNormalMap, texSampleBase).w;\n"" float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening;\n"" float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening;\n"" float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening;\n"" float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening;\n"" float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening;\n"" float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening;\n"" float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening;\n"" \n"" // Compute the actual shadow strength:\n"" float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 );\n""\n"" cResultColor.rgb *= fShadow * 0.6 + 0.4;\n"" }\n""#endif\n"" \n"" return cResultColor;\n""#endif\n""}\n""\n""\n""//======================================//\n""// HSL Color space conversion routines //\n""//======================================//\n""\n""#define HUE 0\n""#define SATURATION 1\n""#define LIGHTNESS 2\n""\n""// Convert from RGB to HSL color space\n""float4 RGBtoHSL( float4 inColor )\n""{\n"" float h, s;\n"" float flMax = max( inColor.r, max( inColor.g, inColor.b ) );\n"" float flMin = min( inColor.r, min( inColor.g, inColor.b ) );\n"" \n"" float l = (flMax + flMin) / 2.0f;\n"" \n"" if (flMax == flMin) // achromatic case\n"" {\n"" s = h = 0;\n"" }\n"" else // chromatic case\n"" {\n"" // Next, calculate the hue\n"" float delta = flMax - flMin;\n"" \n"" // First, calculate the saturation\n"" if (l < 0.5f) // If we're in the lower hexcone\n"" {\n"" s = delta/(flMax + flMin);\n"" }\n"" else\n"" {\n"" s = delta/(2 - flMax - flMin);\n"" }\n"" \n"" if ( inColor.r == flMax )\n"" {\n"" h = (inColor.g - inColor.b)/delta; // color between yellow and magenta\n"" }\n"" else if ( inColor.g == flMax )\n"" {\n"" h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow\n"" }\n"" else // blue must be max\n"" {\n"" h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan\n"" }\n"" \n"" h *= 60.0f;\n"" \n"" if (h < 0.0f)\n"" {\n"" h += 360.0f;\n"" }\n"" \n"" h /= 360.0f; \n"" }\n""\n"" return float4 (h, s, l, 1.0f);\n""}\n""\n""float HueToRGB( float v1, float v2, float vH )\n""{\n"" float fResult = v1;\n"" \n"" vH = fmod (vH + 1.0f, 1.0f);\n""\n"" if ( ( 6.0f * vH ) < 1.0f )\n"" {\n"" fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH );\n"" }\n"" else if ( ( 2.0f * vH ) < 1.0f )\n"" {\n"" fResult = ( v2 );\n"" }\n"" else if ( ( 3.0f * vH ) < 2.0f )\n"" {\n"" fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f );\n"" }\n""\n"" return fResult;\n""}\n""\n""// Convert from HSL to RGB color space\n""float4 HSLtoRGB( float4 hsl )\n""{\n"" float r, g, b;\n"" float h = hsl[HUE];\n"" float s = hsl[SATURATION];\n"" float l = hsl[LIGHTNESS];\n""\n"" if ( s == 0 )\n"" {\n"" r = g = b = l;\n"" }\n"" else\n"" {\n"" float v1, v2;\n"" \n"" if ( l < 0.5f )\n"" v2 = l * ( 1.0f + s );\n"" else\n"" v2 = ( l + s ) - ( s * l );\n""\n"" v1 = 2 * l - v2;\n""\n"" r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) );\n"" g = HueToRGB( v1, v2, h );\n"" b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) );\n"" }\n"" \n"" return float4( r, g, b, 1.0f );\n""}\n""\n""\n""// texture combining modes for combining base and detail/basetexture2\n""#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode\n""#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend\n""#define TCOMBINE_DETAIL_OVER_BASE 2\n""#define TCOMBINE_FADE 3 // straight fade between base and detail.\n""#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail\n""#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting\n""#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6\n""#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail\n""#define TCOMBINE_MULTIPLY 8\n""#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base\n""#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump\n""#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11\n""\n""float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode,\n"" float fBlendFactor )\n""{\n"" if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS)\n"" {\n"" float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a);\n"" baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor);\n"" }\n"" if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2)\n"" baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor);\n"" if ( combine_mode == TCOMBINE_RGB_ADDITIVE )\n"" baseColor.rgb += fBlendFactor * detailColor.rgb;\n"" if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE )\n"" {\n"" float fblend=fBlendFactor * detailColor.a;\n"" baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend);\n"" }\n"" if ( combine_mode == TCOMBINE_FADE )\n"" {\n"" baseColor = lerp( baseColor, detailColor, fBlendFactor);\n"" }\n"" if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL )\n"" {\n"" float fblend=fBlendFactor * (1-baseColor.a);\n"" baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend );\n"" baseColor.a = detailColor.a;\n"" }\n"" if ( combine_mode == TCOMBINE_MULTIPLY )\n"" {\n"" baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor);\n"" }\n""\n"" if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA )\n"" {\n"" baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor );\n"" }\n"" if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP )\n"" {\n"" baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 );\n"" }\n"" return baseColor;\n""}\n""\n""float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x)\n""{\n"" return f1+(f2-f1)*(x-i1)/(i2-i1);\n""}\n""\n""float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode,\n"" float fBlendFactor )\n""{\n"" if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM )\n"" lit_baseColor += fBlendFactor * detailColor.rgb;\n"" if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE )\n"" {\n"" // fade in an unusual way - instead of fading out color, remap an increasing band of it from\n"" // 0..1\n"" //if (fBlendFactor > 0.5)\n"" // lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) );\n"" //else\n"" // lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5);\n""\n"" float f = fBlendFactor - 0.5;\n"" float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor;\n"" float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult;\n"" lit_baseColor += saturate(fMult * detailColor.rgb + fAdd);\n"" }\n"" return lit_baseColor;\n""}\n""\n""//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader\n""float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants )\n""{\n""# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b\n"" {\n"" float flFeatheredAlpha;\n"" float2 flDepths;\n""#define flSceneDepth flDepths.x\n""#define flSpriteDepth flDepths.y\n""\n""# if ( defined( _X360 ) )\n"" {\n"" //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors\n"" asm {\n"" tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point\n"" };\n""\n""# if( !defined( REVERSE_DEPTH_ON_X360 ) )\n"" flSceneDepth = 1.0f - flSceneDepth;\n""# endif\n""\n"" //get the sprite depth into the same range as the texture depth\n"" flSpriteDepth = fProjZ / fProjW;\n""\n"" //unproject to get at the pre-projection z. This value is much more linear than depth\n"" flDepths = vDepthBlendConstants.z / flDepths;\n"" flDepths = vDepthBlendConstants.y - flDepths;\n""\n"" flFeatheredAlpha = flSceneDepth - flSpriteDepth;\n"" flFeatheredAlpha *= vDepthBlendConstants.x;\n"" flFeatheredAlpha = saturate( flFeatheredAlpha );\n"" }\n""# else\n"" {\n"" flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer\n"" flSpriteDepth = SoftParticleDepth( fProjZ );\n""\n"" flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x;\n"" flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering.\n"" flFeatheredAlpha = saturate( flFeatheredAlpha );\n"" }\n""# endif\n""\n""#undef flSceneDepth\n""#undef flSpriteDepth\n""\n"" return flFeatheredAlpha;\n"" }\n""# else\n"" {\n"" return 1.0f;\n"" }\n""# endif\n""}\n""\n""#endif //#ifndef COMMON_PS_FXC_H_\n""\n"; \ No newline at end of file diff --git a/source/common_vertexlitgeneric_dx9.h.inc b/source/common_vertexlitgeneric_dx9.h.inc index cad6691..7a12d2f 100644 --- a/source/common_vertexlitgeneric_dx9.h.inc +++ b/source/common_vertexlitgeneric_dx9.h.inc @@ -1 +1 @@ -const char common_vertexlitgeneric_dx9_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""#ifndef COMMON_VERTEXLITGENERIC_DX9_H_\n""\n""#define COMMON_VERTEXLITGENERIC_DX9_H_\n""\n""\n""#include \"common_ps_fxc.h\"\n""\n""\n""// We store four light colors and positions in an\n""\n""// array of three of these structures like so:\n""\n""//\n""\n""// x y z w\n""\n""// +------+------+------+------+\n""\n""// | L0.rgb | |\n""\n""// +------+------+------+ |\n""\n""// | L0.pos | L3 |\n""\n""// +------+------+------+ rgb |\n""\n""// | L1.rgb | |\n""\n""// +------+------+------+------+\n""\n""// | L1.pos | |\n""\n""// +------+------+------+ |\n""\n""// | L2.rgb | L3 |\n""\n""// +------+------+------+ pos |\n""\n""// | L2.pos | |\n""\n""// +------+------+------+------+\n""\n""//\n""\n""struct PixelShaderLightInfo\n""\n""{\n""\n"" float4 color;\n""\n"" float4 pos;\n""\n""};\n""\n""\n""#define cOverbright 2.0f\n""\n""#define cOOOverbright 0.5f\n""\n""\n""#define LIGHTTYPE_NONE 0\n""\n""#define LIGHTTYPE_SPOT 1\n""\n""#define LIGHTTYPE_POINT 2\n""\n""#define LIGHTTYPE_DIRECTIONAL 3\n""\n""\n""// Better suited to Pixel shader models, 11 instructions in pixel shader\n""\n""// ... actually, now only 9: mul, cmp, cmp, mul, mad, mad, mad, mad, mad\n""\n""float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )\n""\n""{\n""\n"" float3 linearColor, nSquared = worldNormal * worldNormal;\n""\n"" float3 isNegative = ( worldNormal >= 0.0 ) ? 0 : nSquared;\n""\n"" float3 isPositive = ( worldNormal >= 0.0 ) ? nSquared : 0;\n""\n"" linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] +\n""\n"" isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] +\n""\n"" isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5];\n""\n"" return linearColor;\n""\n""}\n""\n""\n""// Better suited to Vertex shader models\n""\n""// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad)\n""\n""float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )\n""\n""{\n""\n"" float3 nSquared = worldNormal * worldNormal;\n""\n"" int3 isNegative = ( worldNormal < 0.0 );\n""\n"" float3 linearColor;\n""\n"" linearColor = nSquared.x * cAmbientCube[isNegative.x] +\n""\n"" nSquared.y * cAmbientCube[isNegative.y+2] +\n""\n"" nSquared.z * cAmbientCube[isNegative.z+4];\n""\n"" return linearColor;\n""\n""}\n""\n""\n""float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )\n""\n""{\n""\n"" // Vertex shader cases\n""\n""#ifdef SHADER_MODEL_VS_1_0\n""\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""\n""#elif SHADER_MODEL_VS_1_1\n""\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""\n""#elif SHADER_MODEL_VS_2_0\n""\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""\n""#elif SHADER_MODEL_VS_3_0\n""\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""\n""#else\n""\n"" // Pixel shader case\n""\n"" return PixelShaderAmbientLight( worldNormal, cAmbientCube );\n""\n""#endif\n""\n""}\n""\n""\n""//-----------------------------------------------------------------------------\n""\n""// Purpose: Compute scalar diffuse term with various optional tweaks such as\n""\n""// Half Lambert and ambient occlusion\n""\n""//-----------------------------------------------------------------------------\n""\n""float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir,\n""\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n""\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""\n""{\n""\n"" float fResult;\n""\n""\n"" float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range)\n""\n""\n"" if ( bHalfLambert )\n""\n"" {\n""\n"" fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range\n""\n""\n"" if ( !bDoLightingWarp )\n""\n"" {\n""\n"" fResult *= fResult; // Square\n""\n"" }\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" fResult = saturate( NDotL ); // Saturate pure Lambertian term\n""\n"" }\n""\n""\n"" if ( bDoAmbientOcclusion )\n""\n"" {\n""\n"" // Raise to higher powers for darker AO values\n""\n""// float fAOPower = lerp( 4.0f, 1.0f, fAmbientOcclusion );\n""\n""// result *= pow( NDotL * 0.5 + 0.5, fAOPower );\n""\n"" fResult *= fAmbientOcclusion;\n""\n"" }\n""\n""\n"" float3 fOut = float3( fResult, fResult, fResult );\n""\n"" if ( bDoLightingWarp )\n""\n"" {\n""\n"" fOut = 2.0f * tex1D( lightWarpSampler, fResult );\n""\n"" }\n""\n""\n"" return fOut;\n""\n""}\n""\n""\n""float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal,\n""\n"" in sampler NormalizeSampler,\n""\n"" const float3 vPosition, const float3 vColor, const bool bHalfLambert,\n""\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n""\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""\n""{\n""\n""#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))\n""\n"" float3 lightDir = normalize( vPosition - worldPos );\n""\n""#else\n""\n"" float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos );\n""\n""#endif\n""\n"" return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, bDoAmbientOcclusion, fAmbientOcclusion, bDoLightingWarp, lightWarpSampler );\n""\n""}\n""\n""\n""float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex )\n""\n""{\n""\n"" if ( nLightIndex == 3 )\n""\n"" {\n""\n"" // Unpack light 3 from w components...\n""\n"" float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );\n""\n"" return normalize( vLight3Pos - worldPos );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" return normalize( cLightInfo[nLightIndex].pos - worldPos );\n""\n"" }\n""\n""}\n""\n""\n""float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex )\n""\n""{\n""\n"" if ( nLightIndex == 3 )\n""\n"" {\n""\n"" // Unpack light 3 from w components...\n""\n"" return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" return cLightInfo[nLightIndex].color.rgb;\n""\n"" }\n""\n""}\n""\n""\n""\n""void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent,\n""\n"" const float3 vEyeDir, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n""\n"" const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel,\n""\n"" const float3 color, const bool bDoRimLighting, const float fRimExponent,\n""\n""\n"" // Outputs\n""\n"" out float3 specularLighting, out float3 rimLighting )\n""\n""{\n""\n"" rimLighting = float3(0.0f, 0.0f, 0.0f);\n""\n""\n"" //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal\n""\n"" float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal\n""\n"" float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?)\n""\n"" specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent\n""\n""\n"" // Optionally warp as function of scalar specular and fresnel\n""\n"" if ( bDoSpecularWarp )\n""\n"" specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }\n""\n""\n"" specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L\n""\n"" specularLighting *= color; // Modulate with light color\n""\n""\n"" if ( bDoAmbientOcclusion ) // Optionally modulate with ambient occlusion\n""\n"" specularLighting *= fAmbientOcclusion;\n""\n""\n"" if ( bDoRimLighting ) // Optionally do rim lighting\n""\n"" {\n""\n"" rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent\n""\n"" rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L\n""\n"" rimLighting *= color; // Modulate with light color\n""\n"" }\n""\n""}\n""\n""\n""// Traditional fresnel term approximation\n""\n""float Fresnel( const float3 vNormal, const float3 vEyeDir )\n""\n""{\n""\n"" float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term\n""\n"" return fresnel * fresnel; // Square for a more subtle look\n""\n""}\n""\n""\n""// Traditional fresnel term approximation which uses 4th power (square twice)\n""\n""float Fresnel4( const float3 vNormal, const float3 vEyeDir )\n""\n""{\n""\n"" float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term\n""\n"" fresnel = fresnel * fresnel; // Square\n""\n"" return fresnel * fresnel; // Square again for a more subtle look\n""\n""}\n""\n""\n""\n""//\n""\n""// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function\n""\n""// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between\n""\n""// low and mid while the 0.5 to 1 range blends between mid and high\n""\n""//\n""\n""// |\n""\n""// | . M . . . H\n""\n""// | . \n""\n""// L\n""\n""// |\n""\n""// +----------------\n""\n""// 0 1\n""\n""//\n""\n""float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges )\n""\n""{\n""\n"" //float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel\n""\n"" //if ( f > 0.5f )\n""\n"" // result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values\n""\n"" //else\n""\n"" // result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values\n""\n""\n"" // note: vRanges is now encoded as ((mid-min)*2, mid, (max-mid)*2) to optimize math\n""\n"" float f = saturate( 1 - dot( vNormal, vEyeDir ) );\n""\n"" f = f*f - 0.5;\n""\n"" return vRanges.y + (f >= 0.0 ? vRanges.z : vRanges.x) * f;\n""\n""}\n""\n""\n""void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir,\n""\n"" const float fAtten, const float3 vLightColor, const float3 vLightDir,\n""\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n""\n"" const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,\n""\n"" const bool bDoRimLighting, const float fRimExponent,\n""\n""\n"" // Outputs\n""\n"" out float3 specularLighting, out float3 rimLighting )\n""\n""{\n""\n"" // Compute Specular and rim terms\n""\n"" SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent,\n""\n"" vEyeDir, bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten,\n""\n"" bDoRimLighting, fRimExponent, specularLighting, rimLighting );\n""\n""}\n""\n""\n""float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal,\n""\n"" const float3 staticLightingColor, const bool bStaticLight,\n""\n"" const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],\n""\n"" in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],\n""\n"" const bool bHalfLambert, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n""\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""\n""{\n""\n"" float3 linearColor = 0.0f;\n""\n""\n"" if ( bStaticLight )\n""\n"" {\n""\n"" // The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright\n""\n"" // need to get it into\n""\n"" // linear space so that we can do adds.\n""\n"" linearColor += GammaToLinear( staticLightingColor * cOverbright );\n""\n"" }\n""\n""\n"" if ( bAmbientLight )\n""\n"" {\n""\n"" float3 ambient = AmbientLight( worldNormal, cAmbientCube );\n""\n""\n"" if ( bDoAmbientOcclusion )\n""\n"" ambient *= fAmbientOcclusion * fAmbientOcclusion; // Note squaring...\n""\n""\n"" linearColor += ambient;\n""\n"" }\n""\n""\n"" if ( nNumLights > 0 )\n""\n"" {\n""\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler,\n""\n"" cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert,\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoLightingWarp, lightWarpSampler );\n""\n"" if ( nNumLights > 1 )\n""\n"" {\n""\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler,\n""\n"" cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert,\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoLightingWarp, lightWarpSampler );\n""\n"" if ( nNumLights > 2 )\n""\n"" {\n""\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler,\n""\n"" cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert,\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoLightingWarp, lightWarpSampler );\n""\n"" if ( nNumLights > 3 )\n""\n"" {\n""\n"" // Unpack the 4th light's data from tight constant packing\n""\n"" float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );\n""\n"" float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );\n""\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler,\n""\n"" vLight3Pos, vLight3Color, bHalfLambert,\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoLightingWarp, lightWarpSampler );\n""\n"" }\n""\n"" }\n""\n"" }\n""\n"" }\n""\n""\n"" return linearColor;\n""\n""}\n""\n""\n""void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir,\n""\n"" const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3],\n""\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n""\n"" const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,\n""\n"" const bool bDoRimLighting, const float fRimExponent,\n""\n""\n"" // Outputs\n""\n"" out float3 specularLighting, out float3 rimLighting )\n""\n""{\n""\n"" specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f );\n""\n"" float3 localSpecularTerm, localRimTerm;\n""\n""\n"" if( nNumLights > 0 )\n""\n"" {\n""\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n""\n"" lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ),\n""\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 0 ),\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n""\n"" bDoRimLighting, fRimExponent,\n""\n"" localSpecularTerm, localRimTerm );\n""\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n""\n"" rimLighting += localRimTerm;\n""\n"" }\n""\n""\n"" if( nNumLights > 1 )\n""\n"" {\n""\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n""\n"" lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ),\n""\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 1 ),\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n""\n"" bDoRimLighting, fRimExponent,\n""\n"" localSpecularTerm, localRimTerm );\n""\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n""\n"" rimLighting += localRimTerm;\n""\n"" }\n""\n""\n""\n"" if( nNumLights > 2 )\n""\n"" {\n""\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n""\n"" lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ),\n""\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 2 ),\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n""\n"" bDoRimLighting, fRimExponent,\n""\n"" localSpecularTerm, localRimTerm );\n""\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n""\n"" rimLighting += localRimTerm;\n""\n"" }\n""\n""\n"" if( nNumLights > 3 )\n""\n"" {\n""\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n""\n"" lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ),\n""\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 3 ),\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n""\n"" bDoRimLighting, fRimExponent,\n""\n"" localSpecularTerm, localRimTerm );\n""\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n""\n"" rimLighting += localRimTerm;\n""\n"" }\n""\n""\n""}\n""\n""\n""float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel )\n""\n""{\n""\n"" float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal\n""\n""\n"" return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube );\n""\n""}\n""\n""\n""// Called directly by newer shaders or through the following wrapper for older shaders\n""\n""float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal,\n""\n"" const float3 staticLightingColor, const bool bStaticLight,\n""\n"" const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],\n""\n"" in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],\n""\n"" const bool bHalfLambert,\n""\n"" \n""\n"" // New optional/experimental parameters\n""\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n""\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""\n""{\n""\n"" float3 linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor, \n""\n"" bStaticLight, bAmbientLight, lightAtten,\n""\n"" cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert,\n""\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n""\n"" bDoLightingWarp, lightWarpSampler );\n""\n""\n"" // go ahead and clamp to the linear space equivalent of overbright 2 so that we match\n""\n"" // everything else.\n""\n""// linearColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) );\n""\n""\n"" return linearColor;\n""\n""}\n""\n""\n""#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_\n""\n""\n"; \ No newline at end of file +const char common_vertexlitgeneric_dx9_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""#ifndef COMMON_VERTEXLITGENERIC_DX9_H_\n""#define COMMON_VERTEXLITGENERIC_DX9_H_\n""\n""#include \"common_ps_fxc.h\"\n""\n""// We store four light colors and positions in an\n""// array of three of these structures like so:\n""//\n""// x y z w\n""// +------+------+------+------+\n""// | L0.rgb | |\n""// +------+------+------+ |\n""// | L0.pos | L3 |\n""// +------+------+------+ rgb |\n""// | L1.rgb | |\n""// +------+------+------+------+\n""// | L1.pos | |\n""// +------+------+------+ |\n""// | L2.rgb | L3 |\n""// +------+------+------+ pos |\n""// | L2.pos | |\n""// +------+------+------+------+\n""//\n""struct PixelShaderLightInfo\n""{\n"" float4 color;\n"" float4 pos;\n""};\n""\n""#define cOverbright 2.0f\n""#define cOOOverbright 0.5f\n""\n""#define LIGHTTYPE_NONE 0\n""#define LIGHTTYPE_SPOT 1\n""#define LIGHTTYPE_POINT 2\n""#define LIGHTTYPE_DIRECTIONAL 3\n""\n""// Better suited to Pixel shader models, 11 instructions in pixel shader\n""// ... actually, now only 9: mul, cmp, cmp, mul, mad, mad, mad, mad, mad\n""float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )\n""{\n"" float3 linearColor, nSquared = worldNormal * worldNormal;\n"" float3 isNegative = ( worldNormal >= 0.0 ) ? 0 : nSquared;\n"" float3 isPositive = ( worldNormal >= 0.0 ) ? nSquared : 0;\n"" linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] +\n"" isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] +\n"" isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5];\n"" return linearColor;\n""}\n""\n""// Better suited to Vertex shader models\n""// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad)\n""float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )\n""{\n"" float3 nSquared = worldNormal * worldNormal;\n"" int3 isNegative = ( worldNormal < 0.0 );\n"" float3 linearColor;\n"" linearColor = nSquared.x * cAmbientCube[isNegative.x] +\n"" nSquared.y * cAmbientCube[isNegative.y+2] +\n"" nSquared.z * cAmbientCube[isNegative.z+4];\n"" return linearColor;\n""}\n""\n""float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )\n""{\n"" // Vertex shader cases\n""#ifdef SHADER_MODEL_VS_1_0\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""#elif SHADER_MODEL_VS_1_1\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""#elif SHADER_MODEL_VS_2_0\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""#elif SHADER_MODEL_VS_3_0\n"" return VertexShaderAmbientLight( worldNormal, cAmbientCube );\n""#else\n"" // Pixel shader case\n"" return PixelShaderAmbientLight( worldNormal, cAmbientCube );\n""#endif\n""}\n""\n""//-----------------------------------------------------------------------------\n""// Purpose: Compute scalar diffuse term with various optional tweaks such as\n""// Half Lambert and ambient occlusion\n""//-----------------------------------------------------------------------------\n""float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir,\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""{\n"" float fResult;\n""\n"" float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range)\n""\n"" if ( bHalfLambert )\n"" {\n"" fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range\n""\n"" if ( !bDoLightingWarp )\n"" {\n"" fResult *= fResult; // Square\n"" }\n"" }\n"" else\n"" {\n"" fResult = saturate( NDotL ); // Saturate pure Lambertian term\n"" }\n""\n"" if ( bDoAmbientOcclusion )\n"" {\n"" // Raise to higher powers for darker AO values\n""// float fAOPower = lerp( 4.0f, 1.0f, fAmbientOcclusion );\n""// result *= pow( NDotL * 0.5 + 0.5, fAOPower );\n"" fResult *= fAmbientOcclusion;\n"" }\n""\n"" float3 fOut = float3( fResult, fResult, fResult );\n"" if ( bDoLightingWarp )\n"" {\n"" fOut = 2.0f * tex1D( lightWarpSampler, fResult );\n"" }\n""\n"" return fOut;\n""}\n""\n""float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal,\n"" in sampler NormalizeSampler,\n"" const float3 vPosition, const float3 vColor, const bool bHalfLambert,\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""{\n""#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))\n"" float3 lightDir = normalize( vPosition - worldPos );\n""#else\n"" float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos );\n""#endif\n"" return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, bDoAmbientOcclusion, fAmbientOcclusion, bDoLightingWarp, lightWarpSampler );\n""}\n""\n""float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex )\n""{\n"" if ( nLightIndex == 3 )\n"" {\n"" // Unpack light 3 from w components...\n"" float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );\n"" return normalize( vLight3Pos - worldPos );\n"" }\n"" else\n"" {\n"" return normalize( cLightInfo[nLightIndex].pos - worldPos );\n"" }\n""}\n""\n""float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex )\n""{\n"" if ( nLightIndex == 3 )\n"" {\n"" // Unpack light 3 from w components...\n"" return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );\n"" }\n"" else\n"" {\n"" return cLightInfo[nLightIndex].color.rgb;\n"" }\n""}\n""\n""\n""void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent,\n"" const float3 vEyeDir, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n"" const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel,\n"" const float3 color, const bool bDoRimLighting, const float fRimExponent,\n""\n"" // Outputs\n"" out float3 specularLighting, out float3 rimLighting )\n""{\n"" rimLighting = float3(0.0f, 0.0f, 0.0f);\n""\n"" //float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal\n"" float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal\n"" float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?)\n"" specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent\n""\n"" // Optionally warp as function of scalar specular and fresnel\n"" if ( bDoSpecularWarp )\n"" specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }\n""\n"" specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L\n"" specularLighting *= color; // Modulate with light color\n""\n"" if ( bDoAmbientOcclusion ) // Optionally modulate with ambient occlusion\n"" specularLighting *= fAmbientOcclusion;\n""\n"" if ( bDoRimLighting ) // Optionally do rim lighting\n"" {\n"" rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent\n"" rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L\n"" rimLighting *= color; // Modulate with light color\n"" }\n""}\n""\n""// Traditional fresnel term approximation\n""float Fresnel( const float3 vNormal, const float3 vEyeDir )\n""{\n"" float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term\n"" return fresnel * fresnel; // Square for a more subtle look\n""}\n""\n""// Traditional fresnel term approximation which uses 4th power (square twice)\n""float Fresnel4( const float3 vNormal, const float3 vEyeDir )\n""{\n"" float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term\n"" fresnel = fresnel * fresnel; // Square\n"" return fresnel * fresnel; // Square again for a more subtle look\n""}\n""\n""\n""//\n""// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function\n""// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between\n""// low and mid while the 0.5 to 1 range blends between mid and high\n""//\n""// |\n""// | . M . . . H\n""// | . \n""// L\n""// |\n""// +----------------\n""// 0 1\n""//\n""float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges )\n""{\n"" //float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel\n"" //if ( f > 0.5f )\n"" // result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values\n"" //else\n"" // result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values\n""\n"" // note: vRanges is now encoded as ((mid-min)*2, mid, (max-mid)*2) to optimize math\n"" float f = saturate( 1 - dot( vNormal, vEyeDir ) );\n"" f = f*f - 0.5;\n"" return vRanges.y + (f >= 0.0 ? vRanges.z : vRanges.x) * f;\n""}\n""\n""void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir,\n"" const float fAtten, const float3 vLightColor, const float3 vLightDir,\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n"" const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,\n"" const bool bDoRimLighting, const float fRimExponent,\n""\n"" // Outputs\n"" out float3 specularLighting, out float3 rimLighting )\n""{\n"" // Compute Specular and rim terms\n"" SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent,\n"" vEyeDir, bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten,\n"" bDoRimLighting, fRimExponent, specularLighting, rimLighting );\n""}\n""\n""float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal,\n"" const float3 staticLightingColor, const bool bStaticLight,\n"" const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],\n"" in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],\n"" const bool bHalfLambert, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""{\n"" float3 linearColor = 0.0f;\n""\n"" if ( bStaticLight )\n"" {\n"" // The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright\n"" // need to get it into\n"" // linear space so that we can do adds.\n"" linearColor += GammaToLinear( staticLightingColor * cOverbright );\n"" }\n""\n"" if ( bAmbientLight )\n"" {\n"" float3 ambient = AmbientLight( worldNormal, cAmbientCube );\n""\n"" if ( bDoAmbientOcclusion )\n"" ambient *= fAmbientOcclusion * fAmbientOcclusion; // Note squaring...\n""\n"" linearColor += ambient;\n"" }\n""\n"" if ( nNumLights > 0 )\n"" {\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler,\n"" cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert,\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoLightingWarp, lightWarpSampler );\n"" if ( nNumLights > 1 )\n"" {\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler,\n"" cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert,\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoLightingWarp, lightWarpSampler );\n"" if ( nNumLights > 2 )\n"" {\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler,\n"" cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert,\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoLightingWarp, lightWarpSampler );\n"" if ( nNumLights > 3 )\n"" {\n"" // Unpack the 4th light's data from tight constant packing\n"" float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );\n"" float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );\n"" linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler,\n"" vLight3Pos, vLight3Color, bHalfLambert,\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoLightingWarp, lightWarpSampler );\n"" }\n"" }\n"" }\n"" }\n""\n"" return linearColor;\n""}\n""\n""void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir,\n"" const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3],\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n"" const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,\n"" const bool bDoRimLighting, const float fRimExponent,\n""\n"" // Outputs\n"" out float3 specularLighting, out float3 rimLighting )\n""{\n"" specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f );\n"" float3 localSpecularTerm, localRimTerm;\n""\n"" if( nNumLights > 0 )\n"" {\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n"" lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ),\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 0 ),\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n"" bDoRimLighting, fRimExponent,\n"" localSpecularTerm, localRimTerm );\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n"" rimLighting += localRimTerm;\n"" }\n""\n"" if( nNumLights > 1 )\n"" {\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n"" lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ),\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 1 ),\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n"" bDoRimLighting, fRimExponent,\n"" localSpecularTerm, localRimTerm );\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n"" rimLighting += localRimTerm;\n"" }\n""\n""\n"" if( nNumLights > 2 )\n"" {\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n"" lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ),\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 2 ),\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n"" bDoRimLighting, fRimExponent,\n"" localSpecularTerm, localRimTerm );\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n"" rimLighting += localRimTerm;\n"" }\n""\n"" if( nNumLights > 3 )\n"" {\n"" PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,\n"" lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ),\n"" PixelShaderGetLightVector( worldPos, cLightInfo, 3 ),\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoSpecularWarp, specularWarpSampler, fFresnel,\n"" bDoRimLighting, fRimExponent,\n"" localSpecularTerm, localRimTerm );\n""\n"" specularLighting += localSpecularTerm; // Accumulate specular and rim terms\n"" rimLighting += localRimTerm;\n"" }\n""\n""}\n""\n""float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel )\n""{\n"" float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal\n""\n"" return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube );\n""}\n""\n""// Called directly by newer shaders or through the following wrapper for older shaders\n""float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal,\n"" const float3 staticLightingColor, const bool bStaticLight,\n"" const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],\n"" in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],\n"" const bool bHalfLambert,\n"" \n"" // New optional/experimental parameters\n"" const bool bDoAmbientOcclusion, const float fAmbientOcclusion,\n"" const bool bDoLightingWarp, in sampler lightWarpSampler )\n""{\n"" float3 linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor, \n"" bStaticLight, bAmbientLight, lightAtten,\n"" cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert,\n"" bDoAmbientOcclusion, fAmbientOcclusion,\n"" bDoLightingWarp, lightWarpSampler );\n""\n"" // go ahead and clamp to the linear space equivalent of overbright 2 so that we match\n"" // everything else.\n""// linearColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) );\n""\n"" return linearColor;\n""}\n""\n""#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_\n""\n"; \ No newline at end of file diff --git a/source/common_vs_fxc.h.inc b/source/common_vs_fxc.h.inc index 719fe04..91ef213 100644 --- a/source/common_vs_fxc.h.inc +++ b/source/common_vs_fxc.h.inc @@ -1 +1 @@ -const char common_vs_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""//\n""\n""// Purpose: This is where all common code for vertex shaders go.\n""\n""//\n""\n""// $NoKeywords: $\n""\n""//\n""\n""//===========================================================================//\n""\n""\n""\n""\n""#ifndef COMMON_VS_FXC_H_\n""\n""#define COMMON_VS_FXC_H_\n""\n""\n""#include \"common_fxc.h\"\n""\n""\n""// Put global skip commands here. . make sure and check that the appropriate vars are defined\n""\n""// so these aren't used on the wrong shaders!\n""\n""// --------------------------------------------------------------------------------\n""\n""// Ditch all fastpath attemps if we are doing LIGHTING_PREVIEW.\n""\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH\n""\n""// --------------------------------------------------------------------------------\n""\n""\n""\n""#ifndef COMPRESSED_VERTS\n""\n""// Default to no vertex compression\n""\n""#define COMPRESSED_VERTS 0\n""\n""#endif\n""\n""\n""#if ( !defined( SHADER_MODEL_VS_2_0 ) && !defined( SHADER_MODEL_VS_3_0 ) )\n""\n""#if COMPRESSED_VERTS == 1\n""\n""#error \"Vertex compression is only for DX9 and up!\"\n""\n""#endif\n""\n""#endif\n""\n""\n""// We're testing 2 normal compression methods\n""\n""// One compressed normals+tangents into a SHORT2 each (8 bytes total)\n""\n""// The other compresses them together, into a single UBYTE4 (4 bytes total)\n""\n""// FIXME: pick one or the other, compare lighting quality in important cases\n""\n""#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0\n""\n""#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1\n""\n""//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2\n""\n""#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4\n""\n""\n""\n""#define FOGTYPE_RANGE 0\n""\n""#define FOGTYPE_HEIGHT 1\n""\n""\n""#define COMPILE_ERROR ( 1/0; )\n""\n""\n""// -------------------------\n""\n""// CONSTANTS\n""\n""// -------------------------\n""\n""\n""#pragma def ( vs, c0, 0.0f, 1.0f, 2.0f, 0.5f )\n""\n""\n""const float4 cConstants1 : register(c1);\n""\n""#define cOOGamma cConstants1.x\n""\n""#define cOverbright 2.0f\n""\n""#define cOneThird cConstants1.z\n""\n""#define cOOOverbright ( 1.0f / 2.0f )\n""\n""\n""\n""// The g_bLightEnabled registers and g_nLightCountRegister hold the same information regarding\n""\n""// enabling lights, but callers internal to this file tend to use the loops, while external\n""\n""// callers will end up using the booleans\n""\n""const bool g_bLightEnabled[4] : register(b0);\n""\n"" // through b3\n""\n""\n""const int g_nLightCountRegister : register(i0);\n""\n""\n""\n""#define g_nLightCount g_nLightCountRegister.x\n""\n""\n""const float4 cEyePosWaterZ : register(c2);\n""\n""#define cEyePos cEyePosWaterZ.xyz\n""\n""\n""// Only cFlexScale.x is used\n""\n""// It is a binary value used to switch on/off the addition of the flex delta stream\n""\n""const float4 cFlexScale : register( c3 );\n""\n""\n""const float4x4 cModelViewProj : register(c4);\n""\n""const float4x4 cViewProj : register(c8);\n""\n""\n""// Used to compute projPosZ in shaders without skinning\n""\n""// Using cModelViewProj with FastClip generates incorrect results\n""\n""// This is just row two of the non-FastClip cModelViewProj matrix\n""\n""const float4 cModelViewProjZ : register(c12);\n""\n""\n""// More constants working back from the top...\n""\n""const float4 cViewProjZ : register(c13);\n""\n""\n""const float4 cFogParams : register(c16);\n""\n""#define cFogEndOverFogRange cFogParams.x\n""\n""#define cFogOne cFogParams.y\n""\n""#define cFogMaxDensity cFogParams.z\n""\n""#define cOOFogRange cFogParams.w\n""\n""\n""const float4x4 cViewModel : register(c17);\n""\n""\n""const float3 cAmbientCubeX [ 2 ] : register ( c21 ) ;\n""\n""const float3 cAmbientCubeY [ 2 ] : register ( c23 ) ;\n""\n""const float3 cAmbientCubeZ [ 2 ] : register ( c25 ) ;\n""\n""\n""#if defined ( SHADER_MODEL_VS_3_0 )\n""\n""const float4 cFlexWeights [ 512 ] : register ( c1024 ) ;\n""\n""#endif\n""\n""\n""struct LightInfo\n""\n""{\n""\n"" float4 color; // {xyz} is color w is light type code (see comment below)\n""\n"" float4 dir; // {xyz} is dir w is light type code\n""\n"" float4 pos;\n""\n"" float4 spotParams;\n""\n"" float4 atten;\n""\n""};\n""\n""\n""// w components of color and dir indicate light type:\n""\n""// 1x - directional\n""\n""// 01 - spot\n""\n""// 00 - point\n""\n""\n""// Four lights x 5 constants each = 20 constants\n""\n""LightInfo cLightInfo[4] : register(c27);\n""\n""#define LIGHT_0_POSITION_REG c29\n""\n""\n""#ifdef SHADER_MODEL_VS_1_1\n""\n""\n""const float4 cModulationColor : register(c37);\n""\n""\n""#define SHADER_SPECIFIC_CONST_0 c38\n""\n""#define SHADER_SPECIFIC_CONST_1 c39\n""\n""#define SHADER_SPECIFIC_CONST_2 c40\n""\n""#define SHADER_SPECIFIC_CONST_3 c41\n""\n""#define SHADER_SPECIFIC_CONST_4 c42\n""\n""#define SHADER_SPECIFIC_CONST_5 c43\n""\n""#define SHADER_SPECIFIC_CONST_6 c44\n""\n""#define SHADER_SPECIFIC_CONST_7 c45\n""\n""#define SHADER_SPECIFIC_CONST_8 c46\n""\n""#define SHADER_SPECIFIC_CONST_9 c47\n""\n""#define SHADER_SPECIFIC_CONST_10 c14\n""\n""#define SHADER_SPECIFIC_CONST_11 c15\n""\n""\n""static const int cModel0Index = 48;\n""\n""const float4x3 cModel[16] : register(c48);\n""\n""// last cmodel is c105 for dx80, c214 for dx90\n""\n""\n""#else // DX9 shaders (vs20 and beyond)\n""\n""\n""const float4 cModulationColor : register( c47 );\n""\n""\n""#define SHADER_SPECIFIC_CONST_0 c48\n""\n""#define SHADER_SPECIFIC_CONST_1 c49\n""\n""#define SHADER_SPECIFIC_CONST_2 c50\n""\n""#define SHADER_SPECIFIC_CONST_3 c51\n""\n""#define SHADER_SPECIFIC_CONST_4 c52\n""\n""#define SHADER_SPECIFIC_CONST_5 c53\n""\n""#define SHADER_SPECIFIC_CONST_6 c54\n""\n""#define SHADER_SPECIFIC_CONST_7 c55\n""\n""#define SHADER_SPECIFIC_CONST_8 c56\n""\n""#define SHADER_SPECIFIC_CONST_9 c57\n""\n""#define SHADER_SPECIFIC_CONST_10 c14\n""\n""#define SHADER_SPECIFIC_CONST_11 c15\n""\n""\n""static const int cModel0Index = 58;\n""\n""const float4x3 cModel[53] : register( c58 );\n""\n""// last cmodel is c105 for dx80, c216 for dx90\n""\n""\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_0 b4\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_1 b5\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_2 b6\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_3 b7\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_4 b8\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_5 b9\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_6 b10\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_7 b11\n""\n""#endif // vertex shader model constant packing changes\n""\n""\n""\n""//=======================================================================================\n""\n""// Methods to decompress vertex normals\n""\n""//=======================================================================================\n""\n""\n""//-----------------------------------------------------------------------------------\n""\n""// Decompress a normal from two-component compressed format\n""\n""// We expect this data to come from a signed SHORT2 stream in the range of -32768..32767\n""\n""//\n""\n""// -32678 and 0 are invalid encodings\n""\n""// w contains the sign to use in the cross product when generating a binormal\n""\n""void _DecompressShort2Tangent( float2 inputTangent, out float4 outputTangent )\n""\n""{\n""\n"" float2 ztSigns = sign( inputTangent ); // sign bits for z and tangent (+1 or -1)\n""\n"" float2 xyAbs = abs( inputTangent ); // 1..32767\n""\n"" outputTangent.xy = (xyAbs - 16384.0f) / 16384.0f; // x and y\n""\n"" outputTangent.z = ztSigns.x * sqrt( saturate( 1.0f - dot( outputTangent.xy, outputTangent.xy ) ) );\n""\n"" outputTangent.w = ztSigns.y;\n""\n""}\n""\n""\n""//-----------------------------------------------------------------------------------\n""\n""// Same code as _DecompressShort2Tangent, just one returns a float4, one a float3\n""\n""void _DecompressShort2Normal( float2 inputNormal, out float3 outputNormal )\n""\n""{\n""\n"" float4 result;\n""\n"" _DecompressShort2Tangent( inputNormal, result );\n""\n"" outputNormal = result.xyz;\n""\n""}\n""\n""\n""//-----------------------------------------------------------------------------------\n""\n""// Decompress normal+tangent together\n""\n""void _DecompressShort2NormalTangent( float2 inputNormal, float2 inputTangent, out float3 outputNormal, out float4 outputTangent )\n""\n""{\n""\n"" // FIXME: if we end up sticking with the SHORT2 format, pack the normal and tangent into a single SHORT4 element\n""\n"" // (that would make unpacking normal+tangent here together much cheaper than the sum of their parts)\n""\n"" _DecompressShort2Normal( inputNormal, outputNormal );\n""\n"" _DecompressShort2Tangent( inputTangent, outputTangent );\n""\n""}\n""\n""\n""//=======================================================================================\n""\n""// Decompress a normal and tangent from four-component compressed format\n""\n""// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255\n""\n""// The final vTangent.w contains the sign to use in the cross product when generating a binormal\n""\n""void _DecompressUByte4NormalTangent( float4 inputNormal,\n""\n"" out float3 outputNormal, // {nX, nY, nZ}\n""\n"" out float4 outputTangent ) // {tX, tY, tZ, sign of binormal}\n""\n""{\n""\n"" float fOne = 1.0f;\n""\n""\n"" float4 ztztSignBits = ( inputNormal - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction\n""\n"" float4 xyxyAbs = abs( inputNormal - 128.0f ) - ztztSignBits; // 0..127\n""\n"" float4 xyxySignBits = ( xyxyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0)\n""\n"" float4 normTan = (abs( xyxyAbs - 64.0f ) - xyxySignBits) / 63.0f; // abs({nX, nY, tX, tY})\n""\n"" outputNormal.xy = normTan.xy; // abs({nX, nY, __, __})\n""\n"" outputTangent.xy = normTan.zw; // abs({tX, tY, __, __})\n""\n""\n"" float4 xyxySigns = 1 - 2*xyxySignBits; // Convert sign bits to signs\n""\n"" float4 ztztSigns = 1 - 2*ztztSignBits; // ( [1,0] -> [-1,+1] )\n""\n""\n"" outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1\n""\n"" outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere\n""\n"" outputNormal.xy *= xyxySigns.xy; // Restore x and y signs\n""\n"" outputNormal.z *= ztztSigns.x; // Restore z sign\n""\n""\n"" outputTangent.z = 1.0f - outputTangent.x - outputTangent.y; // Project onto x+y+z=1\n""\n"" outputTangent.xyz = normalize( outputTangent.xyz ); // Normalize onto unit sphere\n""\n"" outputTangent.xy *= xyxySigns.zw; // Restore x and y signs\n""\n"" outputTangent.z *= ztztSigns.z; // Restore z sign\n""\n"" outputTangent.w = ztztSigns.w; // Binormal sign\n""\n""}\n""\n""\n""\n""//-----------------------------------------------------------------------------------\n""\n""// Decompress just a normal from four-component compressed format (same as above)\n""\n""// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255\n""\n""// [ When compiled, this works out to approximately 17 asm instructions ]\n""\n""void _DecompressUByte4Normal( float4 inputNormal,\n""\n"" out float3 outputNormal) // {nX, nY, nZ}\n""\n""{\n""\n"" float fOne = 1.0f;\n""\n""\n"" float2 ztSigns = ( inputNormal.xy - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction\n""\n"" float2 xyAbs = abs( inputNormal.xy - 128.0f ) - ztSigns; // 0..127\n""\n"" float2 xySigns = ( xyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0)\n""\n"" outputNormal.xy = ( abs( xyAbs - 64.0f ) - xySigns ) / 63.0f; // abs({nX, nY})\n""\n""\n"" outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1\n""\n"" outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere\n""\n""\n"" outputNormal.xy *= lerp( fOne.xx, -fOne.xx, xySigns ); // Restore x and y signs\n""\n"" outputNormal.z *= lerp( fOne.x, -fOne.x, ztSigns.x ); // Restore z sign\n""\n""}\n""\n""\n""\n""void DecompressVertex_Normal( float4 inputNormal, out float3 outputNormal )\n""\n""{\n""\n"" if ( COMPRESSED_VERTS == 1 )\n""\n"" {\n""\n"" if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )\n""\n"" {\n""\n"" _DecompressShort2Normal( inputNormal.xy, outputNormal );\n""\n"" }\n""\n"" else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )\n""\n"" {\n""\n"" _DecompressUByte4Normal( inputNormal, outputNormal );\n""\n"" }\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" outputNormal = inputNormal.xyz;\n""\n"" }\n""\n""}\n""\n""\n""void DecompressVertex_NormalTangent( float4 inputNormal, float4 inputTangent, out float3 outputNormal, out float4 outputTangent )\n""\n""{\n""\n"" if ( COMPRESSED_VERTS == 1 )\n""\n"" {\n""\n"" if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )\n""\n"" {\n""\n"" _DecompressShort2NormalTangent( inputNormal.xy, inputTangent.xy, outputNormal, outputTangent );\n""\n"" }\n""\n"" else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )\n""\n"" {\n""\n"" _DecompressUByte4NormalTangent( inputNormal, outputNormal, outputTangent );\n""\n"" }\n""\n"" }\n""\n"" else\n""\n"" {\n""\n"" outputNormal = inputNormal.xyz;\n""\n"" outputTangent = inputTangent;\n""\n"" }\n""\n""}\n""\n""\n""\n""#ifdef SHADER_MODEL_VS_3_0\n""\n""\n""//-----------------------------------------------------------------------------\n""\n""// Methods to sample morph data from a vertex texture\n""\n""// NOTE: vMorphTargetTextureDim.x = width, cVertexTextureDim.y = height, cVertexTextureDim.z = # of float4 fields per vertex\n""\n""// For position + normal morph for example, there will be 2 fields.\n""\n""//-----------------------------------------------------------------------------\n""\n""float4 SampleMorphDelta( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, const float flField )\n""\n""{\n""\n"" float flColumn = floor( flVertexID / vMorphSubrect.w );\n""\n""\n"" float4 t;\n""\n"" t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + flField + 0.5f;\n""\n"" t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f;\n""\n"" t.xy /= vMorphTargetTextureDim.xy; \n""\n"" t.z = t.w = 0.f;\n""\n""\n"" return tex2Dlod( vt, t );\n""\n""}\n""\n""\n""// Optimized version which reads 2 deltas\n""\n""void SampleMorphDelta2( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, out float4 delta1, out float4 delta2 )\n""\n""{\n""\n"" float flColumn = floor( flVertexID / vMorphSubrect.w );\n""\n""\n"" float4 t;\n""\n"" t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + 0.5f;\n""\n"" t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f;\n""\n"" t.xy /= vMorphTargetTextureDim.xy; \n""\n"" t.z = t.w = 0.f;\n""\n""\n"" delta1 = tex2Dlod( vt, t );\n""\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n""\n"" delta2 = tex2Dlod( vt, t );\n""\n""}\n""\n""\n""#endif // SHADER_MODEL_VS_3_0\n""\n""\n""\n""#if ( defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) )\n""\n""\n""//-----------------------------------------------------------------------------\n""\n""// Method to apply morphs\n""\n""//-----------------------------------------------------------------------------\n""\n""bool ApplyMorph( float3 vPosFlex, inout float3 vPosition )\n""\n""{\n""\n"" // Flexes coming in from a separate stream\n""\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n""\n"" vPosition.xyz += vPosDelta;\n""\n"" return true;\n""\n""}\n""\n""\n""bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, inout float3 vPosition, inout float3 vNormal )\n""\n""{\n""\n"" // Flexes coming in from a separate stream\n""\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n""\n"" float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;\n""\n"" vPosition.xyz += vPosDelta;\n""\n"" vNormal += vNormalDelta;\n""\n"" return true;\n""\n""}\n""\n""\n""bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, \n""\n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent )\n""\n""{\n""\n"" // Flexes coming in from a separate stream\n""\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n""\n"" float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;\n""\n"" vPosition.xyz += vPosDelta;\n""\n"" vNormal += vNormalDelta;\n""\n"" vTangent.xyz += vNormalDelta;\n""\n"" return true;\n""\n""}\n""\n""\n""bool ApplyMorph( float4 vPosFlex, float3 vNormalFlex, \n""\n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle )\n""\n""{\n""\n"" // Flexes coming in from a separate stream\n""\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n""\n"" float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;\n""\n"" flWrinkle = vPosFlex.w * cFlexScale.y;\n""\n"" vPosition.xyz += vPosDelta;\n""\n"" vNormal += vNormalDelta;\n""\n"" vTangent.xyz += vNormalDelta;\n""\n"" return true;\n""\n""}\n""\n""\n""#endif // defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 )\n""\n""\n""\n""#ifdef SHADER_MODEL_VS_3_0\n""\n""\n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, \n""\n"" const float flVertexID, const float3 vMorphTexCoord,\n""\n"" inout float3 vPosition )\n""\n""{\n""\n""#if MORPHING\n""\n""\n""#if !DECAL\n""\n"" // Flexes coming in from a separate stream\n""\n"" float4 vPosDelta = SampleMorphDelta( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, 0 );\n""\n"" vPosition += vPosDelta.xyz;\n""\n""#else\n""\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n""\n"" float3 vPosDelta = tex2Dlod( morphSampler, t );\n""\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n""\n""#endif // DECAL\n""\n""\n"" return true;\n""\n""\n""#else // !MORPHING\n""\n"" return false;\n""\n""#endif\n""\n""}\n""\n"" \n""\n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, \n""\n"" const float flVertexID, const float3 vMorphTexCoord, \n""\n"" inout float3 vPosition, inout float3 vNormal )\n""\n""{\n""\n""#if MORPHING\n""\n""\n""#if !DECAL\n""\n"" float4 vPosDelta, vNormalDelta;\n""\n"" SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );\n""\n"" vPosition += vPosDelta.xyz;\n""\n"" vNormal += vNormalDelta.xyz;\n""\n""#else\n""\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n""\n"" float3 vPosDelta = tex2Dlod( morphSampler, t );\n""\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n""\n"" float3 vNormalDelta = tex2Dlod( morphSampler, t );\n""\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n""\n"" vNormal += vNormalDelta.xyz * vMorphTexCoord.z;\n""\n""#endif // DECAL\n""\n""\n"" return true;\n""\n""\n""#else // !MORPHING\n""\n"" return false;\n""\n""#endif\n""\n""}\n""\n""\n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, \n""\n"" const float flVertexID, const float3 vMorphTexCoord, \n""\n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent )\n""\n""{\n""\n""#if MORPHING\n""\n""\n""#if !DECAL\n""\n"" float4 vPosDelta, vNormalDelta;\n""\n"" SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );\n""\n"" vPosition += vPosDelta.xyz;\n""\n"" vNormal += vNormalDelta.xyz;\n""\n"" vTangent += vNormalDelta.xyz;\n""\n""#else\n""\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n""\n"" float3 vPosDelta = tex2Dlod( morphSampler, t );\n""\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n""\n"" float3 vNormalDelta = tex2Dlod( morphSampler, t );\n""\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n""\n"" vNormal += vNormalDelta.xyz * vMorphTexCoord.z;\n""\n"" vTangent += vNormalDelta.xyz * vMorphTexCoord.z;\n""\n""#endif // DECAL\n""\n""\n"" return true;\n""\n""\n""#else // MORPHING\n""\n""\n"" return false;\n""\n""#endif\n""\n""}\n""\n""\n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect,\n""\n"" const float flVertexID, const float3 vMorphTexCoord,\n""\n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle )\n""\n""{\n""\n""#if MORPHING\n""\n""\n""#if !DECAL\n""\n"" float4 vPosDelta, vNormalDelta;\n""\n"" SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );\n""\n"" vPosition += vPosDelta.xyz;\n""\n"" vNormal += vNormalDelta.xyz;\n""\n"" vTangent += vNormalDelta.xyz;\n""\n"" flWrinkle = vPosDelta.w;\n""\n""#else\n""\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n""\n"" float4 vPosDelta = tex2Dlod( morphSampler, t );\n""\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n""\n"" float3 vNormalDelta = tex2Dlod( morphSampler, t );\n""\n""\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n""\n"" vNormal += vNormalDelta.xyz * vMorphTexCoord.z;\n""\n"" vTangent += vNormalDelta.xyz * vMorphTexCoord.z;\n""\n"" flWrinkle = vPosDelta.w * vMorphTexCoord.z;\n""\n""#endif // DECAL\n""\n""\n"" return true;\n""\n""\n""#else // MORPHING\n""\n""\n"" flWrinkle = 0.0f;\n""\n"" return false;\n""\n""\n""#endif\n""\n""}\n""\n""\n""#endif // SHADER_MODEL_VS_3_0\n""\n""\n""\n""float RangeFog( const float3 projPos )\n""\n""{\n""\n"" return max( cFogMaxDensity, ( -projPos.z * cOOFogRange + cFogEndOverFogRange ) );\n""\n""}\n""\n""\n""float WaterFog( const float3 worldPos, const float3 projPos )\n""\n""{\n""\n"" float4 tmp;\n""\n"" \n""\n"" tmp.xy = cEyePosWaterZ.wz - worldPos.z;\n""\n""\n"" // tmp.x is the distance from the water surface to the vert\n""\n"" // tmp.y is the distance from the eye position to the vert\n""\n""\n"" // if $tmp.x < 0, then set it to 0\n""\n"" // This is the equivalent of moving the vert to the water surface if it's above the water surface\n""\n"" \n""\n"" tmp.x = max( 0.0f, tmp.x );\n""\n""\n"" // $tmp.w = $tmp.x / $tmp.y\n""\n"" tmp.w = tmp.x / tmp.y;\n""\n""\n"" tmp.w *= projPos.z;\n""\n""\n"" // $tmp.w is now the distance that we see through water.\n""\n""\n"" return max( cFogMaxDensity, ( -tmp.w * cOOFogRange + cFogOne ) );\n""\n""}\n""\n""\n""float CalcFog( const float3 worldPos, const float3 projPos, const int fogType )\n""\n""{\n""\n""#if defined( _X360 )\n""\n"" // 360 only does pixel fog\n""\n"" return 1.0f;\n""\n""#endif\n""\n""\n"" if( fogType == FOGTYPE_RANGE )\n""\n"" {\n""\n"" return RangeFog( projPos );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n""#if SHADERMODEL_VS_2_0 == 1\n""\n"" // We do this work in the pixel shader in dx9, so don't do any fog here.\n""\n"" return 1.0f;\n""\n""#else\n""\n"" return WaterFog( worldPos, projPos );\n""\n""#endif\n""\n"" }\n""\n""}\n""\n""\n""float CalcFog( const float3 worldPos, const float3 projPos, const bool bWaterFog )\n""\n""{\n""\n""#if defined( _X360 )\n""\n"" // 360 only does pixel fog\n""\n"" return 1.0f;\n""\n""#endif\n""\n""\n"" float flFog;\n""\n"" if( !bWaterFog )\n""\n"" {\n""\n"" flFog = RangeFog( projPos );\n""\n"" }\n""\n"" else\n""\n"" {\n""\n""#if SHADERMODEL_VS_2_0 == 1\n""\n"" // We do this work in the pixel shader in dx9, so don't do any fog here.\n""\n"" flFog = 1.0f;\n""\n""#else\n""\n"" flFog = WaterFog( worldPos, projPos );\n""\n""#endif\n""\n"" }\n""\n""\n"" return flFog;\n""\n""}\n""\n""\n""float4 DecompressBoneWeights( const float4 weights )\n""\n""{\n""\n"" float4 result = weights;\n""\n""\n"" if ( COMPRESSED_VERTS )\n""\n"" {\n""\n"" // Decompress from SHORT2 to float. In our case, [-1, +32767] -> [0, +1]\n""\n"" // NOTE: we add 1 here so we can divide by 32768 - which is exact (divide by 32767 is not).\n""\n"" // This avoids cracking between meshes with different numbers of bone weights.\n""\n"" // We use SHORT2 instead of SHORT2N for a similar reason - the GPU's conversion\n""\n"" // from [-32768,+32767] to [-1,+1] is imprecise in the same way.\n""\n"" result += 1;\n""\n"" result /= 32768;\n""\n"" }\n""\n""\n"" return result;\n""\n""}\n""\n""\n""void SkinPosition( bool bSkinning, const float4 modelPos, \n""\n"" const float4 boneWeights, float4 fBoneIndices,\n""\n"" out float3 worldPos )\n""\n""{\n""\n""#if !defined( _X360 )\n""\n"" int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );\n""\n""#else\n""\n"" int3 boneIndices = fBoneIndices;\n""\n""#endif\n""\n""\n"" // Needed for invariance issues caused by multipass rendering\n""\n""#if defined( _X360 )\n""\n"" [isolate] \n""\n""#endif\n""\n"" { \n""\n"" if ( !bSkinning )\n""\n"" {\n""\n"" worldPos = mul4x3( modelPos, cModel[0] );\n""\n"" }\n""\n"" else // skinning - always three bones\n""\n"" {\n""\n"" float4x3 mat1 = cModel[boneIndices[0]];\n""\n"" float4x3 mat2 = cModel[boneIndices[1]];\n""\n"" float4x3 mat3 = cModel[boneIndices[2]];\n""\n""\n"" float3 weights = DecompressBoneWeights( boneWeights ).xyz;\n""\n"" weights[2] = 1 - (weights[0] + weights[1]);\n""\n""\n"" float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];\n""\n"" worldPos = mul4x3( modelPos, blendMatrix );\n""\n"" }\n""\n"" }\n""\n""}\n""\n""\n""void SkinPositionAndNormal( bool bSkinning, const float4 modelPos, const float3 modelNormal,\n""\n"" const float4 boneWeights, float4 fBoneIndices,\n""\n"" out float3 worldPos, out float3 worldNormal )\n""\n""{\n""\n"" // Needed for invariance issues caused by multipass rendering\n""\n""#if defined( _X360 )\n""\n"" [isolate] \n""\n""#endif\n""\n"" { \n""\n""\n""#if !defined( _X360 )\n""\n"" int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );\n""\n""#else\n""\n"" int3 boneIndices = fBoneIndices;\n""\n""#endif\n""\n""\n"" if ( !bSkinning )\n""\n"" {\n""\n"" worldPos = mul4x3( modelPos, cModel[0] );\n""\n"" worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] );\n""\n"" }\n""\n"" else // skinning - always three bones\n""\n"" {\n""\n"" float4x3 mat1 = cModel[boneIndices[0]];\n""\n"" float4x3 mat2 = cModel[boneIndices[1]];\n""\n"" float4x3 mat3 = cModel[boneIndices[2]];\n""\n""\n"" float3 weights = DecompressBoneWeights( boneWeights ).xyz;\n""\n"" weights[2] = 1 - (weights[0] + weights[1]);\n""\n""\n"" float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];\n""\n"" worldPos = mul4x3( modelPos, blendMatrix );\n""\n"" worldNormal = mul3x3( modelNormal, ( float3x3 )blendMatrix );\n""\n"" }\n""\n""\n"" } // end [isolate]\n""\n""}\n""\n""\n""// Is it worth keeping SkinPosition and SkinPositionAndNormal around since the optimizer\n""\n""// gets rid of anything that isn't used?\n""\n""void SkinPositionNormalAndTangentSpace( \n""\n"" bool bSkinning,\n""\n"" const float4 modelPos, const float3 modelNormal, \n""\n"" const float4 modelTangentS,\n""\n"" const float4 boneWeights, float4 fBoneIndices,\n""\n"" out float3 worldPos, out float3 worldNormal, \n""\n"" out float3 worldTangentS, out float3 worldTangentT )\n""\n""{\n""\n""#if !defined( _X360 )\n""\n"" int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );\n""\n""#else\n""\n"" int3 boneIndices = fBoneIndices;\n""\n""#endif\n""\n""\n"" // Needed for invariance issues caused by multipass rendering\n""\n""#if defined( _X360 )\n""\n"" [isolate] \n""\n""#endif\n""\n"" { \n""\n"" if ( !bSkinning )\n""\n"" {\n""\n"" worldPos = mul4x3( modelPos, cModel[0] );\n""\n"" worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] );\n""\n"" worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )cModel[0] );\n""\n"" }\n""\n"" else // skinning - always three bones\n""\n"" {\n""\n"" float4x3 mat1 = cModel[boneIndices[0]];\n""\n"" float4x3 mat2 = cModel[boneIndices[1]];\n""\n"" float4x3 mat3 = cModel[boneIndices[2]];\n""\n""\n"" float3 weights = DecompressBoneWeights( boneWeights ).xyz;\n""\n"" weights[2] = 1 - (weights[0] + weights[1]);\n""\n""\n"" float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];\n""\n"" worldPos = mul4x3( modelPos, blendMatrix );\n""\n"" worldNormal = mul3x3( modelNormal, ( const float3x3 )blendMatrix );\n""\n"" worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )blendMatrix );\n""\n"" }\n""\n"" worldTangentT = cross( worldNormal, worldTangentS ) * modelTangentS.w;\n""\n"" }\n""\n""}\n""\n""\n""\n""//-----------------------------------------------------------------------------\n""\n""// Lighting helper functions\n""\n""//-----------------------------------------------------------------------------\n""\n""\n""float3 AmbientLight( const float3 worldNormal )\n""\n""{\n""\n"" float3 nSquared = worldNormal * worldNormal;\n""\n"" int3 isNegative = ( worldNormal < 0.0 );\n""\n"" float3 linearColor;\n""\n"" linearColor = nSquared.x * cAmbientCubeX[isNegative.x] +\n""\n"" nSquared.y * cAmbientCubeY[isNegative.y] +\n""\n"" nSquared.z * cAmbientCubeZ[isNegative.z];\n""\n"" return linearColor;\n""\n""}\n""\n""\n""// The following \"internal\" routines are called \"privately\" by other routines in this file which\n""\n""// handle the particular flavor of vs20 control flow appropriate to the original caller\n""\n""float VertexAttenInternal( const float3 worldPos, int lightNum )\n""\n""{\n""\n"" float result = 0.0f;\n""\n""\n"" // Get light direction\n""\n"" float3 lightDir = cLightInfo[lightNum].pos - worldPos;\n""\n""\n"" // Get light distance squared.\n""\n"" float lightDistSquared = dot( lightDir, lightDir );\n""\n""\n"" // Get 1/lightDistance\n""\n"" float ooLightDist = rsqrt( lightDistSquared );\n""\n""\n"" // Normalize light direction\n""\n"" lightDir *= ooLightDist;\n""\n""\n"" float3 vDist;\n""\n""# if defined( _X360 )\n""\n"" {\n""\n"" //X360 dynamic compile hits an internal compiler error using dst(), this is the breakdown of how dst() works from the 360 docs.\n""\n"" vDist.x = 1;\n""\n"" vDist.y = lightDistSquared * ooLightDist;\n""\n"" vDist.z = lightDistSquared;\n""\n"" //flDist.w = ooLightDist;\n""\n"" }\n""\n""# else\n""\n"" {\n""\n"" vDist = dst( lightDistSquared, ooLightDist );\n""\n"" }\n""\n""# endif\n""\n""\n"" float flDistanceAtten = 1.0f / dot( cLightInfo[lightNum].atten.xyz, vDist );\n""\n""\n"" // Spot attenuation\n""\n"" float flCosTheta = dot( cLightInfo[lightNum].dir.xyz, -lightDir );\n""\n"" float flSpotAtten = (flCosTheta - cLightInfo[lightNum].spotParams.z) * cLightInfo[lightNum].spotParams.w;\n""\n"" flSpotAtten = max( 0.0001f, flSpotAtten );\n""\n"" flSpotAtten = pow( flSpotAtten, cLightInfo[lightNum].spotParams.x );\n""\n"" flSpotAtten = saturate( flSpotAtten );\n""\n""\n"" // Select between point and spot\n""\n"" float flAtten = lerp( flDistanceAtten, flDistanceAtten * flSpotAtten, cLightInfo[lightNum].dir.w );\n""\n""\n"" // Select between above and directional (no attenuation)\n""\n"" result = lerp( flAtten, 1.0f, cLightInfo[lightNum].color.w );\n""\n""\n"" return result;\n""\n""}\n""\n""\n""float CosineTermInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert )\n""\n""{\n""\n"" // Calculate light direction assuming this is a point or spot\n""\n"" float3 lightDir = normalize( cLightInfo[lightNum].pos - worldPos );\n""\n""\n"" // Select the above direction or the one in the structure, based upon light type\n""\n"" lightDir = lerp( lightDir, -cLightInfo[lightNum].dir, cLightInfo[lightNum].color.w );\n""\n""\n"" // compute N dot L\n""\n"" float NDotL = dot( worldNormal, lightDir );\n""\n""\n"" if ( !bHalfLambert )\n""\n"" {\n""\n"" NDotL = max( 0.0f, NDotL );\n""\n"" }\n""\n"" else // Half-Lambert\n""\n"" {\n""\n"" NDotL = NDotL * 0.5 + 0.5;\n""\n"" NDotL = NDotL * NDotL;\n""\n"" }\n""\n"" return NDotL;\n""\n""}\n""\n""\n""// This routine uses booleans to do early-outs and is meant to be called by routines OUTSIDE of this file\n""\n""float GetVertexAttenForLight( const float3 worldPos, int lightNum, bool bUseStaticControlFlow )\n""\n""{\n""\n"" float result = 0.0f;\n""\n""\n"" // Direct3D uses static control flow but OpenGL currently does not\n""\n"" if ( bUseStaticControlFlow )\n""\n"" {\n""\n"" if ( g_bLightEnabled[lightNum] )\n""\n"" {\n""\n"" result = VertexAttenInternal( worldPos, lightNum );\n""\n"" }\n""\n"" }\n""\n"" else // OpenGL non-static-control-flow path\n""\n"" {\n""\n"" result = VertexAttenInternal( worldPos, lightNum );\n""\n"" }\n""\n""\n"" return result;\n""\n""}\n""\n""\n""float3 DoLightInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert )\n""\n""{\n""\n"" return cLightInfo[lightNum].color *\n""\n"" CosineTermInternal( worldPos, worldNormal, lightNum, bHalfLambert ) *\n""\n"" VertexAttenInternal( worldPos, lightNum );\n""\n""}\n""\n""\n""float3 DoLighting( const float3 worldPos, const float3 worldNormal,\n""\n"" const float3 staticLightingColor, const bool bStaticLight,\n""\n"" const bool bDynamicLight, bool bHalfLambert )\n""\n""{\n""\n"" float3 linearColor = float3( 0.0f, 0.0f, 0.0f );\n""\n""\n"" if( bStaticLight ) // Static light\n""\n"" {\n""\n"" float3 col = staticLightingColor * cOverbright;\n""\n""#if defined ( _X360 )\n""\n"" linearColor += col * col;\n""\n""#else\n""\n"" linearColor += GammaToLinear( col );\n""\n""#endif\n""\n"" }\n""\n""\n"" if( bDynamicLight ) // Dynamic light\n""\n"" {\n""\n"" for (int i = 0; i < g_nLightCount; i++)\n""\n"" {\n""\n"" linearColor += DoLightInternal( worldPos, worldNormal, i, bHalfLambert );\n""\n"" } \n""\n"" }\n""\n""\n"" if( bDynamicLight )\n""\n"" {\n""\n"" linearColor += AmbientLight( worldNormal ); //ambient light is already remapped\n""\n"" }\n""\n""\n"" return linearColor;\n""\n""}\n""\n""\n""float3 DoLightingUnrolled( const float3 worldPos, const float3 worldNormal,\n""\n"" const float3 staticLightingColor, const bool bStaticLight,\n""\n"" const bool bDynamicLight, bool bHalfLambert, const int nNumLights )\n""\n""{\n""\n"" float3 linearColor = float3( 0.0f, 0.0f, 0.0f );\n""\n""\n"" if( bStaticLight ) // Static light\n""\n"" {\n""\n"" linearColor += GammaToLinear( staticLightingColor * cOverbright );\n""\n"" }\n""\n""\n"" if( bDynamicLight ) // Ambient light\n""\n"" {\n""\n"" if ( nNumLights >= 1 )\n""\n"" linearColor += DoLightInternal( worldPos, worldNormal, 0, bHalfLambert );\n""\n"" if ( nNumLights >= 2 )\n""\n"" linearColor += DoLightInternal( worldPos, worldNormal, 1, bHalfLambert );\n""\n"" if ( nNumLights >= 3 )\n""\n"" linearColor += DoLightInternal( worldPos, worldNormal, 2, bHalfLambert );\n""\n"" if ( nNumLights >= 4 )\n""\n"" linearColor += DoLightInternal( worldPos, worldNormal, 3, bHalfLambert );\n""\n"" }\n""\n""\n"" if( bDynamicLight )\n""\n"" {\n""\n"" linearColor += AmbientLight( worldNormal ); //ambient light is already remapped\n""\n"" }\n""\n""\n"" return linearColor;\n""\n""}\n""\n""\n""int4 FloatToInt( in float4 floats )\n""\n""{\n""\n"" return D3DCOLORtoUBYTE4( floats.zyxw / 255.001953125 );\n""\n""}\n""\n""\n""float2 ComputeSphereMapTexCoords( in float3 reflectionVector )\n""\n""{\n""\n"" // transform reflection vector into view space\n""\n"" reflectionVector = mul( reflectionVector, ( float3x3 )cViewModel );\n""\n""\n"" // generate \n""\n"" float3 tmp = float3( reflectionVector.x, reflectionVector.y, reflectionVector.z + 1.0f );\n""\n""\n"" // find 1 / len\n""\n"" float ooLen = dot( tmp, tmp );\n""\n"" ooLen = 1.0f / sqrt( ooLen );\n""\n""\n"" // tmp = tmp/|tmp| + 1\n""\n"" tmp.xy = ooLen * tmp.xy + 1.0f;\n""\n""\n"" return tmp.xy * 0.5f;\n""\n""}\n""\n""\n""\n""#define DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE 1\n""\n"" // minxyz.minsoftness / maxxyz.maxsoftness\n""\n""float3 ApplyDeformation( float3 worldpos, int deftype, float4 defparms0, float4 defparms1,\n""\n"" float4 defparms2, float4 defparms3 )\n""\n""{\n""\n"" float3 ret = worldpos;\n""\n"" if ( deftype == DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE )\n""\n"" {\n""\n"" ret=max( ret, defparms2.xyz );\n""\n"" ret=min( ret, defparms3.xyz );\n""\n"" }\n""\n""\n"" return ret;\n""\n""}\n""\n""\n""\n""#endif //#ifndef COMMON_VS_FXC_H_\n""\n""\n"; \ No newline at end of file +const char common_vs_fxc_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""//\n""// Purpose: This is where all common code for vertex shaders go.\n""//\n""// $NoKeywords: $\n""//\n""//===========================================================================//\n""\n""\n""\n""#ifndef COMMON_VS_FXC_H_\n""#define COMMON_VS_FXC_H_\n""\n""#include \"common_fxc.h\"\n""\n""// Put global skip commands here. . make sure and check that the appropriate vars are defined\n""// so these aren't used on the wrong shaders!\n""// --------------------------------------------------------------------------------\n""// Ditch all fastpath attemps if we are doing LIGHTING_PREVIEW.\n""// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH\n""// --------------------------------------------------------------------------------\n""\n""\n""#ifndef COMPRESSED_VERTS\n""// Default to no vertex compression\n""#define COMPRESSED_VERTS 0\n""#endif\n""\n""#if ( !defined( SHADER_MODEL_VS_2_0 ) && !defined( SHADER_MODEL_VS_3_0 ) )\n""#if COMPRESSED_VERTS == 1\n""#error \"Vertex compression is only for DX9 and up!\"\n""#endif\n""#endif\n""\n""// We're testing 2 normal compression methods\n""// One compressed normals+tangents into a SHORT2 each (8 bytes total)\n""// The other compresses them together, into a single UBYTE4 (4 bytes total)\n""// FIXME: pick one or the other, compare lighting quality in important cases\n""#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0\n""#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1\n""//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2\n""#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4\n""\n""\n""#define FOGTYPE_RANGE 0\n""#define FOGTYPE_HEIGHT 1\n""\n""#define COMPILE_ERROR ( 1/0; )\n""\n""// -------------------------\n""// CONSTANTS\n""// -------------------------\n""\n""#pragma def ( vs, c0, 0.0f, 1.0f, 2.0f, 0.5f )\n""\n""const float4 cConstants1 : register(c1);\n""#define cOOGamma cConstants1.x\n""#define cOverbright 2.0f\n""#define cOneThird cConstants1.z\n""#define cOOOverbright ( 1.0f / 2.0f )\n""\n""\n""// The g_bLightEnabled registers and g_nLightCountRegister hold the same information regarding\n""// enabling lights, but callers internal to this file tend to use the loops, while external\n""// callers will end up using the booleans\n""const bool g_bLightEnabled[4] : register(b0);\n"" // through b3\n""\n""const int g_nLightCountRegister : register(i0);\n""\n""\n""#define g_nLightCount g_nLightCountRegister.x\n""\n""const float4 cEyePosWaterZ : register(c2);\n""#define cEyePos cEyePosWaterZ.xyz\n""\n""// Only cFlexScale.x is used\n""// It is a binary value used to switch on/off the addition of the flex delta stream\n""const float4 cFlexScale : register( c3 );\n""\n""const float4x4 cModelViewProj : register(c4);\n""const float4x4 cViewProj : register(c8);\n""\n""// Used to compute projPosZ in shaders without skinning\n""// Using cModelViewProj with FastClip generates incorrect results\n""// This is just row two of the non-FastClip cModelViewProj matrix\n""const float4 cModelViewProjZ : register(c12);\n""\n""// More constants working back from the top...\n""const float4 cViewProjZ : register(c13);\n""\n""const float4 cFogParams : register(c16);\n""#define cFogEndOverFogRange cFogParams.x\n""#define cFogOne cFogParams.y\n""#define cFogMaxDensity cFogParams.z\n""#define cOOFogRange cFogParams.w\n""\n""const float4x4 cViewModel : register(c17);\n""\n""const float3 cAmbientCubeX [ 2 ] : register ( c21 ) ;\n""const float3 cAmbientCubeY [ 2 ] : register ( c23 ) ;\n""const float3 cAmbientCubeZ [ 2 ] : register ( c25 ) ;\n""\n""#if defined ( SHADER_MODEL_VS_3_0 )\n""const float4 cFlexWeights [ 512 ] : register ( c1024 ) ;\n""#endif\n""\n""struct LightInfo\n""{\n"" float4 color; // {xyz} is color w is light type code (see comment below)\n"" float4 dir; // {xyz} is dir w is light type code\n"" float4 pos;\n"" float4 spotParams;\n"" float4 atten;\n""};\n""\n""// w components of color and dir indicate light type:\n""// 1x - directional\n""// 01 - spot\n""// 00 - point\n""\n""// Four lights x 5 constants each = 20 constants\n""LightInfo cLightInfo[4] : register(c27);\n""#define LIGHT_0_POSITION_REG c29\n""\n""#ifdef SHADER_MODEL_VS_1_1\n""\n""const float4 cModulationColor : register(c37);\n""\n""#define SHADER_SPECIFIC_CONST_0 c38\n""#define SHADER_SPECIFIC_CONST_1 c39\n""#define SHADER_SPECIFIC_CONST_2 c40\n""#define SHADER_SPECIFIC_CONST_3 c41\n""#define SHADER_SPECIFIC_CONST_4 c42\n""#define SHADER_SPECIFIC_CONST_5 c43\n""#define SHADER_SPECIFIC_CONST_6 c44\n""#define SHADER_SPECIFIC_CONST_7 c45\n""#define SHADER_SPECIFIC_CONST_8 c46\n""#define SHADER_SPECIFIC_CONST_9 c47\n""#define SHADER_SPECIFIC_CONST_10 c14\n""#define SHADER_SPECIFIC_CONST_11 c15\n""\n""static const int cModel0Index = 48;\n""const float4x3 cModel[16] : register(c48);\n""// last cmodel is c105 for dx80, c214 for dx90\n""\n""#else // DX9 shaders (vs20 and beyond)\n""\n""const float4 cModulationColor : register( c47 );\n""\n""#define SHADER_SPECIFIC_CONST_0 c48\n""#define SHADER_SPECIFIC_CONST_1 c49\n""#define SHADER_SPECIFIC_CONST_2 c50\n""#define SHADER_SPECIFIC_CONST_3 c51\n""#define SHADER_SPECIFIC_CONST_4 c52\n""#define SHADER_SPECIFIC_CONST_5 c53\n""#define SHADER_SPECIFIC_CONST_6 c54\n""#define SHADER_SPECIFIC_CONST_7 c55\n""#define SHADER_SPECIFIC_CONST_8 c56\n""#define SHADER_SPECIFIC_CONST_9 c57\n""#define SHADER_SPECIFIC_CONST_10 c14\n""#define SHADER_SPECIFIC_CONST_11 c15\n""\n""static const int cModel0Index = 58;\n""const float4x3 cModel[53] : register( c58 );\n""// last cmodel is c105 for dx80, c216 for dx90\n""\n""\n""#define SHADER_SPECIFIC_BOOL_CONST_0 b4\n""#define SHADER_SPECIFIC_BOOL_CONST_1 b5\n""#define SHADER_SPECIFIC_BOOL_CONST_2 b6\n""#define SHADER_SPECIFIC_BOOL_CONST_3 b7\n""#define SHADER_SPECIFIC_BOOL_CONST_4 b8\n""#define SHADER_SPECIFIC_BOOL_CONST_5 b9\n""#define SHADER_SPECIFIC_BOOL_CONST_6 b10\n""#define SHADER_SPECIFIC_BOOL_CONST_7 b11\n""#endif // vertex shader model constant packing changes\n""\n""\n""//=======================================================================================\n""// Methods to decompress vertex normals\n""//=======================================================================================\n""\n""//-----------------------------------------------------------------------------------\n""// Decompress a normal from two-component compressed format\n""// We expect this data to come from a signed SHORT2 stream in the range of -32768..32767\n""//\n""// -32678 and 0 are invalid encodings\n""// w contains the sign to use in the cross product when generating a binormal\n""void _DecompressShort2Tangent( float2 inputTangent, out float4 outputTangent )\n""{\n"" float2 ztSigns = sign( inputTangent ); // sign bits for z and tangent (+1 or -1)\n"" float2 xyAbs = abs( inputTangent ); // 1..32767\n"" outputTangent.xy = (xyAbs - 16384.0f) / 16384.0f; // x and y\n"" outputTangent.z = ztSigns.x * sqrt( saturate( 1.0f - dot( outputTangent.xy, outputTangent.xy ) ) );\n"" outputTangent.w = ztSigns.y;\n""}\n""\n""//-----------------------------------------------------------------------------------\n""// Same code as _DecompressShort2Tangent, just one returns a float4, one a float3\n""void _DecompressShort2Normal( float2 inputNormal, out float3 outputNormal )\n""{\n"" float4 result;\n"" _DecompressShort2Tangent( inputNormal, result );\n"" outputNormal = result.xyz;\n""}\n""\n""//-----------------------------------------------------------------------------------\n""// Decompress normal+tangent together\n""void _DecompressShort2NormalTangent( float2 inputNormal, float2 inputTangent, out float3 outputNormal, out float4 outputTangent )\n""{\n"" // FIXME: if we end up sticking with the SHORT2 format, pack the normal and tangent into a single SHORT4 element\n"" // (that would make unpacking normal+tangent here together much cheaper than the sum of their parts)\n"" _DecompressShort2Normal( inputNormal, outputNormal );\n"" _DecompressShort2Tangent( inputTangent, outputTangent );\n""}\n""\n""//=======================================================================================\n""// Decompress a normal and tangent from four-component compressed format\n""// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255\n""// The final vTangent.w contains the sign to use in the cross product when generating a binormal\n""void _DecompressUByte4NormalTangent( float4 inputNormal,\n"" out float3 outputNormal, // {nX, nY, nZ}\n"" out float4 outputTangent ) // {tX, tY, tZ, sign of binormal}\n""{\n"" float fOne = 1.0f;\n""\n"" float4 ztztSignBits = ( inputNormal - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction\n"" float4 xyxyAbs = abs( inputNormal - 128.0f ) - ztztSignBits; // 0..127\n"" float4 xyxySignBits = ( xyxyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0)\n"" float4 normTan = (abs( xyxyAbs - 64.0f ) - xyxySignBits) / 63.0f; // abs({nX, nY, tX, tY})\n"" outputNormal.xy = normTan.xy; // abs({nX, nY, __, __})\n"" outputTangent.xy = normTan.zw; // abs({tX, tY, __, __})\n""\n"" float4 xyxySigns = 1 - 2*xyxySignBits; // Convert sign bits to signs\n"" float4 ztztSigns = 1 - 2*ztztSignBits; // ( [1,0] -> [-1,+1] )\n""\n"" outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1\n"" outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere\n"" outputNormal.xy *= xyxySigns.xy; // Restore x and y signs\n"" outputNormal.z *= ztztSigns.x; // Restore z sign\n""\n"" outputTangent.z = 1.0f - outputTangent.x - outputTangent.y; // Project onto x+y+z=1\n"" outputTangent.xyz = normalize( outputTangent.xyz ); // Normalize onto unit sphere\n"" outputTangent.xy *= xyxySigns.zw; // Restore x and y signs\n"" outputTangent.z *= ztztSigns.z; // Restore z sign\n"" outputTangent.w = ztztSigns.w; // Binormal sign\n""}\n""\n""\n""//-----------------------------------------------------------------------------------\n""// Decompress just a normal from four-component compressed format (same as above)\n""// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255\n""// [ When compiled, this works out to approximately 17 asm instructions ]\n""void _DecompressUByte4Normal( float4 inputNormal,\n"" out float3 outputNormal) // {nX, nY, nZ}\n""{\n"" float fOne = 1.0f;\n""\n"" float2 ztSigns = ( inputNormal.xy - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction\n"" float2 xyAbs = abs( inputNormal.xy - 128.0f ) - ztSigns; // 0..127\n"" float2 xySigns = ( xyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0)\n"" outputNormal.xy = ( abs( xyAbs - 64.0f ) - xySigns ) / 63.0f; // abs({nX, nY})\n""\n"" outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1\n"" outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere\n""\n"" outputNormal.xy *= lerp( fOne.xx, -fOne.xx, xySigns ); // Restore x and y signs\n"" outputNormal.z *= lerp( fOne.x, -fOne.x, ztSigns.x ); // Restore z sign\n""}\n""\n""\n""void DecompressVertex_Normal( float4 inputNormal, out float3 outputNormal )\n""{\n"" if ( COMPRESSED_VERTS == 1 )\n"" {\n"" if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )\n"" {\n"" _DecompressShort2Normal( inputNormal.xy, outputNormal );\n"" }\n"" else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )\n"" {\n"" _DecompressUByte4Normal( inputNormal, outputNormal );\n"" }\n"" }\n"" else\n"" {\n"" outputNormal = inputNormal.xyz;\n"" }\n""}\n""\n""void DecompressVertex_NormalTangent( float4 inputNormal, float4 inputTangent, out float3 outputNormal, out float4 outputTangent )\n""{\n"" if ( COMPRESSED_VERTS == 1 )\n"" {\n"" if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )\n"" {\n"" _DecompressShort2NormalTangent( inputNormal.xy, inputTangent.xy, outputNormal, outputTangent );\n"" }\n"" else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )\n"" {\n"" _DecompressUByte4NormalTangent( inputNormal, outputNormal, outputTangent );\n"" }\n"" }\n"" else\n"" {\n"" outputNormal = inputNormal.xyz;\n"" outputTangent = inputTangent;\n"" }\n""}\n""\n""\n""#ifdef SHADER_MODEL_VS_3_0\n""\n""//-----------------------------------------------------------------------------\n""// Methods to sample morph data from a vertex texture\n""// NOTE: vMorphTargetTextureDim.x = width, cVertexTextureDim.y = height, cVertexTextureDim.z = # of float4 fields per vertex\n""// For position + normal morph for example, there will be 2 fields.\n""//-----------------------------------------------------------------------------\n""float4 SampleMorphDelta( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, const float flField )\n""{\n"" float flColumn = floor( flVertexID / vMorphSubrect.w );\n""\n"" float4 t;\n"" t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + flField + 0.5f;\n"" t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f;\n"" t.xy /= vMorphTargetTextureDim.xy; \n"" t.z = t.w = 0.f;\n""\n"" return tex2Dlod( vt, t );\n""}\n""\n""// Optimized version which reads 2 deltas\n""void SampleMorphDelta2( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, out float4 delta1, out float4 delta2 )\n""{\n"" float flColumn = floor( flVertexID / vMorphSubrect.w );\n""\n"" float4 t;\n"" t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + 0.5f;\n"" t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f;\n"" t.xy /= vMorphTargetTextureDim.xy; \n"" t.z = t.w = 0.f;\n""\n"" delta1 = tex2Dlod( vt, t );\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n"" delta2 = tex2Dlod( vt, t );\n""}\n""\n""#endif // SHADER_MODEL_VS_3_0\n""\n""\n""#if ( defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) )\n""\n""//-----------------------------------------------------------------------------\n""// Method to apply morphs\n""//-----------------------------------------------------------------------------\n""bool ApplyMorph( float3 vPosFlex, inout float3 vPosition )\n""{\n"" // Flexes coming in from a separate stream\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n"" vPosition.xyz += vPosDelta;\n"" return true;\n""}\n""\n""bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, inout float3 vPosition, inout float3 vNormal )\n""{\n"" // Flexes coming in from a separate stream\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n"" float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;\n"" vPosition.xyz += vPosDelta;\n"" vNormal += vNormalDelta;\n"" return true;\n""}\n""\n""bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, \n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent )\n""{\n"" // Flexes coming in from a separate stream\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n"" float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;\n"" vPosition.xyz += vPosDelta;\n"" vNormal += vNormalDelta;\n"" vTangent.xyz += vNormalDelta;\n"" return true;\n""}\n""\n""bool ApplyMorph( float4 vPosFlex, float3 vNormalFlex, \n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle )\n""{\n"" // Flexes coming in from a separate stream\n"" float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;\n"" float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;\n"" flWrinkle = vPosFlex.w * cFlexScale.y;\n"" vPosition.xyz += vPosDelta;\n"" vNormal += vNormalDelta;\n"" vTangent.xyz += vNormalDelta;\n"" return true;\n""}\n""\n""#endif // defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 )\n""\n""\n""#ifdef SHADER_MODEL_VS_3_0\n""\n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, \n"" const float flVertexID, const float3 vMorphTexCoord,\n"" inout float3 vPosition )\n""{\n""#if MORPHING\n""\n""#if !DECAL\n"" // Flexes coming in from a separate stream\n"" float4 vPosDelta = SampleMorphDelta( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, 0 );\n"" vPosition += vPosDelta.xyz;\n""#else\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n"" float3 vPosDelta = tex2Dlod( morphSampler, t );\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n""#endif // DECAL\n""\n"" return true;\n""\n""#else // !MORPHING\n"" return false;\n""#endif\n""}\n"" \n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, \n"" const float flVertexID, const float3 vMorphTexCoord, \n"" inout float3 vPosition, inout float3 vNormal )\n""{\n""#if MORPHING\n""\n""#if !DECAL\n"" float4 vPosDelta, vNormalDelta;\n"" SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );\n"" vPosition += vPosDelta.xyz;\n"" vNormal += vNormalDelta.xyz;\n""#else\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n"" float3 vPosDelta = tex2Dlod( morphSampler, t );\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n"" float3 vNormalDelta = tex2Dlod( morphSampler, t );\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n"" vNormal += vNormalDelta.xyz * vMorphTexCoord.z;\n""#endif // DECAL\n""\n"" return true;\n""\n""#else // !MORPHING\n"" return false;\n""#endif\n""}\n""\n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, \n"" const float flVertexID, const float3 vMorphTexCoord, \n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent )\n""{\n""#if MORPHING\n""\n""#if !DECAL\n"" float4 vPosDelta, vNormalDelta;\n"" SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );\n"" vPosition += vPosDelta.xyz;\n"" vNormal += vNormalDelta.xyz;\n"" vTangent += vNormalDelta.xyz;\n""#else\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n"" float3 vPosDelta = tex2Dlod( morphSampler, t );\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n"" float3 vNormalDelta = tex2Dlod( morphSampler, t );\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n"" vNormal += vNormalDelta.xyz * vMorphTexCoord.z;\n"" vTangent += vNormalDelta.xyz * vMorphTexCoord.z;\n""#endif // DECAL\n""\n"" return true;\n""\n""#else // MORPHING\n""\n"" return false;\n""#endif\n""}\n""\n""bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect,\n"" const float flVertexID, const float3 vMorphTexCoord,\n"" inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle )\n""{\n""#if MORPHING\n""\n""#if !DECAL\n"" float4 vPosDelta, vNormalDelta;\n"" SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );\n"" vPosition += vPosDelta.xyz;\n"" vNormal += vNormalDelta.xyz;\n"" vTangent += vNormalDelta.xyz;\n"" flWrinkle = vPosDelta.w;\n""#else\n"" float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );\n"" float4 vPosDelta = tex2Dlod( morphSampler, t );\n"" t.x += 1.0f / vMorphTargetTextureDim.x;\n"" float3 vNormalDelta = tex2Dlod( morphSampler, t );\n""\n"" vPosition += vPosDelta.xyz * vMorphTexCoord.z;\n"" vNormal += vNormalDelta.xyz * vMorphTexCoord.z;\n"" vTangent += vNormalDelta.xyz * vMorphTexCoord.z;\n"" flWrinkle = vPosDelta.w * vMorphTexCoord.z;\n""#endif // DECAL\n""\n"" return true;\n""\n""#else // MORPHING\n""\n"" flWrinkle = 0.0f;\n"" return false;\n""\n""#endif\n""}\n""\n""#endif // SHADER_MODEL_VS_3_0\n""\n""\n""float RangeFog( const float3 projPos )\n""{\n"" return max( cFogMaxDensity, ( -projPos.z * cOOFogRange + cFogEndOverFogRange ) );\n""}\n""\n""float WaterFog( const float3 worldPos, const float3 projPos )\n""{\n"" float4 tmp;\n"" \n"" tmp.xy = cEyePosWaterZ.wz - worldPos.z;\n""\n"" // tmp.x is the distance from the water surface to the vert\n"" // tmp.y is the distance from the eye position to the vert\n""\n"" // if $tmp.x < 0, then set it to 0\n"" // This is the equivalent of moving the vert to the water surface if it's above the water surface\n"" \n"" tmp.x = max( 0.0f, tmp.x );\n""\n"" // $tmp.w = $tmp.x / $tmp.y\n"" tmp.w = tmp.x / tmp.y;\n""\n"" tmp.w *= projPos.z;\n""\n"" // $tmp.w is now the distance that we see through water.\n""\n"" return max( cFogMaxDensity, ( -tmp.w * cOOFogRange + cFogOne ) );\n""}\n""\n""float CalcFog( const float3 worldPos, const float3 projPos, const int fogType )\n""{\n""#if defined( _X360 )\n"" // 360 only does pixel fog\n"" return 1.0f;\n""#endif\n""\n"" if( fogType == FOGTYPE_RANGE )\n"" {\n"" return RangeFog( projPos );\n"" }\n"" else\n"" {\n""#if SHADERMODEL_VS_2_0 == 1\n"" // We do this work in the pixel shader in dx9, so don't do any fog here.\n"" return 1.0f;\n""#else\n"" return WaterFog( worldPos, projPos );\n""#endif\n"" }\n""}\n""\n""float CalcFog( const float3 worldPos, const float3 projPos, const bool bWaterFog )\n""{\n""#if defined( _X360 )\n"" // 360 only does pixel fog\n"" return 1.0f;\n""#endif\n""\n"" float flFog;\n"" if( !bWaterFog )\n"" {\n"" flFog = RangeFog( projPos );\n"" }\n"" else\n"" {\n""#if SHADERMODEL_VS_2_0 == 1\n"" // We do this work in the pixel shader in dx9, so don't do any fog here.\n"" flFog = 1.0f;\n""#else\n"" flFog = WaterFog( worldPos, projPos );\n""#endif\n"" }\n""\n"" return flFog;\n""}\n""\n""float4 DecompressBoneWeights( const float4 weights )\n""{\n"" float4 result = weights;\n""\n"" if ( COMPRESSED_VERTS )\n"" {\n"" // Decompress from SHORT2 to float. In our case, [-1, +32767] -> [0, +1]\n"" // NOTE: we add 1 here so we can divide by 32768 - which is exact (divide by 32767 is not).\n"" // This avoids cracking between meshes with different numbers of bone weights.\n"" // We use SHORT2 instead of SHORT2N for a similar reason - the GPU's conversion\n"" // from [-32768,+32767] to [-1,+1] is imprecise in the same way.\n"" result += 1;\n"" result /= 32768;\n"" }\n""\n"" return result;\n""}\n""\n""void SkinPosition( bool bSkinning, const float4 modelPos, \n"" const float4 boneWeights, float4 fBoneIndices,\n"" out float3 worldPos )\n""{\n""#if !defined( _X360 )\n"" int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );\n""#else\n"" int3 boneIndices = fBoneIndices;\n""#endif\n""\n"" // Needed for invariance issues caused by multipass rendering\n""#if defined( _X360 )\n"" [isolate] \n""#endif\n"" { \n"" if ( !bSkinning )\n"" {\n"" worldPos = mul4x3( modelPos, cModel[0] );\n"" }\n"" else // skinning - always three bones\n"" {\n"" float4x3 mat1 = cModel[boneIndices[0]];\n"" float4x3 mat2 = cModel[boneIndices[1]];\n"" float4x3 mat3 = cModel[boneIndices[2]];\n""\n"" float3 weights = DecompressBoneWeights( boneWeights ).xyz;\n"" weights[2] = 1 - (weights[0] + weights[1]);\n""\n"" float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];\n"" worldPos = mul4x3( modelPos, blendMatrix );\n"" }\n"" }\n""}\n""\n""void SkinPositionAndNormal( bool bSkinning, const float4 modelPos, const float3 modelNormal,\n"" const float4 boneWeights, float4 fBoneIndices,\n"" out float3 worldPos, out float3 worldNormal )\n""{\n"" // Needed for invariance issues caused by multipass rendering\n""#if defined( _X360 )\n"" [isolate] \n""#endif\n"" { \n""\n""#if !defined( _X360 )\n"" int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );\n""#else\n"" int3 boneIndices = fBoneIndices;\n""#endif\n""\n"" if ( !bSkinning )\n"" {\n"" worldPos = mul4x3( modelPos, cModel[0] );\n"" worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] );\n"" }\n"" else // skinning - always three bones\n"" {\n"" float4x3 mat1 = cModel[boneIndices[0]];\n"" float4x3 mat2 = cModel[boneIndices[1]];\n"" float4x3 mat3 = cModel[boneIndices[2]];\n""\n"" float3 weights = DecompressBoneWeights( boneWeights ).xyz;\n"" weights[2] = 1 - (weights[0] + weights[1]);\n""\n"" float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];\n"" worldPos = mul4x3( modelPos, blendMatrix );\n"" worldNormal = mul3x3( modelNormal, ( float3x3 )blendMatrix );\n"" }\n""\n"" } // end [isolate]\n""}\n""\n""// Is it worth keeping SkinPosition and SkinPositionAndNormal around since the optimizer\n""// gets rid of anything that isn't used?\n""void SkinPositionNormalAndTangentSpace( \n"" bool bSkinning,\n"" const float4 modelPos, const float3 modelNormal, \n"" const float4 modelTangentS,\n"" const float4 boneWeights, float4 fBoneIndices,\n"" out float3 worldPos, out float3 worldNormal, \n"" out float3 worldTangentS, out float3 worldTangentT )\n""{\n""#if !defined( _X360 )\n"" int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );\n""#else\n"" int3 boneIndices = fBoneIndices;\n""#endif\n""\n"" // Needed for invariance issues caused by multipass rendering\n""#if defined( _X360 )\n"" [isolate] \n""#endif\n"" { \n"" if ( !bSkinning )\n"" {\n"" worldPos = mul4x3( modelPos, cModel[0] );\n"" worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] );\n"" worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )cModel[0] );\n"" }\n"" else // skinning - always three bones\n"" {\n"" float4x3 mat1 = cModel[boneIndices[0]];\n"" float4x3 mat2 = cModel[boneIndices[1]];\n"" float4x3 mat3 = cModel[boneIndices[2]];\n""\n"" float3 weights = DecompressBoneWeights( boneWeights ).xyz;\n"" weights[2] = 1 - (weights[0] + weights[1]);\n""\n"" float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];\n"" worldPos = mul4x3( modelPos, blendMatrix );\n"" worldNormal = mul3x3( modelNormal, ( const float3x3 )blendMatrix );\n"" worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )blendMatrix );\n"" }\n"" worldTangentT = cross( worldNormal, worldTangentS ) * modelTangentS.w;\n"" }\n""}\n""\n""\n""//-----------------------------------------------------------------------------\n""// Lighting helper functions\n""//-----------------------------------------------------------------------------\n""\n""float3 AmbientLight( const float3 worldNormal )\n""{\n"" float3 nSquared = worldNormal * worldNormal;\n"" int3 isNegative = ( worldNormal < 0.0 );\n"" float3 linearColor;\n"" linearColor = nSquared.x * cAmbientCubeX[isNegative.x] +\n"" nSquared.y * cAmbientCubeY[isNegative.y] +\n"" nSquared.z * cAmbientCubeZ[isNegative.z];\n"" return linearColor;\n""}\n""\n""// The following \"internal\" routines are called \"privately\" by other routines in this file which\n""// handle the particular flavor of vs20 control flow appropriate to the original caller\n""float VertexAttenInternal( const float3 worldPos, int lightNum )\n""{\n"" float result = 0.0f;\n""\n"" // Get light direction\n"" float3 lightDir = cLightInfo[lightNum].pos - worldPos;\n""\n"" // Get light distance squared.\n"" float lightDistSquared = dot( lightDir, lightDir );\n""\n"" // Get 1/lightDistance\n"" float ooLightDist = rsqrt( lightDistSquared );\n""\n"" // Normalize light direction\n"" lightDir *= ooLightDist;\n""\n"" float3 vDist;\n""# if defined( _X360 )\n"" {\n"" //X360 dynamic compile hits an internal compiler error using dst(), this is the breakdown of how dst() works from the 360 docs.\n"" vDist.x = 1;\n"" vDist.y = lightDistSquared * ooLightDist;\n"" vDist.z = lightDistSquared;\n"" //flDist.w = ooLightDist;\n"" }\n""# else\n"" {\n"" vDist = dst( lightDistSquared, ooLightDist );\n"" }\n""# endif\n""\n"" float flDistanceAtten = 1.0f / dot( cLightInfo[lightNum].atten.xyz, vDist );\n""\n"" // Spot attenuation\n"" float flCosTheta = dot( cLightInfo[lightNum].dir.xyz, -lightDir );\n"" float flSpotAtten = (flCosTheta - cLightInfo[lightNum].spotParams.z) * cLightInfo[lightNum].spotParams.w;\n"" flSpotAtten = max( 0.0001f, flSpotAtten );\n"" flSpotAtten = pow( flSpotAtten, cLightInfo[lightNum].spotParams.x );\n"" flSpotAtten = saturate( flSpotAtten );\n""\n"" // Select between point and spot\n"" float flAtten = lerp( flDistanceAtten, flDistanceAtten * flSpotAtten, cLightInfo[lightNum].dir.w );\n""\n"" // Select between above and directional (no attenuation)\n"" result = lerp( flAtten, 1.0f, cLightInfo[lightNum].color.w );\n""\n"" return result;\n""}\n""\n""float CosineTermInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert )\n""{\n"" // Calculate light direction assuming this is a point or spot\n"" float3 lightDir = normalize( cLightInfo[lightNum].pos - worldPos );\n""\n"" // Select the above direction or the one in the structure, based upon light type\n"" lightDir = lerp( lightDir, -cLightInfo[lightNum].dir, cLightInfo[lightNum].color.w );\n""\n"" // compute N dot L\n"" float NDotL = dot( worldNormal, lightDir );\n""\n"" if ( !bHalfLambert )\n"" {\n"" NDotL = max( 0.0f, NDotL );\n"" }\n"" else // Half-Lambert\n"" {\n"" NDotL = NDotL * 0.5 + 0.5;\n"" NDotL = NDotL * NDotL;\n"" }\n"" return NDotL;\n""}\n""\n""// This routine uses booleans to do early-outs and is meant to be called by routines OUTSIDE of this file\n""float GetVertexAttenForLight( const float3 worldPos, int lightNum, bool bUseStaticControlFlow )\n""{\n"" float result = 0.0f;\n""\n"" // Direct3D uses static control flow but OpenGL currently does not\n"" if ( bUseStaticControlFlow )\n"" {\n"" if ( g_bLightEnabled[lightNum] )\n"" {\n"" result = VertexAttenInternal( worldPos, lightNum );\n"" }\n"" }\n"" else // OpenGL non-static-control-flow path\n"" {\n"" result = VertexAttenInternal( worldPos, lightNum );\n"" }\n""\n"" return result;\n""}\n""\n""float3 DoLightInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert )\n""{\n"" return cLightInfo[lightNum].color *\n"" CosineTermInternal( worldPos, worldNormal, lightNum, bHalfLambert ) *\n"" VertexAttenInternal( worldPos, lightNum );\n""}\n""\n""float3 DoLighting( const float3 worldPos, const float3 worldNormal,\n"" const float3 staticLightingColor, const bool bStaticLight,\n"" const bool bDynamicLight, bool bHalfLambert )\n""{\n"" float3 linearColor = float3( 0.0f, 0.0f, 0.0f );\n""\n"" if( bStaticLight ) // Static light\n"" {\n"" float3 col = staticLightingColor * cOverbright;\n""#if defined ( _X360 )\n"" linearColor += col * col;\n""#else\n"" linearColor += GammaToLinear( col );\n""#endif\n"" }\n""\n"" if( bDynamicLight ) // Dynamic light\n"" {\n"" for (int i = 0; i < g_nLightCount; i++)\n"" {\n"" linearColor += DoLightInternal( worldPos, worldNormal, i, bHalfLambert );\n"" } \n"" }\n""\n"" if( bDynamicLight )\n"" {\n"" linearColor += AmbientLight( worldNormal ); //ambient light is already remapped\n"" }\n""\n"" return linearColor;\n""}\n""\n""float3 DoLightingUnrolled( const float3 worldPos, const float3 worldNormal,\n"" const float3 staticLightingColor, const bool bStaticLight,\n"" const bool bDynamicLight, bool bHalfLambert, const int nNumLights )\n""{\n"" float3 linearColor = float3( 0.0f, 0.0f, 0.0f );\n""\n"" if( bStaticLight ) // Static light\n"" {\n"" linearColor += GammaToLinear( staticLightingColor * cOverbright );\n"" }\n""\n"" if( bDynamicLight ) // Ambient light\n"" {\n"" if ( nNumLights >= 1 )\n"" linearColor += DoLightInternal( worldPos, worldNormal, 0, bHalfLambert );\n"" if ( nNumLights >= 2 )\n"" linearColor += DoLightInternal( worldPos, worldNormal, 1, bHalfLambert );\n"" if ( nNumLights >= 3 )\n"" linearColor += DoLightInternal( worldPos, worldNormal, 2, bHalfLambert );\n"" if ( nNumLights >= 4 )\n"" linearColor += DoLightInternal( worldPos, worldNormal, 3, bHalfLambert );\n"" }\n""\n"" if( bDynamicLight )\n"" {\n"" linearColor += AmbientLight( worldNormal ); //ambient light is already remapped\n"" }\n""\n"" return linearColor;\n""}\n""\n""int4 FloatToInt( in float4 floats )\n""{\n"" return D3DCOLORtoUBYTE4( floats.zyxw / 255.001953125 );\n""}\n""\n""float2 ComputeSphereMapTexCoords( in float3 reflectionVector )\n""{\n"" // transform reflection vector into view space\n"" reflectionVector = mul( reflectionVector, ( float3x3 )cViewModel );\n""\n"" // generate \n"" float3 tmp = float3( reflectionVector.x, reflectionVector.y, reflectionVector.z + 1.0f );\n""\n"" // find 1 / len\n"" float ooLen = dot( tmp, tmp );\n"" ooLen = 1.0f / sqrt( ooLen );\n""\n"" // tmp = tmp/|tmp| + 1\n"" tmp.xy = ooLen * tmp.xy + 1.0f;\n""\n"" return tmp.xy * 0.5f;\n""}\n""\n""\n""#define DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE 1\n"" // minxyz.minsoftness / maxxyz.maxsoftness\n""float3 ApplyDeformation( float3 worldpos, int deftype, float4 defparms0, float4 defparms1,\n"" float4 defparms2, float4 defparms3 )\n""{\n"" float3 ret = worldpos;\n"" if ( deftype == DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE )\n"" {\n"" ret=max( ret, defparms2.xyz );\n"" ret=min( ret, defparms3.xyz );\n"" }\n""\n"" return ret;\n""}\n""\n""\n""#endif //#ifndef COMMON_VS_FXC_H_\n""\n"; \ No newline at end of file diff --git a/source/depthpass.lua.inc b/source/depthpass.lua.inc index fa57d86..7f8c7c3 100644 --- a/source/depthpass.lua.inc +++ b/source/depthpass.lua.inc @@ -1 +1 @@ -const char depthpass_lua[] = "\n""local depthWriteMat = CreateMaterial( \"egsm/depthmat\", \"DepthWrite\", {\n""\n"" [\"$no_fullbright\"] = \"1\",\n""\n"" [\"$color_depth\"] = \"1\",\n""\n"" [\"$alpha_test\"] = \"0\",\n""\n""} )\n""\n""\n""local bDepthPass = false\n""\n""local halo = {}\n""\n""local render = render\n""\n""\n""MaterialOverride = MaterialOverride or render.MaterialOverride\n""\n""BrushMaterialOverride = BrushMaterialOverride or render.BrushMaterialOverride \n""\n""WorldMaterialOverride = WorldMaterialOverride or render.WorldMaterialOverride \n""\n""ModelMaterialOverride = ModelMaterialOverride or render.ModelMaterialOverride \n""\n""\n""local MaterialOverride = MaterialOverride\n""\n""local BrushMaterialOverride = BrushMaterialOverride\n""\n""local WorldMaterialOverride = WorldMaterialOverride\n""\n""local ModelMaterialOverride = ModelMaterialOverride\n""\n""\n""function render.MaterialOverride(m)\n""\n"" if bDepthPass then return end\n""\n"" MaterialOverride(m)\n""\n""end\n""\n""\n""function render.BrushMaterialOverride(m)\n""\n"" if bDepthPass then return end\n""\n"" BrushMaterialOverride(m)\n""\n""end\n""\n""\n""function render.WorldMaterialOverride(m)\n""\n"" if bDepthPass then return end\n""\n"" WorldMaterialOverride(m)\n""\n""end\n""\n""function render.ModelMaterialOverride(m)\n""\n"" if bDepthPass then return end\n""\n"" ModelMaterialOverride(m)\n""\n""end\n""\n""\n""local function dummyFn() end\n""\n""\n""local PushRenderTarget = render.PushRenderTarget\n""\n""local PopRenderTarget = render.PopRenderTarget\n""\n""local rClear = render.Clear\n""\n""local depthRT = render.GetResolvedFullFrameDepth()\n""\n""local hRender = dummyFn\n""\n""local BeginDepthPass = shaderlib.BeginDepthPass\n""\n""local EndDepthPass = shaderlib.EndDepthPass\n""\n""local RenderView = render.RenderView\n""\n""local rClearDepth = render.ClearDepth\n""\n""\n""local function PreDrawEffectsHK() \n""\n"" if bDepthPass then return end\n""\n"" bDepthPass = true\n""\n"" \n""\n"" halo.Render = dummyFn\n""\n"" \n""\n"" MaterialOverride( depthWriteMat )\n""\n"" BrushMaterialOverride( depthWriteMat )\n""\n"" WorldMaterialOverride( depthWriteMat )\n""\n"" ModelMaterialOverride( depthWriteMat )\n""\n"" \n""\n"" BeginDepthPass()\n""\n"" rClear(0,0,0,0) \n""\n"" PopRenderTarget()\n""\n"" \n""\n"" rClear(0,0,0,0)\n""\n"" PopRenderTarget()\n""\n"" \n""\n"" rClear(0,0,0,0) \n""\n""\n"" RenderView()\n""\n"" EndDepthPass()\n""\n""\n"" MaterialOverride()\n""\n"" BrushMaterialOverride()\n""\n"" WorldMaterialOverride()\n""\n"" ModelMaterialOverride()\n""\n"" \n""\n"" halo.Render = hRender\n""\n"" bDepthPass = false\n""\n""end\n""\n""\n""local zero_vec = Vector(0,0,0)\n""\n""local min,max = zero_vec, zero_vec\n""\n""\n""function shaderlib.__INIT()\n""\n"" halo = halo\n""\n"" hRender = halo.Render\n""\n""\n"" hook.Add(\"PreDrawViewModel\", \"!!!EGSM_ImTooLazy\", function() if bDepthPass then rClearDepth() end end) \n""\n"" hook.Add(\"NeedsDepthPass\", \"!!!EGSM_ImTooLazy\", PreDrawEffectsHK)\n""\n"" \n""\n"" hook.Add(\"PostDraw2DSkyBox\", \"!!!EGSM_ImTooLazy\", function()\n""\n"" local rt = render.GetRenderTarget()\n""\n"" if !rt or rt:GetName() != \"egsm_skyboxrt\" \n""\n"" then \n""\n"" return\n""\n"" end\n""\n"" cam.Start3D( zero_vec, EyeAngles() )\n""\n"" min,max = game.GetWorld():GetModelBounds()\n""\n"" \n""\n"" render.SetMaterial( depthWriteMat )\n""\n"" \n""\n"" render.DrawBox( zero_vec, angle_zero, max, min, color_white )\n""\n"" cam.End3D()\n""\n"" end) \n""\n""end\n""\n""\n"; \ No newline at end of file +const char depthpass_lua[] = "local depthWriteMat = CreateMaterial( \"egsm/depthmat\", \"DepthWrite\", {\n"" [\"$no_fullbright\"] = \"1\",\n"" [\"$color_depth\"] = \"1\",\n"" [\"$alpha_test\"] = \"0\",\n""} )\n""\n""local bDepthPass = false\n""local halo = {}\n""local render = render\n""\n""MaterialOverride = MaterialOverride or render.MaterialOverride\n""BrushMaterialOverride = BrushMaterialOverride or render.BrushMaterialOverride \n""WorldMaterialOverride = WorldMaterialOverride or render.WorldMaterialOverride \n""ModelMaterialOverride = ModelMaterialOverride or render.ModelMaterialOverride \n""\n""local MaterialOverride = MaterialOverride\n""local BrushMaterialOverride = BrushMaterialOverride\n""local WorldMaterialOverride = WorldMaterialOverride\n""local ModelMaterialOverride = ModelMaterialOverride\n""\n""function render.MaterialOverride(m)\n"" if bDepthPass then return end\n"" MaterialOverride(m)\n""end\n""\n""function render.BrushMaterialOverride(m)\n"" if bDepthPass then return end\n"" BrushMaterialOverride(m)\n""end\n""\n""function render.WorldMaterialOverride(m)\n"" if bDepthPass then return end\n"" WorldMaterialOverride(m)\n""end\n""function render.ModelMaterialOverride(m)\n"" if bDepthPass then return end\n"" ModelMaterialOverride(m)\n""end\n""\n""local function dummyFn() end\n""\n""local PushRenderTarget = render.PushRenderTarget\n""local PopRenderTarget = render.PopRenderTarget\n""local rClear = render.Clear\n""local depthRT = render.GetResolvedFullFrameDepth()\n""local hRender = dummyFn\n""local BeginDepthPass = shaderlib.BeginDepthPass\n""local EndDepthPass = shaderlib.EndDepthPass\n""local RenderView = render.RenderView\n""local rClearDepth = render.ClearDepth\n""\n""local function PreDrawEffectsHK() \n"" if bDepthPass then return end\n"" bDepthPass = true\n"" \n"" halo.Render = dummyFn\n"" \n"" MaterialOverride( depthWriteMat )\n"" BrushMaterialOverride( depthWriteMat )\n"" WorldMaterialOverride( depthWriteMat )\n"" ModelMaterialOverride( depthWriteMat )\n"" \n"" BeginDepthPass()\n"" rClear(0,0,0,0) \n"" \n"" rClear(0,0,0,0)\n"" \n"" rClear(0,0,0,0) \n""\n"" RenderView()\n"" EndDepthPass()\n""\n"" MaterialOverride()\n"" BrushMaterialOverride()\n"" WorldMaterialOverride()\n"" ModelMaterialOverride()\n"" \n"" halo.Render = hRender\n"" bDepthPass = false\n""end\n""\n""local zero_vec = Vector(0,0,0)\n""local min,max = zero_vec, zero_vec\n""\n""function shaderlib.__INIT()\n"" halo = halo\n"" hRender = halo.Render\n""\n"" hook.Add(\"PreDrawViewModel\", \"!!!EGSM_ImTooLazy\", function() if bDepthPass then rClearDepth() end end) \n"" hook.Add(\"NeedsDepthPass\", \"!!!EGSM_ImTooLazy\", PreDrawEffectsHK)\n"" \n"" hook.Add(\"PostDraw2DSkyBox\", \"!!!EGSM_ImTooLazy\", function()\n"" local rt = render.GetRenderTarget()\n"" if !rt or rt:GetName() != \"egsm_skyboxrt\" \n"" then \n"" return\n"" end\n"" cam.Start3D( zero_vec, EyeAngles() )\n"" min,max = game.GetWorld():GetModelBounds()\n"" \n"" render.SetMaterial( depthWriteMat )\n"" \n"" render.DrawBox( zero_vec, angle_zero, max, min, color_white )\n"" cam.End3D()\n"" end) \n""end\n"; \ No newline at end of file diff --git a/source/f_vmatrix.cpp b/source/f_vmatrix.cpp index f975097..018b536 100644 --- a/source/f_vmatrix.cpp +++ b/source/f_vmatrix.cpp @@ -8,6 +8,7 @@ #if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) + #include "basetypes.h" #include "mathlib/vmatrix.h" #include "mathlib/mathlib.h" @@ -26,23 +27,29 @@ inline void AddPointToBounds(const Vector& v, Vector& mins, Vector& maxs) { Asse #ifdef CHROMIUM -#if defined(__i386__) || defined(_M_IX86) -inline void _SSE_RSqrtInline(float a, float* out) +inline vec_t VectorNormalize(Vector& v) { - __m128 xx = _mm_load_ss(&a); - __m128 xr = _mm_rsqrt_ss(xx); - __m128 xt; - xt = _mm_mul_ss(xr, xr); - xt = _mm_mul_ss(xt, xx); - xt = _mm_sub_ss(_mm_set_ss(3.f), xt); - xt = _mm_mul_ss(xt, _mm_set_ss(0.5f)); - xr = _mm_mul_ss(xr, xt); - _mm_store_ss(out, xr); + Assert(v.IsValid()); + vec_t l = v.Length(); + if (l != 0.0f) + { + v /= l; + } + else + { + // FIXME: + // Just copying the existing implemenation; shouldn't res.z == 0? + v.x = v.y = 0.0f; v.z = 1.0f; + } + return l; } + #endif #ifdef WIN64 + + float FASTCALL pfVectorNormalize(Vector& vec) { #ifdef _VPROF_MATHLIB @@ -61,27 +68,7 @@ float FASTCALL pfVectorNormalize(Vector& vec) return radius; } -#endif - -FORCEINLINE float VectorNormalize(Vector& vec) -{ -#ifndef DEBUG // stop crashing my edit-and-continue! -#if defined(__i386__) || defined(_M_IX86) -#define DO_SSE_OPTIMIZATION -#endif -#endif -#if defined( DO_SSE_OPTIMIZATION ) - float sqrlen = vec.LengthSqr() + 1.0e-10f, invlen; - _SSE_RSqrtInline(sqrlen, &invlen); - vec.x *= invlen; - vec.y *= invlen; - vec.z *= invlen; - return sqrlen * invlen; -#else - return (*pfVectorNormalize)(vec); -#endif -} #endif diff --git a/source/shader_constant_register_map.h.inc b/source/shader_constant_register_map.h.inc index 4fa7b11..f1ba176 100644 --- a/source/shader_constant_register_map.h.inc +++ b/source/shader_constant_register_map.h.inc @@ -1 +1 @@ -const char shader_constant_register_map_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""\n""//\n""\n""// Purpose: Provide convenient mapping for shader constants\n""\n""//\n""\n""// $NoKeywords: $\n""\n""//=============================================================================\n""\n""\n""#ifndef C_CODE_HACK\n""\n""#include \"common_vertexlitgeneric_dx9.h\"\n""\n""#endif\n""\n""\n""#define PSREG_SELFILLUMTINT PSREG_CONSTANT_00\n""\n""#define PSREG_DIFFUSE_MODULATION PSREG_CONSTANT_01\n""\n""#define PSREG_ENVMAP_TINT__SHADOW_TWEAKS PSREG_CONSTANT_02\n""\n""#define PSREG_SELFILLUM_SCALE_BIAS_EXP PSREG_CONSTANT_03\n""\n""#define PSREG_AMBIENT_CUBE PSREG_CONSTANT_04\n""\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_05\n""\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_06\n""\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_07\n""\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_08\n""\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_09\n""\n""#define PSREG_ENVMAP_FRESNEL__SELFILLUMMASK PSREG_CONSTANT_10\n""\n""#define PSREG_EYEPOS_SPEC_EXPONENT PSREG_CONSTANT_11\n""\n""#define PSREG_FOG_PARAMS PSREG_CONSTANT_12\n""\n""#define PSREG_FLASHLIGHT_ATTENUATION PSREG_CONSTANT_13\n""\n""#define PSREG_FLASHLIGHT_POSITION_RIM_BOOST PSREG_CONSTANT_14\n""\n""#define PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_15\n""\n""// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_16\n""\n""// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_17\n""\n""// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_18\n""\n""#define PSREG_FRESNEL_SPEC_PARAMS PSREG_CONSTANT_19\n""\n""#define PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_20\n""\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_21\n""\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_22\n""\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_23\n""\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_24\n""\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_25\n""\n""#define PSREG_SPEC_RIM_PARAMS PSREG_CONSTANT_26\n""\n""// #define **free** PSREG_CONSTANT_27 //actually using this often blows constant limits, since literals have to get stuffed somewhere...\n""\n""#define PSREG_FLASHLIGHT_COLOR PSREG_CONSTANT_28\n""\n""#define PSREG_LINEAR_FOG_COLOR PSREG_CONSTANT_29\n""\n""#define PSREG_LIGHT_SCALE PSREG_CONSTANT_30\n""\n""#define PSREG_FLASHLIGHT_SCREEN_SCALE PSREG_CONSTANT_31\n""\n""\n""#ifdef C_CODE_HACK\n""\n""#define PSREG_SHADER_CONTROLS 32\n""\n""#else\n""\n""#define PSREG_SHADER_CONTROLS c32\n""\n""#endif\n""\n""\n""\n""// --- End of ps_2_0 and ps_2_b constants ---\n""\n""\n""\n""\n""#ifndef C_CODE_HACK\n""\n""//for fxc code, map the constants to register names.\n""\n""#define PSREG_CONSTANT_00 c0\n""\n""#define PSREG_CONSTANT_01 c1\n""\n""#define PSREG_CONSTANT_02 c2\n""\n""#define PSREG_CONSTANT_03 c3\n""\n""#define PSREG_CONSTANT_04 c4\n""\n""#define PSREG_CONSTANT_05 c5\n""\n""#define PSREG_CONSTANT_06 c6\n""\n""#define PSREG_CONSTANT_07 c7\n""\n""#define PSREG_CONSTANT_08 c8\n""\n""#define PSREG_CONSTANT_09 c9\n""\n""#define PSREG_CONSTANT_10 c10\n""\n""#define PSREG_CONSTANT_11 c11\n""\n""#define PSREG_CONSTANT_12 c12\n""\n""#define PSREG_CONSTANT_13 c13\n""\n""#define PSREG_CONSTANT_14 c14\n""\n""#define PSREG_CONSTANT_15 c15\n""\n""#define PSREG_CONSTANT_16 c16\n""\n""#define PSREG_CONSTANT_17 c17\n""\n""#define PSREG_CONSTANT_18 c18\n""\n""#define PSREG_CONSTANT_19 c19\n""\n""#define PSREG_CONSTANT_20 c20\n""\n""#define PSREG_CONSTANT_21 c21\n""\n""#define PSREG_CONSTANT_22 c22\n""\n""#define PSREG_CONSTANT_23 c23\n""\n""#define PSREG_CONSTANT_24 c24\n""\n""#define PSREG_CONSTANT_25 c25\n""\n""#define PSREG_CONSTANT_26 c26\n""\n""#define PSREG_CONSTANT_27 c27\n""\n""#define PSREG_CONSTANT_28 c28\n""\n""#define PSREG_CONSTANT_29 c29\n""\n""#define PSREG_CONSTANT_30 c30\n""\n""#define PSREG_CONSTANT_31 c31\n""\n""#endif\n""\n""\n"; \ No newline at end of file +const char shader_constant_register_map_h[] = "//========= Copyright Valve Corporation, All rights reserved. ============//\n""//\n""// Purpose: Provide convenient mapping for shader constants\n""//\n""// $NoKeywords: $\n""//=============================================================================\n""\n""#ifndef C_CODE_HACK\n""#include \"common_vertexlitgeneric_dx9.h\"\n""#endif\n""\n""#define PSREG_SELFILLUMTINT PSREG_CONSTANT_00\n""#define PSREG_DIFFUSE_MODULATION PSREG_CONSTANT_01\n""#define PSREG_ENVMAP_TINT__SHADOW_TWEAKS PSREG_CONSTANT_02\n""#define PSREG_SELFILLUM_SCALE_BIAS_EXP PSREG_CONSTANT_03\n""#define PSREG_AMBIENT_CUBE PSREG_CONSTANT_04\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_05\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_06\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_07\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_08\n""// PSREG_AMBIENT_CUBE PSREG_CONSTANT_09\n""#define PSREG_ENVMAP_FRESNEL__SELFILLUMMASK PSREG_CONSTANT_10\n""#define PSREG_EYEPOS_SPEC_EXPONENT PSREG_CONSTANT_11\n""#define PSREG_FOG_PARAMS PSREG_CONSTANT_12\n""#define PSREG_FLASHLIGHT_ATTENUATION PSREG_CONSTANT_13\n""#define PSREG_FLASHLIGHT_POSITION_RIM_BOOST PSREG_CONSTANT_14\n""#define PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_15\n""// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_16\n""// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_17\n""// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_18\n""#define PSREG_FRESNEL_SPEC_PARAMS PSREG_CONSTANT_19\n""#define PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_20\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_21\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_22\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_23\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_24\n""// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_25\n""#define PSREG_SPEC_RIM_PARAMS PSREG_CONSTANT_26\n""// #define **free** PSREG_CONSTANT_27 //actually using this often blows constant limits, since literals have to get stuffed somewhere...\n""#define PSREG_FLASHLIGHT_COLOR PSREG_CONSTANT_28\n""#define PSREG_LINEAR_FOG_COLOR PSREG_CONSTANT_29\n""#define PSREG_LIGHT_SCALE PSREG_CONSTANT_30\n""#define PSREG_FLASHLIGHT_SCREEN_SCALE PSREG_CONSTANT_31\n""\n""#ifdef C_CODE_HACK\n""#define PSREG_SHADER_CONTROLS 32\n""#else\n""#define PSREG_SHADER_CONTROLS c32\n""#endif\n""\n""\n""// --- End of ps_2_0 and ps_2_b constants ---\n""\n""\n""\n""#ifndef C_CODE_HACK\n""//for fxc code, map the constants to register names.\n""#define PSREG_CONSTANT_00 c0\n""#define PSREG_CONSTANT_01 c1\n""#define PSREG_CONSTANT_02 c2\n""#define PSREG_CONSTANT_03 c3\n""#define PSREG_CONSTANT_04 c4\n""#define PSREG_CONSTANT_05 c5\n""#define PSREG_CONSTANT_06 c6\n""#define PSREG_CONSTANT_07 c7\n""#define PSREG_CONSTANT_08 c8\n""#define PSREG_CONSTANT_09 c9\n""#define PSREG_CONSTANT_10 c10\n""#define PSREG_CONSTANT_11 c11\n""#define PSREG_CONSTANT_12 c12\n""#define PSREG_CONSTANT_13 c13\n""#define PSREG_CONSTANT_14 c14\n""#define PSREG_CONSTANT_15 c15\n""#define PSREG_CONSTANT_16 c16\n""#define PSREG_CONSTANT_17 c17\n""#define PSREG_CONSTANT_18 c18\n""#define PSREG_CONSTANT_19 c19\n""#define PSREG_CONSTANT_20 c20\n""#define PSREG_CONSTANT_21 c21\n""#define PSREG_CONSTANT_22 c22\n""#define PSREG_CONSTANT_23 c23\n""#define PSREG_CONSTANT_24 c24\n""#define PSREG_CONSTANT_25 c25\n""#define PSREG_CONSTANT_26 c26\n""#define PSREG_CONSTANT_27 c27\n""#define PSREG_CONSTANT_28 c28\n""#define PSREG_CONSTANT_29 c29\n""#define PSREG_CONSTANT_30 c30\n""#define PSREG_CONSTANT_31 c31\n""#endif\n""\n"; \ No newline at end of file diff --git a/source/shaderlib.cpp b/source/shaderlib.cpp index c317f37..ad1acdb 100644 --- a/source/shaderlib.cpp +++ b/source/shaderlib.cpp @@ -981,14 +981,23 @@ namespace ShaderLib MK_CV(mat_drawwater) MK_CV(r_drawtranslucentworld); - LUA_LIB_FUNCTION(shaderlib, BeginDepthPass) { auto pMatRenderContext = g_pMaterialSystem->GetRenderContext(); + pMatRenderContext->PushRenderTargetAndViewport(egsm_fuckofffog); + pMatRenderContext->ClearBuffers(true, true, true); + pMatRenderContext->ClearColor4ub(0, 0, 0, 0); pMatRenderContext->PushRenderTargetAndViewport(g_DepthTex); + pMatRenderContext->ClearBuffers(true, true, true); + pMatRenderContext->ClearColor4ub(0, 0, 0, 0); + pMatRenderContext->PopRenderTargetAndViewport(); + pMatRenderContext->PushRenderTargetAndViewport(g_NormalsTex); + pMatRenderContext->ClearBuffers(true, true, true); + pMatRenderContext->ClearColor4ub(0, 0, 0, 0); + pMatRenderContext->PopRenderTargetAndViewport(); g_pStudioRender->ForcedMaterialOverride(NULL, OVERRIDE_SSAO_DEPTH_WRITE); @@ -1001,12 +1010,12 @@ namespace ShaderLib LUA_LIB_FUNCTION(shaderlib, EndDepthPass) { + g_pStudioRender->ForcedMaterialOverride(0); auto pMatRenderContext = g_pMaterialSystem->GetRenderContext(); pMatRenderContext->PopRenderTargetAndViewport(); RES_CV(mat_drawwater); RES_CV(r_drawtranslucentworld); - bDepthPass = false; return 0; } @@ -1017,7 +1026,7 @@ namespace ShaderLib { g_pShaderManager = _this; #ifndef WIN64 - CShaderManager_CreateVertexShader_hook.Destroy(); + CShaderManager_CreateVertexShader_hook.Disable(); #endif return (int)INVALID_SHADER; } @@ -1158,7 +1167,7 @@ namespace ShaderLib CViewRender_DetermineWaterRenderInfo_trampoline()(_this, idc, info); if (bDepthPass) { - info.m_bCheapWater = false; + //info.m_bCheapWater = false; } } @@ -1223,7 +1232,7 @@ namespace ShaderLib int MenuInit(GarrysMod::Lua::ILuaBase* LUA) { static Color msgc(100, 255, 100, 255); - ConColorMsg(msgc, "ShaderLib\n"); + ConColorMsg(msgc, "ShaderLib\n"); if (!Sys_LoadInterface("materialsystem", "MaterialSystemHardwareConfig012", NULL, (void**)&g_pHardwareConfig)) { ShaderLibError("MaterialSystemHardwareConfig012 == NULL"); } if (g_pHardwareConfig->GetDXSupportLevel() < 90) { ShaderLibError("Unsupported DirectX version(dxlevel<90)"); }; @@ -1322,6 +1331,8 @@ namespace ShaderLib void* DepthPass = ScanSign(clientdll, sign, sizeof(sign) - 1); if (!DepthPass) { ShaderLibError("CBaseWorldView::SSAO_DepthPass == NULL\n"); return 0; } Setup_Hook(CBaseWorldView_SSAO_DepthPass, DepthPass); + + } { diff --git a/source/shaderlib.h b/source/shaderlib.h index 856ab35..9909371 100644 --- a/source/shaderlib.h +++ b/source/shaderlib.h @@ -487,6 +487,11 @@ namespace ShaderLib unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + if (IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) || IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA)) + { + flags |= VERTEX_COLOR; + } + int userDataSize = 4; pShaderShadow->VertexShaderVertexFormat(flags, nTexCoordCount, NULL, userDataSize); diff --git a/source/version.h b/source/version.h index f10e851..cfbda96 100644 --- a/source/version.h +++ b/source/version.h @@ -1 +1 @@ -#define EGSM_VERSION 11 \ No newline at end of file +#define EGSM_VERSION 12 \ No newline at end of file diff --git a/source/version_check.lua.inc b/source/version_check.lua.inc index e972605..6ff8ea3 100644 --- a/source/version_check.lua.inc +++ b/source/version_check.lua.inc @@ -1 +1 @@ -const char version_check_lua[] = "timer.Simple(0, function()\n""\n"" http.Fetch(\"https://raw.githubusercontent.com/devonium/EGSM/master/source/version.h\", function(body)\n""\n"" local version = tonumber(body:match(\"#[^%d]*([%d]*)\"))\n""\n"" if version == nil then return end\n""\n"" if version > EGSM.Version\n""\n"" then\n""\n"" Derma_Query(\n""\n"" \"Your EGSM version is outdated.\\nYou can still play, but some things may not work the right way.\",\n""\n"" \"\",\n""\n"" \"Yes\"\n""\n"" )\n""\n"" end\n""\n"" end)\n""\n""end)\n""\n"; \ No newline at end of file +const char version_check_lua[] = "timer.Simple(0, function()\n"" http.Fetch(\"https://raw.githubusercontent.com/devonium/EGSM/master/source/version.h\", function(body)\n"" local version = tonumber(body:match(\"#[^%d]*([%d]*)\"))\n"" if version == nil then return end\n"" if version > EGSM.Version\n"" then\n"" Derma_Query(\n"" \"Your EGSM version is outdated.\\nYou can still play, but some things may not work the right way.\",\n"" \"\",\n"" \"Yes\"\n"" )\n"" end\n"" end)\n""end)\n"; \ No newline at end of file