mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 17:59:37 +00:00
Add PBR support (#91)
* Add PBR support * Fix physics props turning black
This commit is contained in:
@@ -0,0 +1,616 @@
|
||||
//==================================================================================================
|
||||
//
|
||||
// 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;
|
||||
Reference in New Issue
Block a user