Use shader specialization constants

This commit is contained in:
Magnus Norddahl 2025-03-22 15:12:07 +01:00
commit 3313baad6b
20 changed files with 238 additions and 364 deletions

View file

@ -301,8 +301,14 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
VkShaderProgram *program = fb->GetShaderManager()->Get(key.ShaderKey);
builder.AddVertexShader(program->vert.get());
builder.AddConstant(0, (uint32_t)key.ShaderKey.AsQWORD);
builder.AddConstant(1, (uint32_t)(key.ShaderKey.AsQWORD >> 32));
if (program->frag)
{
builder.AddFragmentShader(program->frag.get());
builder.AddConstant(0, (uint32_t)key.ShaderKey.AsQWORD);
builder.AddConstant(1, (uint32_t)(key.ShaderKey.AsQWORD >> 32));
}
const VkVertexFormat &vfmt = *fb->GetRenderPassManager()->GetVertexFormat(key.ShaderKey.VertexFormat);

View file

@ -331,6 +331,12 @@ void VkShaderManager::BuildLayoutBlock(FString &layoutBlock, bool isFrag, const
}
layoutBlock << "};\n";
if (!isUberShader)
{
layoutBlock << " layout (constant_id = 0) const int uShaderKey1 = 0;\n";
layoutBlock << " layout (constant_id = 1) const int uShaderKey2 = 0;\n";
}
if(!isFrag)
{
AddVertexInFields(fb, layoutBlock, key);
@ -354,7 +360,7 @@ void VkShaderManager::BuildLayoutBlock(FString &layoutBlock, bool isFrag, const
}
}
void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defines, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader, bool isUberShader)
void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defines, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader)
{
if (fb->IsRayQueryEnabled())
{
@ -380,173 +386,81 @@ void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defin
definesBlock << "#define NO_CLIPDISTANCE_SUPPORT\n";
}
if(isUberShader)
{
//ugh EffectState also controls layout, because specular/pbr/etc defines switch texture indices around for normal/specular/etc
definesBlock << LoadPrivateShaderLump("shaders/shaderkey.glsl").GetChars() << "\n";
definesBlock << SubstituteDefines(LoadPrivateShaderLump("shaders/shaderkey.glsl")).GetChars() << "\n";
// What is this define about? Why is it needed?
definesBlock << "#define UBERSHADERS\n";
definesBlock << "#define UBERSHADERS\n";
// Controls layout and has to be defines:
definesBlock << "#define DO_ALPHATEST ((uShaderKey1 & SK1_ALPHATEST) != 0)\n";
//definesBlock << "#define SIMPLE ((uShaderKey1 & SK1_SIMPLE) != 0)\n";
//definesBlock << "#define SIMPLE3D ((uShaderKey1 & SK1_SIMPLE3D) != 0)\n";
// controls layout
if (key.Simple) definesBlock << "#define SIMPLE\n";
if (key.Simple3D) definesBlock << "#define SIMPLE3D\n";
if (key.AlphaTest) definesBlock << "#define DO_ALPHATEST\n";
if (key.Simple) definesBlock << "#define SIMPLE\n";
if (key.Simple3D) definesBlock << "#define SIMPLE3D\n";
if (key.GBufferPass) definesBlock << "#define GBUFFER_PASS\n";
if (key.UseLevelMesh) definesBlock << "#define USE_LEVELMESH\n";
if (key.ShadeVertex) definesBlock << "#define SHADE_VERTEX\n";
definesBlock << "#define SIMPLE2D ((uShaderKey1 & SK1_SIMPLE2D) != 0)\n";
// We could move this to shaders/shaderkey.glsl as its always the same:
definesBlock << "#define TM_STENCIL (SK_GET_TEXTUREMODE() == SK1_TM_STENCIL)\n";
definesBlock << "#define TM_OPAQUE (SK_GET_TEXTUREMODE() == SK1_TM_OPAQUE)\n";
definesBlock << "#define TM_INVERSE (SK_GET_TEXTUREMODE() == SK1_TM_INVERSE)\n";
definesBlock << "#define TM_ALPHATEXTURE (SK_GET_TEXTUREMODE() == SK1_TM_ALPHATEXTURE)\n";
definesBlock << "#define TM_CLAMPY (SK_GET_TEXTUREMODE() == SK1_TM_CLAMPY)\n";
definesBlock << "#define TM_INVERTOPAQUE (SK_GET_TEXTUREMODE() == SK1_TM_INVERTOPAQUE)\n";
definesBlock << "#define TM_FOGLAYER (SK_GET_TEXTUREMODE() == SK1_TM_FOGLAYER)\n";
// Should we define these anyway for completeness?
// definesBlock << "#define DO_ALPHATEST ((uShaderKey1 & SK1_ALPHATEST) != 0)\n";
// definesBlock << "#define SIMPLE ((uShaderKey1 & SK1_SIMPLE) != 0)\n";
// definesBlock << "#define SIMPLE3D ((uShaderKey1 & SK1_SIMPLE3D) != 0)\n";
// definesBlock << "#define GBUFFER_PASS ((uShaderKey1 & SK1_GBUFFER_PASS) != 0)\n";
// definesBlock << "#define USE_LEVELMESH (!!(uShaderKey1 & SK1_USE_LEVELMESH))\n";
// definesBlock << "#define SHADE_VERTEX ((uShaderKey2 & SK2_SHADE_VERTEX) != 0)\n";
definesBlock << "#define TEXF_ClampY ((uShaderKey1 & SK1_TEXF_CLAMPY) != 0)\n";
definesBlock << "#define TEXF_Brightmap ((uShaderKey1 & SK1_TEXF_BRIGHTMAP) != 0)\n";
definesBlock << "#define TEXF_Detailmap ((uShaderKey1 & SK1_TEXF_DETAILMAP) != 0)\n";
definesBlock << "#define TEXF_Glowmap ((uShaderKey1 & SK1_TEXF_GLOWMAP) != 0)\n";
definesBlock << "#define SIMPLE2D ((uShaderKey1 & SK1_SIMPLE2D) != 0)\n";
definesBlock << "#define GBUFFER_PASS ((uShaderKey1 & SK1_GBUFFER_PASS) != 0)\n";
definesBlock << "#define TM_STENCIL (SK_GET_TEXTUREMODE() == SK1_TM_STENCIL)\n";
definesBlock << "#define TM_OPAQUE (SK_GET_TEXTUREMODE() == SK1_TM_OPAQUE)\n";
definesBlock << "#define TM_INVERSE (SK_GET_TEXTUREMODE() == SK1_TM_INVERSE)\n";
definesBlock << "#define TM_ALPHATEXTURE (SK_GET_TEXTUREMODE() == SK1_TM_ALPHATEXTURE)\n";
definesBlock << "#define TM_CLAMPY (SK_GET_TEXTUREMODE() == SK1_TM_CLAMPY)\n";
definesBlock << "#define TM_INVERTOPAQUE (SK_GET_TEXTUREMODE() == SK1_TM_INVERTOPAQUE)\n";
definesBlock << "#define TM_FOGLAYER (SK_GET_TEXTUREMODE() == SK1_TM_FOGLAYER)\n";
definesBlock << "#define USE_SHADOWMAP ((uShaderKey1 & SK1_USE_SHADOWMAP) != 0)\n";
definesBlock << "#define TEXF_ClampY ((uShaderKey1 & SK1_TEXF_CLAMPY) != 0)\n";
definesBlock << "#define TEXF_Brightmap ((uShaderKey1 & SK1_TEXF_BRIGHTMAP) != 0)\n";
definesBlock << "#define TEXF_Detailmap ((uShaderKey1 & SK1_TEXF_DETAILMAP) != 0)\n";
definesBlock << "#define TEXF_Glowmap ((uShaderKey1 & SK1_TEXF_GLOWMAP) != 0)\n";
definesBlock << "#define USE_RAYTRACE ((uShaderKey1 & SK1_USE_RAYTRACE) != 0)\n";
definesBlock << "#define USE_RAYTRACE_PRECISE ((uShaderKey1 & SK1_USE_RAYTRACE_PRECISE) != 0)\n";
definesBlock << "#define PRECISE_MIDTEXTURES ((uShaderKey1 & SK1_PRECISE_MIDTEXTURES) != 0)\n";
definesBlock << "#define USE_SHADOWMAP ((uShaderKey1 & SK1_USE_SHADOWMAP) != 0)\n";
definesBlock << "#define SHADOWMAP_FILTER (SK_GET_SHADOWMAP_FILTER())\n";
definesBlock << "#define USE_RAYTRACE ((uShaderKey1 & SK1_USE_RAYTRACE) != 0)\n";
definesBlock << "#define USE_RAYTRACE_PRECISE ((uShaderKey1 & SK1_USE_RAYTRACE_PRECISE) != 0)\n";
definesBlock << "#define PRECISE_MIDTEXTURES ((uShaderKey1 & SK1_PRECISE_MIDTEXTURES) != 0)\n";
definesBlock << "#define FOG_BEFORE_LIGHTS ((uShaderKey1 & SK1_FOG_BEFORE_LIGHTS) != 0)\n";
definesBlock << "#define FOG_AFTER_LIGHTS ((uShaderKey1 & SK1_FOG_AFTER_LIGHTS) != 0)\n";
definesBlock << "#define FOG_RADIAL ((uShaderKey1 & SK1_FOG_RADIAL) != 0)\n";
definesBlock << "#define SHADOWMAP_FILTER (SK_GET_SHADOWMAP_FILTER())\n";
definesBlock << "#define SWLIGHT_RADIAL ((uShaderKey1 & SK1_SWLIGHT_RADIAL) != 0)\n";
definesBlock << "#define SWLIGHT_BANDED ((uShaderKey1 & SK1_SWLIGHT_BANDED) != 0)\n";
definesBlock << "#define FOG_BEFORE_LIGHTS ((uShaderKey1 & SK1_FOG_BEFORE_LIGHTS) != 0)\n";
definesBlock << "#define FOG_AFTER_LIGHTS ((uShaderKey1 & SK1_FOG_AFTER_LIGHTS) != 0)\n";
definesBlock << "#define FOG_RADIAL ((uShaderKey1 & SK1_FOG_RADIAL) != 0)\n";
definesBlock << "#define LIGHTMODE_DEFAULT (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_DEFAULT)\n";
definesBlock << "#define LIGHTMODE_SOFTWARE (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_SOFTWARE)\n";
definesBlock << "#define LIGHTMODE_VANILLA (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_VANILLA)\n";
definesBlock << "#define LIGHTMODE_BUILD (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_BUILD)\n";
definesBlock << "#define SWLIGHT_RADIAL ((uShaderKey1 & SK1_SWLIGHT_RADIAL) != 0)\n";
definesBlock << "#define SWLIGHT_BANDED ((uShaderKey1 & SK1_SWLIGHT_BANDED) != 0)\n";
definesBlock << "#define LIGHT_BLEND_CLAMPED (SK_GET_LIGHTBLENDMODE() == SK1_LIGHT_BLEND_CLAMPED)\n";
definesBlock << "#define LIGHT_BLEND_COLORED_CLAMP (SK_GET_LIGHTBLENDMODE() == SK1_LIGHT_LIGHT_BLEND_COLORED_CLAMP)\n";
definesBlock << "#define LIGHT_BLEND_UNCLAMPED (SK_GET_LIGHTBLENDMODE() == SK1_LIGHT_BLEND_UNCLAMPED)\n";
definesBlock << "#define LIGHTMODE_DEFAULT (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_DEFAULT)\n";
definesBlock << "#define LIGHTMODE_SOFTWARE (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_SOFTWARE)\n";
definesBlock << "#define LIGHTMODE_VANILLA (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_VANILLA)\n";
definesBlock << "#define LIGHTMODE_BUILD (SK_GET_LIGHTMODE() == SK1_LIGHTMODE_BUILD)\n";
definesBlock << "#define LIGHT_ATTENUATION_LINEAR ((uShaderKey1 & SK1_TEXTUREMODE) == 0)\n";
definesBlock << "#define LIGHT_ATTENUATION_INVERSE_SQUARE ((uShaderKey1 & SK1_TEXTUREMODE) != 0)\n";
definesBlock << "#define LIGHT_BLEND_CLAMPED (SK_GET_LIGHTBLENDMODE() == SK1_LIGHT_BLEND_CLAMPED)\n";
definesBlock << "#define LIGHT_BLEND_COLORED_CLAMP (SK_GET_LIGHTBLENDMODE() == SK1_LIGHT_LIGHT_BLEND_COLORED_CLAMP)\n";
definesBlock << "#define LIGHT_BLEND_UNCLAMPED (SK_GET_LIGHTBLENDMODE() == SK1_LIGHT_BLEND_UNCLAMPED)\n";
//definesBlock << "#define USE_LEVELMESH (!!(uShaderKey1 & SK1_USE_LEVELMESH))\n";
// controls layout
if (key.UseLevelMesh) definesBlock << "#define USE_LEVELMESH\n";
definesBlock << "#define LIGHT_ATTENUATION_LINEAR ((uShaderKey1 & SK1_TEXTUREMODE) == 0)\n";
definesBlock << "#define LIGHT_ATTENUATION_INVERSE_SQUARE ((uShaderKey1 & SK1_TEXTUREMODE) != 0)\n";
definesBlock << "#define FOGBALLS ((uShaderKey1 & SK1_FOGBALLS) != 0)\n";
definesBlock << "#define FOGBALLS ((uShaderKey1 & SK1_FOGBALLS) != 0)\n";
//key.NoFragmentShader not used in defines
definesBlock << "#define USE_DEPTHFADETHRESHOLD ((uShaderKey2 & SK2_USE_DEPTHFADETHRESHOLD) != 0)\n";
definesBlock << "#define NOT_ALPHATEST_ONLY ((uShaderKey2 & SK2_ALPHATEST_ONLY) == 0)\n";
definesBlock << "#define LIGHT_NONORMALS ((uShaderKey2 & SK2_LIGHT_NONORMALS) != 0)\n";
definesBlock << "#define USE_SPRITE_CENTER ((uShaderKey2 & SK2_USE_SPRITECENTER) != 0)\n";
definesBlock << "#define USE_DEPTHFADETHRESHOLD ((uShaderKey2 & SK2_USE_DEPTHFADETHRESHOLD) != 0)\n";
definesBlock << "#define NOT_ALPHATEST_ONLY ((uShaderKey2 & SK2_ALPHATEST_ONLY) == 0)\n";
//definesBlock << "#define SHADE_VERTEX ((uShaderKey2 & SK2_SHADE_VERTEX) != 0)\n";
// controls layout
if (key.ShadeVertex) definesBlock << "#define SHADE_VERTEX\n";
definesBlock << "#define LIGHT_NONORMALS ((uShaderKey2 & SK2_LIGHT_NONORMALS) != 0)\n";
definesBlock << "#define USE_SPRITE_CENTER ((uShaderKey2 & SK2_USE_SPRITECENTER) != 0)\n";
definesBlock << "#define uFogEnabled ((uShaderKey1 & SK1_SIMPLE2D) ? -3 : 0)\n";
}
else
{
if (key.AlphaTest) definesBlock << "#define DO_ALPHATEST\n";
if (key.Simple) definesBlock << "#define SIMPLE\n";
if (key.Simple2D) definesBlock << "#define SIMPLE2D\n";
if (key.Simple3D) definesBlock << "#define SIMPLE3D\n";
switch (key.TextureMode)
{
case TM_STENCIL: definesBlock << "#define TM_STENCIL\n"; break;
case TM_OPAQUE: definesBlock << "#define TM_OPAQUE\n"; break;
case TM_INVERSE: definesBlock << "#define TM_INVERSE\n"; break;
case TM_ALPHATEXTURE: definesBlock << "#define TM_ALPHATEXTURE\n"; break;
case TM_CLAMPY: definesBlock << "#define TM_CLAMPY\n"; break;
case TM_INVERTOPAQUE: definesBlock << "#define TM_INVERTOPAQUE\n"; break;
case TM_FOGLAYER: definesBlock << "#define TM_FOGLAYER\n"; break;
}
if (key.ClampY) definesBlock << "#define TEXF_ClampY\n";
if (key.Brightmap) definesBlock << "#define TEXF_Brightmap\n";
if (key.Detailmap) definesBlock << "#define TEXF_Detailmap\n";
if (key.Glowmap) definesBlock << "#define TEXF_Glowmap\n";
if (key.GBufferPass) definesBlock << "#define GBUFFER_PASS\n";
if (key.UseShadowmap) definesBlock << "#define USE_SHADOWMAP\n";
if (key.UseRaytrace) definesBlock << "#define USE_RAYTRACE\n";
if (key.UseRaytracePrecise) definesBlock << "#define USE_RAYTRACE_PRECISE\n";
if (key.PreciseMidtextureTrace) definesBlock << "#define PRECISE_MIDTEXTURES\n";
definesBlock << "#define SHADOWMAP_FILTER " << std::to_string(key.ShadowmapFilter).c_str() << "\n";
if (key.FogBeforeLights) definesBlock << "#define FOG_BEFORE_LIGHTS\n";
if (key.FogAfterLights) definesBlock << "#define FOG_AFTER_LIGHTS\n";
if (key.FogRadial) definesBlock << "#define FOG_RADIAL\n";
if (key.SWLightRadial) definesBlock << "#define SWLIGHT_RADIAL\n";
if (key.SWLightBanded) definesBlock << "#define SWLIGHT_BANDED\n";
switch (key.LightMode)
{
case 0: definesBlock << "#define LIGHTMODE_DEFAULT\n"; break;
case 1: definesBlock << "#define LIGHTMODE_SOFTWARE\n"; break;
case 2: definesBlock << "#define LIGHTMODE_VANILLA\n"; break;
case 3: definesBlock << "#define LIGHTMODE_BUILD\n"; break;
}
switch(key.LightBlendMode)
{
case 0:
definesBlock << "#define LIGHT_BLEND_CLAMPED\n";
break;
case 1:
definesBlock << "#define LIGHT_BLEND_COLORED_CLAMP\n";
break;
case 2:
definesBlock << "#define LIGHT_BLEND_UNCLAMPED\n";
break;
}
switch(key.LightAttenuationMode)
{
case 0:
definesBlock << "#define LIGHT_ATTENUATION_LINEAR\n";
break;
case 1:
definesBlock << "#define LIGHT_ATTENUATION_INVERSE_SQUARE\n";
break;
}
if (key.UseLevelMesh) definesBlock << "#define USE_LEVELMESH\n";
if (key.FogBalls) definesBlock << "#define FOGBALLS\n";
//key.NoFragmentShader not used in defines
if (key.DepthFadeThreshold) definesBlock << "#define USE_DEPTHFADETHRESHOLD\n";
if (!key.AlphaTestOnly) definesBlock << "#define NOT_ALPHATEST_ONLY\n";
if (key.ShadeVertex) definesBlock << "#define SHADE_VERTEX\n";
if (key.LightNoNormals) definesBlock << "#define LIGHT_NONORMALS\n";
if (key.UseSpriteCenter) definesBlock << "#define USE_SPRITE_CENTER\n";
definesBlock << ((key.Simple2D) ? "#define uFogEnabled -3\n" : "#define uFogEnabled 0\n");
}
definesBlock << "#define uFogEnabled ((uShaderKey1 & SK1_SIMPLE2D) ? -3 : 0)\n";
// Setup fake variables for the 'in' attributes that aren't actually available because the garbage shader code thinks they exist
// God I hate this engine... :(
@ -571,15 +485,15 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
BuildLayoutBlock(layoutBlock, false, key, shader);
FString codeBlock;
codeBlock << SubstituteDefines(LoadPrivateShaderLump(vert_lump)).GetChars() << "\n";
codeBlock << LoadPrivateShaderLump(vert_lump).GetChars() << "\n";
if(vert_lump_custom)
{
codeBlock << "\n#line 1\n";
codeBlock << SubstituteDefines(LoadPublicShaderLump(vert_lump_custom)).GetChars() << "\n";
codeBlock << LoadPublicShaderLump(vert_lump_custom).GetChars() << "\n";
}
else
{
codeBlock << SubstituteDefines(LoadPrivateShaderLump("shaders/scene/vert_nocustom.glsl")).GetChars() << "\n";
codeBlock << LoadPrivateShaderLump("shaders/scene/vert_nocustom.glsl").GetChars() << "\n";
}
return ShaderBuilder()
@ -588,9 +502,8 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
.AddSource("VersionBlock", GetVersionBlock().GetChars())
.AddSource("DefinesBlock", definesBlock.GetChars())
.AddSource("LayoutBlock", layoutBlock.GetChars())
.AddSource("shaders/scene/layout_shared.glsl", SubstituteDefines(LoadPrivateShaderLump("shaders/scene/layout_shared.glsl")).GetChars())
.AddSource("shaders/scene/layout_shared.glsl", LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars())
.AddSource(vert_lump_custom ? vert_lump_custom : vert_lump, codeBlock.GetChars())
.IncludeFilter([](FString s) { return SubstituteDefines(std::move(s), false); })
.Compile(fb))
.DebugName(shadername.GetChars())
.Create(shadername.GetChars(), fb->GetDevice());
@ -605,7 +518,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
BuildLayoutBlock(layoutBlock, true, key, shader);
FString codeBlock;
codeBlock << SubstituteDefines(LoadPrivateShaderLump(frag_lump)).GetChars() << "\n";
codeBlock << LoadPrivateShaderLump(frag_lump).GetChars() << "\n";
FString materialname = "MaterialBlock";
FString materialBlock;
@ -617,7 +530,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
if (material_lump)
{
materialname = material_lump;
materialBlock = SubstituteDefines(LoadPublicShaderLump(material_lump));
materialBlock = LoadPublicShaderLump(material_lump);
// Attempt to fix old custom shaders:
@ -636,15 +549,15 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
FString code;
if (materialBlock.IndexOf("ProcessTexel") >= 0)
{
code = SubstituteDefines(LoadPrivateShaderLump("shaders/scene/material_legacy_ptexel.glsl"));
code = LoadPrivateShaderLump("shaders/scene/material_legacy_ptexel.glsl");
}
else if (materialBlock.IndexOf("Process") >= 0)
{
code = SubstituteDefines(LoadPrivateShaderLump("shaders/scene/material_legacy_process.glsl"));
code = LoadPrivateShaderLump("shaders/scene/material_legacy_process.glsl");
}
else
{
code = SubstituteDefines(LoadPrivateShaderLump("shaders/scene/material_default.glsl"));
code = LoadPrivateShaderLump("shaders/scene/material_default.glsl");
}
code << "\n#line 1\n";
@ -656,7 +569,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
definesBlock << "#define LEGACY_USER_SHADER\n";
FString code = SubstituteDefines(LoadPrivateShaderLump("shaders/scene/material_legacy_pmaterial.glsl"));
FString code = LoadPrivateShaderLump("shaders/scene/material_legacy_pmaterial.glsl");
code << "\n#line 1\n";
materialBlock = code + materialBlock;
@ -669,17 +582,17 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
if(light_lump_shared)
{
lightBlock << SubstituteDefines(LoadPrivateShaderLump(light_lump_shared)).GetChars();
lightBlock << LoadPrivateShaderLump(light_lump_shared).GetChars();
}
lightBlock << SubstituteDefines(LoadPrivateShaderLump(light_lump)).GetChars();
lightBlock << LoadPrivateShaderLump(light_lump).GetChars();
}
if (mateffect_lump && mateffectBlock.IsEmpty())
{
mateffectname = mateffect_lump;
mateffectBlock << SubstituteDefines(LoadPrivateShaderLump(mateffect_lump)).GetChars();
mateffectBlock << LoadPrivateShaderLump(mateffect_lump).GetChars();
}
return ShaderBuilder()
@ -688,13 +601,12 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
.AddSource("VersionBlock", GetVersionBlock().GetChars())
.AddSource("DefinesBlock", definesBlock.GetChars())
.AddSource("LayoutBlock", layoutBlock.GetChars())
.AddSource("shaders/scene/layout_shared.glsl", SubstituteDefines(LoadPrivateShaderLump("shaders/scene/layout_shared.glsl")).GetChars())
.AddSource("shaders/scene/includes.glsl", SubstituteDefines(LoadPrivateShaderLump("shaders/scene/includes.glsl")).GetChars())
.AddSource("shaders/scene/layout_shared.glsl", LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars())
.AddSource("shaders/scene/includes.glsl", LoadPrivateShaderLump("shaders/scene/includes.glsl").GetChars())
.AddSource(mateffectname.GetChars(), mateffectBlock.GetChars())
.AddSource(materialname.GetChars(), materialBlock.GetChars())
.AddSource(lightname.GetChars(), lightBlock.GetChars())
.AddSource(frag_lump, codeBlock.GetChars())
.IncludeFilter([](FString s) { return SubstituteDefines(std::move(s), false); })
.Compile(fb))
.DebugName(shadername.GetChars())
.Create(shadername.GetChars(), fb->GetDevice());
@ -734,29 +646,6 @@ FString VkShaderManager::LoadPrivateShaderLump(const char* lumpname)
return fb->GetShaderCache()->GetPrivateFile(lumpname).Code;
}
FString VkShaderManager::SubstituteDefines(FString str, bool isUberShader)
{
if (isUberShader)
{
str.Substitute("#uifdef", "if");
str.Substitute("#uelifdef", "else if");
str.Substitute("#uif", "if");
str.Substitute("#uelif", "else if");
str.Substitute("#uelse", "else");
str.Substitute("#uendif", "");
}
else
{
str.Substitute("#uifdef", "#if defined");
str.Substitute("#uelifdef", "#elif defined");
str.Substitute("#uif", "#if");
str.Substitute("#uelif", "#elif");
str.Substitute("#uelse", "#else");
str.Substitute("#uendif", "#endif");
}
return str;
}
VkPPShader* VkShaderManager::GetVkShader(PPShader* shader)
{
if (!shader->Backend)

View file

@ -167,10 +167,8 @@ private:
FString LoadPublicShaderLump(const char *lumpname);
FString LoadPrivateShaderLump(const char *lumpname);
static FString SubstituteDefines(FString code, bool isUberShader = false);
void BuildLayoutBlock(FString &definesBlock, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader, bool isUberShader = false);
void BuildDefinesBlock(FString &definesBlock, const char *defines, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader, bool isUberShader = false);
void BuildDefinesBlock(FString &definesBlock, const char *defines, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader);
VulkanRenderDevice* fb = nullptr;

View file

@ -5,20 +5,18 @@ void main()
// calculate fog factor
//
#uifdef(FOG_RADIAL)
if (FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#uelse
else
float fogdist = max(16.0, pixelpos.w);
#uendif
endif
float fogfactor = exp2 (uFogDensity * fogdist);
FragColor = vec4(uFogColor.rgb, 1.0 - fogfactor);
#uifdef(GBUFFER_PASS)
{
#if defined(GBUFFER_PASS)
FragFog = vec4(0.0, 0.0, 0.0, 1.0);
FragNormal = vec4(0.5, 0.5, 0.5, 1.0);
}
#uendif
#endif
}

View file

@ -15,14 +15,14 @@ vec3 rgb2hsv(vec3 c)
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
#ifdef SIMPLE3D
void main()
{
#uifdef(SIMPLE3D)
{
Material material = CreateMaterial();
FragColor = vec4(material.Base.rgb, 1.0);
}
#uelse
#else
void main()
{
#ifdef NO_CLIPDISTANCE_SUPPORT
if (ClipDistanceA.x < 0 || ClipDistanceA.y < 0 || ClipDistanceA.z < 0 || ClipDistanceA.w < 0 || ClipDistanceB.x < 0) discard;
@ -35,20 +35,19 @@ void main()
Material material = CreateMaterial();
#uifdef(DO_ALPHATEST)
#ifdef DO_ALPHATEST
if (material.Base.a <= uAlphaThreshold) discard;
#uendif
#endif
#uifdef(NOT_ALPHATEST_ONLY)
if (NOT_ALPHATEST_ONLY)
{
#uifdef(USE_DEPTHFADETHRESHOLD)
if (USE_DEPTHFADETHRESHOLD)
{
float behindFragmentDepth = texelFetch(LinearDepth, uViewOffset + ivec2(gl_FragCoord.xy), 0).r;
material.Base.a *= clamp((behindFragmentDepth - pixelpos.w) / uDepthFadeThreshold, 0.0, 1.0);
}
#uendif
FragColor = ProcessLightMode(material);
FragColor = ProcessLightMode(material);
#ifdef DITHERTRANS
int index = (int(pixelpos.x) % 8) * 8 + int(pixelpos.y) % 8;
@ -70,14 +69,10 @@ void main()
else FragColor *= 0.5;
#endif
#uifdef(GBUFFER_PASS)
{
#if defined(GBUFFER_PASS)
FragFog = vec4(AmbientOcclusionColor(), 1.0);
FragNormal = vec4(vEyeNormal.xyz * 0.5 + 0.5, 1.0);
}
#uendif
#endif
}
#uendif
}
#uendif
}
#endif

View file

@ -2,11 +2,9 @@
void main()
{
FragColor = vec4(0.0, 1.0, 0.0, 1.0);
#uifdef(GBUFFER_PASS)
{
#if defined(GBUFFER_PASS)
FragFog = vec4(0.0, 0.0, 0.0, 1.0);
FragNormal = vec4(0.5, 0.5, 0.5, 1.0);
}
#uendif
#endif
}

View file

@ -2,11 +2,9 @@
void main()
{
FragColor = vec4(1.0, 1.0, 1.0, 0.0);
#uifdef(GBUFFER_PASS)
{
#if defined(GBUFFER_PASS)
FragFog = vec4(0.0, 0.0, 0.0, 1.0);
FragNormal = vec4(0.5, 0.5, 0.5, 1.0);
}
#uendif
#endif
}

View file

@ -125,11 +125,10 @@ float shadowmapAttenuation(vec3 lightpos, float shadowIndex)
float v = (shadowIndex + 0.5) / 1024.0;
#uif(SHADOWMAP_FILTER == 0)
if (SHADOWMAP_FILTER == 0)
return sampleShadowmap(planePoint, v);
#uelse
else
return sampleShadowmapPCF(planePoint, v);
#uendif
}
float shadowAttenuationShadowMap(vec3 lightpos, int shadowIndex, float softShadowRadius, int flags)

