initial work for ubershaders

This commit is contained in:
Ricardo Luís Vaz Silva 2025-02-17 23:51:51 -03:00 committed by Magnus Norddahl
commit 77f19ba6f5
22 changed files with 678 additions and 385 deletions

View file

@ -112,6 +112,9 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key)
{ "dithertrans", "shaders/scene/frag_main.glsl", "shaders/scene/material_default.glsl", "shaders/scene/mateffect_default.glsl", "shaders/scene/lightmodel_shared.glsl", "shaders/scene/lightmodel_normal.glsl", "#define NO_ALPHATEST\n#define DITHERTRANS\n" },
};
VkShaderKey customKey = key;
customKey.AlphaTest = false;
const auto& desc = effectshaders[key.SpecialEffect];
program.vert = LoadVertShader(desc.ShaderName, mainvp, nullptr, desc.defines, key, nullptr);
if (!key.NoFragmentShader)
@ -274,7 +277,7 @@ static void AddBuiltinFields(FString &layoutBlock, int &index, bool is_in, const
}
}
void VkShaderManager::BuildLayoutBlock(FString &layoutBlock, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader)
void VkShaderManager::BuildLayoutBlock(FString &layoutBlock, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader, bool isUberShader)
{
bool hasClipDistance = fb->GetDevice()->EnabledFeatures.Features.shaderClipDistance;
@ -293,6 +296,17 @@ void VkShaderManager::BuildLayoutBlock(FString &layoutBlock, bool isFrag, const
}
layoutBlock << " int uBoneIndexBase; // bone animation\n";
layoutBlock << " int uFogballIndex; // fog balls\n";
if(isUberShader)
{
layoutBlock << " int uShaderKey1;\n";
layoutBlock << " int uShaderKey2;\n";
}
else
{
layoutBlock << " int unused2;\n";
layoutBlock << " int unused3;\n";
}
if(shader && shader->Uniforms.UniformStructSize)
{
@ -326,7 +340,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)
void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defines, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader, bool isUberShader)
{
if (fb->IsRayQueryEnabled())
{
@ -352,87 +366,174 @@ void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defin
definesBlock << "#define NO_CLIPDISTANCE_SUPPORT\n";
}
if (!key.AlphaTest) definesBlock << "#define NO_ALPHATEST\n";
if (key.GBufferPass) definesBlock << "#define GBUFFER_PASS\n";
if (key.AlphaTestOnly) definesBlock << "#define ALPHATEST_ONLY\n";
if (key.Simple) definesBlock << "#define SIMPLE\n";
if (key.Simple3D) definesBlock << "#define SIMPLE3D\n";
switch(key.LightBlendMode)
if(isUberShader)
{
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;
}
//ugh EffectState also controls layout, because specular/pbr/etc defines switch texture indices around for normal/specular/etc
switch(key.LightAttenuationMode)
definesBlock << LoadPrivateShaderLump("shaders/shaderkey.glsl").GetChars() << "\n";
definesBlock << "#define UBERSHADERS\n";
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";
definesBlock << "#define SIMPLE2D ((uShaderKey1 & SK1_SIMPLE2D) != 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 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 GBUFFER_PASS ((uShaderKey1 & SK1_GBUFFER_PASS) != 0)\n";
definesBlock << "#define USE_SHADOWMAP ((uShaderKey1 & SK1_USE_SHADOWMAP) != 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 SHADOWMAP_FILTER (SK_GET_SHADOWMAP_FILTER())\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 SWLIGHT_RADIAL ((uShaderKey1 & SK1_SWLIGHT_RADIAL) != 0)\n";
definesBlock << "#define SWLIGHT_BANDED ((uShaderKey1 & SK1_SWLIGHT_BANDED) != 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 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 LIGHT_ATTENUATION_LINEAR ((uShaderKey1 & SK1_TEXTUREMODE) == 0)\n";
definesBlock << "#define LIGHT_ATTENUATION_INVERSE_SQUARE ((uShaderKey1 & SK1_TEXTUREMODE) != 0)\n";
//definesBlock << "#define USE_LEVELMESH (!!(uShaderKey1 & SK1_USE_LEVELMESH))\n";
// controls layout
if (key.UseLevelMesh) definesBlock << "#define USE_LEVELMESH\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 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
{
case 0:
definesBlock << "#define LIGHT_ATTENUATION_LINEAR\n";
break;
case 1:
definesBlock << "#define LIGHT_ATTENUATION_INVERSE_SQUARE\n";
break;
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");
}
if (key.DepthFadeThreshold) definesBlock << "#define USE_DEPTHFADETHRESHOLD\n";
if (key.Simple2D) definesBlock << "#define SIMPLE2D\n";
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.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 ";
definesBlock << std::to_string(key.ShadowmapFilter).c_str();
definesBlock << "\n";
if (key.UseShadowmap) definesBlock << "#define USE_SHADOWMAP\n";
if (key.UseLevelMesh) definesBlock << "#define USE_LEVELMESH\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;
}
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;
}
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";
if (key.FogBalls) definesBlock << "#define FOGBALLS\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");
// 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... :(
std::vector<bool> definedFields(vertexShaderInputs.size());
@ -631,19 +732,47 @@ ShaderIncludeResult VkShaderManager::OnInclude(FString headerName, FString inclu
return ShaderIncludeResult(headerName.GetChars(), code.GetChars());
}
FString VkShaderManager::LoadPublicShaderLump(const char *lumpname)
FString VkShaderManager::LoadPublicShaderLump(const char *lumpname, bool isUberShader)
{
int lump = fileSystem.CheckNumForFullName(lumpname, 0);
if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname);
if (lump == -1) I_Error("Unable to load '%s'", lumpname);
return GetStringFromLump(lump);
return LoadShaderLump(lump, isUberShader);
}
FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname)
FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname, bool isUberShader)
{
int lump = fileSystem.CheckNumForFullName(lumpname, 0);
if (lump == -1) I_Error("Unable to load '%s'", lumpname);
return GetStringFromLump(lump);
return LoadShaderLump(lump, isUberShader);
}
FString VkShaderManager::LoadShaderLump(int lumpnum, bool isUberShader)
{
FString str = GetStringFromLump(lumpnum);
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)

