From 29f8d718ccce20db00e7e3ebf5a2b65ffae93ef3 Mon Sep 17 00:00:00 2001 From: DarkShadow44 Date: Sat, 28 Mar 2026 03:07:45 +0100 Subject: [PATCH] Pass texturemap to composite shader and honor texture replacements (#1589) --- .../DeferredWorldRenderingPipeline.java | 28 +++++++--- .../pipeline/transform/ShaderTransformer.java | 1 + .../transform/TextureTransformer.java | 51 +++++++++++++++++++ .../pipeline/transform/TransformPatcher.java | 4 -- .../iris/postprocess/FinalPassRenderer.java | 11 +++- .../iris/shadows/ShadowCompositeRenderer.java | 4 +- 6 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 src/main/java/net/coderbot/iris/pipeline/transform/TextureTransformer.java diff --git a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java index 8c9107f09..5e17a542c 100644 --- a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java @@ -200,14 +200,17 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R public DeferredWorldRenderingPipeline(ProgramSet programs) { Objects.requireNonNull(programs); - final Map>> prepareTransformFutures = submitCompositeTransforms(programs.getPrepare()); - final Map>> deferredTransformFutures = submitCompositeTransforms(programs.getDeferred()); - final Map>> compositeTransformFutures = submitCompositeTransforms(programs.getComposite()); + final Map>> prepareTransformFutures = + submitCompositeTransforms(programs.getPrepare(), TextureStage.PREPARE, programs.getPackDirectives().getTextureMap()); + final Map>> deferredTransformFutures = + submitCompositeTransforms(programs.getDeferred(), TextureStage.DEFERRED, programs.getPackDirectives().getTextureMap()); + final Map>> compositeTransformFutures = + submitCompositeTransforms(programs.getComposite(), TextureStage.COMPOSITE_AND_FINAL, programs.getPackDirectives().getTextureMap()); final CompletableFuture> finalTransformFuture = programs.getCompositeFinal() .filter(ProgramSource::isValid) - .map(DeferredWorldRenderingPipeline::submitCompositeTransform) + .map(source -> submitCompositeTransform(source, TextureStage.COMPOSITE_AND_FINAL, programs.getPackDirectives().getTextureMap())) .orElse(null); resolver = new ProgramFallbackResolver(programs); @@ -1710,11 +1713,20 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R private static final InputAvailability INPUT_TEXTURE_LIGHTMAP = new InputAvailability(true, true); private static final InputAvailability[] INPUT_AVAILABILITIES = { INPUT_NONE, INPUT_TEXTURE, INPUT_TEXTURE_LIGHTMAP }; - private static CompletableFuture> submitCompositeTransform(ProgramSource source) { - return Iris.ShaderTransformExecutor.submitTracked(() -> TransformPatcher.patchComposite(source.getVertexSource().orElse(null), source.getGeometrySource().orElse(null), source.getTessControlSource().orElse(null), source.getTessEvalSource().orElse(null), source.getFragmentSource().orElse(null))); + private static CompletableFuture> submitCompositeTransform(ProgramSource source, TextureStage stage, + Object2ObjectMap, String> textureMap) { + return Iris.ShaderTransformExecutor.submitTracked(() -> TransformPatcher.patchComposite( + source.getVertexSource().orElse(null), + source.getGeometrySource().orElse(null), + source.getTessControlSource().orElse(null), + source.getTessEvalSource().orElse(null), + source.getFragmentSource().orElse(null), + stage, + textureMap)); } - private static Map>> submitCompositeTransforms(ProgramSource[] sources) { + private static Map>> submitCompositeTransforms(ProgramSource[] sources, + TextureStage stage, Object2ObjectMap, String> textureMap) { // Count valid sources for initial capacity int count = 0; for (ProgramSource source : sources) { @@ -1723,7 +1735,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R final Map>> futures = new HashMap<>(count); for (int i = 0; i < sources.length; i++) { if (sources[i] != null && sources[i].isValid()) { - futures.put(i, submitCompositeTransform(sources[i])); + futures.put(i, submitCompositeTransform(sources[i], stage, textureMap)); } } return futures; diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java index f2e8a32fc..eefb1c351 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/ShaderTransformer.java @@ -448,6 +448,7 @@ public class ShaderTransformer { default: throw new IllegalStateException("Unknown patch type: " + patchType.name()); } + TextureTransformer.transform(transformer, parameters); CompatibilityTransformer.transformEach(transformer, parameters); } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/TextureTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/TextureTransformer.java new file mode 100644 index 000000000..56793f68d --- /dev/null +++ b/src/main/java/net/coderbot/iris/pipeline/transform/TextureTransformer.java @@ -0,0 +1,51 @@ +package net.coderbot.iris.pipeline.transform; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.coderbot.iris.gl.texture.TextureType; +import net.coderbot.iris.helpers.Tri; +import net.coderbot.iris.pipeline.transform.parameter.Parameters; +import net.coderbot.iris.shaderpack.texture.TextureStage; +import org.taumc.glsl.Transformer; +import org.taumc.glsl.grammar.GLSLLexer; + +final class TextureTransformer { + private TextureTransformer() { + } + + static void transform(Transformer transformer, Parameters parameters) { + final Object2ObjectMap, String> textureMap = parameters.getTextureMap(); + if (textureMap == null || textureMap.isEmpty()) { + return; + } + + final TextureStage stage = parameters.getTextureStage(); + textureMap.forEach((key, replacement) -> { + if (key.third() != stage) { + return; + } + + final String name = key.first(); + final int type = transformer.findType(name); + if (type != 0 && isTypeValid(key.second(), type)) { + transformer.rename(name, replacement); + } + }); + } + + private static boolean isTypeValid(TextureType expectedType, int extractedType) { + return switch (expectedType) { + case TEXTURE_1D -> extractedType == GLSLLexer.SAMPLER1D || + extractedType == GLSLLexer.ISAMPLER1D || + extractedType == GLSLLexer.USAMPLER1D; + case TEXTURE_RECTANGLE -> extractedType == GLSLLexer.SAMPLER2DRECT || + extractedType == GLSLLexer.ISAMPLER2DRECT || + extractedType == GLSLLexer.USAMPLER2DRECT; + case TEXTURE_2D -> extractedType == GLSLLexer.SAMPLER2D || + extractedType == GLSLLexer.ISAMPLER2D || + extractedType == GLSLLexer.USAMPLER2D; + case TEXTURE_3D -> extractedType == GLSLLexer.SAMPLER3D || + extractedType == GLSLLexer.ISAMPLER3D || + extractedType == GLSLLexer.USAMPLER3D; + }; + } +} diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java b/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java index 8c45d378f..365b584d1 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java @@ -120,10 +120,6 @@ public class TransformPatcher { return patchComposite(vertex, geometry, null, null, fragment, TextureStage.COMPOSITE_AND_FINAL, null); } - public static Map patchComposite(String vertex, String geometry, String tessControl, String tessEval, String fragment) { - return patchComposite(vertex, geometry, tessControl, tessEval, fragment, TextureStage.COMPOSITE_AND_FINAL, null); - } - public static Map patchComposite(String vertex, String geometry, String tessControl, String tessEval, String fragment, TextureStage stage, Object2ObjectMap, String> textureMap) { return transform(vertex, geometry, tessControl, tessEval, fragment, new TextureStageParameters(Patch.COMPOSITE, stage, textureMap)); } diff --git a/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java b/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java index e642d33b8..92331d046 100644 --- a/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java +++ b/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java @@ -146,7 +146,7 @@ public class FinalPassRenderer { GLStateManager.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, 0); } - private static Map getTransformed(ProgramSource source, CompletableFuture> precomputedTransformFuture, String stageName) { + private Map getTransformed(ProgramSource source, CompletableFuture> precomputedTransformFuture, String stageName) { if (precomputedTransformFuture != null) { try { final Map result = precomputedTransformFuture.join(); @@ -157,7 +157,14 @@ public class FinalPassRenderer { throw new RuntimeException("Shader transformation failed for '" + source.getName() + "' in stage '" + stageName + "'", e.getCause() != null ? e.getCause() : e); } } - return TransformPatcher.patchComposite(source.getVertexSource().orElseThrow(NullPointerException::new), source.getGeometrySource().orElse(null), source.getTessControlSource().orElse(null), source.getTessEvalSource().orElse(null), source.getFragmentSource().orElseThrow(NullPointerException::new)); + return TransformPatcher.patchComposite( + source.getVertexSource().orElseThrow(NullPointerException::new), + source.getGeometrySource().orElse(null), + source.getTessControlSource().orElse(null), + source.getTessEvalSource().orElse(null), + source.getFragmentSource().orElseThrow(NullPointerException::new), + TextureStage.COMPOSITE_AND_FINAL, + pipeline != null ? pipeline.getTextureMap() : null); } private static final class Pass { diff --git a/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java index 42ab8fa80..017c1c1a3 100644 --- a/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java +++ b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java @@ -263,7 +263,9 @@ public class ShadowCompositeRenderer { source.getGeometrySource().orElse(null), source.getTessControlSource().orElse(null), source.getTessEvalSource().orElse(null), - source.getFragmentSource().orElseThrow(NullPointerException::new)); + source.getFragmentSource().orElseThrow(NullPointerException::new), + TextureStage.SHADOWCOMP, + pipeline.getTextureMap()); String vertex = transformed.get(PatchShaderType.VERTEX); String geometry = transformed.get(PatchShaderType.GEOMETRY); String tessControl = transformed.get(PatchShaderType.TESS_CONTROL);