diff --git a/src/common/rendering/gl/gl_renderstate.cpp b/src/common/rendering/gl/gl_renderstate.cpp index 9eee22c66..5628ca0a5 100644 --- a/src/common/rendering/gl/gl_renderstate.cpp +++ b/src/common/rendering/gl/gl_renderstate.cpp @@ -142,6 +142,9 @@ bool FGLRenderState::ApplyShader() activeShader->muTextureModulateColor.Set(mStreamData.uTextureModulateColor); activeShader->muTextureBlendColor.Set(mStreamData.uTextureBlendColor); activeShader->muDetailParms.Set(&mStreamData.uDetailParms.X); +#ifdef NPOT_EMULATION + activeShader->muNpotEmulation.Set(&mStreamData.uNpotEmulation.X); +#endif if (mGlowEnabled || activeShader->currentglowstate) { diff --git a/src/common/rendering/gl/gl_shader.cpp b/src/common/rendering/gl/gl_shader.cpp index 51f3fb3eb..0505a1d2e 100644 --- a/src/common/rendering/gl/gl_shader.cpp +++ b/src/common/rendering/gl/gl_shader.cpp @@ -40,6 +40,7 @@ #include "hw_lightbuffer.h" #include "i_specialpaths.h" #include "printf.h" +#include "version.h" #include "gl_interface.h" #include "gl_debug.h" @@ -232,105 +233,106 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * float uClipHeightDirection; int uShadowmapFilter; }; + + uniform int uTextureMode; + uniform vec2 uClipSplit; + uniform float uAlphaThreshold; + + // colors + uniform vec4 uObjectColor; + uniform vec4 uObjectColor2; + uniform vec4 uDynLightColor; + uniform vec4 uAddColor; + uniform vec4 uTextureBlendColor; + uniform vec4 uTextureModulateColor; + uniform vec4 uTextureAddColor; + uniform vec4 uBlendColor; + uniform vec4 uFogColor; + uniform float uDesaturationFactor; + uniform float uInterpolationFactor; + + // Glowing walls stuff + uniform vec4 uGlowTopPlane; + uniform vec4 uGlowTopColor; + uniform vec4 uGlowBottomPlane; + uniform vec4 uGlowBottomColor; + + uniform vec4 uGradientTopPlane; + uniform vec4 uGradientBottomPlane; + + uniform vec4 uSplitTopPlane; + uniform vec4 uSplitBottomPlane; + + uniform vec4 uDetailParms; + // Lighting + Fog + uniform vec4 uLightAttr; + #define uLightLevel uLightAttr.a + #define uFogDensity uLightAttr.b + #define uLightFactor uLightAttr.g + #define uLightDist uLightAttr.r + uniform int uFogEnabled; + + // dynamic lights + uniform int uLightIndex; + + // Blinn glossiness and specular level + uniform vec2 uSpecularMaterial; + + // matrices + uniform mat4 ModelMatrix; + uniform mat4 NormalModelMatrix; + uniform mat4 TextureMatrix; + + // light buffers + #ifdef SHADER_STORAGE_LIGHTS + layout(std430, binding = 1) buffer LightBufferSSO + { + vec4 lights[]; + }; + #elif defined NUM_UBO_LIGHTS + uniform LightBufferUBO + { + vec4 lights[NUM_UBO_LIGHTS]; + }; + #endif + + // textures + uniform sampler2D tex; + uniform sampler2D ShadowMap; + uniform sampler2D texture2; + uniform sampler2D texture3; + uniform sampler2D texture4; + uniform sampler2D texture5; + uniform sampler2D texture6; + uniform sampler2D texture7; + uniform sampler2D texture8; + + // timer data + uniform float timer; + + // material types + #if defined(SPECULAR) + #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 + #else + #define brighttexture texture2 + #define detailtexture texture3 + #define glowtexture texture4 + #endif + )"; - i_data += "uniform int uTextureMode;\n"; - i_data += "uniform vec2 uClipSplit;\n"; - i_data += "uniform float uAlphaThreshold;\n"; - - // colors - i_data += "uniform vec4 uObjectColor;\n"; - i_data += "uniform vec4 uObjectColor2;\n"; - i_data += "uniform vec4 uDynLightColor;\n"; - i_data += "uniform vec4 uAddColor;\n"; - i_data += "uniform vec4 uTextureBlendColor;\n"; - i_data += "uniform vec4 uTextureModulateColor;\n"; - i_data += "uniform vec4 uTextureAddColor;\n"; - i_data += "uniform vec4 uBlendColor;\n"; - i_data += "uniform vec4 uFogColor;\n"; - i_data += "uniform float uDesaturationFactor;\n"; - i_data += "uniform float uInterpolationFactor;\n"; - - // Glowing walls stuff - i_data += "uniform vec4 uGlowTopPlane;\n"; - i_data += "uniform vec4 uGlowTopColor;\n"; - i_data += "uniform vec4 uGlowBottomPlane;\n"; - i_data += "uniform vec4 uGlowBottomColor;\n"; - - i_data += "uniform vec4 uGradientTopPlane;\n"; - i_data += "uniform vec4 uGradientBottomPlane;\n"; - - i_data += "uniform vec4 uSplitTopPlane;\n"; - i_data += "uniform vec4 uSplitBottomPlane;\n"; - - i_data += "uniform vec4 uDetailParms;\n"; - - // Lighting + Fog - i_data += "uniform vec4 uLightAttr;\n"; - i_data += "#define uLightLevel uLightAttr.a\n"; - i_data += "#define uFogDensity uLightAttr.b\n"; - i_data += "#define uLightFactor uLightAttr.g\n"; - i_data += "#define uLightDist uLightAttr.r\n"; - i_data += "uniform int uFogEnabled;\n"; - - // dynamic lights - i_data += "uniform int uLightIndex;\n"; - - // Blinn glossiness and specular level - i_data += "uniform vec2 uSpecularMaterial;\n"; - - // matrices - i_data += "uniform mat4 ModelMatrix;\n"; - i_data += "uniform mat4 NormalModelMatrix;\n"; - i_data += "uniform mat4 TextureMatrix;\n"; - - // light buffers - i_data += "#ifdef SHADER_STORAGE_LIGHTS\n"; - i_data += "layout(std430, binding = 1) buffer LightBufferSSO\n"; - i_data += "{\n"; - i_data += " vec4 lights[];\n"; - i_data += "};\n"; - i_data += "#elif defined NUM_UBO_LIGHTS\n"; - i_data += "uniform LightBufferUBO\n"; - i_data += "{\n"; - i_data += " vec4 lights[NUM_UBO_LIGHTS];\n"; - i_data += "};\n"; - i_data += "#endif\n"; - - // textures - i_data += "uniform sampler2D tex;\n"; - i_data += "uniform sampler2D ShadowMap;\n"; - i_data += "uniform sampler2D texture2;\n"; - i_data += "uniform sampler2D texture3;\n"; - i_data += "uniform sampler2D texture4;\n"; - i_data += "uniform sampler2D texture5;\n"; - i_data += "uniform sampler2D texture6;\n"; - i_data += "uniform sampler2D texture7;\n"; - i_data += "uniform sampler2D texture8;\n"; - - // timer data - i_data += "uniform float timer;\n"; - - // material types - i_data += "#if defined(SPECULAR)\n"; - i_data += "#define normaltexture texture2\n"; - i_data += "#define speculartexture texture3\n"; - i_data += "#define brighttexture texture4\n"; - i_data += "#define detailtexture texture5\n"; - i_data += "#define glowtexture texture6\n"; - i_data += "#elif defined(PBR)\n"; - i_data += "#define normaltexture texture2\n"; - i_data += "#define metallictexture texture3\n"; - i_data += "#define roughnesstexture texture4\n"; - i_data += "#define aotexture texture5\n"; - i_data += "#define brighttexture texture6\n"; - i_data += "#define detailtexture texture7\n"; - i_data += "#define glowtexture texture8\n"; - i_data += "#else\n"; - i_data += "#define brighttexture texture2\n"; - i_data += "#define detailtexture texture3\n"; - i_data += "#define glowtexture texture4\n"; - i_data += "#endif\n"; #ifdef __APPLE__ // The noise functions are completely broken in macOS OpenGL drivers @@ -342,6 +344,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * i_data += "#define noise4(unused) vec4(0)\n"; #endif // __APPLE__ +#ifdef NPOT_EMULATION + i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; +#endif + int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump, 0); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump); FileData vp_data = fileSystem.ReadFile(vp_lump); @@ -577,6 +583,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * muSplitBottomPlane.Init(hShader, "uSplitBottomPlane"); muSplitTopPlane.Init(hShader, "uSplitTopPlane"); muDetailParms.Init(hShader, "uDetailParms"); +#ifdef NPOT_EMULATION + muNpotEmulation.Init(hShader, "uNpotEmulation"); +#endif muInterpolationFactor.Init(hShader, "uInterpolationFactor"); muAlphaThreshold.Init(hShader, "uAlphaThreshold"); muSpecularMaterial.Init(hShader, "uSpecularMaterial"); diff --git a/src/common/rendering/gl/gl_shader.h b/src/common/rendering/gl/gl_shader.h index fef8372cd..b42e144ef 100644 --- a/src/common/rendering/gl/gl_shader.h +++ b/src/common/rendering/gl/gl_shader.h @@ -262,6 +262,9 @@ class FShader FBufferedUniform1f muAlphaThreshold; FBufferedUniform2f muSpecularMaterial; FBufferedUniform1f muTimer; +#ifdef NPOT_EMULATION + FBufferedUniform2f muNpotEmulation; +#endif int lights_index; int modelmatrix_index; diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index fac9574f7..1a9964194 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -4,6 +4,7 @@ #include "matrix.h" #include "hw_material.h" #include "texmanip.h" +#include "version.h" struct FColormap; class IVertexBuffer; @@ -198,6 +199,9 @@ struct StreamData FVector4 uSplitBottomPlane; FVector4 uDetailParms; +#ifdef NPOT_EMULATION + FVector2 uNpotEmulation; +#endif }; class FRenderState @@ -289,7 +293,9 @@ public: mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f }; mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 0.0f }; mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f }; - +#ifdef NPOT_EMULATION + mStreamData.uNpotEmulation = { 0,0 }; +#endif mModelMatrix.loadIdentity(); mTextureMatrix.loadIdentity(); ClearClipSplit(); @@ -472,6 +478,13 @@ public: mStreamData.uAddColor = pe; } + void SetNpotEmulation(float factor, float offset) + { +#ifdef NPOT_EMULATION + mStreamData.uNpotEmulation = { offset, factor }; +#endif + } + void ApplyTextureManipulation(TextureManipulation* texfx) { if (!texfx || texfx->AddColor.a == 0) diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 092a20e69..7f9fa9a6f 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -25,6 +25,7 @@ #include "hw_shaderpatcher.h" #include "filesystem.h" #include "engineerrors.h" +#include "version.h" #include VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device) @@ -162,6 +163,9 @@ static const char *shaderBindings = R"( vec4 uSplitBottomPlane; vec4 uDetailParms; + #ifdef NPOT_EMULATION + vec2 uNpotEmulation; + #endif }; layout(set = 0, binding = 3, std140) uniform StreamUBO { @@ -248,6 +252,7 @@ static const char *shaderBindings = R"( #define uSplitTopPlane data[uDataIndex].uSplitTopPlane #define uSplitBottomPlane data[uDataIndex].uSplitBottomPlane #define uDetailParms data[uDataIndex].uDetailParms + #define uNpotEmulation data[uDataIndex].uNpotEmulation #define SUPPORTS_SHADOWMAPS #define VULKAN_COORDINATE_SYSTEM @@ -270,6 +275,9 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername FString code = GetTargetGlslVersion(); code << defines; code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; +#ifdef NPOT_EMULATION + code << "#define NPOT_EMULATION\n" +#endif code << shaderBindings; if (!device->UsedDeviceFeatures.shaderClipDistance) code << "#define NO_CLIPDISTANCE_SUPPORT\n"; code << "#line 1\n"; diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 3137679be..6a2d3ea9f 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -175,6 +175,10 @@ static const uint8_t renderwalltotier[] = side_t::mid, }; +#ifdef NPOT_EMULATION +CVAR(Bool, hw_npottest, false, 0) +#endif + void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) { int tmode = state.GetTextureMode(); @@ -187,6 +191,23 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) SetGlowPlanes(state, frontsector->ceilingplane, frontsector->floorplane); } state.SetMaterial(texture, UF_Texture, 0, flags & 3, 0, -1); +#ifdef NPOT_EMULATION + // Test code, could be reactivated as a compatibility option in the unlikely event that some old vanilla map eve needs it. + if (hw_npottest) + { + int32_t size = xs_CRoundToInt(texture->GetDisplayHeight()); + int32_t size2; + for (size2 = 1; size2 < size; size2 += size2) {} + if (size == size2) + state.SetNpotEmulation(0.f, 0.f); + else + { + float xOffset = 1.f / texture->GetDisplayWidth(); + state.SetNpotEmulation((1.f * size2) / size, xOffset); + } + } +#endif + if (type == RENDERWALL_M2SNF) { @@ -274,6 +295,7 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) state.EnableSplit(false); } + state.SetNpotEmulation(0.f, 0.f); state.SetObjectColor(0xffffffff); state.SetObjectColor2(0); state.SetAddColor(0); diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index 8960103bf..048579eee 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -540,6 +540,14 @@ vec3 ApplyNormalMap(vec2 texcoord) void SetMaterialProps(inout Material material, vec2 texCoord) { +#ifdef NPOT_EMULATION + if (uNpotEmulation.y != 0.0) + { + float period = floor(texCoord.t / uNpotEmulation.y); + texCoord.s += uNpotEmulation.x * floor(mod(texCoord.t, uNpotEmulation.y)); + texCoord.t = period + mod(texCoord.t, uNpotEmulation.y); + } +#endif material.Base = getTexel(texCoord.st); material.Normal = ApplyNormalMap(texCoord.st);