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 <Adam@sigterm.info>
This commit is contained in:
Runemoro
2020-09-22 08:02:27 -04:00
committed by Adam
parent 1777b2d6bd
commit 8c00f6da88
4 changed files with 32 additions and 138 deletions

View File

@@ -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();