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

View File

@@ -35,9 +35,6 @@ import net.runelite.api.TextureProvider;
@Slf4j @Slf4j
class TextureManager 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; private static final int TEXTURE_SIZE = 128;
int initTextureArray(TextureProvider textureProvider, GL4 gl) int initTextureArray(TextureProvider textureProvider, GL4 gl)
@@ -207,64 +204,40 @@ class TextureManager
return pixels; return pixels;
} }
/** float[] computeTextureAnimations(TextureProvider textureProvider)
* Animate the given texture
*
* @param texture
* @param diff Number of elapsed client ticks since last animation
*/
void animate(Texture texture, int diff)
{ {
final int[] pixels = texture.getPixels(); Texture[] textures = textureProvider.getTextures();
if (pixels == null) 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;
}
} }
return anims;
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);
} }
} }

View File

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

View File

@@ -27,6 +27,10 @@
#define TILE_SIZE 128 #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_MIN TILE_SIZE
#define FOG_SCENE_EDGE_MAX (103 * TILE_SIZE) #define FOG_SCENE_EDGE_MAX (103 * TILE_SIZE)
#define FOG_CORNER_ROUNDING 1.5 #define FOG_CORNER_ROUNDING 1.5
@@ -52,6 +56,8 @@ uniform int useFog;
uniform int fogDepth; uniform int fogDepth;
uniform int drawDistance; uniform int drawDistance;
uniform mat4 projectionMatrix; uniform mat4 projectionMatrix;
uniform vec2 textureAnimations[128];
uniform int tick;
out vec4 Color; out vec4 Color;
noperspective centroid out float fHsl; noperspective centroid out float fHsl;
@@ -77,8 +83,17 @@ void main()
gl_Position = projectionMatrix * vec4(vertex, 1.f); gl_Position = projectionMatrix * vec4(vertex, 1.f);
Color = vec4(rgb, 1.f - a); Color = vec4(rgb, 1.f - a);
fHsl = float(hsl); 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 fogWest = max(FOG_SCENE_EDGE_MIN, cameraX - drawDistance);
int fogEast = min(FOG_SCENE_EDGE_MAX, cameraX + drawDistance - TILE_SIZE); int fogEast = min(FOG_SCENE_EDGE_MAX, cameraX + drawDistance - TILE_SIZE);