View file

@ -17,7 +17,7 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
{
TraceResult result;
SurfaceInfo surface;
#uifdef(PRECISE_MIDTEXTURES)
if (PRECISE_MIDTEXTURES)
{
bool skip = true;
@ -89,7 +89,7 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
return 0.0;
}
}
#uelse
else
{
result = TraceFirstHit(origin, tmin, direction, dist);
@ -106,7 +106,6 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
if (alpha <= 0.0)
return 0.0;
}
#uendif
// Move to surface hit point
origin += direction * result.t;
@ -121,11 +120,10 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
float traceHit(vec3 origin, vec3 direction, float dist)
{
#uifdef(USE_RAYTRACE_PRECISE)
if (USE_RAYTRACE_PRECISE)
return TraceDynLightRay(origin, 0.01f, direction, dist);
#uelse
else
return TraceAnyHit(origin, 0.01f, direction, dist) ? 0.0 : 1.0;
#uendif
}
float traceShadow(vec3 lightpos, float softShadowRadius)
@ -133,29 +131,34 @@ float traceShadow(vec3 lightpos, float softShadowRadius)
vec3 target = lightpos.xyz + 0.01; // nudge light position slightly as Doom maps tend to have their lights perfectly aligned with planes
vec3 origin;
vec3 direction;
#uifdef(USE_SPRITE_CENTER)
if (USE_SPRITE_CENTER)
{
origin = uActorCenter.xyz;
direction = normalize(target - origin);
}
#uelifdef(LIGHT_NONORMALS)
else if (LIGHT_NONORMALS)
{
origin = pixelpos.xyz;
direction = normalize(target - origin);
origin -= direction;
}
#uelse
else
{
origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
direction = normalize(target - origin);
}
#uendif
float dist = distance(origin, target);
#uif(SHADOWMAP_FILTER == 0)
#if defined(SHADE_VERTEX)
return traceHit(origin, direction, dist);
#else
if(SHADOWMAP_FILTER == 0)
{
return traceHit(origin, direction, dist);
#uelse
}
else
{
if (softShadowRadius == 0)
{
return traceHit(origin, direction, dist);
@ -176,32 +179,37 @@ float traceShadow(vec3 lightpos, float softShadowRadius)
}
return (sum / step_count);
}
#uendif
}
#endif
}
float traceSun(vec3 SunDir)
{
vec3 origin;
#uifdef(USE_SPRITE_CENTER)
if (USE_SPRITE_CENTER)
{
origin = uActorCenter.xyz;
}
#uelifdef(LIGHT_NONORMALS)
else if (LIGHT_NONORMALS)
{
origin = pixelpos.xyz;
origin -= SunDir;
}
#uelse
else
{
origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
}
#uendif
float dist = 65536.0;
#uif(SHADOWMAP_FILTER == 0)
#if defined(SHADE_VERTEX)
return TraceDynLightRay(origin, 0.01f, SunDir, dist);
#else
if (SHADOWMAP_FILTER == 0)
{
return TraceDynLightRay(origin, 0.01f, SunDir, dist);
#uelse
}
else
{
vec3 target = (SunDir * dist) + origin;
vec3 v = (abs(SunDir.x) > abs(SunDir.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
@ -218,5 +226,5 @@ float traceSun(vec3 SunDir)
}
return (sum / step_count);
}
#uendif
}
#endif
}

