From ea203e8ca5af6b34c4c5b4425c5fec2c4e8481de Mon Sep 17 00:00:00 2001 From: logarithm Date: Thu, 28 Nov 2019 13:40:17 +0200 Subject: [PATCH] GPU: Catmull-Rom bicubic scaled UI in non-fast stretched mode --- .../client/plugins/gpu/GpuPlugin.java | 32 +++++- .../client/plugins/gpu/fragui_bicubic.glsl | 98 +++++++++++++++++++ 2 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui_bicubic.glsl 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 66e0977b32..db724195f4 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 @@ -145,6 +145,10 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int glUiVertexShader; private int glUiFragmentShader; + private int glUiBicubicProgram; + private int glUiBicubicVertexShader; + private int glUiBicubicFragmentShader; + private int vaoUiHandle; private int vboUiHandle; @@ -218,6 +222,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int uniProjectionMatrix; private int uniBrightness; private int uniTex; + private int uniTexBicubic; private int uniTextures; private int uniTextureOffsets; private int uniBlockSmall; @@ -504,6 +509,15 @@ public class GpuPlugin extends Plugin implements DrawCallbacks null, inputStreamToString(getClass().getResourceAsStream("fragui.glsl"))); + glUiBicubicProgram = gl.glCreateProgram(); + glUiBicubicVertexShader = gl.glCreateShader(gl.GL_VERTEX_SHADER); + glUiBicubicFragmentShader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER); + GLUtil.loadShaders(gl, glUiBicubicProgram, glUiBicubicVertexShader, -1, glUiBicubicFragmentShader, + inputStreamToString(getClass().getResourceAsStream("vertui.glsl")), + null, + inputStreamToString(getClass().getResourceAsStream("fragui_bicubic.glsl"))); + + initUniforms(); } @@ -518,6 +532,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks uniDrawDistance = gl.glGetUniformLocation(glProgram, "drawDistance"); uniTex = gl.glGetUniformLocation(glUiProgram, "tex"); + uniTexBicubic = gl.glGetUniformLocation(glUiBicubicProgram, "tex"); uniTextures = gl.glGetUniformLocation(glProgram, "textures"); uniTextureOffsets = gl.glGetUniformLocation(glProgram, "textureOffsets"); @@ -570,6 +585,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glDeleteProgram(glUiProgram); glUiProgram = -1; + + gl.glDeleteProgram(glUiBicubicProgram); + glUiBicubicProgram = -1; } private void initVao() @@ -1163,15 +1181,23 @@ public class GpuPlugin extends Plugin implements DrawCallbacks glDpiAwareViewport(0, 0, canvasWidth, canvasHeight); } - // Use the texture bound in the first pass - gl.glUseProgram(glUiProgram); - gl.glUniform1i(uniTex, 0); + if (client.isStretchedEnabled() && !client.isStretchedFast()) { + // Use the texture bound in the first pass + gl.glUseProgram(glUiBicubicProgram); + gl.glUniform1i(uniTexBicubic, 0); + } + else { + // Use the texture bound in the first pass + gl.glUseProgram(glUiProgram); + gl.glUniform1i(uniTex, 0); + } // Set the sampling function used when stretching the UI. // This is probably better done with sampler objects instead of texture parameters, but this is easier and likely more portable. // See https://www.khronos.org/opengl/wiki/Sampler_Object for details. if (client.isStretchedEnabled()) { + // This needs adjustments if we want to give the option of linear sampling in fast mode, now that slow mode is actually a more demanding sampler final int function = client.isStretchedFast() ? gl.GL_NEAREST : gl.GL_LINEAR; gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, function); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, function); diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui_bicubic.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui_bicubic.glsl new file mode 100644 index 0000000000..29780650a6 --- /dev/null +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui_bicubic.glsl @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018, Adam + * 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. + */ +#version 330 + +uniform sampler2D tex; + +in vec2 TexCoord; + +out vec4 FragColor; + +float CatmullRom( float x ) +{ + const float B = 0.0; + const float C = 0.5; + + float f = abs(x); + float f2 = f * f; + float f3 = f * f * f; + + if (f >= 2) { + return 0.0; + } + + if ( f < 1.0 ) { + return ( + ( 12 - 9 * B - 6 * C ) * f3 + + ( -18 + 12 * B + 6 *C ) * f2 + + ( 6 - 2 * B ) + ) / 6.0; + } + else { + return ( + ( -B - 6 * C ) * f3 + + ( 6 * B + 30 * C ) * f2 + + ( - ( 12 * B ) - 48 * C ) * f + + 8 * B + 24 * C + ) / 6.0; + } +} + +vec4 textureBicubic(sampler2D sampler, vec2 texCoords){ + vec2 texSize = textureSize(tex, 0); + vec2 texelSize = 1.0 / texSize; + texCoords *= texSize; + texCoords -= 0.5; + + vec4 nSum = vec4( 0.0, 0.0, 0.0, 0.0 ); + vec4 nDenom = vec4( 0.0, 0.0, 0.0, 0.0 ); + + ivec2 texelCoords = ivec2(floor(texCoords)); + vec2 fxy = fract(texCoords); + + for (int m = -1; m <= 2; m++) + { + for (int n = -1; n <= 2; n++) + { + vec4 vecData = texelFetch( + sampler, + texelCoords + ivec2(m, n), + 0 + ); + + float cx = CatmullRom( m - fxy.x ); + float cy = CatmullRom( n - fxy.y ); + + nSum += vecData * cx * cy; + nDenom += cx * cy; + } + } + return nSum / nDenom; +} + +void main() { + vec4 c = textureBicubic(tex, TexCoord); + FragColor = c; +} \ No newline at end of file