gpu: move texture animation to gpu

This commit is contained in:
Adam
2022-03-01 22:02:44 -05:00
parent 3ad8452d41
commit 2520da4dca
4 changed files with 66 additions and 87 deletions

View File

@@ -223,7 +223,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
private int textureArrayId;
private final GLBuffer uniformBuffer = new GLBuffer();
private final float[] textureOffsets = new float[256];
private GpuIntBuffer vertexBuffer;
private GpuFloatBuffer uvBuffer;
@@ -291,12 +290,13 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
private int uniTexTargetDimensions;
private int uniUiAlphaOverlay;
private int uniTextures;
private int uniTextureOffsets;
private int uniTextureAnimations;
private int uniBlockSmall;
private int uniBlockLarge;
private int uniBlockMain;
private int uniSmoothBanding;
private int uniTextureLightMode;
private int uniTick;
private int needsReset;
@@ -665,6 +665,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
uniDrawDistance = gl.glGetUniformLocation(glProgram, "drawDistance");
uniColorBlindMode = gl.glGetUniformLocation(glProgram, "colorBlindMode");
uniTextureLightMode = gl.glGetUniformLocation(glProgram, "textureLightMode");
uniTick = gl.glGetUniformLocation(glProgram, "tick");
uniTex = gl.glGetUniformLocation(glUiProgram, "tex");
uniTexSamplingMode = gl.glGetUniformLocation(glUiProgram, "samplingMode");
@@ -673,7 +674,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
uniUiColorBlindMode = gl.glGetUniformLocation(glUiProgram, "colorBlindMode");
uniUiAlphaOverlay = gl.glGetUniformLocation(glUiProgram, "alphaOverlay");
uniTextures = gl.glGetUniformLocation(glProgram, "textures");
uniTextureOffsets = gl.glGetUniformLocation(glProgram, "textureOffsets");
uniTextureAnimations = gl.glGetUniformLocation(glProgram, "textureAnimations");
uniBlockSmall = gl.glGetUniformBlockIndex(glSmallComputeProgram, "uniforms");
uniBlockLarge = gl.glGetUniformBlockIndex(glComputeProgram, "uniforms");
@@ -1222,18 +1223,25 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
gl.glClear(gl.GL_COLOR_BUFFER_BIT);
// Draw 3d scene
final TextureProvider textureProvider = client.getTextureProvider();
final GameState gameState = client.getGameState();
if (textureProvider != null && gameState.getState() >= GameState.LOADING.getState())
if (gameState.getState() >= GameState.LOADING.getState())
{
final TextureProvider textureProvider = client.getTextureProvider();
if (textureArrayId == -1)
{
// lazy init textures as they may not be loaded at plugin start.
// this will return -1 and retry if not all textures are loaded yet, too.
textureArrayId = textureManager.initTextureArray(textureProvider, gl);
if (textureArrayId > -1)
{
// if texture upload is successful, compute and set texture animations
float[] texAnims = textureManager.computeTextureAnimations(textureProvider);
gl.glUseProgram(glProgram);
gl.glUniform2fv(uniTextureAnimations, texAnims.length, texAnims, 0);
gl.glUseProgram(0);
}
}
final Texture[] textures = textureProvider.getTextures();
int renderWidthOff = viewportOffsetX;
int renderHeightOff = viewportOffsetY;
int renderCanvasHeight = canvasHeight;
@@ -1285,6 +1293,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
gl.glUniform1f(uniSmoothBanding, config.smoothBanding() ? 0f : 1f);
gl.glUniform1i(uniColorBlindMode, config.colorBlindMode().ordinal());
gl.glUniform1f(uniTextureLightMode, config.brightTextures() ? 1f : 0f);
gl.glUniform1i(uniTick, client.getGameCycle());
// Calculate projection matrix
Matrix4 projectionMatrix = new Matrix4();
@@ -1295,24 +1304,9 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
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];
if (texture == null)
{
continue;
}
textureProvider.load(id); // trips the texture load flag which lets textures animate
textureOffsets[id * 2] = texture.getU();
textureOffsets[id * 2 + 1] = texture.getV();
}
// Bind uniforms
gl.glUniformBlockBinding(glProgram, uniBlockMain, 0);
gl.glUniform1i(uniTextures, 1); // texture sampler array is bound to texture1
gl.glUniform2fv(uniTextureOffsets, textureOffsets.length, textureOffsets, 0);
// We just allow the GL to do face culling. Note this requires the priority renderer
// to have logic to disregard culled faces in the priority depth testing.
@@ -1518,7 +1512,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
@Override
public void animate(Texture texture, int diff)
{
textureManager.animate(texture, diff);
// texture animation happens on gpu
}
@Subscribe