View file

@ -55,6 +55,7 @@ struct PushConstants
int uLightIndex; // dynamic lights
int uBoneIndexBase; // bone animation
int uFogballIndex; // fog balls
uint64_t shaderKey;
};
struct ZMinMaxPushConstants
@ -93,25 +94,25 @@ public:
uint64_t GBufferPass : 1; // GBUFFER_PASS
uint64_t UseShadowmap : 1; // USE_SHADOWMAP
uint64_t UseRaytrace : 1; // USE_RAYTRACE
uint64_t UseRaytracePrecise : 1; // USE_RAYTRACE_PRECISE
uint64_t PreciseMidtextureTrace : 1; // PRECISE_MIDTEXTURES
uint64_t ShadowmapFilter : 4; // SHADOWMAP_FILTER
uint64_t FogBeforeLights : 1; // FOG_BEFORE_LIGHTS
uint64_t FogAfterLights : 1; // FOG_AFTER_LIGHTS
uint64_t FogRadial : 1; // FOG_RADIAL
uint64_t SWLightRadial : 1; // SWLIGHT_RADIAL
uint64_t SWLightBanded : 1; // SWLIGHT_BANDED
uint64_t LightMode : 2; // LIGHTMODE_DEFAULT, LIGHTMODE_SOFTWARE, LIGHTMODE_VANILLA, LIGHTMODE_BUILD
uint64_t LightBlendMode : 2; // LIGHT_BLEND_CLAMPED , LIGHT_BLEND_COLORED_CLAMP , LIGHT_BLEND_UNCLAMPED
uint64_t LightAttenuationMode : 1; // LIGHT_ATTENUATION_LINEAR , LIGHT_ATTENUATION_INVERSE_SQUARE
uint64_t UseLevelMesh : 1; // USE_LEVELMESH
uint64_t FogBalls : 1; // FOGBALLS
uint64_t NoFragmentShader : 1;
uint64_t DepthFadeThreshold : 1;
uint64_t AlphaTestOnly : 1; // ALPHATEST_ONLY
uint64_t LightBlendMode : 2; // LIGHT_BLEND_CLAMPED , LIGHT_BLEND_COLORED_CLAMP , LIGHT_BLEND_UNCLAMPED
uint64_t LightAttenuationMode : 1; // LIGHT_ATTENUATION_LINEAR , LIGHT_ATTENUATION_INVERSE_SQUARE
uint64_t UseRaytracePrecise : 1; // USE_RAYTRACE_PRECISE
uint64_t ShadowmapFilter : 4; // SHADOWMAP_FILTER
uint64_t ShadeVertex : 1; // SHADE_VERTEX
uint64_t LightNoNormals : 1; // LIGHT_NONORMALS
uint64_t UseSpriteCenter : 1; // USE_SPRITE_CENTER
uint64_t PreciseMidtextureTrace : 1; // PRECISE_MIDTEXTURES
uint64_t Unused : 26;
};
uint64_t AsQWORD = 0;
@ -166,11 +167,13 @@ private:
ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system);
FString GetVersionBlock();
FString LoadPublicShaderLump(const char *lumpname);
FString LoadPrivateShaderLump(const char *lumpname);
FString LoadPublicShaderLump(const char *lumpname, bool isUberShader = false);
FString LoadPrivateShaderLump(const char *lumpname, bool isUberShader = false);
FString LoadShaderLump(int lumpnum, bool isUberShader);
void BuildLayoutBlock(FString &definesBlock, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader);
void BuildDefinesBlock(FString &definesBlock, const char *defines, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader);
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);
VulkanRenderDevice* fb = nullptr;

