diff options
author | Juuz <6596629+Juuxel@users.noreply.github.com> | 2023-03-18 16:25:38 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-18 16:25:38 +0200 |
commit | c3600612a83442eeadf99a1602ab07537b071b66 (patch) | |
tree | 1d88bdedd4c00c332fa4f4e7f78b9c0ee842a2a9 /src/main | |
parent | 91e4e6401089d6dc5b92589fa1fb1501b7217cf0 (diff) | |
download | LibGui-c3600612a83442eeadf99a1602ab07537b071b66.tar.gz LibGui-c3600612a83442eeadf99a1602ab07537b071b66.tar.bz2 LibGui-c3600612a83442eeadf99a1602ab07537b071b66.zip |
Improve tiled NinePatchBackgroundPainter performance (#185)
* Improve tiled NinePatchBackgroundPainter performance
* Use Fabric API's CoreShaderRegistrationCallback
* Switch to LibNinePatch release build
* Rename libgui:tiled -> libgui:tiled_rectangle
* Fix grammar
Diffstat (limited to 'src/main')
7 files changed, 150 insertions, 2 deletions
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiClient.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiClient.java index 6bc69fe..526fe96 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiClient.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiClient.java @@ -30,6 +30,8 @@ public class LibGuiClient implements ClientModInitializer { ClientPlayNetworking.registerGlobalReceiver(ScreenNetworkingImpl.SCREEN_MESSAGE_S2C, (client, networkHandler, buf, responseSender) -> { ScreenNetworkingImpl.handle(client, client.player, buf); }); + + LibGuiShaders.register(); } public static LibGuiConfig loadConfig() { diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiShaders.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiShaders.java new file mode 100644 index 0000000..fbbad66 --- /dev/null +++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/LibGuiShaders.java @@ -0,0 +1,33 @@ +package io.github.cottonmc.cotton.gui.impl.client; + +import net.fabricmc.fabric.api.client.rendering.v1.CoreShaderRegistrationCallback; +import net.minecraft.client.gl.ShaderProgram; +import net.minecraft.client.render.VertexFormats; +import net.minecraft.util.Identifier; + +import io.github.cottonmc.cotton.gui.impl.LibGuiCommon; +import org.jetbrains.annotations.Nullable; + +public final class LibGuiShaders { + private static @Nullable ShaderProgram tiledRectangle; + + static void register() { + CoreShaderRegistrationCallback.EVENT.register(context -> { + // Register our core shaders. + // The tiled rectangle shader is used for performant tiled texture rendering. + context.register(new Identifier(LibGuiCommon.MOD_ID, "tiled_rectangle"), VertexFormats.POSITION, program -> tiledRectangle = program); + }); + } + + private static ShaderProgram assertPresent(ShaderProgram program, String name) { + if (program == null) { + throw new NullPointerException("Shader libgui:" + name + " not initialised!"); + } + + return program; + } + + public static ShaderProgram getTiledRectangle() { + return assertPresent(tiledRectangle, "tiled_rectangle"); + } +} diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchTextureRendererImpl.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchTextureRendererImpl.java index 7161373..9227f94 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchTextureRendererImpl.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NinePatchTextureRendererImpl.java @@ -1,10 +1,20 @@ package io.github.cottonmc.cotton.gui.impl.client; +import com.mojang.blaze3d.systems.RenderCall; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gl.ShaderProgram; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.BufferRenderer; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormat; +import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.Identifier; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; import juuxel.libninepatch.ContextualTextureRenderer; +import org.jetbrains.annotations.Nullable; +import org.joml.Matrix4f; /** * An implementation of LibNinePatch's {@link ContextualTextureRenderer} for identifiers. @@ -16,4 +26,40 @@ public enum NinePatchTextureRendererImpl implements ContextualTextureRenderer<Id public void draw(Identifier texture, MatrixStack matrices, int x, int y, int width, int height, float u1, float v1, float u2, float v2) { ScreenDrawing.texturedRect(matrices, x, y, width, height, texture, u1, v1, u2, v2, 0xFF_FFFFFF); } + + @Override + public void drawTiled(Identifier texture, MatrixStack matrices, int x, int y, int regionWidth, int regionHeight, int tileWidth, int tileHeight, float u1, float v1, float u2, float v2) { + RenderSystem.setShader(LibGuiShaders::getTiledRectangle); + RenderSystem.setShaderTexture(0, texture); + RenderSystem.setShaderColor(1, 1, 1, 1); + Matrix4f positionMatrix = matrices.peek().getPositionMatrix(); + onRenderThread(() -> { + @Nullable ShaderProgram program = RenderSystem.getShader(); + if (program != null) { + program.getUniformOrDefault("LibGuiRectanglePos").set((float) x, (float) y); + program.getUniformOrDefault("LibGuiTileDimensions").set((float) tileWidth, (float) tileHeight); + program.getUniformOrDefault("LibGuiTileUvs").set(u1, v1, u2, v2); + program.getUniformOrDefault("LibGuiPositionMatrix").set(positionMatrix); + } + }); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + RenderSystem.enableBlend(); + buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION); + buffer.vertex(positionMatrix, x, y, 0).next(); + buffer.vertex(positionMatrix, x, y + regionHeight, 0).next(); + buffer.vertex(positionMatrix, x + regionWidth, y + regionHeight, 0).next(); + buffer.vertex(positionMatrix, x + regionWidth, y, 0).next(); + BufferRenderer.drawWithGlobalProgram(buffer.end()); + RenderSystem.disableBlend(); + } + + private static void onRenderThread(RenderCall renderCall) { + if (RenderSystem.isOnRenderThread()) { + renderCall.execute(); + } else { + RenderSystem.recordRenderCall(renderCall); + } + } } diff --git a/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.fsh b/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.fsh new file mode 100644 index 0000000..15e3185 --- /dev/null +++ b/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.fsh @@ -0,0 +1,32 @@ +#version 150 + +uniform sampler2D Sampler0; +uniform vec4 ColorModulator; + +uniform vec2 LibGuiRectanglePos; +uniform vec2 LibGuiTileDimensions; +uniform vec4 LibGuiTileUvs; + +in vec2 vertexPosition; +out vec4 fragColor; + +float lerp(float time, float a, float b) { + return (1 - time) * a + time * b; +} + +vec2 getTextureCoords(vec2 pos) { + float deltaX = mod(pos.x - LibGuiRectanglePos.x, LibGuiTileDimensions.x) / LibGuiTileDimensions.x; + float deltaY = mod(pos.y - LibGuiRectanglePos.y, LibGuiTileDimensions.y) / LibGuiTileDimensions.y; + return vec2( + lerp(deltaX, LibGuiTileUvs.x, LibGuiTileUvs.z), + lerp(deltaY, LibGuiTileUvs.y, LibGuiTileUvs.w) + ); +} + +void main() { + vec4 color = texture(Sampler0, getTextureCoords(vertexPosition)); + if (color.a < 0.1) { + discard; + } + fragColor = color * ColorModulator; +} diff --git a/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.json b/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.json new file mode 100644 index 0000000..2ca0af3 --- /dev/null +++ b/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.json @@ -0,0 +1,20 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "libgui:tiled_rectangle", + "fragment": "libgui:tiled_rectangle", + "attributes": ["Position"], + "samplers": [{ "name": "Sampler0" }], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, + { "name": "LibGuiRectanglePos", "type": "float", "count": 2, "values": [ 0.0, 0.0 ] }, + { "name": "LibGuiTileDimensions", "type": "float", "count": 2, "values": [ 0.0, 0.0 ] }, + { "name": "LibGuiTileUvs", "type": "float", "count": 4, "values": [ 0.0, 0.0, 1.0, 1.0 ] }, + { "name": "LibGuiPositionMatrix", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] } + ] +} diff --git a/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.vsh b/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.vsh new file mode 100644 index 0000000..6a1209d --- /dev/null +++ b/src/main/resources/assets/libgui/shaders/core/tiled_rectangle.vsh @@ -0,0 +1,15 @@ +#version 150 + +in vec3 Position; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; +uniform mat4 LibGuiPositionMatrix; + +out vec2 vertexPosition; + +void main() { + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); + vec4 rawPos = inverse(LibGuiPositionMatrix) * vec4(Position, 1.0); + vertexPosition = rawPos.xy; +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 22868a2..b5d1caf 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -28,10 +28,10 @@ "fabric-api-base": ">=0.4.4", "fabric-lifecycle-events-v1": "^2.0.2", "fabric-networking-api-v1": "^1.0.21", - "fabric-rendering-v1": "^1.10.7", + "fabric-rendering-v1": "^1.13.0", "minecraft": ">=1.19.3", "jankson": "^5.0.0", - "libninepatch": "^1.1.0" + "libninepatch": "^1.2.0" }, "suggests": { "flamingo": "*" |