You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
616 lines
26 KiB
616 lines
26 KiB
//================================================================================================== |
|
// |
|
// 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;
|
|
|