View file

@ -149,7 +149,7 @@ struct DynLightInfo
vec3 color; float padding1;
vec3 spotDir; float padding2;
float radius;
float linarity;
float linearity;
float softShadowRadius;
float strength;
float spotInnerAngle;

View file

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

View file

@ -17,10 +17,13 @@ vec3 rgb2hsv(vec3 c)
void main()
{
#ifdef SIMPLE3D
#uifdef(SIMPLE3D)
{
Material material = CreateMaterial();
FragColor = vec4(material.Base.rgb, 1.0);
#else
}
#uelse
{
#ifdef NO_CLIPDISTANCE_SUPPORT
if (ClipDistanceA.x < 0 || ClipDistanceA.y < 0 || ClipDistanceA.z < 0 || ClipDistanceA.w < 0 || ClipDistanceB.x < 0) discard;
#endif
@ -32,16 +35,18 @@ void main()
Material material = CreateMaterial();
#ifndef NO_ALPHATEST
#uifdef(DO_ALPHATEST)
if (material.Base.a <= uAlphaThreshold) discard;
#endif
#uendif
#ifndef ALPHATEST_ONLY
#ifdef USE_DEPTHFADETHRESHOLD
#uifdef(NOT_ALPHATEST_ONLY)
{
#uifdef(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);
#endif
}
#uendif
FragColor = ProcessLightMode(material);
@ -65,10 +70,14 @@ void main()
else FragColor *= 0.5;
#endif
#ifdef GBUFFER_PASS
#uifdef(GBUFFER_PASS)
{
FragFog = vec4(AmbientOcclusionColor(), 1.0);
FragNormal = vec4(vEyeNormal.xyz * 0.5 + 0.5, 1.0);
#endif
#endif
#endif
}
#uendif
}
#uendif
}
#uendif
}

View file

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

View file

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

View file

@ -5,23 +5,23 @@
// material types
#if defined(SPECULAR)
#define normaltexture texture2
#define speculartexture texture3
#define brighttexture texture4
#define detailtexture texture5
#define glowtexture texture6
#define normaltexture texture2
#define speculartexture texture3
#define brighttexture texture4
#define detailtexture texture5
#define glowtexture texture6
#elif defined(PBR)
#define normaltexture texture2
#define metallictexture texture3
#define roughnesstexture texture4
#define aotexture texture5
#define brighttexture texture6
#define detailtexture texture7
#define glowtexture texture8
#define normaltexture texture2
#define metallictexture texture3
#define roughnesstexture texture4
#define aotexture texture5
#define brighttexture texture6
#define detailtexture texture7
#define glowtexture texture8
#else
#define brighttexture texture2
#define detailtexture texture3
#define glowtexture texture4
#define brighttexture texture2
#define detailtexture texture3
#define glowtexture texture4
#endif
#define BrdfLUT 1 // the BRDF convoluted texture is always in this texture slot
@ -59,14 +59,14 @@
#define uActorCenter data[uDataIndex].uActorCenter
#if defined(USE_LEVELMESH)
#define uVertexColor lightdata[uDataIndex].uVertexColor
#define uDesaturationFactor lightdata[uDataIndex].uDesaturationFactor
#define uLightLevel lightdata[uDataIndex].uLightLevel
int uLightIndex;
#define uVertexColor lightdata[uDataIndex].uVertexColor
#define uDesaturationFactor lightdata[uDataIndex].uDesaturationFactor
#define uLightLevel lightdata[uDataIndex].uLightLevel
int uLightIndex;
#else
#define uVertexColor data[uDataIndex].uVertexColor
#define uDesaturationFactor data[uDataIndex].uDesaturationFactor
#define uLightLevel data[uDataIndex].uLightLevel
#define uVertexColor data[uDataIndex].uVertexColor
#define uDesaturationFactor data[uDataIndex].uDesaturationFactor
#define uLightLevel data[uDataIndex].uLightLevel
#endif
#define VULKAN_COORDINATE_SYSTEM

View file