View file

@ -23,15 +23,14 @@
vec4 getLightColor(Material material)
{
vec4 color;
#uifdef(LIGHTMODE_DEFAULT)
if (LIGHTMODE_DEFAULT)
color = Lightmode_Default();
#uelifdef(LIGHTMODE_SOFTWARE)
else if (LIGHTMODE_SOFTWARE)
color = Lightmode_Software();
#uelifdef(LIGHTMODE_VANILLA)
else if (LIGHTMODE_VANILLA)
color = Lightmode_Vanilla();
#uelifdef(LIGHTMODE_BUILD)
else if (LIGHTMODE_BUILD)
color = Lightmode_Build();
#uendif
//
// handle glowing walls
@ -75,24 +74,21 @@ vec4 getLightColor(Material material)
//
// colored fog
//
#uifdef(FOG_AFTER_LIGHTS)
{
// calculate fog factor
float fogdist;
#uifdef(FOG_RADIAL)
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#uelse
fogdist = max(16.0, pixelpos.w);
#uendif
float fogfactor = exp2 (uFogDensity * fogdist);
if (FOG_AFTER_LIGHTS)
{
// calculate fog factor
float fogdist;
if (FOG_RADIAL)
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
else
fogdist = max(16.0, pixelpos.w);
float fogfactor = exp2 (uFogDensity * fogdist);
frag = vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
}
#uendif
frag = vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
}
#uifdef(FOGBALLS)
if (FOGBALLS)
frag = ProcessFogBalls(frag);
#uendif
return frag;
}
@ -103,27 +99,25 @@ vec3 AmbientOcclusionColor()
{
// calculate fog factor
float fogdist;
#uifdef(FOG_RADIAL)
if (FOG_RADIAL)
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#uelse
else
fogdist = max(16.0, pixelpos.w);
#uendif
float fogfactor = exp2 (uFogDensity * fogdist);
vec4 color = vec4(mix(uFogColor.rgb, vec3(0.0), fogfactor), 0.0);
#uifdef(FOGBALLS)
if (FOGBALLS)
color = ProcessFogBalls(color);
#uendif
return color.rgb;
}
vec4 ProcessLightMode(Material material)
{
#uifdef(SIMPLE2D) // uses the fog color to add a color overlay
if (SIMPLE2D) // uses the fog color to add a color overlay
{
#uifdef(TM_FOGLAYER)
if (TM_FOGLAYER)
{
vec4 frag = material.Base;
float gray = grayscale(frag);
@ -133,49 +127,34 @@ vec4 ProcessLightMode(Material material)
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
}
#uelse
else
{
vec4 frag = material.Base * vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
}
#uendif
}
#uelse
else
{
#uifdef(TM_FOGLAYER)
if (TM_FOGLAYER)
{
#uifdef(FOG_BEFORE_LIGHTS)
if (FOG_BEFORE_LIGHTS || FOG_AFTER_LIGHTS)
{
float fogdist;
#uifdef(FOG_RADIAL)
if (FOG_RADIAL)
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#uelse
else
fogdist = max(16.0, pixelpos.w);
#uendif
float fogfactor = exp2 (uFogDensity * fogdist);
return vec4(uFogColor.rgb, (1.0 - fogfactor) * material.Base.a * 0.75 * vColor.a);
}
#uelifdef(FOG_AFTER_LIGHTS)
{ // duplicated, TODO figure out how to handle || in uifdef
float fogdist;
#uifdef(FOG_RADIAL)
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#uelse
fogdist = max(16.0, pixelpos.w);
#uendif
float fogfactor = exp2 (uFogDensity * fogdist);
return vec4(uFogColor.rgb, (1.0 - fogfactor) * material.Base.a * 0.75 * vColor.a);
}
#uelse
else
{
return vec4(uFogColor.rgb, material.Base.a * 0.75 * vColor.a);
#uendif
}
}
#uelse
else
return getLightColor(material);
#uendif
}
#uendif
}

