From d13459ecf98c4dfe0949d10ad4b5dec73817ab62 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 5 Jan 2021 22:21:54 +0000 Subject: [PATCH 1/3] Scale mipmap alpha to preserve coverage --- files/shaders/alpha.glsl | 23 +++++++++++++++++++++++ files/shaders/objects_fragment.glsl | 3 +++ files/shaders/shadowcasting_fragment.glsl | 2 ++ 3 files changed, 28 insertions(+) diff --git a/files/shaders/alpha.glsl b/files/shaders/alpha.glsl index 2551a02052..6ead9e6ca2 100644 --- a/files/shaders/alpha.glsl +++ b/files/shaders/alpha.glsl @@ -12,6 +12,29 @@ uniform float alphaRef; #endif +float mipmapLevel(vec2 scaleduv) +{ + vec2 dUVdx = dFdx(scaleduv); + vec2 dUVdy = dFdy(scaleduv); + float maxDUVSquared = max(dot(dUVdx, dUVdx), dot(dUVdy, dUVdy)); + return max(0.0, 0.5 * log2(maxDUVSquared)); +} + +float coveragePreservingAlphaScale(sampler2D diffuseMap, vec2 uv) +{ + #if @alphaFunc != FUNC_ALWAYS && @alphaFunc != FUNC_NEVER + vec2 textureSize; + #ifdef GL_EXT_gpu_shader4 + textureSize = textureSize2D(diffuseMap, 0); + #else + textureSize = 256.0; + #endif + return 1.0 + mipmapLevel(uv * textureSize) * 0.25; + #else + return 1.0; + #endif +} + void alphaTest() { #if @alphaToCoverage diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index 995c2adaf3..c5f397789a 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -1,5 +1,7 @@ #version 120 +#extension EXT_gpu_shader4: enable + #if @diffuseMap uniform sampler2D diffuseMap; varying vec2 diffuseMapUV; @@ -109,6 +111,7 @@ void main() #if @diffuseMap gl_FragData[0] = texture2D(diffuseMap, adjustedDiffuseUV); + gl_FragData[0].a *= coveragePreservingAlphaScale(diffuseMap, adjustedDiffuseUV); #else gl_FragData[0] = vec4(1.0); #endif diff --git a/files/shaders/shadowcasting_fragment.glsl b/files/shaders/shadowcasting_fragment.glsl index 8c53c542bd..ea8a63313e 100644 --- a/files/shaders/shadowcasting_fragment.glsl +++ b/files/shaders/shadowcasting_fragment.glsl @@ -1,5 +1,7 @@ #version 120 +#extension EXT_gpu_shader4: enable + uniform sampler2D diffuseMap; varying vec2 diffuseMapUV; From 4ed32520018dff5debf8d66ff7e1d7aa367a6c3b Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 7 Jan 2021 18:13:51 +0000 Subject: [PATCH 2/3] Check for EXT_gpu_shader4 CPU-side Mesa lies and always defines GL_EXT_gpu_shader4 even when the extension isn't present. --- apps/openmw/mwrender/renderingmanager.cpp | 1 + components/sceneutil/mwshadowtechnique.cpp | 7 ++++++- components/shader/shadervisitor.cpp | 7 +++++++ files/shaders/alpha.glsl | 4 ++-- files/shaders/objects_fragment.glsl | 4 +++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 17a6527fc9..95e98f55b2 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -252,6 +252,7 @@ namespace MWRender globalDefines["clamp"] = Settings::Manager::getBool("clamp lighting", "Shaders") ? "1" : "0"; globalDefines["preLightEnv"] = Settings::Manager::getBool("apply lighting to environment maps", "Shaders") ? "1" : "0"; globalDefines["radialFog"] = Settings::Manager::getBool("radial fog", "Shaders") ? "1" : "0"; + globalDefines["useGPUShader4"] = "0"; // It is unnecessary to stop/start the viewer as no frames are being rendered yet. mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(globalDefines); diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index c781318faf..41e64e1247 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -892,12 +892,17 @@ void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & sh // This can't be part of the constructor as OSG mandates that there be a trivial constructor available osg::ref_ptr castingVertexShader = shaderManager.getShader("shadowcasting_vertex.glsl", {}, osg::Shader::VERTEX); + osg::ref_ptr exts = osg::GLExtensions::Get(0, false); + std::string useGPUShader4 = exts && exts->isGpuShader4Supported ? "1" : "0"; for (int alphaFunc = GL_NEVER; alphaFunc <= GL_ALWAYS; ++alphaFunc) { auto& program = _castingPrograms[alphaFunc - GL_NEVER]; program = new osg::Program(); program->addShader(castingVertexShader); - program->addShader(shaderManager.getShader("shadowcasting_fragment.glsl", { {"alphaFunc", std::to_string(alphaFunc)}, {"alphaToCoverage", "0"} }, osg::Shader::FRAGMENT)); + program->addShader(shaderManager.getShader("shadowcasting_fragment.glsl", { {"alphaFunc", std::to_string(alphaFunc)}, + {"alphaToCoverage", "0"}, + {"useGPUShader4", useGPUShader4} + }, osg::Shader::FRAGMENT)); } } diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 165be6745d..d719daec28 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -411,6 +412,12 @@ namespace Shader writableStateSet->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, osg::StateAttribute::ON); defineMap["alphaToCoverage"] = "1"; } + + // Preventing alpha tested stuff shrinking as lower mip levels are used requires knowing the texture size + osg::ref_ptr exts = osg::GLExtensions::Get(0, false); + if (exts && exts->isGpuShader4Supported) + defineMap["useGPUShader4"] = "1"; + // We could fall back to a texture size uniform if EXT_gpu_shader4 is missing } if (writableStateSet->getMode(GL_ALPHA_TEST) != osg::StateAttribute::INHERIT) diff --git a/files/shaders/alpha.glsl b/files/shaders/alpha.glsl index 6ead9e6ca2..05be801e93 100644 --- a/files/shaders/alpha.glsl +++ b/files/shaders/alpha.glsl @@ -24,10 +24,10 @@ float coveragePreservingAlphaScale(sampler2D diffuseMap, vec2 uv) { #if @alphaFunc != FUNC_ALWAYS && @alphaFunc != FUNC_NEVER vec2 textureSize; - #ifdef GL_EXT_gpu_shader4 + #if @useGPUShader4 textureSize = textureSize2D(diffuseMap, 0); #else - textureSize = 256.0; + textureSize = vec2(256.0); #endif return 1.0 + mipmapLevel(uv * textureSize) * 0.25; #else diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index c5f397789a..37cca273fc 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -1,6 +1,8 @@ #version 120 -#extension EXT_gpu_shader4: enable +#if @useGPUShader4 + #extension EXT_gpu_shader4: require +#endif #if @diffuseMap uniform sampler2D diffuseMap; From 0068c7bb252428571c1f6ae4ca57220873d0c701 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 8 Jan 2021 17:32:15 +0000 Subject: [PATCH 3/3] Spec says GL_ --- files/shaders/objects_fragment.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index 37cca273fc..693c045847 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -1,7 +1,7 @@ #version 120 #if @useGPUShader4 - #extension EXT_gpu_shader4: require + #extension GL_EXT_gpu_shader4: require #endif #if @diffuseMap