@ -5,10 +5,11 @@
#if defined(USE_RAYTRACE)
#define shadowAttenuation(lightpos, shadowIndex, softShadowRadius, flags) traceShadow(lightpos, softShadowRadius)
#define shadowAttenuationRaytrace(lightpos, shadowIndex, softShadowRadius, flags) traceShadow(lightpos, softShadowRadius)
#elif defined(USE_SHADOWMAP)
#endif
#if defined(USE_SHADOWMAP)
float shadowDirToU(vec2 dir)
{
if (abs(dir.y) > abs(dir.x))
@ -124,14 +125,14 @@ float shadowmapAttenuation(vec3 lightpos, float shadowIndex)
float v = (shadowIndex + 0.5) / 1024.0;
#if SHADOWMAP_FILTER == 0
#uif(SHADOWMAP_FILTER == 0)
return sampleShadowmap(planePoint, v);
#else
#uelse
return sampleShadowmapPCF(planePoint, v);
#endif
#uendif
}
float shadowAttenuation(vec3 lightpos, int shadowIndex, float softShadowRadius, int flags)
float shadowAttenuationShadowMap(vec3 lightpos, int shadowIndex, float softShadowRadius, int flags)
{
if((flags & LIGHTINFO_TRACE) > 0)
{
@ -144,9 +145,10 @@ float shadowAttenuation(vec3 lightpos, int shadowIndex, float softShadowRadius,
return shadowmapAttenuation(lightpos, float(shadowIndex));
}
}
#else
#endif
float shadowAttenuation(vec3 lightpos, int shadowIndex, float softShadowRadius, int flags)
#if !defined(USE_RAYTRACE) && !defined(USE_SHADOWMAP) || defined(UBERSHADERS)
float shadowAttenuationNoShadow(vec3 lightpos, int shadowIndex, float softShadowRadius, int flags)
{
if((flags & LIGHTINFO_TRACE) > 0)
{
@ -157,5 +159,33 @@ float shadowAttenuation(vec3 lightpos, int shadowIndex, float softShadowRadius,
return 1.0;
}
}
#endif
#ifdef UBERSHADERS
float shadowAttenuation(vec3 lightpos, int shadowIndex, float softShadowRadius, int flags)
{
if(USE_RAYTRACE)
{
return shadowAttenuationRaytrace(lightpos, shadowIndex, softShadowRadius, flags);
}
else if(USE_SHADOWMAP)
{
return shadowAttenuationShadowMap(lightpos, shadowIndex, softShadowRadius, flags);
}
else
{
return shadowAttenuationNoShadow(lightpos, shadowIndex, softShadowRadius, flags);
}
}
#else
#if defined(USE_RAYTRACE)
#define shadowAttenuation(lightpos, shadowIndex, softShadowRadius, flags) shadowAttenuationRaytrace(lightpos, shadowIndex, softShadowRadius, flags)
#elif defined(USE_SHADOWMAP)
#define shadowAttenuation shadowAttenuationShadowMap
#else
#define shadowAttenuation shadowAttenuationNoShadow
#endif
#endif

View file

@ -15,9 +15,10 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
for (int i = 0; i < 3; i++)
{
#ifdef PRECISE_MIDTEXTURES
TraceResult result;
SurfaceInfo surface;
TraceResult result;
SurfaceInfo surface;
#uifdef(PRECISE_MIDTEXTURES)
{
bool skip = true;
{
@ -87,14 +88,16 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
if (alpha <= 0.0)
return 0.0;
}
#else
TraceResult result = TraceFirstHit(origin, tmin, direction, dist);
}
#uelse
{
result = TraceFirstHit(origin, tmin, direction, dist);
// Stop if we hit nothing - the point light is visible.
if (result.primitiveIndex == -1)
return alpha;
SurfaceInfo surface = GetSurface(result.primitiveIndex);
surface = GetSurface(result.primitiveIndex);
// Pass through surface texture
alpha = PassRayThroughSurfaceDynLight(surface, GetSurfaceUV(result.primitiveIndex, result.primitiveWeights), alpha);
@ -102,7 +105,8 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
// Stop if there is no light left
if (alpha <= 0.0)
return 0.0;
#endif
}
#uendif
// Move to surface hit point
origin += direction * result.t;
@ -117,85 +121,102 @@ float TraceDynLightRay(vec3 origin, float tmin, vec3 direction, float dist)
float traceHit(vec3 origin, vec3 direction, float dist)
{
#if defined(USE_RAYTRACE_PRECISE)
#uifdef(USE_RAYTRACE_PRECISE)
return TraceDynLightRay(origin, 0.01f, direction, dist);
#else
#uelse
return TraceAnyHit(origin, 0.01f, direction, dist) ? 0.0 : 1.0;
#endif
#uendif
}
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
#ifdef USE_SPRITE_CENTER
vec3 origin = uActorCenter.xyz;
vec3 direction = normalize(target - origin);
#elif defined(LIGHT_NONORMALS)
vec3 origin = pixelpos.xyz;
vec3 direction = normalize(target - origin);
origin -= direction;
#else
vec3 origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
vec3 direction = normalize(target - origin);
#endif
vec3 origin;
vec3 direction;
#uifdef(USE_SPRITE_CENTER)
{
origin = uActorCenter.xyz;
direction = normalize(target - origin);
}
#uelifdef(LIGHT_NONORMALS)
{
origin = pixelpos.xyz;
direction = normalize(target - origin);
origin -= direction;
}
#uelse
{
origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
direction = normalize(target - origin);
}
#uendif
float dist = distance(origin, target);
#if SHADOWMAP_FILTER == 0
return traceHit(origin, direction, dist);
#else
if (softShadowRadius == 0)
{
#uif(SHADOWMAP_FILTER == 0)
return traceHit(origin, direction, dist);
}
else
#uelse
if (softShadowRadius == 0)
{
return traceHit(origin, direction, dist);
}
else
{
vec3 v = (abs(direction.x) > abs(direction.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 xdir = normalize(cross(direction, v));
vec3 ydir = cross(direction, xdir);
float sum = 0.0;
const int step_count = SHADOWMAP_FILTER * 4;
for (int i = 0; i < step_count; i++)
{
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * softShadowRadius;
vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y;
sum += traceHit(origin, normalize(pos - origin), dist);
}
return (sum / step_count);
}
#uendif
}
float traceSun(vec3 SunDir)
{
vec3 origin;
#uifdef(USE_SPRITE_CENTER)
{
vec3 v = (abs(direction.x) > abs(direction.y)) ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 xdir = normalize(cross(direction, v));
vec3 ydir = cross(direction, xdir);
origin = uActorCenter.xyz;
}
#uelifdef(LIGHT_NONORMALS)
{
origin = pixelpos.xyz;
origin -= SunDir;
}
#uelse
{
origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
}
#uendif
float dist = 65536.0;
#uif(SHADOWMAP_FILTER == 0)
return TraceDynLightRay(origin, 0.01f, SunDir, dist);
#uelse
{
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);
vec3 xdir = normalize(cross(SunDir, v));
vec3 ydir = cross(SunDir, xdir);
float sum = 0.0;
const int step_count = SHADOWMAP_FILTER * 4;
for (int i = 0; i < step_count; i++)
{
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * softShadowRadius;
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * 100.0;
vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y;
sum += traceHit(origin, normalize(pos - origin), dist);
sum += TraceDynLightRay(origin, 0.01f, normalize(pos - origin), dist);
}
return (sum / step_count);
}
#endif
}
float traceSun(vec3 SunDir)
{
#ifdef USE_SPRITE_CENTER
vec3 origin = uActorCenter.xyz;
#elif defined(LIGHT_NONORMALS)
vec3 origin = pixelpos.xyz;
origin -= SunDir;
#else
vec3 origin = pixelpos.xyz + (vWorldNormal.xyz * 0.1);
#endif
float dist = 65536.0;
#if SHADOWMAP_FILTER == 0
return TraceDynLightRay(origin, 0.01f, SunDir, dist);
#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);
vec3 xdir = normalize(cross(SunDir, v));
vec3 ydir = cross(SunDir, xdir);
float sum = 0.0;
const int step_count = SHADOWMAP_FILTER * 4;
for (int i = 0; i < step_count; i++)
{
vec2 gridoffset = getVogelDiskSample(i, step_count, gl_FragCoord.x + gl_FragCoord.y * 13.37) * 100.0;
vec3 pos = target + xdir * gridoffset.x + ydir * gridoffset.y;
sum += TraceDynLightRay(origin, 0.01f, normalize(pos - origin), dist);
}
return (sum / step_count);
#endif
#uendif
}

View file

@ -22,15 +22,16 @@
vec4 getLightColor(Material material)
{
#if defined(LIGHTMODE_DEFAULT)
vec4 color = Lightmode_Default();
#elif defined(LIGHTMODE_SOFTWARE)
vec4 color = Lightmode_Software();
#elif defined(LIGHTMODE_VANILLA)
vec4 color = Lightmode_Vanilla();
#elif defined(LIGHTMODE_BUILD)
vec4 color = Lightmode_Build();
#endif
vec4 color;
#uifdef(LIGHTMODE_DEFAULT)
color = Lightmode_Default();
#uelifdef(LIGHTMODE_SOFTWARE)
color = Lightmode_Software();
#uelifdef(LIGHTMODE_VANILLA)
color = Lightmode_Vanilla();
#uelifdef(LIGHTMODE_BUILD)
color = Lightmode_Build();
#uendif
//
// handle glowing walls
@ -74,23 +75,24 @@ vec4 getLightColor(Material material)
//
// colored fog
//
#if defined(FOG_AFTER_LIGHTS)
#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);
// calculate fog factor
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
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);
#endif
#if defined(FOGBALLS)
frag = ProcessFogBalls(frag);
#endif
#uifdef(FOGBALLS)
frag = ProcessFogBalls(frag);
#uendif
return frag;
}
@ -100,54 +102,80 @@ vec4 getLightColor(Material material)
vec3 AmbientOcclusionColor()
{
// calculate fog factor
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
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);
vec4 color = vec4(mix(uFogColor.rgb, vec3(0.0), fogfactor), 0.0);
#if defined(FOGBALLS)
color = ProcessFogBalls(color);
#endif
#uifdef(FOGBALLS)
color = ProcessFogBalls(color);
#uendif
return color.rgb;
}
vec4 ProcessLightMode(Material material)
{
#ifdef SIMPLE2D // uses the fog color to add a color overlay
#ifdef TM_FOGLAYER
vec4 frag = material.Base;
float gray = grayscale(frag);
vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2;
frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a);
frag *= vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
#else
vec4 frag = material.Base * vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
#endif
#else
#ifdef TM_FOGLAYER
#if defined(FOG_BEFORE_LIGHTS) || defined(FOG_AFTER_LIGHTS)
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
float fogfactor = exp2 (uFogDensity * fogdist);
#uifdef(SIMPLE2D) // uses the fog color to add a color overlay
{
#uifdef(TM_FOGLAYER)
{
vec4 frag = material.Base;
float gray = grayscale(frag);
vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2;
frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a);
frag *= vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
}
#uelse
{
vec4 frag = material.Base * vColor;
frag.rgb = frag.rgb + uFogColor.rgb;
return frag;
}
#uendif
}
#uelse
{
#uifdef(TM_FOGLAYER)
{
#uifdef(FOG_BEFORE_LIGHTS)
{
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);
#else
return vec4(uFogColor.rgb, material.Base.a * 0.75 * vColor.a);
#endif
#else
return getLightColor(material);
#endif
#endif
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
return vec4(uFogColor.rgb, material.Base.a * 0.75 * vColor.a);
#uendif
}
#uelse
return getLightColor(material);
#uendif
}
#uendif
}