View file

@ -3,11 +3,10 @@ vec4 Lightmode_Build()
{
// z is the depth in view space, positive going into the screen
float z;
#uifdef(SWLIGHT_RADIAL)
if (SWLIGHT_RADIAL)
z = distance(pixelpos.xyz, uCameraPos.xyz);
#uelse
else
z = pixelpos.w;
#uendif
// This is a lot more primitive than Doom's lighting...
float numShades = float(uPalLightLevels & 255);

View file

@ -3,15 +3,14 @@ vec4 Lightmode_Default()
{
vec4 color = vColor;
#uifdef(FOG_BEFORE_LIGHTS)
if (FOG_BEFORE_LIGHTS)
{
// calculate fog factor
float fogdist;
#uifdef(FOG_RADIAL)
if (FOG_RADIAL)
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#uelse
else
fogdist = max(16.0, pixelpos.w);
#uendif
float fogfactor = exp2 (uFogDensity * fogdist);
// brightening around the player for light mode 2
@ -23,7 +22,6 @@ vec4 Lightmode_Default()
// apply light diminishing through fog equation
color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor);
}
#uendif
return color;
}

View file

@ -12,17 +12,15 @@ vec4 Lightmode_Software()
{
// z is the depth in view space, positive going into the screen
float z;
#uifdef(SWLIGHT_RADIAL)
if (SWLIGHT_RADIAL)
z = distance(pixelpos.xyz, uCameraPos.xyz);
#uelse
else
z = pixelpos.w;
#uendif
float colormap = SoftwareColormap(uLightLevel, z);
#uifdef(SWLIGHT_BANDED)
if (SWLIGHT_BANDED)
colormap = floor(colormap) + 0.5;
#uendif
// Result is the normalized colormap index (0 bright .. 1 dark)
float newlightlevel = 1.0 - clamp(colormap, 0.0, 31.0) / 32.0;

View file

@ -43,17 +43,15 @@ vec4 Lightmode_Vanilla()
{
// z is the depth in view space, positive going into the screen
float z;
#uifdef(SWLIGHT_RADIAL)
if (SWLIGHT_RADIAL)
z = distance(pixelpos.xyz, uCameraPos.xyz);
#uelse
else
z = pixelpos.w;
#uendif
float colormap = VanillaColormap(uLightLevel, z);
#uifdef(SWLIGHT_BANDED)
if (SWLIGHT_BANDED)
colormap = floor(colormap) + 0.5;
#uendif
// Result is the normalized colormap index (0 bright .. 1 dark)
float newlightlevel = 1.0 - clamp(colormap, 0.0, 31.0) / 32.0;

View file

@ -1,3 +1,4 @@
#ifndef SIMPLE3D
vec3 lightContribution(DynLightInfo light, vec3 normal)
{
@ -10,13 +11,11 @@
float dotprod;
#uifdef(LIGHT_NONORMALS)
#uelse
if (!LIGHT_NONORMALS)
{
dotprod = dot(normal, lightdir);
if (dotprod < -0.0001) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases. Note that this can cause precision issues.
}
#uendif
float attenuation = distanceAttenuation(lightdistance, light.radius, light.strength, light.linearity);
@ -25,14 +24,13 @@
attenuation *= spotLightAttenuation(light.pos.xyz, light.spotDir.xyz, light.spotInnerAngle, light.spotOuterAngle);
}
#uifdef(LIGHT_NONORMALS)
#uelse
if (!LIGHT_NONORMALS)
{
if ((light.flags & LIGHTINFO_ATTENUATED) != 0)
{
attenuation *= clamp(dotprod, 0.0, 1.0);
}
#uendif
}
if (attenuation > 0.0) // Skip shadow map test if possible
{
@ -84,17 +82,19 @@
vec3 frag;
#uifdef(LIGHT_BLEND_CLAMPED)
if (LIGHT_BLEND_CLAMPED)
{
frag = material.Base.rgb * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
#uelifdef(LIGHT_BLEND_COLORED_CLAMP)
{
frag = color + desaturate(dynlight).rgb;
frag = material.Base.rgb * ((frag / max(max(max(frag.r, frag.g), frag.b), 1.4) * 1.4));
}
#uelse
}
else if (LIGHT_BLEND_COLORED_CLAMP)
{
frag = color + desaturate(dynlight).rgb;
frag = material.Base.rgb * ((frag / max(max(max(frag.r, frag.g), frag.b), 1.4) * 1.4));
}
else
{
frag = material.Base.rgb * (color + desaturate(dynlight).rgb);
#uendif
}
#ifndef SHADE_VERTEX
if (uLightIndex >= 0)
@ -122,4 +122,4 @@
{
return material.Base.rgb;
}
#endif
#endif

View file

@ -1,14 +1,17 @@
float distanceAttenuation(float dist, float radius, float strength, float linearity)
{
#uifdef(LIGHT_ATTENUATION_INVERSE_SQUARE)
// light.radius >= 1000000.0 is sunlight, skip attenuation
if(light.radius >= 1000000.0) return 1.0;
if (LIGHT_ATTENUATION_INVERSE_SQUARE)
{
// radius >= 1000000.0 is sunlight, skip attenuation
if (radius >= 1000000.0) return 1.0;
float a = dist / radius;
float b = clamp(1.0 - a * a * a * a, 0.0, 1.0);
return mix((b * b) / (dist * dist + 1.0) * strength, clamp((radius - dist) / radius, 0.0, 1.0), linearity);
#uelse
}
else
{
return clamp((radius - dist) / radius, 0.0, 1.0);
#uendif
}
}

View file

@ -69,12 +69,12 @@ vec3 ProcessMaterialLight(Material material, vec3 color)
}
}
#uifdef(LIGHT_BLEND_CLAMPED)
if (LIGHT_BLEND_CLAMPED)
{
dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4);
}
#uelifdef(LIGHT_BLEND_COLORED_CLAMP)
else if (LIGHT_BLEND_COLORED_CLAMP)
{
dynlight.rgb = color + desaturate(dynlight).rgb;
specular.rgb = desaturate(specular).rgb;
@ -82,12 +82,11 @@ vec3 ProcessMaterialLight(Material material, vec3 color)
dynlight.rgb = ((dynlight.rgb / max(max(max(dynlight.r, dynlight.g), dynlight.b), 1.4) * 1.4));
specular.rgb = ((specular.rgb / max(max(max(specular.r, specular.g), specular.b), 1.4) * 1.4));
}
#uelse
else
{
dynlight.rgb = color + desaturate(dynlight).rgb;
specular.rgb = desaturate(specular).rgb;
}
#uendif
vec3 frag = material.Base.rgb * dynlight.rgb + material.Specular * specular.rgb;

