From 8c00f6da8847f45b7dac4ba0537cf54a218762d2 Mon Sep 17 00:00:00 2001 From: Runemoro Date: Tue, 22 Sep 2020 08:02:27 -0400 Subject: [PATCH] gpu: replace toScreen function with a projection matrix The face sorting still requires the toScreen function to match exactly the same order that would be computed on CPU, but for the projection for rendering we can simplify it by replacing it with a projection matrix. This also drops the requirement of having a geometry shader to remove faces too close to or behind the camera. Upon closer inspection it looks like the client can draw faces which have at least one vertex which is >= 50 from the camera, so this now more accurately reflects the software renderer. Co-authored-by: Adam --- .../java/net/runelite/api/Perspective.java | 2 +- .../client/plugins/gpu/GpuPlugin.java | 51 ++++------ .../net/runelite/client/plugins/gpu/geom.glsl | 97 ------------------- .../net/runelite/client/plugins/gpu/vert.glsl | 20 ++-- 4 files changed, 32 insertions(+), 138 deletions(-) delete mode 100644 runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl diff --git a/runelite-api/src/main/java/net/runelite/api/Perspective.java b/runelite-api/src/main/java/net/runelite/api/Perspective.java index a248f9e0bb..ad052e27db 100644 --- a/runelite-api/src/main/java/net/runelite/api/Perspective.java +++ b/runelite-api/src/main/java/net/runelite/api/Perspective.java @@ -49,7 +49,7 @@ import net.runelite.api.widgets.WidgetInfo; */ public class Perspective { - private static final double UNIT = Math.PI / 1024d; // How much of the circle each unit of SINE/COSINE is + public static final double UNIT = Math.PI / 1024d; // How much of the circle each unit of SINE/COSINE is public static final int LOCAL_COORD_BITS = 7; public static final int LOCAL_TILE_SIZE = 1 << LOCAL_COORD_BITS; // 128 - size of a tile in local coordinates 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 3d751d9427..60cb6b2f8b 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 @@ -37,6 +37,7 @@ import com.jogamp.opengl.GLDrawableFactory; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLFBODrawable; import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.math.Matrix4; import java.awt.Canvas; import java.awt.Dimension; import java.awt.Graphics2D; @@ -57,7 +58,6 @@ import jogamp.newt.awt.NewtFactoryAWT; import lombok.extern.slf4j.Slf4j; import net.runelite.api.BufferProvider; import net.runelite.api.Client; -import net.runelite.api.Constants; import net.runelite.api.GameState; import net.runelite.api.Model; import net.runelite.api.NodeCache; @@ -150,7 +150,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks static final Shader PROGRAM = new Shader() .add(GL4.GL_VERTEX_SHADER, "vert.glsl") - .add(GL4.GL_GEOMETRY_SHADER, "geom.glsl") .add(GL4.GL_FRAGMENT_SHADER, "frag.glsl"); static final Shader COMPUTE_PROGRAM = new Shader() @@ -768,26 +767,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks } } - private void createProjectionMatrix(float left, float right, float bottom, float top, float near, float far) - { - // create a standard orthographic projection - float tx = -((right + left) / (right - left)); - float ty = -((top + bottom) / (top - bottom)); - float tz = -((far + near) / (far - near)); - - gl.glUseProgram(glProgram); - - float[] matrix = new float[]{ - 2 / (right - left), 0, 0, 0, - 0, 2 / (top - bottom), 0, 0, - 0, 0, -2 / (far - near), 0, - tx, ty, tz, 1 - }; - gl.glUniformMatrix4fv(uniProjectionMatrix, 1, false, matrix, 0); - - gl.glUseProgram(0); - } - @Override public void drawScene(int cameraX, int cameraY, int cameraZ, int cameraPitch, int cameraYaw, int plane) { @@ -879,14 +858,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks private void resize(int canvasWidth, int canvasHeight, int viewportWidth, int viewportHeight) { - // If the viewport has changed, update the projection matrix - if (viewportWidth > 0 && viewportHeight > 0 && (viewportWidth != lastViewportWidth || viewportHeight != lastViewportHeight)) - { - lastViewportWidth = viewportWidth; - lastViewportHeight = viewportHeight; - createProjectionMatrix(0, viewportWidth, viewportHeight, 0, 0, Constants.SCENE_SIZE * Perspective.LOCAL_TILE_SIZE); - } - if (canvasWidth != lastCanvasWidth || canvasHeight != lastCanvasHeight) { lastCanvasWidth = canvasWidth; @@ -1151,6 +1122,15 @@ public class GpuPlugin extends Plugin implements DrawCallbacks gl.glUniform1f(uniBrightness, (float) textureProvider.getBrightness()); gl.glUniform1f(uniSmoothBanding, config.smoothBanding() ? 0f : 1f); + // Calculate projection matrix + Matrix4 projectionMatrix = new Matrix4(); + projectionMatrix.scale(client.getScale(), client.getScale(), 1); + projectionMatrix.multMatrix(makeProjectionMatrix(viewportWidth, viewportHeight, 50)); + projectionMatrix.rotate((float) (Math.PI - pitch * Perspective.UNIT), -1, 0, 0); + projectionMatrix.rotate((float) (yaw * Perspective.UNIT), 0, 1, 0); + projectionMatrix.translate(-client.getCameraX2(), -client.getCameraY2(), -client.getCameraZ2()); + gl.glUniformMatrix4fv(uniProjectionMatrix, 1, false, projectionMatrix.getMatrix(), 0); + for (int id = 0; id < textures.length; ++id) { Texture texture = textures[id]; @@ -1230,6 +1210,17 @@ public class GpuPlugin extends Plugin implements DrawCallbacks drawManager.processDrawComplete(this::screenshot); } + private float[] makeProjectionMatrix(float w, float h, float n) + { + return new float[] + { + 2 / w, 0, 0, 0, + 0, 2 / h, 0, 0, + 0, 0, -1, -1, + 0, 0, -2 * n, 0 + }; + } + private void drawUi(final int canvasHeight, final int canvasWidth) { final BufferProvider bufferProvider = client.getBufferProvider(); diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl deleted file mode 100644 index 0f7f1bad23..0000000000 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/geom.glsl +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 - -#define PI 3.1415926535897932384626433832795f -#define UNIT PI / 1024.0f - -layout(triangles) in; -layout(triangle_strip, max_vertices = 3) out; - -layout(std140) uniform uniforms { - int cameraYaw; - int cameraPitch; - int centerX; - int centerY; - int zoom; - int cameraX; - int cameraY; - int cameraZ; - ivec2 sinCosTable[2048]; -}; - -uniform mat4 projectionMatrix; - -in ivec3 vPosition[]; -in vec4 vColor[]; -in float vHsl[]; -in vec4 vUv[]; -in float vFogAmount[]; - -out vec4 Color; -centroid out float fHsl; -out vec4 fUv; -out float fogAmount; - -#include to_screen.glsl - -void main() { - ivec3 cameraPos = ivec3(cameraX, cameraY, cameraZ); - vec3 screenA = toScreen(vPosition[0] - cameraPos, cameraYaw, cameraPitch, centerX, centerY, zoom); - vec3 screenB = toScreen(vPosition[1] - cameraPos, cameraYaw, cameraPitch, centerX, centerY, zoom); - vec3 screenC = toScreen(vPosition[2] - cameraPos, cameraYaw, cameraPitch, centerX, centerY, zoom); - - if (-screenA.z < 50 || -screenB.z < 50 || -screenC.z < 50) { - // the client does not draw a triangle if any vertex distance is <50 - return; - } - - vec4 tmp = vec4(screenA.xyz, 1.0); - Color = vColor[0]; - fHsl = vHsl[0]; - fUv = vUv[0]; - fogAmount = vFogAmount[0]; - gl_Position = projectionMatrix * tmp; - EmitVertex(); - - tmp = vec4(screenB.xyz, 1.0); - Color = vColor[1]; - fHsl = vHsl[1]; - fUv = vUv[1]; - fogAmount = vFogAmount[1]; - gl_Position = projectionMatrix * tmp; - EmitVertex(); - - tmp = vec4(screenC.xyz, 1.0); - Color = vColor[2]; - fHsl = vHsl[2]; - fUv = vUv[2]; - fogAmount = vFogAmount[2]; - gl_Position = projectionMatrix * tmp; - EmitVertex(); - - EndPrimitive(); -} diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/vert.glsl b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/vert.glsl index 642aa688eb..ef2080d8d7 100644 --- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/vert.glsl +++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/vert.glsl @@ -51,12 +51,12 @@ uniform float brightness; uniform int useFog; uniform int fogDepth; uniform int drawDistance; +uniform mat4 projectionMatrix; -out ivec3 vPosition; -out vec4 vColor; -out float vHsl; -out vec4 vUv; -out float vFogAmount; +out vec4 Color; +centroid out float fHsl; +out vec4 fUv; +out float fogAmount; #include hsl_to_rgb.glsl @@ -73,10 +73,10 @@ void main() vec3 rgb = hslToRgb(hsl); - vPosition = vertex; - vColor = vec4(rgb, 1.f - a); - vHsl = float(hsl); - vUv = uv; + gl_Position = projectionMatrix * vec4(vertex, 1.f); + Color = vec4(rgb, 1.f - a); + fHsl = float(hsl); + fUv = uv; int fogWest = max(FOG_SCENE_EDGE_MIN, cameraX - drawDistance); int fogEast = min(FOG_SCENE_EDGE_MAX, cameraX + drawDistance - TILE_SIZE); @@ -92,5 +92,5 @@ void main() max(0, (nearestEdgeDistance + FOG_CORNER_ROUNDING_SQUARED) / (secondNearestEdgeDistance + FOG_CORNER_ROUNDING_SQUARED)); - vFogAmount = fogFactorLinear(fogDistance, 0, fogDepth * TILE_SIZE) * useFog; + fogAmount = fogFactorLinear(fogDistance, 0, fogDepth * TILE_SIZE) * useFog; }