View file

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

View file

@ -3,14 +3,15 @@ vec4 Lightmode_Default()
{
vec4 color = vColor;
#if defined(FOG_BEFORE_LIGHTS)
#uifdef(FOG_BEFORE_LIGHTS)
{
// calculate fog factor
#if defined(FOG_RADIAL)
float fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#else
float fogdist = max(16.0, pixelpos.w);
#endif
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);
// brightening around the player for light mode 2
@ -21,8 +22,8 @@ vec4 Lightmode_Default()
// apply light diminishing through fog equation
color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor);
#endif
}
#uendif
return color;
}

View file

@ -11,17 +11,18 @@ float SoftwareColormap(float light, float z)
vec4 Lightmode_Software()
{
// z is the depth in view space, positive going into the screen
#if defined(SWLIGHT_RADIAL)
float z = distance(pixelpos.xyz, uCameraPos.xyz);
#else
float z = pixelpos.w;
#endif
float z;
#uifdef(SWLIGHT_RADIAL)
z = distance(pixelpos.xyz, uCameraPos.xyz);
#uelse
z = pixelpos.w;
#uendif
float colormap = SoftwareColormap(uLightLevel, z);
#if defined(SWLIGHT_BANDED)
#uifdef(SWLIGHT_BANDED)
colormap = floor(colormap) + 0.5;
#endif
#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

@ -42,17 +42,18 @@ float VanillaColormap(float light, float z)
vec4 Lightmode_Vanilla()
{
// z is the depth in view space, positive going into the screen
#if defined(SWLIGHT_RADIAL)
float z = distance(pixelpos.xyz, uCameraPos.xyz);
#else
float z = pixelpos.w;
#endif
float z;
#uifdef(SWLIGHT_RADIAL)
z = distance(pixelpos.xyz, uCameraPos.xyz);
#uelse
z = pixelpos.w;
#uendif
float colormap = VanillaColormap(uLightLevel, z);
#if defined(SWLIGHT_BANDED)
#uifdef(SWLIGHT_BANDED)
colormap = floor(colormap) + 0.5;
#endif
#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

@ -8,10 +8,15 @@
vec3 lightdir = normalize(light.pos.xyz - pixelpos.xyz);
#ifndef LIGHT_NONORMALS
float dotprod = dot(normal, lightdir);
float dotprod;
#uifdef(LIGHT_NONORMALS)
#uelse
{
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.
#endif
}
#uendif
float attenuation = distanceAttenuation(lightdistance, light.radius, light.strength, light.linearity);
@ -20,12 +25,13 @@
attenuation *= spotLightAttenuation(light.pos.xyz, light.spotDir.xyz, light.spotInnerAngle, light.spotOuterAngle);
}
#ifndef LIGHT_NONORMALS
#uifdef(LIGHT_NONORMALS)
#uelse
if ((light.flags & LIGHTINFO_ATTENUATED) != 0)
{
attenuation *= clamp(dotprod, 0.0, 1.0);
}
#endif
#uendif
if (attenuation > 0.0) // Skip shadow map test if possible
@ -52,64 +58,62 @@
vec4 dynlight = uDynLightColor;
vec3 normal = material.Normal;
#if !defined(SHADE_VERTEX)
if (uLightIndex >= 0)
{
ivec4 lightRange = getLightRange();
if (lightRange.z > lightRange.x)
#ifdef SHADE_VERTEX
dynlight.rgb += vLightColor;
#else
if (uLightIndex >= 0)
{
// modulated lights
for(int i=lightRange.x; i<lightRange.y; i++)
ivec4 lightRange = getLightRange();
if (lightRange.z > lightRange.x)
{
dynlight.rgb += lightContribution(getLights()[i], normal);
}
// modulated lights
for(int i=lightRange.x; i<lightRange.y; i++)
{
dynlight.rgb += lightContribution(getLights()[i], normal);
}
// subtractive lights
for(int i=lightRange.y; i<lightRange.z; i++)
{
dynlight.rgb -= lightContribution(getLights()[i], normal);
// subtractive lights
for(int i=lightRange.y; i<lightRange.z; i++)
{
dynlight.rgb -= lightContribution(getLights()[i], normal);
}
}
}
}
#else
dynlight.rgb += vLightColor;
#endif
#ifdef LIGHT_BLEND_CLAMPED
vec3 frag = material.Base.rgb * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
#elif defined(LIGHT_BLEND_COLORED_CLAMP)
vec3 frag = color + desaturate(dynlight).rgb;
frag = material.Base.rgb * ((frag / max(max(max(frag.r, frag.g), frag.b), 1.4) * 1.4));
#else // elif defined(LIGHT_BLEND_UNCLAMPED)
vec3 frag = material.Base.rgb * (color + desaturate(dynlight).rgb);
#endif
#if !defined(SHADE_VERTEX)
if (uLightIndex >= 0)
{
ivec4 lightRange = getLightRange();
if (lightRange.w > lightRange.z)
vec3 frag;
#uifdef(LIGHT_BLEND_CLAMPED)
frag = material.Base.rgb * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
#uelifdef(LIGHT_BLEND_COLORED_CLAMP)
{
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
// additive lights
for(int i=lightRange.z; i<lightRange.w; i++)
{
addlight.rgb += lightContribution(getLights()[i], normal);
}
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
frag = color + desaturate(dynlight).rgb;
frag = material.Base.rgb * ((frag / max(max(max(frag.r, frag.g), frag.b), 1.4) * 1.4));
}
}
#endif
#uelse
frag = material.Base.rgb * (color + desaturate(dynlight).rgb);
#uendif
#ifndef SHADE_VERTEX
if (uLightIndex >= 0)
{
ivec4 lightRange = getLightRange();
if (lightRange.w > lightRange.z)
{
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
// additive lights
for(int i=lightRange.z; i<lightRange.w; i++)
{
addlight.rgb += lightContribution(getLights()[i], normal);
}
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
}
}
#endif
return frag;
}