View File

@@ -35,9 +35,6 @@ import net.runelite.api.TextureProvider;
@Slf4j
class TextureManager
{
private static final float PERC_64 = 1f / 64f;
private static final float PERC_128 = 1f / 128f;
private static final int TEXTURE_SIZE = 128;
int initTextureArray(TextureProvider textureProvider, GL4 gl)
@@ -207,64 +204,40 @@ class TextureManager
return pixels;
}
/**
* Animate the given texture
*
* @param texture
* @param diff Number of elapsed client ticks since last animation
*/
void animate(Texture texture, int diff)
float[] computeTextureAnimations(TextureProvider textureProvider)
{
final int[] pixels = texture.getPixels();
if (pixels == null)
Texture[] textures = textureProvider.getTextures();
float[] anims = new float[TEXTURE_SIZE * 2];
int idx = 0;
for (Texture texture : textures)
{
return;
if (texture != null)
{
float u = 0f, v = 0f;
switch (texture.getAnimationDirection())
{
case 1:
v = -1f;
break;
case 3:
v = 1f;
break;
case 2:
u = -1f;
break;
case 4:
u = 1f;
break;
}
int speed = texture.getAnimationSpeed();
u *= speed;
v *= speed;
anims[idx++] = u;
anims[idx++] = v;
}
}
final int animationSpeed = texture.getAnimationSpeed();
final float uvdiff = pixels.length == 4096 ? PERC_64 : PERC_128;
float u = texture.getU();
float v = texture.getV();
int offset = animationSpeed * diff;
float d = (float) offset * uvdiff;
switch (texture.getAnimationDirection())
{
case 1:
v -= d;
if (v < 0f)
{
v += 1f;
}
break;
case 3:
v += d;
if (v > 1f)
{
v -= 1f;
}
break;
case 2:
u -= d;
if (u < 0f)
{
u += 1f;
}
break;
case 4:
u += d;
if (u > 1f)
{
u -= 1f;
}
break;
default:
return;
}
texture.setU(u);
texture.setV(v);
return anims;
}
}

View File

@@ -25,7 +25,6 @@
#version 330
uniform sampler2DArray textures;
uniform vec2 textureOffsets[128];
uniform float brightness;
uniform float smoothBanding;
uniform vec4 fogColor;
@@ -49,9 +48,7 @@ void main() {
if (textureId > 0) {
int textureIdx = textureId - 1;
vec2 animatedUv = fUv + textureOffsets[textureIdx];
vec4 textureColor = texture(textures, vec3(animatedUv, float(textureIdx)));
vec4 textureColor = texture(textures, vec3(fUv, float(textureIdx)));
vec4 textureColorBrightness = pow(textureColor, vec4(brightness, brightness, brightness, 1.0f));
// textured triangles hsl is a 7 bit lightness 2-126

View File

@@ -27,6 +27,10 @@
#define TILE_SIZE 128
// smallest unit of the texture which can be moved per tick. textures are all
// 128x128px - so this is equivalent to +1px
#define TEXTURE_ANIM_UNIT (1.0f / 128.0f)
#define FOG_SCENE_EDGE_MIN TILE_SIZE
#define FOG_SCENE_EDGE_MAX (103 * TILE_SIZE)
#define FOG_CORNER_ROUNDING 1.5
@@ -52,6 +56,8 @@ uniform int useFog;
uniform int fogDepth;
uniform int drawDistance;
uniform mat4 projectionMatrix;
uniform vec2 textureAnimations[128];
uniform int tick;
out vec4 Color;
noperspective centroid out float fHsl;
@@ -77,8 +83,17 @@ void main()
gl_Position = projectionMatrix * vec4(vertex, 1.f);
Color = vec4(rgb, 1.f - a);
fHsl = float(hsl);
textureId = int(uv.x);
fUv = uv.yz;
int textureIdx = int(uv.x); // the texture id + 1
vec2 textureUv = uv.yz;
vec2 textureAnim = vec2(0);
if (textureIdx > 0) {
textureAnim = textureAnimations[textureIdx - 1];
}
textureId = textureIdx;
fUv = textureUv + tick * textureAnim * TEXTURE_ANIM_UNIT;
int fogWest = max(FOG_SCENE_EDGE_MIN, cameraX - drawDistance);
int fogEast = min(FOG_SCENE_EDGE_MAX, cameraX + drawDistance - TILE_SIZE);