From 9e51a2f63cff797756a76aaec6bf8aff1ad45f8a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 8 Jun 2020 08:01:56 +0200 Subject: [PATCH] - added Build's NPOT emulation to the backend. For GZDoom this is completely disabled, of course, because the Doom engine does not need it, but in order to have the same backend code in both engines it needs to be present. --- src/common/rendering/gl/gl_renderstate.cpp | 3 + src/common/rendering/gl/gl_shader.cpp | 203 +++++++++--------- src/common/rendering/gl/gl_shader.h | 3 + .../hwrenderer/data/hw_renderstate.h | 15 +- .../rendering/vulkan/shaders/vk_shader.cpp | 8 + src/rendering/hwrenderer/scene/hw_walls.cpp | 22 ++ wadsrc/static/shaders/glsl/main.fp | 8 + 7 files changed, 164 insertions(+), 98 deletions(-) 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);