View file

@ -1,17 +1,14 @@
#ifdef LIGHT_ATTENUATION_INVERSE_SQUARE
float distanceAttenuation(float dist, float radius, float strength, float linearity)
{
// light.radius >= 1000000.0 is sunlight, skip attenuation
if(light.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);
#uifdef(LIGHT_ATTENUATION_INVERSE_SQUARE)
// light.radius >= 1000000.0 is sunlight, skip attenuation
if(light.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
return clamp((radius - dist) / radius, 0.0, 1.0);
#uendif
}
#else //elif defined(LIGHT_ATTENUATION_LINEAR)
#define distanceAttenuation(dist, radius, strength, linearity) clamp((radius - dist) / radius, 0.0, 1.0)
#endif

View file

@ -69,25 +69,25 @@ vec3 ProcessMaterialLight(Material material, vec3 color)
}
}
#if defined(LIGHT_BLEND_CLAMPED)
#uifdef(LIGHT_BLEND_CLAMPED)
{
dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4);
#elif defined(LIGHT_BLEND_COLORED_CLAMP)
}
#elifdef(LIGHT_BLEND_COLORED_CLAMP)
{
dynlight.rgb = color + desaturate(dynlight).rgb;
specular.rgb = desaturate(specular).rgb;
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));
#else // elif defined(LIGHT_BLEND_UNCLAMPED)
}
#uelse
{
dynlight.rgb = color + desaturate(dynlight).rgb;
specular.rgb = desaturate(specular).rgb;
#endif
}
#uendif
vec3 frag = material.Base.rgb * dynlight.rgb + material.Specular * specular.rgb;

