diff --git a/src/main/java/rs117/hd/HdPlugin.java b/src/main/java/rs117/hd/HdPlugin.java index 6cdf8b6741..7381735930 100644 --- a/src/main/java/rs117/hd/HdPlugin.java +++ b/src/main/java/rs117/hd/HdPlugin.java @@ -77,6 +77,7 @@ import org.lwjgl.opengl.*; import org.lwjgl.system.Callback; import org.lwjgl.system.Configuration; +import rs117.hd.config.AntiAliasingMode; import rs117.hd.config.ColorFilter; import rs117.hd.config.DynamicLights; import rs117.hd.config.SeasonalHemisphere; @@ -95,7 +96,6 @@ import rs117.hd.overlays.FrameTimer; import rs117.hd.overlays.GammaCalibrationOverlay; import rs117.hd.overlays.ShadowMapOverlay; -import rs117.hd.overlays.TiledLightingOverlay; import rs117.hd.overlays.Timer; import rs117.hd.renderer.Renderer; import rs117.hd.renderer.legacy.LegacyRenderer; @@ -165,6 +165,7 @@ public class HdPlugin extends Plugin { public static int MAX_TEXTURE_UNITS; public static int TEXTURE_UNIT_COUNT = 0; + public static final int TEXTURE_UNIT_SCENE_COLOR = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++; public static final int TEXTURE_UNIT_UI = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++; public static final int TEXTURE_UNIT_GAME = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++; public static final int TEXTURE_UNIT_SHADOW_MAP = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++; @@ -316,9 +317,6 @@ public class HdPlugin extends Plugin { @Inject private ShadowMapOverlay shadowMapOverlay; - @Inject - private TiledLightingOverlay tiledLightingOverlay; - @Inject public HDVariables vars; @@ -374,9 +372,9 @@ public class HdPlugin extends Plugin { public int[] sceneResolution; public int fboScene; private int rboSceneColor; + private int texSceneColor; private int rboSceneDepth; - public int fboSceneResolve; - private int rboSceneResolveColor; + private int fboSceneResolve; public int shadowMapResolution; public int fboShadowMap; @@ -537,7 +535,6 @@ protected void startUp() { rboSceneColor = 0; rboSceneDepth = 0; fboSceneResolve = 0; - rboSceneResolveColor = 0; fboShadowMap = 0; frame = 0; elapsedTime = 0; @@ -915,6 +912,7 @@ public ShaderIncludes getShaderIncludes() { .define("MAX_LIGHT_COUNT", configTiledLighting ? UBOLights.MAX_LIGHTS : configDynamicLights.getMaxSceneLights()) .define("NORMAL_MAPPING", config.normalMapping()) .define("PARALLAX_OCCLUSION_MAPPING", config.parallaxOcclusionMapping()) + .define("FXAA_ENABLED", config.antiAliasingMode() == AntiAliasingMode.FXAA) .define("SHADOW_MODE", configShadowMode) .define("SHADOW_TRANSPARENCY", config.shadowTransparency()) .define("SHADOW_FILTERING", config.shadowFiltering()) @@ -1317,33 +1315,62 @@ public void updateSceneFbo() { uboGlobal.sceneResolution.set(sceneResolution); uboGlobal.upload(); // Ensure this is up to date with rendering + // Create and bind the FBO fboScene = glGenFramebuffers(); glBindFramebuffer(GL_FRAMEBUFFER, fboScene); - // Create color render buffer - rboSceneColor = glGenRenderbuffers(); - glBindRenderbuffer(GL_RENDERBUFFER, rboSceneColor); - // Flush out all pending errors, so we can check whether the next step succeeds clearGLErrors(); int format = 0; - for (int desiredFormat : desiredFormats) { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaSamples, desiredFormat, sceneResolution[0], sceneResolution[1]); + if (msaaSamples > 1) { + rboSceneColor = glGenRenderbuffers(); + glBindRenderbuffer(GL_RENDERBUFFER, rboSceneColor); + + for (int desiredFormat : desiredFormats) { + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaSamples, desiredFormat, sceneResolution[0], sceneResolution[1]); + if (glGetError() == GL_NO_ERROR) { + format = desiredFormat; + break; + } + } - if (glGetError() == GL_NO_ERROR) { - format = desiredFormat; - break; + if (format == 0) + throw new RuntimeException("No supported " + (sRGB ? "sRGB" : "linear") + " formats"); + + // Found a usable format. Bind the RBO to the scene FBO + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboSceneColor); + checkGLErrors(); + } else { + for (int desiredFormat : desiredFormats) { + final int probe = glGenRenderbuffers(); + glBindRenderbuffer(GL_RENDERBUFFER, probe); + glRenderbufferStorage(GL_RENDERBUFFER, desiredFormat, sceneResolution[0], sceneResolution[1]); + + final boolean supported = glGetError() == GL_NO_ERROR; + + glDeleteRenderbuffers(probe); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + if (supported) { + format = desiredFormat; + break; + } } - } - if (format == 0) - throw new RuntimeException("No supported " + (sRGB ? "sRGB" : "linear") + " formats"); + if (format == 0) + throw new RuntimeException("No supported " + (sRGB ? "sRGB" : "linear") + " formats"); - // Found a usable format. Bind the RBO to the scene FBO - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboSceneColor); - checkGLErrors(); + texSceneColor = glGenTextures(); + glActiveTexture(TEXTURE_UNIT_SCENE_COLOR); + glBindTexture(GL_TEXTURE_2D, texSceneColor); + glTexImage2D(GL_TEXTURE_2D, 0, format, sceneResolution[0], sceneResolution[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texSceneColor, 0); + checkGLErrors(); + } // Create depth render buffer rboSceneDepth = glGenRenderbuffers(); @@ -1353,17 +1380,23 @@ public void updateSceneFbo() { checkGLErrors(); // If necessary, create an FBO for resolving multisampling - if (msaaSamples > 1 && resolutionScale != 1) { + if (msaaSamples > 1) { fboSceneResolve = glGenFramebuffers(); glBindFramebuffer(GL_FRAMEBUFFER, fboSceneResolve); - rboSceneResolveColor = glGenRenderbuffers(); - glBindRenderbuffer(GL_RENDERBUFFER, rboSceneResolveColor); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, sceneResolution[0], sceneResolution[1]); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboSceneResolveColor); + + texSceneColor = glGenTextures(); + glActiveTexture(TEXTURE_UNIT_SCENE_COLOR); + glBindTexture(GL_TEXTURE_2D, texSceneColor); + glTexImage2D(GL_TEXTURE_2D, 0, format, sceneResolution[0], sceneResolution[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texSceneColor, 0); checkGLErrors(); } // Reset + glActiveTexture(TEXTURE_UNIT_UI); + glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, awtContext.getFramebuffer(false)); glBindRenderbuffer(GL_RENDERBUFFER, 0); } @@ -1375,9 +1408,9 @@ private void destroySceneFbo() { glDeleteFramebuffers(fboScene); fboScene = 0; - if (rboSceneColor != 0) - glDeleteRenderbuffers(rboSceneColor); - rboSceneColor = 0; + if (texSceneColor != 0) + glDeleteTextures(texSceneColor); + texSceneColor = 0; if (rboSceneDepth != 0) glDeleteRenderbuffers(rboSceneDepth); @@ -1386,10 +1419,6 @@ private void destroySceneFbo() { if (fboSceneResolve != 0) glDeleteFramebuffers(fboSceneResolve); fboSceneResolve = 0; - - if (rboSceneResolveColor != 0) - glDeleteRenderbuffers(rboSceneResolveColor); - rboSceneResolveColor = 0; } private void initializeShadowMapFbo() { @@ -1537,15 +1566,27 @@ public void drawUi(int overlayColor) { frameTimer.begin(Timer.RENDER_UI); - glBindFramebuffer(GL_FRAMEBUFFER, awtContext.getFramebuffer(false)); - // Disable alpha writes, just in case the default FBO has an alpha channel - glColorMask(true, true, true, false); + if(fboSceneResolve != 0) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, fboScene); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboSceneResolve); + glBlitFramebuffer( + 0, 0, sceneResolution[0], sceneResolution[1], + 0, 0, sceneResolution[0], sceneResolution[1], + GL_COLOR_BUFFER_BIT, GL_NEAREST + ); - glViewport(0, 0, actualUiResolution[0], actualUiResolution[1]); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } - tiledLightingOverlay.render(); + glBindFramebuffer(GL_FRAMEBUFFER, awtContext.getFramebuffer(false)); + glViewport(0, 0, actualUiResolution[0], actualUiResolution[1]); uiProgram.use(); + if(sceneViewport != null) + uboUI.sceneViewport.set(sceneViewport); + else + uboUI.sceneViewport.set(0, 0, 0, 0); uboUI.sourceDimensions.set(uiResolution); uboUI.targetDimensions.set(actualUiResolution); uboUI.alphaOverlay.set(ColorUtils.srgba(overlayColor)); @@ -1578,19 +1619,12 @@ public void drawUi(int overlayColor) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, function); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, function); - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); glBindVertexArray(vaoTri); glDrawArrays(GL_TRIANGLES, 0, 3); shadowMapOverlay.render(); gammaCalibrationOverlay.render(); - // Reset - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); - glDisable(GL_BLEND); - glColorMask(true, true, true, true); - frameTimer.end(Timer.RENDER_UI); } @@ -1820,6 +1854,7 @@ public void processPendingConfigChanges() { recompilePrograms = true; break; case KEY_ANTI_ALIASING_MODE: + recompilePrograms = true; case KEY_SCENE_RESOLUTION_SCALE: recreateSceneFbo = true; break; diff --git a/src/main/java/rs117/hd/config/AntiAliasingMode.java b/src/main/java/rs117/hd/config/AntiAliasingMode.java index 576453b1e1..99a0f04fac 100644 --- a/src/main/java/rs117/hd/config/AntiAliasingMode.java +++ b/src/main/java/rs117/hd/config/AntiAliasingMode.java @@ -32,6 +32,7 @@ public enum AntiAliasingMode { DISABLED("Disabled", 0), + FXAA("FXAA", 0), MSAA_2("MSAA x2", 2), MSAA_4("MSAA x4", 4), MSAA_8("MSAA x8", 8), diff --git a/src/main/java/rs117/hd/opengl/shader/UIShaderProgram.java b/src/main/java/rs117/hd/opengl/shader/UIShaderProgram.java index 779671555d..9104ba3a09 100644 --- a/src/main/java/rs117/hd/opengl/shader/UIShaderProgram.java +++ b/src/main/java/rs117/hd/opengl/shader/UIShaderProgram.java @@ -1,10 +1,12 @@ package rs117.hd.opengl.shader; import static org.lwjgl.opengl.GL33C.*; +import static rs117.hd.HdPlugin.TEXTURE_UNIT_SCENE_COLOR; import static rs117.hd.HdPlugin.TEXTURE_UNIT_UI; public class UIShaderProgram extends ShaderProgram { private final UniformTexture uniUiTexture = addUniformTexture("uiTexture"); + private final UniformTexture uniSceneTexture = addUniformTexture("sceneTexture"); public UIShaderProgram() { super(t -> t @@ -15,5 +17,6 @@ public UIShaderProgram() { @Override protected void initialize() { uniUiTexture.set(TEXTURE_UNIT_UI); + uniSceneTexture.set(TEXTURE_UNIT_SCENE_COLOR); } } diff --git a/src/main/java/rs117/hd/opengl/uniforms/UBOUI.java b/src/main/java/rs117/hd/opengl/uniforms/UBOUI.java index 084af5d386..7d223f5c61 100644 --- a/src/main/java/rs117/hd/opengl/uniforms/UBOUI.java +++ b/src/main/java/rs117/hd/opengl/uniforms/UBOUI.java @@ -9,6 +9,7 @@ public UBOUI() { super(GL_DYNAMIC_DRAW); } + public Property sceneViewport = addProperty(PropertyType.IVec4, "sceneViewport"); public Property sourceDimensions = addProperty(PropertyType.IVec2, "sourceDimensions"); public Property targetDimensions = addProperty(PropertyType.IVec2, "targetDimensions"); public Property alphaOverlay = addProperty(PropertyType.FVec4, "alphaOverlay"); diff --git a/src/main/java/rs117/hd/renderer/legacy/LegacyRenderer.java b/src/main/java/rs117/hd/renderer/legacy/LegacyRenderer.java index 41ce789d62..62f7d32d7f 100644 --- a/src/main/java/rs117/hd/renderer/legacy/LegacyRenderer.java +++ b/src/main/java/rs117/hd/renderer/legacy/LegacyRenderer.java @@ -39,6 +39,7 @@ import rs117.hd.opengl.uniforms.UBOCompute; import rs117.hd.opengl.uniforms.UBOLights; import rs117.hd.overlays.FrameTimer; +import rs117.hd.overlays.TiledLightingOverlay; import rs117.hd.overlays.Timer; import rs117.hd.renderer.Renderer; import rs117.hd.scene.AreaManager; @@ -136,6 +137,9 @@ public class LegacyRenderer implements Renderer { @Inject private ShadowShaderProgram.Legacy shadowProgram; + @Inject + private TiledLightingOverlay tiledLightingOverlay; + @Inject private JobSystem jobSystem; @@ -1209,42 +1213,14 @@ public void draw(int overlayColor) { frameTimer.end(Timer.RENDER_SCENE); + tiledLightingOverlay.render(); + glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDisable(GL_MULTISAMPLE); glDisable(GL_DEPTH_TEST); glDepthMask(true); glUseProgram(0); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, plugin.fboScene); - if (plugin.fboSceneResolve != 0) { - // Blit from the scene FBO to the multisample resolve FBO - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, plugin.fboSceneResolve); - glBlitFramebuffer( - 0, 0, plugin.sceneResolution[0], plugin.sceneResolution[1], - 0, 0, plugin.sceneResolution[0], plugin.sceneResolution[1], - GL_COLOR_BUFFER_BIT, GL_NEAREST - ); - glBindFramebuffer(GL_READ_FRAMEBUFFER, plugin.fboSceneResolve); - } - - // Blit from the resolved FBO to the default FBO - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, plugin.awtContext.getFramebuffer(false)); - glBlitFramebuffer( - 0, - 0, - plugin.sceneResolution[0], - plugin.sceneResolution[1], - plugin.sceneViewport[0], - plugin.sceneViewport[1], - plugin.sceneViewport[0] + plugin.sceneViewport[2], - plugin.sceneViewport[1] + plugin.sceneViewport[3], - GL_COLOR_BUFFER_BIT, - config.sceneScalingMode().glFilter - ); - } else { - glClearColor(0, 0, 0, 1f); - glClear(GL_COLOR_BUFFER_BIT); } plugin.drawUi(overlayColor); diff --git a/src/main/java/rs117/hd/renderer/zone/ZoneRenderer.java b/src/main/java/rs117/hd/renderer/zone/ZoneRenderer.java index 6a914772ec..94f52ef139 100644 --- a/src/main/java/rs117/hd/renderer/zone/ZoneRenderer.java +++ b/src/main/java/rs117/hd/renderer/zone/ZoneRenderer.java @@ -32,10 +32,8 @@ import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; import net.runelite.api.*; -import net.runelite.api.events.*; import net.runelite.api.hooks.*; import net.runelite.client.callback.ClientThread; -import net.runelite.client.eventbus.Subscribe; import net.runelite.client.ui.DrawManager; import org.lwjgl.opengl.*; import rs117.hd.HdPlugin; @@ -50,6 +48,7 @@ import rs117.hd.opengl.uniforms.UBOLights; import rs117.hd.opengl.uniforms.UBOWorldViews; import rs117.hd.overlays.FrameTimer; +import rs117.hd.overlays.TiledLightingOverlay; import rs117.hd.overlays.Timer; import rs117.hd.renderer.Renderer; import rs117.hd.scene.EnvironmentManager; @@ -139,6 +138,9 @@ public class ZoneRenderer implements Renderer { @Inject private ShadowShaderProgram.Detailed detailedShadowProgram; + @Inject + private TiledLightingOverlay tiledLightingOverlay; + @Inject private JobSystem jobSystem; @@ -160,7 +162,6 @@ public class ZoneRenderer implements Renderer { public static GLBuffer.EBO eboAlpha; public static GLMappedBufferIntWriter eboAlphaWriter; - private boolean sceneFboValid; private boolean shouldRenderSkybox; private boolean shouldRenderScene; private boolean shouldClearShadowFbo; @@ -684,8 +685,6 @@ private void postDrawTopLevel() { if (!sceneManager.isTopLevelValid() || plugin.sceneViewport == null) return; - sceneFboValid = true; - // Upload world views before rendering uboWorldViews.upload(); @@ -1121,39 +1120,8 @@ public void draw(int overlayColor) { tiledLightingPass(); directionalShadowPass(); scenePass(); - } - - if (sceneFboValid && plugin.sceneResolution != null && plugin.sceneViewport != null) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, plugin.fboScene); - if (plugin.fboSceneResolve != 0) { - // Blit from the scene FBO to the multisample resolve FBO - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, plugin.fboSceneResolve); - glBlitFramebuffer( - 0, 0, plugin.sceneResolution[0], plugin.sceneResolution[1], - 0, 0, plugin.sceneResolution[0], plugin.sceneResolution[1], - GL_COLOR_BUFFER_BIT, GL_NEAREST - ); - glBindFramebuffer(GL_READ_FRAMEBUFFER, plugin.fboSceneResolve); - } - // Blit from the resolved FBO to the default FBO - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, plugin.awtContext.getFramebuffer(false)); - glBlitFramebuffer( - 0, - 0, - plugin.sceneResolution[0], - plugin.sceneResolution[1], - plugin.sceneViewport[0], - plugin.sceneViewport[1], - plugin.sceneViewport[0] + plugin.sceneViewport[2], - plugin.sceneViewport[1] + plugin.sceneViewport[3], - GL_COLOR_BUFFER_BIT, - config.sceneScalingMode().glFilter - ); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, plugin.awtContext.getFramebuffer(false)); - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); + tiledLightingOverlay.render(); } plugin.drawUi(overlayColor); @@ -1191,16 +1159,6 @@ public void draw(int overlayColor) { } } - @Subscribe - public void onGameStateChanged(GameStateChanged gameStateChanged) { - GameState state = gameStateChanged.getGameState(); - if (state.getState() < GameState.LOADING.getState()) { - // this is to avoid scene fbo blit when going from =loading, - // but keep it when doing >loading to loading - sceneFboValid = false; - } - } - @Override public void invalidateZone(Scene scene, int zx, int zz) { sceneManager.invalidateZone(scene, zx, zz); diff --git a/src/main/resources/rs117/hd/scene_frag.glsl b/src/main/resources/rs117/hd/scene_frag.glsl index bcc9ac06f0..0d782a8175 100644 --- a/src/main/resources/rs117/hd/scene_frag.glsl +++ b/src/main/resources/rs117/hd/scene_frag.glsl @@ -532,9 +532,5 @@ void main() { outputColor.rgb = pow(outputColor.rgb, vec3(gammaCorrection)); - #if WINDOWS_HDR_CORRECTION - outputColor.rgb = windowsHdrCorrection(outputColor.rgb); - #endif - FragColor = outputColor; } diff --git a/src/main/resources/rs117/hd/ui_frag.glsl b/src/main/resources/rs117/hd/ui_frag.glsl index b2835c9310..0ba4aed398 100644 --- a/src/main/resources/rs117/hd/ui_frag.glsl +++ b/src/main/resources/rs117/hd/ui_frag.glsl @@ -24,15 +24,19 @@ */ #version 330 +#extension GL_ARB_gpu_shader5 : enable + #include #include +uniform sampler2D sceneTexture; uniform sampler2D uiTexture; #include #include #include #include +#include #if UI_SCALING_MODE == UI_SCALING_MODE_XBR #include @@ -44,6 +48,10 @@ uniform sampler2D uiTexture; in vec2 fUv; +#if FXAA_ENABLED + in FXAACoords sceneFxaaCoords; +#endif + out vec4 FragColor; vec4 alphaBlend(vec4 src, vec4 dst) { @@ -54,23 +62,37 @@ vec4 alphaBlend(vec4 src, vec4 dst) { } void main() { - vec4 c; + vec4 uiColor; #if UI_SCALING_MODE == UI_SCALING_MODE_MITCHELL || UI_SCALING_MODE == UI_SCALING_MODE_CATROM - c = textureCubic(uiTexture, fUv); + uiColor = textureCubic(uiTexture, fUv); #elif UI_SCALING_MODE == UI_SCALING_MODE_XBR - c = textureXBR(uiTexture, fUv, xbrTable, ceil(1.0 * targetDimensions.x / sourceDimensions.x)); + uiColor = textureXBR(uiTexture, fUv, xbrTable, ceil(1.0 * targetDimensions.x / sourceDimensions.x)); #elif UI_SCALING_MODE == UI_SCALING_MODE_HYBRID - c = textureHybrid(uiTexture, fUv); - #else // NEAREST or LINEAR, which uses GL_TEXTURE_MIN_FILTER/GL_TEXTURE_MAG_FILTER to affect sampling - c = texture(uiTexture, fUv); + uiColor = textureHybrid(uiTexture, fUv); + #else + uiColor = texture(uiTexture, fUv); #endif - c = alphaBlend(c, alphaOverlay); - c.rgb = colorBlindnessCompensation(c.rgb); + vec2 scenePixel = vec2(fUv.x, 1.0 - fUv.y) * vec2(targetDimensions); + vec3 sceneColor = vec3(0.0); + if (contains(scenePixel, sceneViewport.xy, sceneViewport.xy + sceneViewport.zw)) { + #if FXAA_ENABLED + vec2 sceneFragCoord = scenePixel - sceneViewport.xy; + sceneColor = fxaa(sceneTexture, sceneFragCoord, sceneViewport.zw, sceneFxaaCoords).rgb; + #else + vec2 sceneUV = saturate((scenePixel - sceneViewport.xy) / sceneViewport.zw); + sceneColor = texture(sceneTexture, sceneUV).rgb; + #endif + } + + uiColor = alphaBlend(uiColor, alphaOverlay); + uiColor.rgb = colorBlindnessCompensation(uiColor.rgb); + + vec3 outputColor = mix(sceneColor, uiColor.rgb, uiColor.a); #if WINDOWS_HDR_CORRECTION - c.rgb = windowsHdrCorrection(c.rgb); + outputColor = windowsHdrCorrection(outputColor); #endif - FragColor = c; + FragColor = vec4(outputColor, 1.0); } diff --git a/src/main/resources/rs117/hd/ui_vert.glsl b/src/main/resources/rs117/hd/ui_vert.glsl index df8d6611d9..64e1814b46 100644 --- a/src/main/resources/rs117/hd/ui_vert.glsl +++ b/src/main/resources/rs117/hd/ui_vert.glsl @@ -24,9 +24,11 @@ */ #version 330 -#include UI_SCALING_MODE +#extension GL_ARB_gpu_shader5 : enable #include +#include +#include layout (location = 0) in vec2 vPos; layout (location = 1) in vec2 vUv; @@ -39,10 +41,20 @@ layout (location = 1) in vec2 vUv; out vec2 fUv; +#if FXAA_ENABLED + out FXAACoords sceneFxaaCoords; +#endif + + void main() { gl_Position = vec4(vPos, 0, 1); fUv = vec2(vUv.x, 1.0 - vUv.y); + #if FXAA_ENABLED + vec2 sceneFragCoord = (vec2(fUv.x, 1.0 - fUv.y) * vec2(targetDimensions)) - sceneViewport.xy; + sceneFxaaCoords = fxaa_coords(sceneFragCoord, sceneViewport.zw); + #endif + #if UI_SCALING_MODE == UI_SCALING_MODE_XBR xbrTable = xbr_vert(fUv, sourceDimensions); #endif diff --git a/src/main/resources/rs117/hd/uniforms/ui.glsl b/src/main/resources/rs117/hd/uniforms/ui.glsl index f9165984b8..4e20b1fb5b 100644 --- a/src/main/resources/rs117/hd/uniforms/ui.glsl +++ b/src/main/resources/rs117/hd/uniforms/ui.glsl @@ -1,6 +1,7 @@ #pragma once layout(std140) uniform UBOUI { + ivec4 sceneViewport; ivec2 sourceDimensions; ivec2 targetDimensions; vec4 alphaOverlay; diff --git a/src/main/resources/rs117/hd/utils/constants.glsl b/src/main/resources/rs117/hd/utils/constants.glsl index 1ef390944e..326f642ced 100644 --- a/src/main/resources/rs117/hd/utils/constants.glsl +++ b/src/main/resources/rs117/hd/utils/constants.glsl @@ -55,6 +55,8 @@ #define SHADOW_DEFAULT_OPACITY_THRESHOLD 0.71 // Lowest while keeping Prifddinas glass walkways transparent #endif +#include UI_SCALING_MODE +#include FXAA_ENABLED #include VANILLA_COLOR_BANDING #include UNDO_VANILLA_SHADING #include LEGACY_GREY_COLORS diff --git a/src/main/resources/rs117/hd/utils/fxaa.glsl b/src/main/resources/rs117/hd/utils/fxaa.glsl new file mode 100644 index 0000000000..14a03af3a7 --- /dev/null +++ b/src/main/resources/rs117/hd/utils/fxaa.glsl @@ -0,0 +1,136 @@ +#pragma once + +/** +From: +https://github.com/mitsuhiko/webgl-meincraft + +Copyright (c) 2011 by Armin Ronacher. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#if GL_ARB_gpu_shader5 + #define FXAA_TEX_GATHER 1 +#endif + +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 4.0 +#endif + +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0/FXAA_SPAN_MAX) +#endif + +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/128.0) +#endif + +#define FXAA_LUMA vec3(0.299, 0.587, 0.114) + +struct FXAACoords { +#if !FXAA_TEX_GATHER + vec2 rgbNW; + vec2 rgbNE; + vec2 rgbSW; + vec2 rgbSE; +#endif + vec2 rgbM; +}; + +FXAACoords fxaa_coords(vec2 fragCoord, vec2 resolution) { + vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); + FXAACoords coords; +#if !FXAA_TEX_GATHER + coords.rgbNW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; + coords.rgbNE = (fragCoord + vec2( 1.0, 1.0)) * inverseVP; + coords.rgbSW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; + coords.rgbSE = (fragCoord + vec2( 1.0, -1.0)) * inverseVP; +#endif + coords.rgbM = fragCoord * inverseVP; + return coords; +} + +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, FXAACoords coords) { + vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); + vec2 snappedM = (floor(fragCoord) + 0.5) * inverseVP; + + #if FXAA_TEX_GATHER + // Three textureGather calls replace four corner texture2D calls. + // Each gathers one channel from the 2x2 quad centred on rgbM. + vec4 gR = textureGather(tex, snappedM, 0); + vec4 gG = textureGather(tex, snappedM, 1); + vec4 gB = textureGather(tex, snappedM, 2); + + vec3 rgbNW = vec3(gR.w, gG.w, gB.w); + vec3 rgbNE = vec3(gR.z, gG.z, gB.z); + vec3 rgbSW = vec3(gR.x, gG.x, gB.x); + vec3 rgbSE = vec3(gR.y, gG.y, gB.y); + #else + vec3 rgbNW = textureLod(tex, coords.rgbNW, 0.0).xyz; + vec3 rgbNE = textureLod(tex, coords.rgbNE, 0.0).xyz; + vec3 rgbSW = textureLod(tex, coords.rgbSW, 0.0).xyz; + vec3 rgbSE = textureLod(tex, coords.rgbSE, 0.0).xyz; + #endif + + vec4 texColor = textureLod(tex, snappedM, 0.0); + float lumaNW = dot(rgbNW, FXAA_LUMA); + float lumaNE = dot(rgbNE, FXAA_LUMA); + float lumaSW = dot(rgbSW, FXAA_LUMA); + float lumaSE = dot(rgbSE, FXAA_LUMA); + float lumaM = dot(texColor.rgb, FXAA_LUMA); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + textureLod(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + + textureLod(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5), 0.0).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + textureLod(tex, fragCoord * inverseVP + dir * -0.5, 0.0).xyz + + textureLod(tex, fragCoord * inverseVP + dir * 0.5, 0.0).xyz); + + float lumaB = dot(rgbB, FXAA_LUMA); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + return vec4(rgbA, texColor.a); + + return vec4(rgbB, texColor.a); +} \ No newline at end of file diff --git a/src/main/resources/rs117/hd/utils/misc.glsl b/src/main/resources/rs117/hd/utils/misc.glsl index 6e5406693b..33a96b39a8 100644 --- a/src/main/resources/rs117/hd/utils/misc.glsl +++ b/src/main/resources/rs117/hd/utils/misc.glsl @@ -189,6 +189,17 @@ vec4 saturate(vec4 value) { return clamp(value, vec4(0.0), vec4(1.0)); } +bool contains(vec2 value, vec2 min, vec2 max) { + return value.x >= min.x && value.x < max.x && + value.y >= min.y && value.y < max.y; +} + +bool contains(vec3 value, vec3 min, vec3 max) { + return value.x >= min.x && value.x < max.x && + value.y >= min.y && value.y < max.y && + value.z >= min.z && value.z < max.z; +} + #define POISSON_DISK_LENGTH 16 vec2 getPoissonDisk(int idx) { switch(idx) {