From 504b6f4d5f5b6d528b45dec2a0206bafd364c515 Mon Sep 17 00:00:00 2001 From: Kli Kli Date: Wed, 5 Feb 2025 09:50:43 +0100 Subject: [PATCH] chore: prepare changes for wires rendering in distance See #224 --- .../java/com/klikli_dev/theurgy/Theurgy.java | 1 + .../theurgy/content/render/RenderTypes.java | 27 ++++++++++ .../theurgy/logistics/WireRenderer.java | 3 +- .../theurgy/registry/ShaderRegistry.java | 23 ++++++++ .../core/rendertype_distance_lines.fsh | 18 +++++++ .../core/rendertype_distance_lines.json | 17 ++++++ .../core/rendertype_distance_lines.vsh | 53 +++++++++++++++++++ 7 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/klikli_dev/theurgy/registry/ShaderRegistry.java create mode 100644 src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.fsh create mode 100644 src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.json create mode 100644 src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.vsh diff --git a/src/main/java/com/klikli_dev/theurgy/Theurgy.java b/src/main/java/com/klikli_dev/theurgy/Theurgy.java index 0f7af53ca..9b0e06a97 100644 --- a/src/main/java/com/klikli_dev/theurgy/Theurgy.java +++ b/src/main/java/com/klikli_dev/theurgy/Theurgy.java @@ -146,6 +146,7 @@ public Theurgy(IEventBus modEventBus, ModContainer modContainer) { modEventBus.addListener(Client::onRegisterMenuScreens); modEventBus.addListener(BlockOverlays::onTextureAtlasStitched); modEventBus.addListener(KeyMappingsRegistry::onRegisterKeyMappings); + modEventBus.addListener(ShaderRegistry::onRegisterShaders); NeoForge.EVENT_BUS.addListener(Client::onRenderLevelStage); NeoForge.EVENT_BUS.addListener(Client::onClientTick); NeoForge.EVENT_BUS.addListener(Client::onRecipesUpdated); diff --git a/src/main/java/com/klikli_dev/theurgy/content/render/RenderTypes.java b/src/main/java/com/klikli_dev/theurgy/content/render/RenderTypes.java index 8192c430d..420279fba 100644 --- a/src/main/java/com/klikli_dev/theurgy/content/render/RenderTypes.java +++ b/src/main/java/com/klikli_dev/theurgy/content/render/RenderTypes.java @@ -12,13 +12,36 @@ import net.minecraft.Util; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.resources.ResourceLocation; +import java.util.OptionalDouble; import java.util.function.Function; public class RenderTypes extends RenderStateShard { + public static ShaderInstance rendertypeDistanceLines; + protected static final ShaderStateShard RENDERTYPE_DISTANCE_LINES_SHADER = new ShaderStateShard(() -> rendertypeDistanceLines); + + protected static final RenderType DISTANCE_LINES = RenderType.create( + "distance_lines", + DefaultVertexFormat.POSITION_COLOR_NORMAL, + VertexFormat.Mode.LINES, + 1536, + false, + false, + RenderType.CompositeState.builder() + .setShaderState(RENDERTYPE_DISTANCE_LINES_SHADER) + .setLineState(new RenderStateShard.LineStateShard(OptionalDouble.empty())) + .setLayeringState(VIEW_OFFSET_Z_LAYERING) + .setTransparencyState(TRANSLUCENT_TRANSPARENCY) + .setOutputState(ITEM_ENTITY_TARGET) + .setWriteMaskState(COLOR_DEPTH_WRITE) + .setCullState(NO_CULL) + .createCompositeState(false) + ); + protected static final Function ENTITY_TRANSLUCENT_CULL_NO_DEPTH = Util.memoize( p_286165_ -> { RenderType.CompositeState rendertype$compositestate = RenderType.CompositeState.builder() @@ -114,4 +137,8 @@ public static RenderType fluid() { public static RenderType srcMinusOne(ResourceLocation location) { return SRC_MINUS_ONE.apply(location); } + + public static RenderType distanceLines() { + return DISTANCE_LINES; + } } diff --git a/src/main/java/com/klikli_dev/theurgy/logistics/WireRenderer.java b/src/main/java/com/klikli_dev/theurgy/logistics/WireRenderer.java index d178494d2..e6211282a 100644 --- a/src/main/java/com/klikli_dev/theurgy/logistics/WireRenderer.java +++ b/src/main/java/com/klikli_dev/theurgy/logistics/WireRenderer.java @@ -7,6 +7,7 @@ package com.klikli_dev.theurgy.logistics; +import com.klikli_dev.theurgy.content.render.RenderTypes; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -43,7 +44,7 @@ public void onRenderLevelStage(RenderLevelStageEvent event) { poseStack.translate(-renderPosX, -renderPosY, -renderPosZ); //we use lines() to avoid all the wires getting connected as it would happen with linestrip - var buffer = bufferSource.getBuffer(RenderType.lines()); + var buffer = bufferSource.getBuffer(RenderTypes.distanceLines()); for (var wire : this.wires) { poseStack.pushPose(); poseStack.translate(wire.from().getX(), wire.from().getY(), wire.from().getZ()); diff --git a/src/main/java/com/klikli_dev/theurgy/registry/ShaderRegistry.java b/src/main/java/com/klikli_dev/theurgy/registry/ShaderRegistry.java new file mode 100644 index 000000000..0b7db8c87 --- /dev/null +++ b/src/main/java/com/klikli_dev/theurgy/registry/ShaderRegistry.java @@ -0,0 +1,23 @@ +package com.klikli_dev.theurgy.registry; + +import com.klikli_dev.theurgy.Theurgy; +import com.klikli_dev.theurgy.content.render.RenderTypes; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import net.minecraft.client.renderer.ShaderInstance; +import net.neoforged.neoforge.client.event.RegisterShadersEvent; + +import java.io.IOException; + + +public class ShaderRegistry { + + public static void onRegisterShaders(RegisterShadersEvent event) { + try { + event.registerShader(new ShaderInstance(event.getResourceProvider(), Theurgy.loc("rendertype_distance_lines"), DefaultVertexFormat.POSITION_COLOR_NORMAL), shaderInstance -> { + RenderTypes.rendertypeDistanceLines = shaderInstance; + }); + } catch (IOException e) { + Theurgy.LOGGER.error("Failed to register shader", e); + } + } +} diff --git a/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.fsh b/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.fsh new file mode 100644 index 000000000..057f31fc3 --- /dev/null +++ b/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.fsh @@ -0,0 +1,18 @@ +#version 150 + +#moj_import + +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; +uniform vec4 FogColor; + +in float vertexDistance; +in vec4 vertexColor; + +out vec4 fragColor; + +void main() { + vec4 color = vertexColor * ColorModulator; + fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); +} diff --git a/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.json b/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.json new file mode 100644 index 000000000..670a8bd76 --- /dev/null +++ b/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.json @@ -0,0 +1,17 @@ +{ + "vertex": "rendertype_lines", + "fragment": "rendertype_lines", + "samplers": [ + ], + "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": "LineWidth", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "ScreenSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, + { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } + ] +} diff --git a/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.vsh b/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.vsh new file mode 100644 index 000000000..45f7a29a3 --- /dev/null +++ b/src/main/resources/assets/theurgy/shaders/core/rendertype_distance_lines.vsh @@ -0,0 +1,53 @@ +#version 150 + +#moj_import + +in vec3 Position; +in vec4 Color; +in vec3 Normal; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; +uniform float LineWidth; +uniform vec2 ScreenSize; +uniform int FogShape; + +out float vertexDistance; +out vec4 vertexColor; + +const float VIEW_SHRINK = 1.0 - (1.0 / 256.0); +const mat4 VIEW_SCALE = mat4( + VIEW_SHRINK, 0.0, 0.0, 0.0, + 0.0, VIEW_SHRINK, 0.0, 0.0, + 0.0, 0.0, VIEW_SHRINK, 0.0, + 0.0, 0.0, 0.0, 1.0 +); + +void main() { + vertexDistance = fog_distance(Position, FogShape); + + + vec4 linePosStart = ProjMat * VIEW_SCALE * ModelViewMat * vec4(Position, 1.0); + vec4 linePosEnd = ProjMat * VIEW_SCALE * ModelViewMat * vec4(Position + Normal, 1.0); + + vec3 ndc1 = linePosStart.xyz / linePosStart.w; + vec3 ndc2 = linePosEnd.xyz / linePosEnd.w; + + + vec2 lineScreenDirection = normalize((ndc2.xy - ndc1.xy) * ScreenSize); + + //divide by distance to scale line thickness based on distance to camera, see https://github.com/klikli-dev/theurgy/issues/224 + vec2 lineOffset = (vec2(-lineScreenDirection.y, lineScreenDirection.x) * LineWidth / ScreenSize) / vertexDistance; + + if (lineOffset.x < 0.0) { + lineOffset *= -1.0; + } + + if (gl_VertexID % 2 == 0) { + gl_Position = vec4((ndc1 + vec3(lineOffset, 0.0)) * linePosStart.w, linePosStart.w); + } else { + gl_Position = vec4((ndc1 - vec3(lineOffset, 0.0)) * linePosStart.w, linePosStart.w); + } + + vertexColor = Color; +}