View file

@ -1,6 +1,6 @@
#ifndef SIMPLE3D
#include "shaders/scene/material_getTexel.glsl"
#include "shaders/scene/material_gettexel.glsl"
#include "shaders/scene/material_normalmap.glsl"
#endif
@ -56,22 +56,21 @@ Material CreateMaterial()
// OpenGL doesn't care, but Vulkan pukes all over the place if these texture samplings are included in no-texture shaders, even though never called.
#ifndef NO_LAYERS
#uifdef(TEXF_Brightmap)
if (TEXF_Brightmap)
{
material.Bright = desaturate(texture(brighttexture, texCoord.st));
#uendif
}
#uifdef(TEXF_Detailmap)
if (TEXF_Detailmap)
{
vec4 Detail = texture(detailtexture, texCoord.st * uDetailParms.xy) * uDetailParms.z;
material.Base.rgb *= Detail.rgb;
}
#uendif
#uifdef(TEXF_Glowmap)
if (TEXF_Glowmap)
{
material.Glow = desaturate(texture(glowtexture, texCoord.st));
}
#uendif
#ifdef PBR
material.Metallic = texture(metallictexture, texCoord.st).r;

View file

@ -10,34 +10,46 @@ vec4 getTexel(vec2 st)
vec4 texel = texture(tex, st);
// Apply texture modes
#uifdef(TM_STENCIL)
if (TM_STENCIL)
{
texel.rgb = vec3(1.0,1.0,1.0);
#uelifdef(TM_OPAQUE)
}
else if (TM_OPAQUE)
{
texel.a = 1.0;
#uelifdef(TM_INVERSE)
}
else if (TM_INVERSE)
{
texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, texel.a);
#uelifdef(TM_ALPHATEXTURE)
}
else if (TM_ALPHATEXTURE)
{
float gray = grayscale(texel);
texel = vec4(1.0, 1.0, 1.0, gray*texel.a);
}
#uelifdef(TM_CLAMPY)
else if (TM_CLAMPY)
{
if (st.t < 0.0 || st.t > 1.0)
{
texel.a = 0.0;
}
#uelifdef(TM_INVERTOPAQUE)
}
else if (TM_INVERTOPAQUE)
{
texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, 1.0);
#uelifdef(TM_FOGLAYER)
}
else if (TM_FOGLAYER)
{
return texel;
#uendif
}
#uifdef(TEXF_ClampY)
if (TEXF_ClampY)
{
if (st.t < 0.0 || st.t > 1.0)
{
texel.a = 0.0;
}
#uendif
}
// Apply the texture modification colors.
int blendflags = int(uTextureAddColor.a); // this alpha is unused otherwise

View file

@ -34,14 +34,14 @@
attenuation *= spotLightAttenuation(light.pos.xyz, light.spotDir.xyz, light.spotInnerAngle, light.spotOuterAngle);
}
#uifdef(LIGHT_NONORMALS)
#uelse
if (!LIGHT_NONORMALS)
{
if ((light.flags & LIGHTINFO_ATTENUATED) != 0)
{
float dotprod = dot(vWorldNormal.xyz, lightdir);
attenuation *= clamp(dotprod, 0.0, 1.0);
}
#uendif
}
if (attenuation > 0.0) // Skip shadow map test if possible
{