From 246b0f8a863d3e1973628c2ef58f967a32ec5c87 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 28 Dec 2020 20:52:49 -0500 Subject: [PATCH] gpu: draw full screen widgets on gpu This adjusts the draw callbacks api to take in the color of the full screen overlay the client would have rendered. This is primarily used in godwars, underwater, darkmeyer, etc. Having them rasterized on the cpu is slow, especially with gpu on since we additionally have to compute the alpha per-pixel. --- .../net/runelite/api/hooks/DrawCallbacks.java | 7 ++++++- .../runelite/client/plugins/gpu/GpuPlugin.java | 18 +++++++++++++----- .../runelite/client/plugins/gpu/fragui.glsl | 11 +++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/hooks/DrawCallbacks.java b/runelite-api/src/main/java/net/runelite/api/hooks/DrawCallbacks.java index 989cc45dd2..7cf7469f37 100644 --- a/runelite-api/src/main/java/net/runelite/api/hooks/DrawCallbacks.java +++ b/runelite-api/src/main/java/net/runelite/api/hooks/DrawCallbacks.java @@ -43,7 +43,12 @@ public interface DrawCallbacks SceneTileModel model, int tileZ, int tileX, int tileY, int zoom, int centerX, int centerY); - void draw(); + /** + * Called when a frame should be drawn. + * + * @param overlayColor Color of full-viewport overlays, if any + */ + void draw(int overlayColor); boolean drawFace(Model model, int face); 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 2d3b0c78d4..e82373edd5 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 @@ -264,6 +264,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private int uniTexSamplingMode; private int uniTexSourceDimensions; private int uniTexTargetDimensions; + private int uniUiAlphaOverlay; private int uniTextures; private int uniTextureOffsets; private int uniBlockSmall; @@ -545,6 +546,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks uniTexTargetDimensions = gl.glGetUniformLocation(glUiProgram, "targetDimensions"); uniTexSourceDimensions = gl.glGetUniformLocation(glUiProgram, "sourceDimensions"); uniUiColorBlindMode = gl.glGetUniformLocation(glUiProgram, "colorBlindMode"); + uniUiAlphaOverlay = gl.glGetUniformLocation(glUiProgram, "alphaOverlay"); uniTextures = gl.glGetUniformLocation(glProgram, "textures"); uniTextureOffsets = gl.glGetUniformLocation(glProgram, "textureOffsets"); @@ -855,9 +857,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } @Override - public void draw() + public void draw(int overlayColor) { - invokeOnMainThread(this::drawFrame); + invokeOnMainThread(() -> drawFrame(overlayColor)); } private void resize(int canvasWidth, int canvasHeight, int viewportWidth, int viewportHeight) @@ -883,7 +885,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } } - private void drawFrame() + private void drawFrame(int overlayColor) { if (jawtWindow.getAWTComponent() != client.getCanvas()) { @@ -1208,7 +1210,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks tempUvOffset = 0; // Texture on UI - drawUi(canvasHeight, canvasWidth); + drawUi(overlayColor, canvasHeight, canvasWidth); glDrawable.swapBuffers(); @@ -1226,7 +1228,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks }; } - private void drawUi(final int canvasHeight, final int canvasWidth) + private void drawUi(final int overlayColor, final int canvasHeight, final int canvasWidth) { final BufferProvider bufferProvider = client.getBufferProvider(); final int[] pixels = bufferProvider.getPixels(); @@ -1254,6 +1256,12 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glUniform1i(uniTexSamplingMode, uiScalingMode.getMode()); gl.glUniform2i(uniTexSourceDimensions, canvasWidth, canvasHeight); gl.glUniform1i(uniUiColorBlindMode, config.colorBlindMode().ordinal()); + gl.glUniform4f(uniUiAlphaOverlay, + (overlayColor >> 16 & 0xFF) / 255f, + (overlayColor >> 8 & 0xFF) / 255f, + (overlayColor & 0xFF) / 255f, + (overlayColor >>> 24) / 255f + ); if (client.isStretchedEnabled()) { diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui.glsl index e522d34400..5a54522f83 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/fragui.glsl @@ -34,6 +34,7 @@ uniform int samplingMode; uniform ivec2 sourceDimensions; uniform ivec2 targetDimensions; uniform int colorBlindMode; +uniform vec4 alphaOverlay; #include scale/bicubic.glsl #include scale/xbr_lv2_frag.glsl @@ -44,6 +45,13 @@ in XBRTable xbrTable; out vec4 FragColor; +vec4 alphaBlend(vec4 src, vec4 dst) { + return vec4( + src.rgb + dst.rgb * (1.0f - src.a), + src.a + dst.a * (1.0f - src.a) + ); +} + void main() { vec4 c; @@ -51,14 +59,17 @@ void main() { case SAMPLING_CATROM: case SAMPLING_MITCHELL: c = textureCubic(tex, TexCoord, samplingMode); + c = alphaBlend(c, alphaOverlay); c.rgb = colorblind(colorBlindMode, c.rgb); break; case SAMPLING_XBR: c = textureXBR(tex, TexCoord, xbrTable, ceil(1.0 * targetDimensions.x / sourceDimensions.x)); + c = alphaBlend(c, alphaOverlay); c.rgb = colorblind(colorBlindMode, c.rgb); break; default: // NEAREST or LINEAR, which uses GL_TEXTURE_MIN_FILTER/GL_TEXTURE_MAG_FILTER to affect sampling c = texture(tex, TexCoord); + c = alphaBlend(c, alphaOverlay); c.rgb = colorblind(colorBlindMode, c.rgb); }