source-engine/materialsystem/stdshaders/pbr_dx9.cpp
LegendGuard a87918565a
Add PBR support (#91)
* Add PBR support
* Fix physics props turning black
2022-08-10 17:41:01 +03:00

617 lines
26 KiB
C++

//==================================================================================================
//
// Physically Based Rendering shader for brushes and models
//
//==================================================================================================
// Includes for all shaders
#include "BaseVSShader.h"
#include "cpp_shader_constant_register_map.h"
// Includes for PS30
#include "pbr_vs30.inc"
#include "pbr_ps30.inc"
// Includes for PS20b
#include "pbr_vs20b.inc"
#include "pbr_ps20b.inc"
// Defining samplers
const Sampler_t SAMPLER_BASETEXTURE = SHADER_SAMPLER0;
const Sampler_t SAMPLER_NORMAL = SHADER_SAMPLER1;
const Sampler_t SAMPLER_ENVMAP = SHADER_SAMPLER2;
const Sampler_t SAMPLER_SHADOWDEPTH = SHADER_SAMPLER4;
const Sampler_t SAMPLER_RANDOMROTATION = SHADER_SAMPLER5;
const Sampler_t SAMPLER_FLASHLIGHT = SHADER_SAMPLER6;
const Sampler_t SAMPLER_LIGHTMAP = SHADER_SAMPLER7;
const Sampler_t SAMPLER_MRAO = SHADER_SAMPLER10;
const Sampler_t SAMPLER_EMISSIVE = SHADER_SAMPLER11;
const Sampler_t SAMPLER_SPECULAR = SHADER_SAMPLER12;
// Convars
static ConVar mat_fullbright("mat_fullbright", "0", FCVAR_CHEAT);
static ConVar mat_specular("mat_specular", "1", FCVAR_CHEAT);
static ConVar mat_pbr_force_20b("mat_pbr_force_20b", "0", FCVAR_CHEAT);
static ConVar mat_pbr_parallaxmap("mat_pbr_parallaxmap", "1");
// Variables for this shader
struct PBR_Vars_t
{
PBR_Vars_t()
{
memset(this, 0xFF, sizeof(*this));
}
int baseTexture;
int baseColor;
int normalTexture;
int bumpMap;
int envMap;
int baseTextureFrame;
int baseTextureTransform;
int useParallax;
int parallaxDepth;
int parallaxCenter;
int alphaTestReference;
int flashlightTexture;
int flashlightTextureFrame;
int emissionTexture;
int mraoTexture;
int useEnvAmbient;
int specularTexture;
};
// Beginning the shader
BEGIN_VS_SHADER(PBR, "PBR shader")
// Setting up vmt parameters
BEGIN_SHADER_PARAMS;
SHADER_PARAM(ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0", "");
SHADER_PARAM(ENVMAP, SHADER_PARAM_TYPE_ENVMAP, "", "Set the cubemap for this material.");
SHADER_PARAM(MRAOTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Texture with metalness in R, roughness in G, ambient occlusion in B.");
SHADER_PARAM(EMISSIONTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Emission texture");
SHADER_PARAM(NORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Normal texture (deprecated, use $bumpmap)");
SHADER_PARAM(BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "Normal texture");
SHADER_PARAM(USEENVAMBIENT, SHADER_PARAM_TYPE_BOOL, "0", "Use the cubemaps to compute ambient light.");
SHADER_PARAM(SPECULARTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Specular F0 RGB map");
SHADER_PARAM(PARALLAX, SHADER_PARAM_TYPE_BOOL, "0", "Use Parallax Occlusion Mapping.");
SHADER_PARAM(PARALLAXDEPTH, SHADER_PARAM_TYPE_FLOAT, "0.0030", "Depth of the Parallax Map");
SHADER_PARAM(PARALLAXCENTER, SHADER_PARAM_TYPE_FLOAT, "0.5", "Center depth of the Parallax Map");
END_SHADER_PARAMS;
// Setting up variables for this shader
void SetupVars(PBR_Vars_t &info)
{
info.baseTexture = BASETEXTURE;
info.baseColor = COLOR;
info.normalTexture = NORMALTEXTURE;
info.bumpMap = BUMPMAP;
info.baseTextureFrame = FRAME;
info.baseTextureTransform = BASETEXTURETRANSFORM;
info.alphaTestReference = ALPHATESTREFERENCE;
info.flashlightTexture = FLASHLIGHTTEXTURE;
info.flashlightTextureFrame = FLASHLIGHTTEXTUREFRAME;
info.envMap = ENVMAP;
info.emissionTexture = EMISSIONTEXTURE;
info.mraoTexture = MRAOTEXTURE;
info.useEnvAmbient = USEENVAMBIENT;
info.specularTexture = SPECULARTEXTURE;
info.useParallax = PARALLAX;
info.parallaxDepth = PARALLAXDEPTH;
info.parallaxCenter = PARALLAXCENTER;
};
// Initializing parameters
SHADER_INIT_PARAMS()
{
// Fallback for changed parameter
if (params[NORMALTEXTURE]->IsDefined())
params[BUMPMAP]->SetStringValue(params[NORMALTEXTURE]->GetStringValue());
// Dynamic lights need a bumpmap
if (!params[BUMPMAP]->IsDefined())
params[BUMPMAP]->SetStringValue("dev/flat_normal");
// Set a good default mrao texture
if (!params[MRAOTEXTURE]->IsDefined())
params[MRAOTEXTURE]->SetStringValue("dev/pbr_mraotexture");
// PBR relies heavily on envmaps
if (!params[ENVMAP]->IsDefined())
params[ENVMAP]->SetStringValue("env_cubemap");
// Check if the hardware supports flashlight border color
if (g_pHardwareConfig->SupportsBorderColor())
{
params[FLASHLIGHTTEXTURE]->SetStringValue("effects/flashlight_border");
}
else
{
params[FLASHLIGHTTEXTURE]->SetStringValue("effects/flashlight001");
}
};
// Define shader fallback
SHADER_FALLBACK
{
return 0;
};
SHADER_INIT
{
PBR_Vars_t info;
SetupVars(info);
Assert(info.flashlightTexture >= 0);
LoadTexture(info.flashlightTexture, TEXTUREFLAGS_SRGB);
Assert(info.bumpMap >= 0);
LoadBumpMap(info.bumpMap);
Assert(info.envMap >= 0);
int envMapFlags = g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0;
envMapFlags |= TEXTUREFLAGS_ALL_MIPS;
LoadCubeMap(info.envMap, envMapFlags);
if (info.emissionTexture >= 0 && params[EMISSIONTEXTURE]->IsDefined())
LoadTexture(info.emissionTexture, TEXTUREFLAGS_SRGB);
Assert(info.mraoTexture >= 0);
LoadTexture(info.mraoTexture, 0);
if (params[info.baseTexture]->IsDefined())
{
LoadTexture(info.baseTexture, TEXTUREFLAGS_SRGB);
}
if (params[info.specularTexture]->IsDefined())
{
LoadTexture(info.specularTexture, TEXTUREFLAGS_SRGB);
}
if (IS_FLAG_SET(MATERIAL_VAR_MODEL)) // Set material var2 flags specific to models
{
SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_HW_SKINNING); // Required for skinning
SET_FLAGS2(MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL); // Required for dynamic lighting
SET_FLAGS2(MATERIAL_VAR2_NEEDS_TANGENT_SPACES); // Required for dynamic lighting
SET_FLAGS2(MATERIAL_VAR2_LIGHTING_VERTEX_LIT); // Required for dynamic lighting
SET_FLAGS2(MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS); // Required for ambient cube
SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_FLASHLIGHT); // Required for flashlight
SET_FLAGS2(MATERIAL_VAR2_USE_FLASHLIGHT); // Required for flashlight
}
else // Set material var2 flags specific to brushes
{
SET_FLAGS2(MATERIAL_VAR2_LIGHTING_LIGHTMAP); // Required for lightmaps
SET_FLAGS2(MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP); // Required for lightmaps
SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_FLASHLIGHT); // Required for flashlight
SET_FLAGS2(MATERIAL_VAR2_USE_FLASHLIGHT); // Required for flashlight
}
};
// Drawing the shader
SHADER_DRAW
{
PBR_Vars_t info;
SetupVars(info);
// Setting up booleans
bool bHasBaseTexture = (info.baseTexture != -1) && params[info.baseTexture]->IsTexture();
bool bHasNormalTexture = (info.bumpMap != -1) && params[info.bumpMap]->IsTexture();
bool bHasMraoTexture = (info.mraoTexture != -1) && params[info.mraoTexture]->IsTexture();
bool bHasEmissionTexture = (info.emissionTexture != -1) && params[info.emissionTexture]->IsTexture();
bool bHasEnvTexture = (info.envMap != -1) && params[info.envMap]->IsTexture();
bool bIsAlphaTested = IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) != 0;
bool bHasFlashlight = UsingFlashlight(params);
bool bHasColor = (info.baseColor != -1) && params[info.baseColor]->IsDefined();
bool bLightMapped = !IS_FLAG_SET(MATERIAL_VAR_MODEL);
bool bUseEnvAmbient = (info.useEnvAmbient != -1) && (params[info.useEnvAmbient]->GetIntValue() == 1);
bool bHasSpecularTexture = (info.specularTexture != -1) && params[info.specularTexture]->IsTexture();
// Determining whether we're dealing with a fully opaque material
BlendType_t nBlendType = EvaluateBlendRequirements(info.baseTexture, true);
bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested;
if (IsSnapshotting())
{
// If alphatest is on, enable it
pShaderShadow->EnableAlphaTest(bIsAlphaTested);
if (info.alphaTestReference != -1 && params[info.alphaTestReference]->GetFloatValue() > 0.0f)
{
pShaderShadow->AlphaFunc(SHADER_ALPHAFUNC_GEQUAL, params[info.alphaTestReference]->GetFloatValue());
}
if (bHasFlashlight )
{
pShaderShadow->EnableBlending(true);
pShaderShadow->BlendFunc(SHADER_BLEND_ONE, SHADER_BLEND_ONE); // Additive blending
}
else
{
SetDefaultBlendingShadowState(info.baseTexture, true);
}
int nShadowFilterMode = bHasFlashlight ? g_pHardwareConfig->GetShadowFilterMode() : 0;
// Setting up samplers
pShaderShadow->EnableTexture(SAMPLER_BASETEXTURE, true); // Basecolor texture
pShaderShadow->EnableSRGBRead(SAMPLER_BASETEXTURE, true); // Basecolor is sRGB
pShaderShadow->EnableTexture(SAMPLER_EMISSIVE, true); // Emission texture
pShaderShadow->EnableSRGBRead(SAMPLER_EMISSIVE, true); // Emission is sRGB
pShaderShadow->EnableTexture(SAMPLER_LIGHTMAP, true); // Lightmap texture
pShaderShadow->EnableSRGBRead(SAMPLER_LIGHTMAP, false); // Lightmaps aren't sRGB
pShaderShadow->EnableTexture(SAMPLER_MRAO, true); // MRAO texture
pShaderShadow->EnableSRGBRead(SAMPLER_MRAO, false); // MRAO isn't sRGB
pShaderShadow->EnableTexture(SAMPLER_NORMAL, true); // Normal texture
pShaderShadow->EnableSRGBRead(SAMPLER_NORMAL, false); // Normals aren't sRGB
pShaderShadow->EnableTexture(SAMPLER_SPECULAR, true); // Specular F0 texture
pShaderShadow->EnableSRGBRead(SAMPLER_SPECULAR, true); // Specular F0 is sRGB
// If the flashlight is on, set up its textures
if (bHasFlashlight)
{
pShaderShadow->EnableTexture(SAMPLER_SHADOWDEPTH, true); // Shadow depth map
pShaderShadow->SetShadowDepthFiltering(SAMPLER_SHADOWDEPTH);
pShaderShadow->EnableSRGBRead(SAMPLER_SHADOWDEPTH, false);
pShaderShadow->EnableTexture(SAMPLER_RANDOMROTATION, true); // Noise map
pShaderShadow->EnableTexture(SAMPLER_FLASHLIGHT, true); // Flashlight cookie
pShaderShadow->EnableSRGBRead(SAMPLER_FLASHLIGHT, true);
}
// Setting up envmap
if (bHasEnvTexture)
{
pShaderShadow->EnableTexture(SAMPLER_ENVMAP, true); // Envmap
if (g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE)
{
pShaderShadow->EnableSRGBRead(SAMPLER_ENVMAP, true); // Envmap is only sRGB with HDR disabled?
}
}
// Enabling sRGB writing
// See common_ps_fxc.h line 349
// PS2b shaders and up write sRGB
pShaderShadow->EnableSRGBWrite(true);
if (IS_FLAG_SET(MATERIAL_VAR_MODEL))
{
// We only need the position and surface normal
unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED;
// We need three texcoords, all in the default float2 size
pShaderShadow->VertexShaderVertexFormat(flags, 1, 0, 0);
}
else
{
// We need the position, surface normal, and vertex compression format
unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
// We only need one texcoord, in the default float2 size
pShaderShadow->VertexShaderVertexFormat(flags, 3, 0, 0);
}
int useParallax = params[info.useParallax]->GetIntValue();
if (!mat_pbr_parallaxmap.GetBool())
{
useParallax = 0;
}
if (!g_pHardwareConfig->SupportsShaderModel_3_0() || mat_pbr_force_20b.GetBool())
{
// Setting up static vertex shader
DECLARE_STATIC_VERTEX_SHADER(pbr_vs20b);
SET_STATIC_VERTEX_SHADER(pbr_vs20b);
// Setting up static pixel shader
DECLARE_STATIC_PIXEL_SHADER(pbr_ps20b);
SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHT, bHasFlashlight);
SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode);
SET_STATIC_PIXEL_SHADER_COMBO(LIGHTMAPPED, bLightMapped);
SET_STATIC_PIXEL_SHADER_COMBO(EMISSIVE, bHasEmissionTexture);
SET_STATIC_PIXEL_SHADER_COMBO(SPECULAR, 0);
SET_STATIC_PIXEL_SHADER(pbr_ps20b);
}
else
{
// Setting up static vertex shader
DECLARE_STATIC_VERTEX_SHADER(pbr_vs30);
SET_STATIC_VERTEX_SHADER(pbr_vs30);
// Setting up static pixel shader
DECLARE_STATIC_PIXEL_SHADER(pbr_ps30);
SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHT, bHasFlashlight);
SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode);
SET_STATIC_PIXEL_SHADER_COMBO(LIGHTMAPPED, bLightMapped);
SET_STATIC_PIXEL_SHADER_COMBO(USEENVAMBIENT, bUseEnvAmbient);
SET_STATIC_PIXEL_SHADER_COMBO(EMISSIVE, bHasEmissionTexture);
SET_STATIC_PIXEL_SHADER_COMBO(SPECULAR, bHasSpecularTexture);
SET_STATIC_PIXEL_SHADER_COMBO(PARALLAXOCCLUSION, useParallax);
SET_STATIC_PIXEL_SHADER(pbr_ps30);
}
// Setting up fog
DefaultFog(); // I think this is correct
// HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff
pShaderShadow->EnableAlphaWrites(bFullyOpaque);
}
else // Not snapshotting -- begin dynamic state
{
bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET(MATERIAL_VAR_NO_DEBUG_OVERRIDE);
// Setting up albedo texture
if (bHasBaseTexture)
{
BindTexture(SAMPLER_BASETEXTURE, info.baseTexture, info.baseTextureFrame);
}
else
{
pShaderAPI->BindStandardTexture(SAMPLER_BASETEXTURE, TEXTURE_GREY);
}
// Setting up vmt color
Vector color;
if (bHasColor)
{
params[info.baseColor]->GetVecValue(color.Base(), 3);
}
else
{
color = Vector{1.f, 1.f, 1.f};
}
pShaderAPI->SetPixelShaderConstant(PSREG_SELFILLUMTINT, color.Base());
// Setting up environment map
if (bHasEnvTexture)
{
BindTexture(SAMPLER_ENVMAP, info.envMap, 0);
}
else
{
pShaderAPI->BindStandardTexture(SAMPLER_ENVMAP, TEXTURE_BLACK);
}
// Setting up emissive texture
if (bHasEmissionTexture)
{
BindTexture(SAMPLER_EMISSIVE, info.emissionTexture, 0);
}
else
{
pShaderAPI->BindStandardTexture(SAMPLER_EMISSIVE, TEXTURE_BLACK);
}
// Setting up normal map
if (bHasNormalTexture)
{
BindTexture(SAMPLER_NORMAL, info.bumpMap, 0);
}
else
{
pShaderAPI->BindStandardTexture(SAMPLER_NORMAL, TEXTURE_NORMALMAP_FLAT);
}
// Setting up mrao map
if (bHasMraoTexture)
{
BindTexture(SAMPLER_MRAO, info.mraoTexture, 0);
}
else
{
pShaderAPI->BindStandardTexture(SAMPLER_MRAO, TEXTURE_WHITE);
}
if (bHasSpecularTexture)
{
BindTexture(SAMPLER_SPECULAR, info.specularTexture, 0);
}
else
{
pShaderAPI->BindStandardTexture(SAMPLER_SPECULAR, TEXTURE_BLACK);
}
// Getting the light state
LightState_t lightState;
pShaderAPI->GetDX9LightState(&lightState);
// Brushes don't need ambient cubes or dynamic lights
if (!IS_FLAG_SET(MATERIAL_VAR_MODEL))
{
lightState.m_bAmbientLight = false;
lightState.m_nNumLights = 0;
}
// Setting up the flashlight related textures and variables
bool bFlashlightShadows = false;
if (bHasFlashlight)
{
Assert(info.flashlightTexture >= 0 && info.flashlightTextureFrame >= 0);
Assert(params[info.flashlightTexture]->IsTexture());
BindTexture(SAMPLER_FLASHLIGHT, info.flashlightTexture, info.flashlightTextureFrame);
VMatrix worldToTexture;
ITexture *pFlashlightDepthTexture;
FlashlightState_t state = pShaderAPI->GetFlashlightStateEx(worldToTexture, &pFlashlightDepthTexture);
bFlashlightShadows = state.m_bEnableShadows && (pFlashlightDepthTexture != NULL);
SetFlashLightColorFromState(state, pShaderAPI, PSREG_FLASHLIGHT_COLOR);
if (pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows)
{
BindTexture(SAMPLER_SHADOWDEPTH, pFlashlightDepthTexture, 0);
pShaderAPI->BindStandardTexture(SAMPLER_RANDOMROTATION, TEXTURE_SHADOW_NOISE_2D);
}
}
// Getting fog info
MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
int fogIndex = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z) ? 1 : 0;
// Getting skinning info
int numBones = pShaderAPI->GetCurrentNumBones();
// Some debugging stuff
bool bWriteDepthToAlpha = false;
bool bWriteWaterFogToAlpha = false;
if (bFullyOpaque)
{
bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha();
bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
AssertMsg(!(bWriteDepthToAlpha && bWriteWaterFogToAlpha),
"Can't write two values to alpha at the same time.");
}
float vEyePos_SpecExponent[4];
pShaderAPI->GetWorldSpaceCameraPosition(vEyePos_SpecExponent);
// Determining the max level of detail for the envmap
int iEnvMapLOD = 6;
auto envTexture = params[info.envMap]->GetTextureValue();
if (envTexture)
{
// Get power of 2 of texture width
int width = envTexture->GetMappingWidth();
int mips = 0;
while (width >>= 1)
++mips;
// Cubemap has 4 sides so 2 mips less
iEnvMapLOD = mips;
}
// Dealing with very high and low resolution cubemaps
if (iEnvMapLOD > 12)
iEnvMapLOD = 12;
if (iEnvMapLOD < 4)
iEnvMapLOD = 4;
// This has some spare space
vEyePos_SpecExponent[3] = iEnvMapLOD;
pShaderAPI->SetPixelShaderConstant(PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1);
// Setting lightmap texture
s_pShaderAPI->BindStandardTexture(SAMPLER_LIGHTMAP, TEXTURE_LIGHTMAP_BUMPED);
if (!g_pHardwareConfig->SupportsShaderModel_3_0() || mat_pbr_force_20b.GetBool())
{
// Setting up dynamic vertex shader
DECLARE_DYNAMIC_VERTEX_SHADER(pbr_vs20b);
SET_DYNAMIC_VERTEX_SHADER_COMBO(DOWATERFOG, fogIndex);
SET_DYNAMIC_VERTEX_SHADER_COMBO(SKINNING, numBones > 0);
SET_DYNAMIC_VERTEX_SHADER_COMBO(LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) != 0);
SET_DYNAMIC_VERTEX_SHADER_COMBO(COMPRESSED_VERTS, (int)vertexCompression);
SET_DYNAMIC_VERTEX_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights);
SET_DYNAMIC_VERTEX_SHADER(pbr_vs20b);
// Setting up dynamic pixel shader
DECLARE_DYNAMIC_PIXEL_SHADER(pbr_ps20b);
SET_DYNAMIC_PIXEL_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights);
SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha);
SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha);
SET_DYNAMIC_PIXEL_SHADER_COMBO(PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo());
SET_DYNAMIC_PIXEL_SHADER_COMBO(FLASHLIGHTSHADOWS, bFlashlightShadows);
SET_DYNAMIC_PIXEL_SHADER(pbr_ps20b);
}
else
{
// Setting up dynamic vertex shader
DECLARE_DYNAMIC_VERTEX_SHADER(pbr_vs30);
SET_DYNAMIC_VERTEX_SHADER_COMBO(DOWATERFOG, fogIndex);
SET_DYNAMIC_VERTEX_SHADER_COMBO(SKINNING, numBones > 0);
SET_DYNAMIC_VERTEX_SHADER_COMBO(LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) != 0);
SET_DYNAMIC_VERTEX_SHADER_COMBO(COMPRESSED_VERTS, (int)vertexCompression);
SET_DYNAMIC_VERTEX_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights);
SET_DYNAMIC_VERTEX_SHADER(pbr_vs30);
// Setting up dynamic pixel shader
DECLARE_DYNAMIC_PIXEL_SHADER(pbr_ps30);
SET_DYNAMIC_PIXEL_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights);
SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha);
SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha);
SET_DYNAMIC_PIXEL_SHADER_COMBO(PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo());
SET_DYNAMIC_PIXEL_SHADER_COMBO(FLASHLIGHTSHADOWS, bFlashlightShadows);
SET_DYNAMIC_PIXEL_SHADER(pbr_ps30);
}
// Setting up base texture transform
SetVertexShaderTextureTransform(VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.baseTextureTransform);
// This is probably important
SetModulationPixelShaderDynamicState_LinearColorSpace(1);
// Send ambient cube to the pixel shader, force to black if not available
pShaderAPI->SetPixelShaderStateAmbientLightCube(PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight);
// Send lighting array to the pixel shader
pShaderAPI->CommitPixelShaderLighting(PSREG_LIGHT_INFO_ARRAY);
// Handle mat_fullbright 2 (diffuse lighting only)
if (bLightingOnly)
{
pShaderAPI->BindStandardTexture(SAMPLER_BASETEXTURE, TEXTURE_GREY); // Basecolor
}
// Handle mat_specular 0 (no envmap reflections)
if (!mat_specular.GetBool())
{
pShaderAPI->BindStandardTexture(SAMPLER_ENVMAP, TEXTURE_BLACK); // Envmap
}
// Sending fog info to the pixel shader
pShaderAPI->SetPixelShaderFogParams(PSREG_FOG_PARAMS);
// Set up shader modulation color
float modulationColor[4] = { 1.0, 1.0, 1.0, 1.0 };
ComputeModulationColor(modulationColor);
float flLScale = pShaderAPI->GetLightMapScaleFactor();
modulationColor[0] *= flLScale;
modulationColor[1] *= flLScale;
modulationColor[2] *= flLScale;
pShaderAPI->SetPixelShaderConstant(PSREG_DIFFUSE_MODULATION, modulationColor);
// More flashlight related stuff
if (bHasFlashlight)
{
VMatrix worldToTexture;
float atten[4], pos[4], tweaks[4];
const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState(worldToTexture);
SetFlashLightColorFromState(flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR);
BindTexture(SAMPLER_FLASHLIGHT, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame);
// Set the flashlight attenuation factors
atten[0] = flashlightState.m_fConstantAtten;
atten[1] = flashlightState.m_fLinearAtten;
atten[2] = flashlightState.m_fQuadraticAtten;
atten[3] = flashlightState.m_FarZ;
pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_ATTENUATION, atten, 1);
// Set the flashlight origin
pos[0] = flashlightState.m_vecLightOrigin[0];
pos[1] = flashlightState.m_vecLightOrigin[1];
pos[2] = flashlightState.m_vecLightOrigin[2];
pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1);
pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4);
// Tweaks associated with a given flashlight
tweaks[0] = ShadowFilterFromState(flashlightState);
tweaks[1] = ShadowAttenFromState(flashlightState);
HashShadow2DJitter(flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3]);
pShaderAPI->SetPixelShaderConstant(PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1);
}
float flParams[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
// Parallax Depth (the strength of the effect)
flParams[0] = GetFloatParam(info.parallaxDepth, params, 3.0f);
// Parallax Center (the height at which it's not moved)
flParams[1] = GetFloatParam(info.parallaxCenter, params, 3.0f);
pShaderAPI->SetPixelShaderConstant(27, flParams, 1);
}
// Actually draw the shader
Draw();
};
// Closing it off
END_SHADER;