From d5fae8603ba6fe2a1ca6b6622a794699c2b9a4a2 Mon Sep 17 00:00:00 2001 From: Lotto <8920674+devLotto@users.noreply.github.com> Date: Mon, 3 Dec 2018 01:35:24 +0100 Subject: [PATCH] gpu: add scene anti-aliasing --- .../client/plugins/gpu/GpuPlugin.java | 107 ++++++++++++++++++ .../client/plugins/gpu/GpuPluginConfig.java | 12 ++ .../plugins/gpu/config/AntiAliasingMode.java | 48 ++++++++ 3 files changed, 167 insertions(+) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/gpu/config/AntiAliasingMode.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index bbbb430fe6..dfcdf67309 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -73,13 +73,16 @@ import net.runelite.client.plugins.PluginInstantiationException; import net.runelite.client.plugins.PluginManager; import static net.runelite.client.plugins.gpu.GLUtil.glDeleteBuffer; import static net.runelite.client.plugins.gpu.GLUtil.glDeleteFrameBuffer; +import static net.runelite.client.plugins.gpu.GLUtil.glDeleteRenderbuffers; import static net.runelite.client.plugins.gpu.GLUtil.glDeleteTexture; import static net.runelite.client.plugins.gpu.GLUtil.glDeleteVertexArrays; import static net.runelite.client.plugins.gpu.GLUtil.glGenBuffers; import static net.runelite.client.plugins.gpu.GLUtil.glGenFrameBuffer; +import static net.runelite.client.plugins.gpu.GLUtil.glGenRenderbuffer; import static net.runelite.client.plugins.gpu.GLUtil.glGenTexture; import static net.runelite.client.plugins.gpu.GLUtil.glGenVertexArrays; import static net.runelite.client.plugins.gpu.GLUtil.inputStreamToString; +import net.runelite.client.plugins.gpu.config.AntiAliasingMode; import net.runelite.client.plugins.gpu.template.Template; import net.runelite.client.ui.DrawManager; @@ -153,6 +156,10 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int vaoUiHandle; private int vboUiHandle; + private int fboSceneHandle; + private int texSceneHandle; + private int rboSceneHandle; + private int fboUiHandle; private int texUiHandle; @@ -205,6 +212,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int lastViewportHeight; private int lastCanvasWidth; private int lastCanvasHeight; + private int lastStretchedCanvasWidth; + private int lastStretchedCanvasHeight; + private AntiAliasingMode lastAntiAliasingMode; private int centerX; private int centerY; @@ -304,6 +314,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks client.resizeCanvas(); lastViewportWidth = lastViewportHeight = lastCanvasWidth = lastCanvasHeight = -1; + lastStretchedCanvasWidth = lastStretchedCanvasHeight = -1; + lastAntiAliasingMode = null; textureArrayId = -1; @@ -376,6 +388,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks shutdownProgram(); shutdownVao(); shutdownUiFBO(); + shutdownSceneFbo(); } if (jawtWindow != null) @@ -631,6 +644,53 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0); } + private void initSceneFbo(int width, int height, int aaSamples) + { + // Create and bind the FBO + fboSceneHandle = glGenFrameBuffer(gl); + gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fboSceneHandle); + + // Create color render buffer + rboSceneHandle = glGenRenderbuffer(gl); + gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, rboSceneHandle); + gl.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, aaSamples, gl.GL_RGBA, width, height); + gl.glFramebufferRenderbuffer(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_RENDERBUFFER, rboSceneHandle); + + // Create texture + texSceneHandle = glGenTexture(gl); + gl.glBindTexture(gl.GL_TEXTURE_2D_MULTISAMPLE, texSceneHandle); + gl.glTexImage2DMultisample(gl.GL_TEXTURE_2D_MULTISAMPLE, aaSamples, gl.GL_RGBA, width, height, true); + + // Bind texture + gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_2D_MULTISAMPLE, texSceneHandle, 0); + + // Reset + gl.glBindTexture(gl.GL_TEXTURE_2D_MULTISAMPLE, 0); + gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0); + gl.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0); + } + + private void shutdownSceneFbo() + { + if (texSceneHandle != -1) + { + glDeleteTexture(gl, texSceneHandle); + texSceneHandle = -1; + } + + if (fboSceneHandle != -1) + { + glDeleteFrameBuffer(gl, fboSceneHandle); + fboSceneHandle = -1; + } + + if (rboSceneHandle != -1) + { + glDeleteRenderbuffers(gl, rboSceneHandle); + rboSceneHandle = -1; + } + } + private void initUiFBO(int width, int height) { // Create and bind the FBO @@ -790,6 +850,41 @@ public class GpuPlugin extends Plugin implements DrawCallbacks lastViewportHeight = viewportHeight; } + // Setup anti-aliasing + final AntiAliasingMode antiAliasingMode = config.antiAliasingMode(); + final boolean aaEnabled = antiAliasingMode != AntiAliasingMode.DISABLED; + + if (aaEnabled) + { + gl.glEnable(gl.GL_MULTISAMPLE); + + final Dimension stretchedDimensions = client.getStretchedDimensions(); + + final int stretchedCanvasWidth = client.isStretchedEnabled() ? stretchedDimensions.width : canvasWidth; + final int stretchedCanvasHeight = client.isStretchedEnabled() ? stretchedDimensions.height : canvasHeight; + + // Re-create fbo + if (lastStretchedCanvasWidth != stretchedCanvasWidth + || lastStretchedCanvasHeight != stretchedCanvasHeight + || lastAntiAliasingMode != antiAliasingMode) + { + shutdownSceneFbo(); + initSceneFbo(stretchedCanvasWidth, stretchedCanvasHeight, antiAliasingMode.getSamples()); + + lastStretchedCanvasWidth = stretchedCanvasWidth; + lastStretchedCanvasHeight = stretchedCanvasHeight; + } + + gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, fboSceneHandle); + } + else + { + gl.glDisable(gl.GL_MULTISAMPLE); + shutdownSceneFbo(); + } + + lastAntiAliasingMode = antiAliasingMode; + // Clear scene gl.glClear(gl.GL_COLOR_BUFFER_BIT); @@ -1006,6 +1101,18 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glUseProgram(0); } + if (aaEnabled) + { + gl.glBindFramebuffer(gl.GL_READ_FRAMEBUFFER, fboSceneHandle); + gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, 0); + gl.glBlitFramebuffer(0, 0, lastStretchedCanvasWidth, lastStretchedCanvasHeight, + 0, 0, lastStretchedCanvasWidth, lastStretchedCanvasHeight, + gl.GL_COLOR_BUFFER_BIT, gl.GL_NEAREST); + + // Reset + gl.glBindFramebuffer(gl.GL_READ_FRAMEBUFFER, 0); + } + vertexBuffer.clear(); uvBuffer.clear(); modelBuffer.clear(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java index 378f36e0cd..cdfa6ddd05 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java @@ -27,6 +27,7 @@ package net.runelite.client.plugins.gpu; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.plugins.gpu.config.AntiAliasingMode; @ConfigGroup("gpu") public interface GpuPluginConfig extends Config @@ -52,4 +53,15 @@ public interface GpuPluginConfig extends Config { return false; } + + @ConfigItem( + keyName = "antiAliasingMode", + name = "Anti Aliasing", + description = "Configures the anti-aliasing mode", + position = 3 + ) + default AntiAliasingMode antiAliasingMode() + { + return AntiAliasingMode.DISABLED; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/config/AntiAliasingMode.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/config/AntiAliasingMode.java new file mode 100644 index 0000000000..3d1efa2d56 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/config/AntiAliasingMode.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018, Lotto + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. 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. + * + * 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. + */ +package net.runelite.client.plugins.gpu.config; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum AntiAliasingMode +{ + DISABLED("Disabled", 0), + MSAA_2("MSAA x2", 2), + MSAA_4("MSAA x4", 4), + MSAA_8("MSAA x8", 8), + MSAA_16("MSAA x16", 16); + + private final String name; + private final int samples; + + @Override + public String toString() + { + return name; + } +}