View file

@ -56,18 +56,22 @@ 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
#if defined(TEXF_Brightmap)
#uifdef(TEXF_Brightmap)
material.Bright = desaturate(texture(brighttexture, texCoord.st));
#endif
#uendif
#if defined(TEXF_Detailmap)
#uifdef(TEXF_Detailmap)
{
vec4 Detail = texture(detailtexture, texCoord.st * uDetailParms.xy) * uDetailParms.z;
material.Base.rgb *= Detail.rgb;
#endif
}
#uendif
#if defined(TEXF_Glowmap)
#uifdef(TEXF_Glowmap)
{
material.Glow = desaturate(texture(glowtexture, texCoord.st));
#endif
}
#uendif
#ifdef PBR
material.Metallic = texture(metallictexture, texCoord.st).r;

View file

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

View file

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

View file

@ -0,0 +1,54 @@
#define SK1_ALPHATEST (1 << 0)
//#define SK1_SIMPLE (1 << 1)
#define SK1_SIMPLE2D (1 << 2)
//#define SK1_SIMPLE3D (1 << 3)
#define SK1_TEXTUREMODE (7 << 4)
// #define SK1_TM_NORMAL 0
#define SK1_TM_STENCIL 1
#define SK1_TM_OPAQUE 2
#define SK1_TM_INVERSE 3
#define SK1_TM_ALPHATEXTURE 4
#define SK1_TM_CLAMPY 5
#define SK1_TM_INVERTOPAQUE 6
#define SK1_TM_FOGLAYER 7
#define SK1_TEXF_CLAMPY (1 << 7)
#define SK1_TEXF_BRIGHTMAP (1 << 8)
#define SK1_TEXF_DETAILMAP (1 << 9)
#define SK1_TEXF_GLOWMAP (1 << 10)
#define SK1_GBUFFER_PASS (1 << 11)
#define SK1_USE_SHADOWMAP (1 << 12)
#define SK1_USE_RAYTRACE (1 << 13)
#define SK1_USE_RAYTRACE_PRECISE (1 << 14)
#define SK1_PRECISE_MIDTEXTURES (1 << 15)
#define SK1_SHADOWMAP_FILTER (15 << 16)
#define SK1_FOG_BEFORE_LIGHTS (1 << 20)
#define SK1_FOG_AFTER_LIGHTS (1 << 21)
#define SK1_FOG_RADIAL (1 << 22)
#define SK1_SWLIGHT_RADIAL (1 << 23)
#define SK1_SWLIGHT_BANDED (1 << 24)
#define SK1_LIGHTMODE (3 << 25)
#define SK1_LIGHTMODE_DEFAULT 0
#define SK1_LIGHTMODE_SOFTWARE 1
#define SK1_LIGHTMODE_VANILLA 2
#define SK1_LIGHTMODE_BUILD 3
#define SK1_LIGHTBLENDMODE (3 << 27)
#define SK1_LIGHT_BLEND_CLAMPED 1
#define SK1_LIGHT_LIGHT_BLEND_COLORED_CLAMP 2
#define SK1_LIGHT_BLEND_UNCLAMPED 3
#define SK1_LIGHTATTENUATIONMODE (1 << 29)
//#define SK1_USE_LEVELMESH (1 << 30)
#define SK1_FOGBALLS (1 << 31)
//#define SK2_NOFRAGMENTSHADER (1 << 0)
#define SK2_USE_DEPTHFADETHRESHOLD (1 << 1)
#define SK2_ALPHATEST_ONLY (1 << 2)
//#define SK2_SHADE_VERTEX (1 << 3)
#define SK2_LIGHT_NONORMALS (1 << 4)
#define SK2_USE_SPRITECENTER (1 << 5)
#define SK_GET_TEXTUREMODE() ((uShaderKey1 & SK1_TEXTUREMODE) >> 4)
#define SK_GET_SHADOWMAP_FILTER() ((uShaderKey1 & SK1_SHADOWMAP_FILTER) >> 16)
#define SK_GET_LIGHTMODE() ((uShaderKey1 & SK1_LIGHTMODE) >> 25)
#define SK_GET_LIGHTBLENDMODE() ((uShaderKey1 & SK1_LIGHTBLENDMODE) >> 27)