diff --git a/src/main/java/net/coderbot/iris/Iris.java b/src/main/java/net/coderbot/iris/Iris.java index e008548b8d..cfa24a62f9 100644 --- a/src/main/java/net/coderbot/iris/Iris.java +++ b/src/main/java/net/coderbot/iris/Iris.java @@ -3,6 +3,7 @@ import com.google.common.base.Throwables; import com.mojang.blaze3d.platform.GlDebug; import com.mojang.blaze3d.platform.InputConstants; +import com.sun.jna.platform.unix.LibC; import net.coderbot.iris.config.IrisConfig; import net.coderbot.iris.gl.GLDebug; import net.coderbot.iris.gl.shader.ShaderCompileException; @@ -31,6 +32,7 @@ import net.fabricmc.loader.api.Version; import net.minecraft.ChatFormatting; import net.minecraft.SharedConstants; +import net.minecraft.Util; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -42,6 +44,7 @@ import net.minecraft.world.level.dimension.DimensionType; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; +import org.lwjgl.system.Configuration; import java.io.IOException; import java.io.InputStream; @@ -87,6 +90,7 @@ public class Iris { private static KeyMapping reloadKeybind; private static KeyMapping toggleShadersKeybind; private static KeyMapping shaderpackScreenKeybind; + private static KeyMapping wireframeKeybind; private static final Map shaderPackOptionQueue = new HashMap<>(); // Flag variable used when reloading @@ -98,6 +102,14 @@ public class Iris { private static UpdateChecker updateChecker; private static boolean fallback; + static { + // Custom fix only for me for Plasma 6 + if (FabricLoader.getInstance().isDevelopmentEnvironment() && Util.getPlatform() == Util.OS.LINUX && System.getProperty("user.name").contains("ims")) { + LibC.INSTANCE.setenv("__GL_THREADED_OPTIMIZATIONS", "0", 1); + Configuration.GLFW_LIBRARY_NAME.set("/usr/lib/libglfw.so"); + } + } + // Change this for snapshots! private static String backupVersionNumber = "1.19.4"; @@ -121,6 +133,7 @@ public void onEarlyInitialize() { reloadKeybind = KeyBindingHelper.registerKeyBinding(new KeyMapping("iris.keybind.reload", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_R, "iris.keybinds")); toggleShadersKeybind = KeyBindingHelper.registerKeyBinding(new KeyMapping("iris.keybind.toggleShaders", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_K, "iris.keybinds")); shaderpackScreenKeybind = KeyBindingHelper.registerKeyBinding(new KeyMapping("iris.keybind.shaderPackSelection", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_O, "iris.keybinds")); + wireframeKeybind = KeyBindingHelper.registerKeyBinding(new KeyMapping("iris.keybind.wireframe", InputConstants.Type.KEYSYM, InputConstants.UNKNOWN.getValue(), "iris.keybinds")); try { if (!Files.exists(getShaderpacksDirectory())) { @@ -248,9 +261,17 @@ public static void handleKeybinds(Minecraft minecraft) { } } else if (shaderpackScreenKeybind.consumeClick()) { minecraft.setScreen(new ShaderPackScreen(null)); + } else if (wireframeKeybind.consumeClick()) { + if (irisConfig.areDebugOptionsEnabled() && minecraft.player != null && !Minecraft.getInstance().isLocalServer()) { + minecraft.player.displayClientMessage(Component.literal("No cheating; wireframe only in singleplayer!"), false); + } } } + public static boolean shouldActivateWireframe() { + return irisConfig.areDebugOptionsEnabled() && wireframeKeybind.isDown(); + } + public static void toggleShaders(Minecraft minecraft, boolean enabled) throws IOException { irisConfig.setShadersEnabled(enabled); irisConfig.save(); diff --git a/src/main/java/net/coderbot/iris/features/FeatureFlags.java b/src/main/java/net/coderbot/iris/features/FeatureFlags.java index 99a9ef7dff..01ca0059ff 100644 --- a/src/main/java/net/coderbot/iris/features/FeatureFlags.java +++ b/src/main/java/net/coderbot/iris/features/FeatureFlags.java @@ -14,6 +14,7 @@ public enum FeatureFlags { CUSTOM_IMAGES(() -> true, IrisRenderSystem::supportsImageLoadStore), PER_BUFFER_BLENDING(() -> true, IrisRenderSystem::supportsBufferBlending), COMPUTE_SHADERS(() -> true, IrisRenderSystem::supportsCompute), + TESSELATION_SHADERS(() -> true, IrisRenderSystem::supportsTesselation), ENTITY_TRANSLUCENT(() -> true, () -> true), REVERSED_CULLING(() -> true, () -> true), SSBO(() -> true, IrisRenderSystem::supportsSSBO), diff --git a/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java b/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java index 91c93941a2..0a1042dff5 100644 --- a/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java +++ b/src/main/java/net/coderbot/iris/gl/IrisRenderSystem.java @@ -42,6 +42,9 @@ public class IrisRenderSystem { private static DSAAccess dsaState; private static boolean hasMultibind; private static boolean supportsCompute; + private static boolean supportsTesselation; + private static int polygonMode = GL43C.GL_FILL; + private static int backupPolygonMode = GL43C.GL_FILL; private static int[] samplers; public static void initRenderer() { @@ -59,6 +62,7 @@ public static void initRenderer() { hasMultibind = GL.getCapabilities().OpenGL45 || GL.getCapabilities().GL_ARB_multi_bind; supportsCompute = GL.getCapabilities().glDispatchCompute != MemoryUtil.NULL; + supportsTesselation = GL.getCapabilities().GL_ARB_tessellation_shader || GL.getCapabilities().OpenGL40; samplers = new int[SamplerLimits.get().getMaxTextureUnits()]; } @@ -365,6 +369,10 @@ public static boolean supportsCompute() { return supportsCompute; } + public static boolean supportsTesselation() { + return supportsTesselation; + } + public static int genSampler() { return GL33C.glGenSamplers(); } @@ -425,6 +433,23 @@ public static void deleteBuffers(int glId) { GL43C.glDeleteBuffers(glId); } + public static void setPolygonMode(int mode) { + if (mode != polygonMode) { + polygonMode = mode; + GL43C.glPolygonMode(GL43C.GL_FRONT_AND_BACK, mode); + } + } + + public static void overridePolygonMode() { + backupPolygonMode = polygonMode; + setPolygonMode(GL43C.GL_FILL); + } + + public static void restorePolygonMode() { + setPolygonMode(backupPolygonMode); + backupPolygonMode = GL43C.GL_FILL; + } + public interface DSAAccess { void generateMipmaps(int texture, int target); diff --git a/src/main/java/net/coderbot/iris/gl/framebuffer/ViewportData.java b/src/main/java/net/coderbot/iris/gl/framebuffer/ViewportData.java new file mode 100644 index 0000000000..0b33fdbd69 --- /dev/null +++ b/src/main/java/net/coderbot/iris/gl/framebuffer/ViewportData.java @@ -0,0 +1,9 @@ +package net.coderbot.iris.gl.framebuffer; + +public record ViewportData(float scale, float viewportX, float viewportY) { + private static ViewportData DEFAULT = new ViewportData(1.0f, 0.0f, 0.0f); + + public static ViewportData defaultValue() { + return DEFAULT; + } +} diff --git a/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java b/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java index 8368c41b22..0bcc1c52f7 100644 --- a/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java +++ b/src/main/java/net/coderbot/iris/gl/shader/ShaderType.java @@ -13,7 +13,9 @@ public enum ShaderType { VERTEX(GL20.GL_VERTEX_SHADER), GEOMETRY(GL32C.GL_GEOMETRY_SHADER), FRAGMENT(GL20.GL_FRAGMENT_SHADER), - COMPUTE(GL43C.GL_COMPUTE_SHADER); + COMPUTE(GL43C.GL_COMPUTE_SHADER), + TESSELATION_CONTROL(GL43C.GL_TESS_CONTROL_SHADER), + TESSELATION_EVAL(GL43C.GL_TESS_EVALUATION_SHADER); public final int id; diff --git a/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java b/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java index 6900d50697..078129f326 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinGameRenderer.java @@ -65,6 +65,8 @@ public class MixinGameRenderer { private ArrayList iris$reloadGeometryShaders() { ArrayList programs = Lists.newArrayList(); programs.addAll(IrisProgramTypes.GEOMETRY.getPrograms().values()); + programs.addAll(IrisProgramTypes.TESS_CONTROL.getPrograms().values()); + programs.addAll(IrisProgramTypes.TESS_EVAL.getPrograms().values()); return programs; } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java index 1581e44318..3eca1cf158 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_DepthColorOverride.java @@ -2,9 +2,12 @@ import com.mojang.blaze3d.platform.GlStateManager; import net.coderbot.iris.gl.blending.DepthColorStorage; +import net.coderbot.iris.vertices.ImmediateState; +import org.lwjgl.opengl.GL43C; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GlStateManager.class) @@ -24,4 +27,18 @@ public class MixinGlStateManager_DepthColorOverride { ci.cancel(); } } + + @Redirect(method = "_drawElements", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glDrawElements(IIIJ)V"), remap = false) + private static void iris$modify(int mode, int count, int type, long indices) { + if (mode == GL43C.GL_TRIANGLES && ImmediateState.usingTessellation) { + mode = GL43C.GL_PATCHES; + } + + GL43C.glDrawElements(mode, count, type, indices); + } + + @Inject(method = "_glUseProgram", at = @At("TAIL"), remap = false) + private static void iris$resetTessellation(int pInt0, CallbackInfo ci) { + ImmediateState.usingTessellation = false; + } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java index 91c5b7141b..1ec636a8f0 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinGlStateManager_FramebufferBinding.java @@ -16,6 +16,7 @@ public class MixinGlStateManager_FramebufferBinding { private static int iris$drawFramebuffer = 0; private static int iris$readFramebuffer = 0; + private static int iris$program = 0; @Inject(method = "_glBindFramebuffer(II)V", at = @At("HEAD"), cancellable = true, remap = false) private static void iris$avoidRedundantBind(int target, int framebuffer, CallbackInfo ci) { @@ -43,6 +44,15 @@ public class MixinGlStateManager_FramebufferBinding { } } + @Inject(method = "_glUseProgram", at = @At("HEAD"), cancellable = true, remap = false) + private static void iris$avoidRedundantBind2(int pInt0, CallbackInfo ci) { + if (iris$program == pInt0) { + ci.cancel(); + } else { + iris$program = pInt0; + } + } + @Inject(method = "_glDeleteFramebuffers(I)V", at = @At("HEAD"), remap = false) private static void iris$trackFramebufferDelete(int framebuffer, CallbackInfo ci) { if (iris$drawFramebuffer == framebuffer) { diff --git a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java index de01f1433a..cb22f3aec4 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinLevelRenderer.java @@ -7,6 +7,7 @@ import org.joml.Matrix4f; import net.coderbot.iris.Iris; import net.coderbot.iris.fantastic.WrappingMultiBufferSource; +import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.program.Program; import net.coderbot.iris.layer.IsOutlineRenderStateShard; import net.coderbot.iris.layer.OuterWrappedRenderType; @@ -22,6 +23,7 @@ import net.fabricmc.api.Environment; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LightTexture; @@ -31,6 +33,8 @@ import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL43C; import org.spongepowered.asm.mixin.Final; import net.minecraft.client.Options; @@ -69,6 +73,9 @@ public class MixinLevelRenderer { @Shadow private Frustum cullingFrustum; + @Shadow + private @Nullable ClientLevel level; + // Begin shader rendering after buffers have been cleared. // At this point we've ensured that Minecraft's main framebuffer is cleared. // This is important or else very odd issues will happen with shaders that have a final pass that doesn't write to @@ -90,6 +97,10 @@ public class MixinLevelRenderer { if (pipeline.shouldDisableFrustumCulling()) { this.cullingFrustum = new NonCullingFrustum(); } + + if (Iris.shouldActivateWireframe() && this.minecraft.isLocalServer()) { + IrisRenderSystem.setPolygonMode(GL43C.GL_LINE); + } } // Begin shader rendering after buffers have been cleared. @@ -113,6 +124,10 @@ public class MixinLevelRenderer { Minecraft.getInstance().getProfiler().popPush("iris_final"); pipeline.finalizeLevelRendering(); pipeline = null; + + if (Iris.shouldActivateWireframe() && this.minecraft.isLocalServer()) { + IrisRenderSystem.setPolygonMode(GL43C.GL_FILL); + } } // Setup shadow terrain & render shadows before the main terrain setup. We need to do things in this order to diff --git a/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java b/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java index 6768728d96..a41ba8d0a9 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinProgramManager.java @@ -15,5 +15,11 @@ public class MixinProgramManager { if (shader instanceof ExtendedShader && ((ExtendedShader) shader).getGeometry() != null) { ((ExtendedShader) shader).getGeometry().close(); } + if (shader instanceof ExtendedShader && ((ExtendedShader) shader).getTessControl() != null) { + ((ExtendedShader) shader).getTessControl().close(); + } + if (shader instanceof ExtendedShader && ((ExtendedShader) shader).getTessEval() != null) { + ((ExtendedShader) shader).getTessEval().close(); + } } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java b/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java index 5e0bdc5744..44316a1ff2 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinProgramType.java @@ -4,6 +4,7 @@ import net.coderbot.iris.pipeline.newshader.IrisProgramTypes; import org.apache.commons.lang3.ArrayUtils; import org.lwjgl.opengl.GL32C; +import org.lwjgl.opengl.GL42C; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -23,6 +24,12 @@ public class MixinProgramType { IrisProgramTypes.GEOMETRY = ProgramTypeAccessor.createProgramType("GEOMETRY", baseOrdinal, "geometry", ".gsh", GL32C.GL_GEOMETRY_SHADER); - $VALUES = ArrayUtils.addAll($VALUES, IrisProgramTypes.GEOMETRY); + IrisProgramTypes.TESS_CONTROL + = ProgramTypeAccessor.createProgramType("TESS_CONTROL", baseOrdinal + 1, "tess_control", ".tcs", GL42C.GL_TESS_CONTROL_SHADER); + + IrisProgramTypes.TESS_EVAL + = ProgramTypeAccessor.createProgramType("TESS_EVAL", baseOrdinal + 2, "tess_eval", ".tes", GL42C.GL_TESS_EVALUATION_SHADER); + + $VALUES = ArrayUtils.addAll($VALUES, IrisProgramTypes.GEOMETRY, IrisProgramTypes.TESS_CONTROL, IrisProgramTypes.TESS_EVAL); } } diff --git a/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java b/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java index 37d0b46f6c..3baa14ba62 100644 --- a/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java +++ b/src/main/java/net/coderbot/iris/mixin/MixinShaderInstance.java @@ -4,7 +4,6 @@ import com.mojang.blaze3d.shaders.Uniform; import com.mojang.blaze3d.vertex.VertexFormat; import net.coderbot.iris.Iris; -import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.blending.DepthColorStorage; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.coderbot.iris.pipeline.newshader.CoreWorldRenderingPipeline; @@ -13,9 +12,6 @@ import net.coderbot.iris.pipeline.newshader.fallback.FallbackShader; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.server.packs.resources.ResourceProvider; -import org.lwjgl.opengl.ARBTextureSwizzle; -import org.lwjgl.opengl.GL20C; -import org.lwjgl.opengl.GL30C; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -24,9 +20,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.Objects; @Mixin(ShaderInstance.class) public abstract class MixinShaderInstance implements ShaderInstanceInterface { @@ -85,11 +78,11 @@ private static boolean shouldOverrideShaders() { @Inject(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/GsonHelper;parse(Ljava/io/Reader;)Lcom/google/gson/JsonObject;")) public void iris$setupGeometryShader(ResourceProvider resourceProvider, String string, VertexFormat vertexFormat, CallbackInfo ci) { - this.iris$createGeometryShader(resourceProvider, string); + this.iris$createExtraShaders(resourceProvider, string); } @Override - public void iris$createGeometryShader(ResourceProvider provider, String name) { + public void iris$createExtraShaders(ResourceProvider provider, String name) { //no-op, used for ExtendedShader to call before the super constructor } } diff --git a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java index 20564a9ab9..3607e3fdf5 100644 --- a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java @@ -684,17 +684,9 @@ private Pass createDefaultPass() { private Pass createPass(ProgramSource source, InputAvailability availability, boolean shadow, ProgramId id) { // TODO: Properly handle empty shaders? - Map transformed = null; // 1.16 is the zombie haunting us all - String vertex = transformed.get(PatchShaderType.VERTEX); - String geometry = transformed.get(PatchShaderType.GEOMETRY); - String fragment = transformed.get(PatchShaderType.FRAGMENT); - ShaderPrinter.printProgram(source.getName()).addSources(transformed).print(); - ProgramBuilder builder = ProgramBuilder.begin(source.getName(), vertex, geometry, fragment, - IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS); - - return createPassInner(builder, source.getParent().getPack().getIdMap(), source.getDirectives(), source.getParent().getPackDirectives(), availability, shadow, id); + return createPassInner(null, source.getParent().getPack().getIdMap(), source.getDirectives(), source.getParent().getPackDirectives(), availability, shadow, id); } private Pass createPassInner(ProgramBuilder builder, IdMap map, ProgramDirectives programDirectives, diff --git a/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java b/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java index f1efa8c5af..b1b854e0a2 100644 --- a/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java +++ b/src/main/java/net/coderbot/iris/pipeline/SodiumTerrainPipeline.java @@ -39,6 +39,8 @@ public class SodiumTerrainPipeline { Optional terrainSolidVertex; Optional terrainSolidGeometry; + Optional terrainSolidTessControl; + Optional terrainSolidTessEval; Optional terrainSolidFragment; GlFramebuffer terrainSolidFramebuffer; BlendModeOverride terrainSolidBlendOverride; @@ -46,6 +48,8 @@ public class SodiumTerrainPipeline { Optional terrainCutoutVertex; Optional terrainCutoutGeometry; + Optional terrainCutoutTessControl; + Optional terrainCutoutTessEval; Optional terrainCutoutFragment; GlFramebuffer terrainCutoutFramebuffer; BlendModeOverride terrainCutoutBlendOverride; @@ -54,6 +58,8 @@ public class SodiumTerrainPipeline { Optional translucentVertex; Optional translucentGeometry; + Optional translucentTessControl; + Optional translucentTessEval; Optional translucentFragment; GlFramebuffer translucentFramebuffer; BlendModeOverride translucentBlendOverride; @@ -62,6 +68,8 @@ public class SodiumTerrainPipeline { Optional shadowVertex; Optional shadowGeometry; + Optional shadowTessControl; + Optional shadowTessEval; Optional shadowFragment; Optional shadowCutoutFragment; GlFramebuffer shadowFramebuffer; @@ -292,10 +300,14 @@ public void patchShaders(ChunkVertexType vertexType) { sources.getName(), sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), AlphaTest.ALWAYS, inputs, parent.getTextureMap()); terrainSolidVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); terrainSolidGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); + terrainSolidTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + terrainSolidTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); terrainSolidFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); ShaderPrinter.printProgram(sources.getName() + "_sodium_solid").addSources(transformed).print(); @@ -304,6 +316,8 @@ public void patchShaders(ChunkVertexType vertexType) { terrainSolidBufferOverrides = Collections.emptyList(); terrainSolidVertex = Optional.of(defaultVertex); terrainSolidGeometry = Optional.empty(); + terrainSolidTessControl = Optional.empty(); + terrainSolidTessEval = Optional.empty(); terrainSolidFragment = Optional.of(defaultFragment); }); @@ -322,10 +336,14 @@ public void patchShaders(ChunkVertexType vertexType) { sources.getName(), sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), terrainCutoutAlpha.orElse(AlphaTests.ONE_TENTH_ALPHA), inputs, parent.getTextureMap()); terrainCutoutVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); terrainCutoutGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); + terrainCutoutTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + terrainCutoutTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); terrainCutoutFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); ShaderPrinter.printProgram(sources.getName() + "_sodium_cutout").addSources(transformed).print(); @@ -335,6 +353,8 @@ public void patchShaders(ChunkVertexType vertexType) { terrainCutoutAlpha = terrainCutoutDefault.get(); terrainCutoutVertex = Optional.of(defaultVertex); terrainCutoutGeometry = Optional.empty(); + terrainCutoutTessControl = Optional.empty(); + terrainCutoutTessEval = Optional.empty(); terrainCutoutFragment = Optional.of(defaultFragment); }); @@ -354,10 +374,14 @@ public void patchShaders(ChunkVertexType vertexType) { sources.getName(), sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), translucentAlpha.orElse(AlphaTest.ALWAYS), inputs, parent.getTextureMap()); translucentVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); translucentGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); + translucentTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + translucentTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); translucentFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); ShaderPrinter.printProgram(sources.getName() + "_sodium").addSources(transformed).print(); @@ -367,6 +391,8 @@ public void patchShaders(ChunkVertexType vertexType) { translucentAlpha = translucentDefault.get(); translucentVertex = Optional.of(defaultVertex); translucentGeometry = Optional.empty(); + translucentTessControl = Optional.empty(); + translucentTessEval = Optional.empty(); translucentFragment = Optional.of(defaultFragment); }); @@ -385,16 +411,22 @@ public void patchShaders(ChunkVertexType vertexType) { sources.getName(), sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), AlphaTest.ALWAYS, inputs, parent.getTextureMap()); Map transformedCutout = TransformPatcher.patchSodium( sources.getName(), sources.getVertexSource().orElse(null), sources.getGeometrySource().orElse(null), + sources.getTessControlSource().orElse(null), + sources.getTessEvalSource().orElse(null), sources.getFragmentSource().orElse(null), shadowAlpha.get(), inputs, parent.getTextureMap()); shadowVertex = Optional.ofNullable(transformed.get(PatchShaderType.VERTEX)); shadowGeometry = Optional.ofNullable(transformed.get(PatchShaderType.GEOMETRY)); + shadowTessControl = Optional.ofNullable(transformed.get(PatchShaderType.TESS_CONTROL)); + shadowTessEval = Optional.ofNullable(transformed.get(PatchShaderType.TESS_EVAL)); shadowCutoutFragment = Optional.ofNullable(transformedCutout.get(PatchShaderType.FRAGMENT)); shadowFragment = Optional.ofNullable(transformed.get(PatchShaderType.FRAGMENT)); @@ -409,6 +441,8 @@ public void patchShaders(ChunkVertexType vertexType) { shadowAlpha = shadowDefault.get(); shadowVertex = Optional.empty(); shadowGeometry = Optional.empty(); + shadowTessControl = Optional.empty(); + shadowTessEval = Optional.empty(); shadowCutoutFragment = Optional.empty(); shadowFragment = Optional.empty(); }); @@ -422,6 +456,14 @@ public Optional getTerrainSolidGeometryShaderSource() { return terrainSolidGeometry; } + public Optional getTerrainSolidTessControlShaderSource() { + return terrainSolidTessControl; + } + + public Optional getTerrainSolidTessEvalShaderSource() { + return terrainSolidTessEval; + } + public Optional getTerrainSolidFragmentShaderSource() { return terrainSolidFragment; } @@ -434,6 +476,14 @@ public Optional getTerrainCutoutGeometryShaderSource() { return terrainCutoutGeometry; } + public Optional getTerrainCutoutTessControlShaderSource() { + return terrainCutoutTessControl; + } + + public Optional getTerrainCutoutTessEvalShaderSource() { + return terrainCutoutTessEval; + } + public Optional getTerrainCutoutFragmentShaderSource() { return terrainCutoutFragment; } @@ -473,6 +523,14 @@ public Optional getTranslucentGeometryShaderSource() { return translucentGeometry; } + public Optional getTranslucentTessControlShaderSource() { + return translucentTessControl; + } + + public Optional getTranslucentTessEvalShaderSource() { + return translucentTessEval; + } + public Optional getTranslucentFragmentShaderSource() { return translucentFragment; } @@ -501,6 +559,14 @@ public Optional getShadowGeometryShaderSource() { return shadowGeometry; } + public Optional getShadowTessControlShaderSource() { + return shadowTessControl; + } + + public Optional getShadowTessEvalShaderSource() { + return shadowTessEval; + } + public Optional getShadowFragmentShaderSource() { return shadowFragment; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java b/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java index 414e39947b..61e29609ee 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/ExtendedShader.java @@ -30,6 +30,7 @@ import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.uniforms.custom.CustomUniforms; import org.joml.Vector3f; +import net.coderbot.iris.vertices.ImmediateState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.resources.ResourceLocation; @@ -70,13 +71,14 @@ public class ExtendedShader extends ShaderInstance implements ShaderInstanceInte GlFramebuffer baseline; BlendModeOverride blendModeOverride; float alphaTest; - private Program geometry; + boolean usesTessellation; + private Program geometry, tessControl, tessEval; private final ShaderAttributeInputs inputs; private static ExtendedShader lastApplied; private final Vector3f chunkOffset = new Vector3f(); - public ExtendedShader(ResourceProvider resourceFactory, String string, VertexFormat vertexFormat, + public ExtendedShader(ResourceProvider resourceFactory, String string, VertexFormat vertexFormat, boolean usesTessellation, GlFramebuffer writingToBeforeTranslucent, GlFramebuffer writingToAfterTranslucent, GlFramebuffer baseline, BlendModeOverride blendModeOverride, AlphaTest alphaTest, Consumer uniformCreator, BiConsumer samplerCreator, boolean isIntensity, @@ -91,6 +93,7 @@ public ExtendedShader(ResourceProvider resourceFactory, String string, VertexFor ProgramImages.Builder builder = ProgramImages.builder(programId); samplerCreator.accept(samplerBuilder, builder); customUniforms.mapholderToPass(uniformBuilder, this); + this.usesTessellation = usesTessellation; uniforms = uniformBuilder.buildUniforms(); this.customUniforms = customUniforms; @@ -160,6 +163,8 @@ public void apply() { IrisRenderSystem.bindTextureToUnit(TextureType.TEXTURE_2D.getGlType(), IrisSamplers.OVERLAY_TEXTURE_UNIT, RenderSystem.getShaderTexture(1)); IrisRenderSystem.bindTextureToUnit(TextureType.TEXTURE_2D.getGlType(), IrisSamplers.LIGHTMAP_TEXTURE_UNIT, RenderSystem.getShaderTexture(2)); + ImmediateState.usingTessellation = usesTessellation; + if (PROJECTION_MATRIX != null) { if (projectionInverse != null) { projectionInverse.set(tempMatrix4f.set(PROJECTION_MATRIX.getFloatBuffer()).invert().get(tempFloats)); @@ -237,10 +242,16 @@ public void attachToProgram() { if (this.geometry != null) { this.geometry.attachToShader(this); } + if (this.tessControl != null) { + this.tessControl.attachToShader(this); + } + if (this.tessEval != null) { + this.tessEval.attachToShader(this); + } } @Override - public void iris$createGeometryShader(ResourceProvider factory, String name) throws IOException { + public void iris$createExtraShaders(ResourceProvider factory, String name) throws IOException { factory.getResource(new ResourceLocation("minecraft", name + "_geometry.gsh")).ifPresent(geometry -> { try { this.geometry = Program.compileShader(IrisProgramTypes.GEOMETRY, name, geometry.open(), geometry.sourcePackId(), new GlslPreprocessor() { @@ -254,12 +265,46 @@ public String applyImport(boolean bl, String string) { e.printStackTrace(); } }); + factory.getResource(new ResourceLocation("minecraft", name + "_tessControl.tcs")).ifPresent(tessControl -> { + try { + this.tessControl = Program.compileShader(IrisProgramTypes.TESS_CONTROL, name, tessControl.open(), tessControl.sourcePackId(), new GlslPreprocessor() { + @Nullable + @Override + public String applyImport(boolean bl, String string) { + return null; + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + }); + factory.getResource(new ResourceLocation("minecraft", name + "_tessEval.tes")).ifPresent(tessEval -> { + try { + this.tessEval = Program.compileShader(IrisProgramTypes.TESS_EVAL, name, tessEval.open(), tessEval.sourcePackId(), new GlslPreprocessor() { + @Nullable + @Override + public String applyImport(boolean bl, String string) { + return null; + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + }); } public Program getGeometry() { return this.geometry; } + public Program getTessControl() { + return this.tessControl; + } + + public Program getTessEval() { + return this.tessEval; + } + public boolean hasActiveImages() { return images.getActiveImages() > 0; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/FakeChainedJsonException.java b/src/main/java/net/coderbot/iris/pipeline/newshader/FakeChainedJsonException.java index ebf79e12a2..5d387a45b9 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/FakeChainedJsonException.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/FakeChainedJsonException.java @@ -7,7 +7,7 @@ public class FakeChainedJsonException extends ChainedJsonException { private final ShaderCompileException trueException; public FakeChainedJsonException(ShaderCompileException e) { - super(""); + super("", e); this.trueException = e; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java b/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java index 43ddb734dd..2ab068c930 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/IrisProgramTypes.java @@ -4,4 +4,6 @@ public class IrisProgramTypes { public static Program.Type GEOMETRY; + public static Program.Type TESS_CONTROL; + public static Program.Type TESS_EVAL; } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java b/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java index f9f9c2a4eb..7138074bfe 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/NewShaderTests.java @@ -55,10 +55,14 @@ public static ExtendedShader create(WorldRenderingPipeline pipeline, String name name, source.getVertexSource().orElseThrow(RuntimeException::new), source.getGeometrySource().orElse(null), + source.getTessControlSource().orElse(null), + source.getTessEvalSource().orElse(null), source.getFragmentSource().orElseThrow(RuntimeException::new), alpha, isLines, true, inputs, pipeline.getTextureMap()); String vertex = transformed.get(PatchShaderType.VERTEX); String geometry = transformed.get(PatchShaderType.GEOMETRY); + String tessControl = transformed.get(PatchShaderType.TESS_CONTROL); + String tessEval = transformed.get(PatchShaderType.TESS_EVAL); String fragment = transformed.get(PatchShaderType.FRAGMENT); StringBuilder shaderJson = new StringBuilder("{\n" + @@ -97,7 +101,7 @@ public static ExtendedShader create(WorldRenderingPipeline pipeline, String name ShaderPrinter.printProgram(name).addSources(transformed).addJson(shaderJsonString).print(); - ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, geometry, fragment); + ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, geometry, tessControl, tessEval, fragment); List overrides = new ArrayList<>(); source.getDirectives().getBufferBlendOverrides().forEach(information -> { @@ -107,7 +111,7 @@ public static ExtendedShader create(WorldRenderingPipeline pipeline, String name } }); - return new ExtendedShader(shaderResourceFactory, name, vertexFormat, writingToBeforeTranslucent, writingToAfterTranslucent, baseline, blendModeOverride, alpha, uniforms -> { + return new ExtendedShader(shaderResourceFactory, name, vertexFormat, tessControl != null || tessEval != null, writingToBeforeTranslucent, writingToAfterTranslucent, baseline, blendModeOverride, alpha, uniforms -> { CommonUniforms.addDynamicUniforms(uniforms, FogMode.PER_VERTEX); customUniforms.assignTo(uniforms); //SamplerUniforms.addWorldSamplerUniforms(uniforms); @@ -174,7 +178,7 @@ public static FallbackShader createFallback(String name, GlFramebuffer writingTo .addJson(shaderJsonString) .print(); - ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, null, fragment); + ResourceProvider shaderResourceFactory = new IrisProgramResourceFactory(shaderJsonString, vertex, null, null, null, fragment); return new FallbackShader(shaderResourceFactory, name, vertexFormat, writingToBeforeTranslucent, writingToAfterTranslucent, blendModeOverride, alpha.getReference(), parent); @@ -184,12 +188,16 @@ private static class IrisProgramResourceFactory implements ResourceProvider { private final String json; private final String vertex; private final String geometry; + private final String tessControl; + private final String tessEval; private final String fragment; - public IrisProgramResourceFactory(String json, String vertex, String geometry, String fragment) { + public IrisProgramResourceFactory(String json, String vertex, String geometry, String tessControl, String tessEval, String fragment) { this.json = json; this.vertex = vertex; this.geometry = geometry; + this.tessControl = tessControl; + this.tessEval = tessEval; this.fragment = fragment; } @@ -206,6 +214,16 @@ public Optional getResource(ResourceLocation id) { return Optional.empty(); } return Optional.of(new StringResource(id, geometry)); + } else if (path.endsWith("tcs")) { + if (tessControl == null) { + return Optional.empty(); + } + return Optional.of(new StringResource(id, tessControl)); + } else if (path.endsWith("tes")) { + if (tessEval == null) { + return Optional.empty(); + } + return Optional.of(new StringResource(id, tessEval)); } else if (path.endsWith("fsh")) { return Optional.of(new StringResource(id, fragment)); } diff --git a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java index eda7a42905..a06505c06d 100644 --- a/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java +++ b/src/main/java/net/coderbot/iris/pipeline/newshader/ShaderInstanceInterface.java @@ -5,5 +5,5 @@ import java.io.IOException; public interface ShaderInstanceInterface { - void iris$createGeometryShader(ResourceProvider factory, String name) throws IOException; + void iris$createExtraShaders(ResourceProvider factory, String name) throws IOException; } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java b/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java index 7bfb08fd26..a3c8474b69 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/PatchShaderType.java @@ -5,6 +5,8 @@ public enum PatchShaderType { VERTEX(ShaderType.VERTEX, ".vsh"), GEOMETRY(ShaderType.GEOMETRY, ".gsh"), + TESS_CONTROL(ShaderType.TESSELATION_CONTROL, ".tcs"), + TESS_EVAL(ShaderType.TESSELATION_EVAL, ".tes"), FRAGMENT(ShaderType.FRAGMENT, ".fsh"), COMPUTE(ShaderType.COMPUTE, ".csh"); @@ -22,6 +24,10 @@ public static PatchShaderType[] fromGlShaderType(ShaderType glShaderType) { return new PatchShaderType[] { VERTEX }; case GEOMETRY: return new PatchShaderType[] { GEOMETRY }; + case TESSELATION_CONTROL: + return new PatchShaderType[] { TESS_CONTROL }; + case TESSELATION_EVAL: + return new PatchShaderType[] { TESS_EVAL }; case COMPUTE: return new PatchShaderType[] { COMPUTE }; case FRAGMENT: 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 f41bd8793b..2f6450c7af 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/TransformPatcher.java @@ -78,13 +78,17 @@ private static class CacheKey { final Parameters parameters; final String vertex; final String geometry; + final String tessControl; + final String tessEval; final String fragment; final String compute; - public CacheKey(Parameters parameters, String vertex, String geometry, String fragment) { + public CacheKey(Parameters parameters, String vertex, String geometry, String tessControl, String tessEval, String fragment) { this.parameters = parameters; this.vertex = vertex; this.geometry = geometry; + this.tessControl = tessControl; + this.tessEval = tessEval; this.fragment = fragment; this.compute = null; } @@ -93,6 +97,8 @@ public CacheKey(Parameters parameters, String compute) { this.parameters = parameters; this.vertex = null; this.geometry = null; + this.tessControl = null; + this.tessEval = null; this.fragment = null; this.compute = compute; } @@ -104,6 +110,8 @@ public int hashCode() { result = prime * result + ((parameters == null) ? 0 : parameters.hashCode()); result = prime * result + ((vertex == null) ? 0 : vertex.hashCode()); result = prime * result + ((geometry == null) ? 0 : geometry.hashCode()); + result = prime * result + ((tessControl == null) ? 0 : tessControl.hashCode()); + result = prime * result + ((tessEval == null) ? 0 : tessEval.hashCode()); result = prime * result + ((fragment == null) ? 0 : fragment.hashCode()); result = prime * result + ((compute == null) ? 0 : compute.hashCode()); return result; @@ -133,6 +141,16 @@ public boolean equals(Object obj) { return false; } else if (!geometry.equals(other.geometry)) return false; + if (tessControl == null) { + if (other.tessControl != null) + return false; + } else if (!tessControl.equals(other.tessControl)) + return false; + if (tessEval == null) { + if (other.tessEval != null) + return false; + } else if (!tessEval.equals(other.tessEval)) + return false; if (fragment == null) { if (other.fragment != null) return false; @@ -177,11 +195,7 @@ public TranslationUnit parseTranslationUnit(Root rootInstance, String input) { throw new IllegalArgumentException( "No #version directive found in source code! See debugging.md for more information."); } - Version version = Version.fromNumber(Integer.parseInt(matcher.group(1))); - if (version.number >= 200) { - version = Version.GLSL33; - } - transformer.getLexer().version = version; + transformer.getLexer().version = Version.fromNumber(Integer.parseInt(matcher.group(1))); return super.parseTranslationUnit(rootInstance, input); } @@ -301,10 +315,10 @@ private static Map transformInternal( } } - private static Map transform(String name, String vertex, String geometry, String fragment, + private static Map transform(String name, String vertex, String geometry, String tessControl, String tessEval, String fragment, Parameters parameters) { // stop if all are null - if (vertex == null && geometry == null && fragment == null) { + if (vertex == null && geometry == null && tessControl == null && tessEval == null && fragment == null) { return null; } @@ -312,7 +326,7 @@ private static Map transform(String name, String vertex CacheKey key; Map result = null; if (useCache) { - key = new CacheKey(parameters, vertex, geometry, fragment); + key = new CacheKey(parameters, vertex, geometry, tessControl, tessEval, fragment); if (cache.containsKey(key)) { result = cache.get(key); } @@ -324,6 +338,8 @@ private static Map transform(String name, String vertex EnumMap inputs = new EnumMap<>(PatchShaderType.class); inputs.put(PatchShaderType.VERTEX, vertex); inputs.put(PatchShaderType.GEOMETRY, geometry); + inputs.put(PatchShaderType.TESS_CONTROL, tessControl); + inputs.put(PatchShaderType.TESS_EVAL, tessEval); inputs.put(PatchShaderType.FRAGMENT, fragment); result = transformInternal(name, inputs, parameters); @@ -365,19 +381,19 @@ private static Map transformCompute(String name, String } public static Map patchVanilla( - String name, String vertex, String geometry, String fragment, + String name, String vertex, String geometry, String tessControl, String tessEval, String fragment, AlphaTest alpha, boolean isLines, boolean hasChunkOffset, ShaderAttributeInputs inputs, Object2ObjectMap, String> textureMap) { - return transform(name, vertex, geometry, fragment, - new VanillaParameters(Patch.VANILLA, textureMap, alpha, isLines, hasChunkOffset, inputs, geometry != null)); + return transform(name, vertex, geometry, tessControl, tessEval, fragment, + new VanillaParameters(Patch.VANILLA, textureMap, alpha, isLines, hasChunkOffset, inputs, geometry != null, tessControl != null || tessEval != null)); } - public static Map patchSodium(String name, String vertex, String geometry, String fragment, + public static Map patchSodium(String name, String vertex, String geometry, String tessControl, String tessEval, String fragment, AlphaTest alpha, ShaderAttributeInputs inputs, Object2ObjectMap, String> textureMap) { - return transform(name, vertex, geometry, fragment, + return transform(name, vertex, geometry, tessControl, tessEval, fragment, new SodiumParameters(Patch.SODIUM, textureMap, alpha, inputs)); } @@ -385,7 +401,7 @@ public static Map patchComposite( String name, String vertex, String geometry, String fragment, TextureStage stage, Object2ObjectMap, String> textureMap) { - return transform(name, vertex, geometry, fragment, new TextureStageParameters(Patch.COMPOSITE, stage, textureMap)); + return transform(name, vertex, geometry, null, null, fragment, new TextureStageParameters(Patch.COMPOSITE, stage, textureMap)); } public static String patchCompute( diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java index 83b6659530..fd9a81ecfe 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/AttributeParameters.java @@ -15,7 +15,7 @@ public AttributeParameters(Patch patch, Object2ObjectMap, String> textureMap, boolean hasGeometry, InputAvailability inputs) { - super(patch, textureMap, hasGeometry); + super(patch, textureMap, hasGeometry, false); this.inputs = inputs; } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/GeometryInfoParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/GeometryInfoParameters.java index ad57e6add9..dcfec4f283 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/GeometryInfoParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/GeometryInfoParameters.java @@ -8,12 +8,14 @@ public abstract class GeometryInfoParameters extends Parameters { public final boolean hasGeometry; + public final boolean hasTesselation; // WARNING: adding new fields requires updating hashCode and equals methods! public GeometryInfoParameters(Patch patch, - Object2ObjectMap, String> textureMap, boolean hasGeometry) { + Object2ObjectMap, String> textureMap, boolean hasGeometry, boolean hasTesselation) { super(patch, textureMap); this.hasGeometry = hasGeometry; + this.hasTesselation = hasTesselation; } @Override diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java index 86f027b4a9..08f6309aad 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/parameter/VanillaParameters.java @@ -19,8 +19,8 @@ public VanillaParameters( Patch patch, Object2ObjectMap, String> textureMap, AlphaTest alpha, boolean isLines, boolean hasChunkOffset, - ShaderAttributeInputs inputs, boolean hasGeometry) { - super(patch, textureMap, hasGeometry); + ShaderAttributeInputs inputs, boolean hasGeometry, boolean hasTesselation) { + super(patch, textureMap, hasGeometry, hasTesselation); this.alpha = alpha; this.isLines = isLines; this.hasChunkOffset = hasChunkOffset; diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java index e140e1bcd5..baa53ad1d8 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/AttributeTransformer.java @@ -167,6 +167,32 @@ public static void patchOverlayColor( // Some shader packs incorrectly ignore the alpha value, and assume that rgb // will be zero if there is no hit flash, we try to emulate that here "entityColor.rgb *= float(entityColor.a != 0.0);"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_CONTROL) { + // replace read references to grab the color from the first vertex. + root.replaceReferenceExpressions(t, "entityColor", "entityColor[gl_InvocationID]"); + + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "patch out vec4 entityColorTCS;", + "in vec4 entityColor[];", + "out vec4 iris_vertexColorTCS[];", + "in vec4 iris_vertexColor[];"); + tree.prependMainFunctionBody(t, + "entityColorTCS = entityColor[gl_InvocationID];", + "iris_vertexColorTCS[gl_InvocationID] = iris_vertexColor[gl_InvocationID];"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_EVAL) { + // replace read references to grab the color from the first vertex. + root.replaceReferenceExpressions(t, "entityColor", "entityColorTCS"); + + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "out vec4 entityColorTES;", + "patch in vec4 entityColorTCS;", + "out vec4 iris_vertexColorTES;", + "in vec4 iris_vertexColorTCS[];"); + tree.prependMainFunctionBody(t, + "entityColorTES = entityColorTCS;", + "iris_vertexColorTES = iris_vertexColorTCS[0];"); } else if (parameters.type.glShaderType == ShaderType.GEOMETRY) { // replace read references to grab the color from the first vertex. root.replaceReferenceExpressions(t, "entityColor", "entityColor[0]"); @@ -180,6 +206,11 @@ public static void patchOverlayColor( tree.prependMainFunctionBody(t, "entityColorGS = entityColor[0];", "iris_vertexColorGS = iris_vertexColor[0];"); + + if (parameters.hasTesselation) { + root.rename("iris_vertexColor", "iris_vertexColorTES"); + root.rename("entityColor", "entityColorTES"); + } } else if (parameters.type.glShaderType == ShaderType.FRAGMENT) { tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "in vec4 entityColor;", "in vec4 iris_vertexColor;"); @@ -190,6 +221,9 @@ public static void patchOverlayColor( if (parameters.hasGeometry) { root.rename("entityColor", "entityColorGS"); root.rename("iris_vertexColor", "iris_vertexColorGS"); + } else if (parameters.hasTesselation) { + root.rename("entityColor", "entityColorTES"); + root.rename("iris_vertexColor", "iris_vertexColorTES"); } } } @@ -238,13 +272,32 @@ public static void patchEntityId( // stage. tree.prependMainFunctionBody(t, "iris_entityInfo = iris_Entity;"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_CONTROL) { + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "flat out ivec3 iris_entityInfoTCS[];", + "flat in ivec3 iris_entityInfo[];"); + root.replaceReferenceExpressions(t, "iris_entityInfo", "iris_EntityInfo[gl_InvocationID]"); + + tree.prependMainFunctionBody(t, + "iris_entityInfoTCS[gl_InvocationID] = iris_entityInfo[gl_InvocationID];"); + } else if (parameters.type.glShaderType == ShaderType.TESSELATION_EVAL) { + // TODO: this is passthrough behavior + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "flat out ivec3 iris_entityInfoTES;", + "flat in ivec3 iris_entityInfoTCS[];"); + tree.prependMainFunctionBody(t, + "iris_entityInfoTES = iris_entityInfoTCS[0];"); + + root.replaceReferenceExpressions(t, "iris_entityInfo", "iris_EntityInfoTCS[0]"); + } else if (parameters.type.glShaderType == ShaderType.GEOMETRY) { // TODO: this is passthrough behavior tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "flat out ivec3 iris_entityInfoGS;", - "flat in ivec3 iris_entityInfo[];"); + "flat in ivec3 iris_entityInfo" + (parameters.hasTesselation ? "TES" : "") + "[];"); tree.prependMainFunctionBody(t, - "iris_entityInfoGS = iris_entityInfo[0];"); + "iris_entityInfoGS = iris_entityInfo" + (parameters.hasTesselation ? "TES" : "") + "[0];"); } else if (parameters.type.glShaderType == ShaderType.FRAGMENT) { tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, "flat in ivec3 iris_entityInfo;"); @@ -252,6 +305,8 @@ public static void patchEntityId( // Different output name to avoid a name collision in the geometry shader. if (parameters.hasGeometry) { root.rename("iris_entityInfo", "iris_EntityInfoGS"); + } else if (parameters.hasTesselation) { + root.rename("iris_entityInfo", "iris_entityInfoTES"); } } } diff --git a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java index 8c403790fe..334e7f7842 100644 --- a/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java +++ b/src/main/java/net/coderbot/iris/pipeline/transform/transformer/CompatibilityTransformer.java @@ -308,7 +308,7 @@ public boolean matchesExtract(ExternalDeclaration tree) { } } - private static final ShaderType[] pipeline = { ShaderType.VERTEX, ShaderType.GEOMETRY, ShaderType.FRAGMENT }; + private static final ShaderType[] pipeline = { ShaderType.VERTEX, ShaderType.TESSELATION_CONTROL, ShaderType.TESSELATION_EVAL, ShaderType.GEOMETRY, ShaderType.FRAGMENT }; private static final Matcher outDeclarationMatcher = new DeclarationMatcher( StorageType.OUT); private static final Matcher inDeclarationMatcher = new DeclarationMatcher( diff --git a/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java b/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java index 9bda863650..63e116473c 100644 --- a/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java +++ b/src/main/java/net/coderbot/iris/postprocess/CompositeRenderer.java @@ -18,6 +18,7 @@ import net.coderbot.iris.gl.IrisRenderSystem; import net.coderbot.iris.gl.blending.BlendModeOverride; import net.coderbot.iris.gl.framebuffer.GlFramebuffer; +import net.coderbot.iris.gl.framebuffer.ViewportData; import net.coderbot.iris.gl.image.GlImage; import net.coderbot.iris.gl.program.ComputeProgram; import net.coderbot.iris.gl.program.Program; @@ -27,6 +28,7 @@ import net.coderbot.iris.gl.sampler.SamplerLimits; import net.coderbot.iris.gl.shader.ShaderCompileException; import net.coderbot.iris.gl.texture.TextureAccess; +import net.coderbot.iris.mixin.GlStateManagerAccessor; import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline; import net.coderbot.iris.pipeline.WorldRenderingPipeline; import net.coderbot.iris.rendertarget.RenderTarget; @@ -212,7 +214,7 @@ private static class Pass { ImmutableSet flippedAtLeastOnce; ImmutableSet stageReadsFromAlt; ImmutableSet mipmappedBuffers; - float viewportScale; + ViewportData viewportScale; protected void destroy() { this.program.destroy(); @@ -270,9 +272,11 @@ public void renderAll() { } } - float scaledWidth = renderPass.viewWidth * renderPass.viewportScale; - float scaledHeight = renderPass.viewHeight * renderPass.viewportScale; - RenderSystem.viewport(0, 0, (int) scaledWidth, (int) scaledHeight); + float scaledWidth = renderPass.viewWidth * renderPass.viewportScale.scale(); + float scaledHeight = renderPass.viewHeight * renderPass.viewportScale.scale(); + int beginWidth = (int) (renderPass.viewWidth * renderPass.viewportScale.viewportX()); + int beginHeight = (int) (renderPass.viewHeight * renderPass.viewportScale.viewportY()); + RenderSystem.viewport(beginWidth, beginHeight, (int) scaledWidth, (int) scaledHeight); renderPass.framebuffer.bind(); renderPass.program.use(); @@ -303,8 +307,10 @@ public void renderAll() { for (int i = 0; i < SamplerLimits.get().getMaxTextureUnits(); i++) { // Unbind all textures that we may have used. // NB: This is necessary for shader pack reloading to work propely - RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); - RenderSystem.bindTexture(0); + if (GlStateManagerAccessor.getTEXTURES()[i].binding != 0) { + RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); + RenderSystem.bindTexture(0); + } } RenderSystem.activeTexture(GL15C.GL_TEXTURE0); diff --git a/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java b/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java index de5b78a2c0..c9e8261c9a 100644 --- a/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java +++ b/src/main/java/net/coderbot/iris/postprocess/FinalPassRenderer.java @@ -19,6 +19,7 @@ import net.coderbot.iris.gl.program.ProgramUniforms; import net.coderbot.iris.gl.sampler.SamplerLimits; import net.coderbot.iris.gl.texture.TextureAccess; +import net.coderbot.iris.mixin.GlStateManagerAccessor; import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline; import net.coderbot.iris.pipeline.ShaderPrinter; import net.coderbot.iris.pipeline.WorldRenderingPipeline; @@ -276,8 +277,10 @@ public void renderFinalPass() { for (int i = 0; i < SamplerLimits.get().getMaxTextureUnits(); i++) { // Unbind all textures that we may have used. // NB: This is necessary for shader pack reloading to work properly - RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); - RenderSystem.bindTexture(0); + if (GlStateManagerAccessor.getTEXTURES()[i].binding != 0) { + RenderSystem.activeTexture(GL15C.GL_TEXTURE0 + i); + RenderSystem.bindTexture(0); + } } RenderSystem.activeTexture(GL15C.GL_TEXTURE0); diff --git a/src/main/java/net/coderbot/iris/postprocess/FullScreenQuadRenderer.java b/src/main/java/net/coderbot/iris/postprocess/FullScreenQuadRenderer.java index fe398adda5..0a72570989 100644 --- a/src/main/java/net/coderbot/iris/postprocess/FullScreenQuadRenderer.java +++ b/src/main/java/net/coderbot/iris/postprocess/FullScreenQuadRenderer.java @@ -7,6 +7,7 @@ import com.mojang.blaze3d.vertex.VertexBuffer; import com.mojang.blaze3d.vertex.VertexFormat; import net.coderbot.iris.fantastic.VertexBufferHelper; +import net.coderbot.iris.gl.IrisRenderSystem; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20C; @@ -53,7 +54,9 @@ public void begin() { } public void renderQuad() { + IrisRenderSystem.overridePolygonMode(); quad.draw(); + IrisRenderSystem.restorePolygonMode(); } public void end() { diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java index 618977d06f..6f93cea169 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramDirectives.java @@ -11,6 +11,7 @@ import net.coderbot.iris.gl.blending.BlendMode; import net.coderbot.iris.gl.blending.BlendModeOverride; import net.coderbot.iris.gl.blending.BufferBlendInformation; +import net.coderbot.iris.gl.framebuffer.ViewportData; import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -24,7 +25,7 @@ public class ProgramDirectives { private static final ImmutableList LEGACY_RENDER_TARGETS = PackRenderTargetDirectives.LEGACY_RENDER_TARGETS; private final int[] drawBuffers; - private final float viewportScale; + private final ViewportData viewportScale; @Nullable private final AlphaTest alphaTestOverride; @@ -34,7 +35,7 @@ public class ProgramDirectives { private final ImmutableMap explicitFlips; private boolean unknownDrawBuffers; - private ProgramDirectives(int[] drawBuffers, float viewportScale, @Nullable AlphaTest alphaTestOverride, + private ProgramDirectives(int[] drawBuffers, ViewportData viewportScale, @Nullable AlphaTest alphaTestOverride, Optional blendModeOverride, List bufferBlendInformations, ImmutableSet mipmappedBuffers, ImmutableMap explicitFlips) { this.drawBuffers = drawBuffers; @@ -74,7 +75,7 @@ private ProgramDirectives(int[] drawBuffers, float viewportScale, @Nullable Alph }); if (properties != null) { - viewportScale = properties.getViewportScaleOverrides().getOrDefault(source.getName(), 1.0f); + viewportScale = properties.getViewportScaleOverrides().getOrDefault(source.getName(), ViewportData.defaultValue()); alphaTestOverride = properties.getAlphaTestOverrides().get(source.getName()); BlendModeOverride blendModeOverride = properties.getBlendModeOverrides().get(source.getName()); @@ -84,7 +85,7 @@ private ProgramDirectives(int[] drawBuffers, float viewportScale, @Nullable Alph explicitFlips = source.getParent().getPackDirectives().getExplicitFlips(source.getName()); } else { - viewportScale = 1.0f; + viewportScale = ViewportData.defaultValue(); alphaTestOverride = null; blendModeOverride = Optional.ofNullable(defaultBlendOverride); bufferBlendInformations = Collections.emptyList(); @@ -173,7 +174,7 @@ public boolean hasUnknownDrawBuffers() { return unknownDrawBuffers; } - public float getViewportScale() { + public ViewportData getViewportScale() { return viewportScale; } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java index 36c37b0681..10d5a25a4a 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramSet.java @@ -1,6 +1,7 @@ package net.coderbot.iris.shaderpack; import net.coderbot.iris.Iris; +import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gl.blending.BlendMode; import net.coderbot.iris.gl.blending.BlendModeFunction; import net.coderbot.iris.gl.blending.BlendModeOverride; @@ -81,11 +82,13 @@ public ProgramSet(AbsolutePackPath directory, Function // // - https://github.com/IrisShaders/Iris/issues/483 // - https://github.com/IrisShaders/Iris/issues/987 + boolean readTesselation = pack.hasFeature(FeatureFlags.TESSELATION_SHADERS); + this.shadow = readProgramSource(directory, sourceProvider, "shadow", this, shaderProperties, - BlendModeOverride.OFF); + BlendModeOverride.OFF, readTesselation); this.shadowCompute = readComputeArray(directory, sourceProvider, "shadow"); - this.shadowcomp = readProgramArray(directory, sourceProvider, "shadowcomp", shaderProperties); + this.shadowcomp = readProgramArray(directory, sourceProvider, "shadowcomp", shaderProperties, readTesselation); this.shadowCompCompute = new ComputeSource[shadowcomp.length][]; for (int i = 0; i < shadowcomp.length; i++) { @@ -94,57 +97,57 @@ public ProgramSet(AbsolutePackPath directory, Function this.setup = readProgramArray(directory, sourceProvider, "setup"); - this.begin = readProgramArray(directory, sourceProvider, "begin", shaderProperties); + this.begin = readProgramArray(directory, sourceProvider, "begin", shaderProperties, readTesselation); this.beginCompute = new ComputeSource[begin.length][]; for (int i = 0; i < begin.length; i++) { this.beginCompute[i] = readComputeArray(directory, sourceProvider, "begin" + ((i == 0) ? "" : i)); } - this.prepare = readProgramArray(directory, sourceProvider, "prepare", shaderProperties); + this.prepare = readProgramArray(directory, sourceProvider, "prepare", shaderProperties, readTesselation); this.prepareCompute = new ComputeSource[prepare.length][]; for (int i = 0; i < prepare.length; i++) { this.prepareCompute[i] = readComputeArray(directory, sourceProvider, "prepare" + ((i == 0) ? "" : i)); } - this.gbuffersBasic = readProgramSource(directory, sourceProvider, "gbuffers_basic", this, shaderProperties); - this.gbuffersLine = readProgramSource(directory, sourceProvider, "gbuffers_line", this, shaderProperties); - this.gbuffersBeaconBeam = readProgramSource(directory, sourceProvider, "gbuffers_beaconbeam", this, shaderProperties); - this.gbuffersTextured = readProgramSource(directory, sourceProvider, "gbuffers_textured", this, shaderProperties); - this.gbuffersTexturedLit = readProgramSource(directory, sourceProvider, "gbuffers_textured_lit", this, shaderProperties); - this.gbuffersTerrain = readProgramSource(directory, sourceProvider, "gbuffers_terrain", this, shaderProperties); - this.gbuffersTerrainSolid = readProgramSource(directory, sourceProvider, "gbuffers_terrain_solid", this, shaderProperties); - this.gbuffersTerrainCutout = readProgramSource(directory, sourceProvider, "gbuffers_terrain_cutout", this, shaderProperties); - this.gbuffersDamagedBlock = readProgramSource(directory, sourceProvider, "gbuffers_damagedblock", this, shaderProperties); - this.gbuffersSkyBasic = readProgramSource(directory, sourceProvider, "gbuffers_skybasic", this, shaderProperties); - this.gbuffersSkyTextured = readProgramSource(directory, sourceProvider, "gbuffers_skytextured", this, shaderProperties); - this.gbuffersClouds = readProgramSource(directory, sourceProvider, "gbuffers_clouds", this, shaderProperties); - this.gbuffersWeather = readProgramSource(directory, sourceProvider, "gbuffers_weather", this, shaderProperties); - this.gbuffersEntities = readProgramSource(directory, sourceProvider, "gbuffers_entities", this, shaderProperties); - this.gbuffersEntitiesTrans = readProgramSource(directory, sourceProvider, "gbuffers_entities_translucent", this, shaderProperties); - this.gbuffersParticles = readProgramSource(directory, sourceProvider, "gbuffers_particles", this, shaderProperties); - this.gbuffersParticlesTrans = readProgramSource(directory, sourceProvider, "gbuffers_particles_translucent", this, shaderProperties); - this.gbuffersEntitiesGlowing = readProgramSource(directory, sourceProvider, "gbuffers_entities_glowing", this, shaderProperties); - this.gbuffersGlint = readProgramSource(directory, sourceProvider, "gbuffers_armor_glint", this, shaderProperties); - this.gbuffersEntityEyes = readProgramSource(directory, sourceProvider, "gbuffers_spidereyes", this, shaderProperties); - this.gbuffersBlock = readProgramSource(directory, sourceProvider, "gbuffers_block", this, shaderProperties); - this.gbuffersBlockTrans = readProgramSource(directory, sourceProvider, "gbuffers_block_translucent", this, shaderProperties); - this.gbuffersHand = readProgramSource(directory, sourceProvider, "gbuffers_hand", this, shaderProperties); - - this.deferred = readProgramArray(directory, sourceProvider, "deferred", shaderProperties); + this.gbuffersBasic = readProgramSource(directory, sourceProvider, "gbuffers_basic", this, shaderProperties, readTesselation); + this.gbuffersLine = readProgramSource(directory, sourceProvider, "gbuffers_line", this, shaderProperties, readTesselation); + this.gbuffersBeaconBeam = readProgramSource(directory, sourceProvider, "gbuffers_beaconbeam", this, shaderProperties, readTesselation); + this.gbuffersTextured = readProgramSource(directory, sourceProvider, "gbuffers_textured", this, shaderProperties, readTesselation); + this.gbuffersTexturedLit = readProgramSource(directory, sourceProvider, "gbuffers_textured_lit", this, shaderProperties, readTesselation); + this.gbuffersTerrain = readProgramSource(directory, sourceProvider, "gbuffers_terrain", this, shaderProperties, readTesselation); + this.gbuffersTerrainSolid = readProgramSource(directory, sourceProvider, "gbuffers_terrain_solid", this, shaderProperties, readTesselation); + this.gbuffersTerrainCutout = readProgramSource(directory, sourceProvider, "gbuffers_terrain_cutout", this, shaderProperties, readTesselation); + this.gbuffersDamagedBlock = readProgramSource(directory, sourceProvider, "gbuffers_damagedblock", this, shaderProperties, readTesselation); + this.gbuffersSkyBasic = readProgramSource(directory, sourceProvider, "gbuffers_skybasic", this, shaderProperties, readTesselation); + this.gbuffersSkyTextured = readProgramSource(directory, sourceProvider, "gbuffers_skytextured", this, shaderProperties, readTesselation); + this.gbuffersClouds = readProgramSource(directory, sourceProvider, "gbuffers_clouds", this, shaderProperties, readTesselation); + this.gbuffersWeather = readProgramSource(directory, sourceProvider, "gbuffers_weather", this, shaderProperties, readTesselation); + this.gbuffersEntities = readProgramSource(directory, sourceProvider, "gbuffers_entities", this, shaderProperties, readTesselation); + this.gbuffersEntitiesTrans = readProgramSource(directory, sourceProvider, "gbuffers_entities_translucent", this, shaderProperties, readTesselation); + this.gbuffersParticles = readProgramSource(directory, sourceProvider, "gbuffers_particles", this, shaderProperties, readTesselation); + this.gbuffersParticlesTrans = readProgramSource(directory, sourceProvider, "gbuffers_particles_translucent", this, shaderProperties, readTesselation); + this.gbuffersEntitiesGlowing = readProgramSource(directory, sourceProvider, "gbuffers_entities_glowing", this, shaderProperties, readTesselation); + this.gbuffersGlint = readProgramSource(directory, sourceProvider, "gbuffers_armor_glint", this, shaderProperties, readTesselation); + this.gbuffersEntityEyes = readProgramSource(directory, sourceProvider, "gbuffers_spidereyes", this, shaderProperties, readTesselation); + this.gbuffersBlock = readProgramSource(directory, sourceProvider, "gbuffers_block", this, shaderProperties, readTesselation); + this.gbuffersBlockTrans = readProgramSource(directory, sourceProvider, "gbuffers_block_translucent", this, shaderProperties, readTesselation); + this.gbuffersHand = readProgramSource(directory, sourceProvider, "gbuffers_hand", this, shaderProperties, readTesselation); + + this.deferred = readProgramArray(directory, sourceProvider, "deferred", shaderProperties, readTesselation); this.deferredCompute = new ComputeSource[deferred.length][]; for (int i = 0; i < deferred.length; i++) { this.deferredCompute[i] = readComputeArray(directory, sourceProvider, "deferred" + ((i == 0) ? "" : i)); } - this.gbuffersWater = readProgramSource(directory, sourceProvider, "gbuffers_water", this, shaderProperties); - this.gbuffersHandWater = readProgramSource(directory, sourceProvider, "gbuffers_hand_water", this, shaderProperties); + this.gbuffersWater = readProgramSource(directory, sourceProvider, "gbuffers_water", this, shaderProperties, readTesselation); + this.gbuffersHandWater = readProgramSource(directory, sourceProvider, "gbuffers_hand_water", this, shaderProperties, readTesselation); - this.composite = readProgramArray(directory, sourceProvider, "composite", shaderProperties); + this.composite = readProgramArray(directory, sourceProvider, "composite", shaderProperties, readTesselation); this.compositeCompute = new ComputeSource[composite.length][]; for (int i = 0; i < deferred.length; i++) { this.compositeCompute[i] = readComputeArray(directory, sourceProvider, "composite" + ((i == 0) ? "" : i)); } - this.compositeFinal = readProgramSource(directory, sourceProvider, "final", this, shaderProperties); + this.compositeFinal = readProgramSource(directory, sourceProvider, "final", this, shaderProperties, readTesselation); this.finalCompute = readComputeArray(directory, sourceProvider, "final"); locateDirectives(); @@ -173,13 +176,13 @@ private static Optional first(Optional... candidates) { private ProgramSource[] readProgramArray(AbsolutePackPath directory, Function sourceProvider, String name, - ShaderProperties shaderProperties) { + ShaderProperties shaderProperties, boolean readTesselation) { ProgramSource[] programs = new ProgramSource[100]; for (int i = 0; i < programs.length; i++) { String suffix = i == 0 ? "" : Integer.toString(i); - programs[i] = readProgramSource(directory, sourceProvider, name + suffix, this, shaderProperties); + programs[i] = readProgramSource(directory, sourceProvider, name + suffix, this, shaderProperties, readTesselation); } return programs; @@ -501,20 +504,31 @@ public ShaderPack getPack() { private static ProgramSource readProgramSource(AbsolutePackPath directory, Function sourceProvider, String program, - ProgramSet programSet, ShaderProperties properties) { - return readProgramSource(directory, sourceProvider, program, programSet, properties, null); + ProgramSet programSet, ShaderProperties properties, boolean readTesselation) { + return readProgramSource(directory, sourceProvider, program, programSet, properties, null, readTesselation); } private static ProgramSource readProgramSource(AbsolutePackPath directory, Function sourceProvider, String program, ProgramSet programSet, ShaderProperties properties, - BlendModeOverride defaultBlendModeOverride) { + BlendModeOverride defaultBlendModeOverride, boolean readTesselation) { AbsolutePackPath vertexPath = directory.resolve(program + ".vsh"); String vertexSource = sourceProvider.apply(vertexPath); AbsolutePackPath geometryPath = directory.resolve(program + ".gsh"); String geometrySource = sourceProvider.apply(geometryPath); + String tessControlSource = null; + String tessEvalSource = null; + + if (readTesselation) { + AbsolutePackPath tessControlPath = directory.resolve(program + ".tcs"); + tessControlSource = sourceProvider.apply(tessControlPath); + + AbsolutePackPath tessEvalPath = directory.resolve(program + ".tes"); + tessEvalSource = sourceProvider.apply(tessEvalPath); + } + AbsolutePackPath fragmentPath = directory.resolve(program + ".fsh"); String fragmentSource = sourceProvider.apply(fragmentPath); @@ -537,7 +551,7 @@ void main() { """; } - return new ProgramSource(program, vertexSource, geometrySource, fragmentSource, programSet, properties, + return new ProgramSource(program, vertexSource, geometrySource, tessControlSource, tessEvalSource, fragmentSource, programSet, properties, defaultBlendModeOverride); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java b/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java index 9ef8500a73..c519567dc8 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ProgramSource.java @@ -8,25 +8,31 @@ public class ProgramSource { private final String name; private final String vertexSource; private final String geometrySource; + private final String tessControlSource; + private final String tessEvalSource; private final String fragmentSource; private final ProgramDirectives directives; private final ProgramSet parent; - private ProgramSource(String name, String vertexSource, String geometrySource, String fragmentSource, + private ProgramSource(String name, String vertexSource, String geometrySource, String tessControlSource, String tessEvalSource, String fragmentSource, ProgramDirectives directives, ProgramSet parent) { this.name = name; this.vertexSource = vertexSource; this.geometrySource = geometrySource; + this.tessControlSource = tessControlSource; + this.tessEvalSource = tessEvalSource; this.fragmentSource = fragmentSource; this.directives = directives; this.parent = parent; } - public ProgramSource(String name, String vertexSource, String geometrySource, String fragmentSource, + public ProgramSource(String name, String vertexSource, String geometrySource, String tessControlSource, String tessEvalSource, String fragmentSource, ProgramSet parent, ShaderProperties properties, BlendModeOverride defaultBlendModeOverride) { this.name = name; this.vertexSource = vertexSource; this.geometrySource = geometrySource; + this.tessControlSource = tessControlSource; + this.tessEvalSource = tessEvalSource; this.fragmentSource = fragmentSource; this.parent = parent; this.directives = new ProgramDirectives(this, properties, @@ -34,7 +40,7 @@ public ProgramSource(String name, String vertexSource, String geometrySource, St } public ProgramSource withDirectiveOverride(ProgramDirectives overrideDirectives) { - return new ProgramSource(name, vertexSource, geometrySource, fragmentSource, overrideDirectives, parent); + return new ProgramSource(name, vertexSource, geometrySource, tessControlSource, tessEvalSource, fragmentSource, overrideDirectives, parent); } public String getName() { @@ -49,6 +55,14 @@ public Optional getGeometrySource() { return Optional.ofNullable(geometrySource); } + public Optional getTessControlSource() { + return Optional.ofNullable(tessControlSource); + } + + public Optional getTessEvalSource() { + return Optional.ofNullable(tessEvalSource); + } + public Optional getFragmentSource() { return Optional.ofNullable(fragmentSource); } diff --git a/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java b/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java index 6276c953e3..732750bb83 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java +++ b/src/main/java/net/coderbot/iris/shaderpack/ShaderProperties.java @@ -17,6 +17,7 @@ import net.coderbot.iris.gl.blending.BlendModeFunction; import net.coderbot.iris.gl.blending.BlendModeOverride; import net.coderbot.iris.gl.buffer.ShaderStorageInfo; +import net.coderbot.iris.gl.framebuffer.ViewportData; import net.coderbot.iris.gl.texture.InternalTextureFormat; import net.coderbot.iris.gl.texture.PixelFormat; import net.coderbot.iris.gl.texture.PixelType; @@ -92,7 +93,7 @@ public class ShaderProperties { // TODO: private Map optifineVersionRequirements; // TODO: Parse custom uniforms / variables private final Object2ObjectMap alphaTestOverrides = new Object2ObjectOpenHashMap<>(); - private final Object2FloatMap viewportScaleOverrides = new Object2FloatOpenHashMap<>(); + private final Object2ObjectMap viewportScaleOverrides = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap textureScaleOverrides = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap blendModeOverrides = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap> bufferBlendOverrides = new Object2ObjectOpenHashMap<>(); @@ -212,16 +213,22 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It // TODO: Custom uniforms handlePassDirective("scale.", key, value, pass -> { - float scale; + float scale, offsetX = 0.0f, offsetY = 0.0f; + String[] parts = value.split(" "); try { - scale = Float.parseFloat(value); - } catch (NumberFormatException e) { + scale = Float.parseFloat(parts[0]); + + if (parts.length > 1) { + offsetX = Float.parseFloat(parts[1]); + offsetY = Float.parseFloat(parts[2]); + } + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { Iris.logger.error("Unable to parse scale directive for " + pass + ": " + value, e); return; } - viewportScaleOverrides.put(pass, scale); + viewportScaleOverrides.put(pass, new ViewportData(scale, offsetX, offsetY)); }); handlePassDirective("size.buffer.", key, value, pass -> { @@ -793,7 +800,7 @@ public OptionalBoolean getPrepareBeforeShadow() { return prepareBeforeShadow; } - public Object2FloatMap getViewportScaleOverrides() { + public Object2ObjectMap getViewportScaleOverrides() { return viewportScaleOverrides; } diff --git a/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java b/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java index 7709618e0e..31556ab7c9 100644 --- a/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java +++ b/src/main/java/net/coderbot/iris/shaderpack/include/ShaderPackSourceNames.java @@ -74,6 +74,8 @@ private static ImmutableList findPotentialStarts() { private static void addStarts(ImmutableList.Builder potentialFileNames, String baseName) { potentialFileNames.add(baseName + ".vsh"); + potentialFileNames.add(baseName + ".tcs"); + potentialFileNames.add(baseName + ".tes"); potentialFileNames.add(baseName + ".gsh"); potentialFileNames.add(baseName + ".fsh"); } diff --git a/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java index fe6adb8adb..6185064ffe 100644 --- a/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java +++ b/src/main/java/net/coderbot/iris/shadows/ShadowCompositeRenderer.java @@ -7,6 +7,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.coderbot.iris.Iris; +import net.coderbot.iris.gl.framebuffer.ViewportData; import net.coderbot.iris.gl.image.GlImage; import net.coderbot.iris.features.FeatureFlags; import net.coderbot.iris.gl.IrisRenderSystem; @@ -154,7 +155,7 @@ private static class Pass { ImmutableSet flippedAtLeastOnce; ImmutableSet stageReadsFromAlt; ImmutableSet mipmappedBuffers; - float viewportScale; + ViewportData viewportScale; ComputeProgram[] computes; protected void destroy() { @@ -213,9 +214,11 @@ public void renderAll() { } } - float scaledWidth = renderTargets.getResolution() * renderPass.viewportScale; - float scaledHeight = renderTargets.getResolution() * renderPass.viewportScale; - RenderSystem.viewport(0, 0, (int) scaledWidth, (int) scaledHeight); + float scaledWidth = renderTargets.getResolution() * renderPass.viewportScale.scale(); + float scaledHeight = renderTargets.getResolution() * renderPass.viewportScale.scale(); + int beginWidth = (int) (renderTargets.getResolution() * renderPass.viewportScale.viewportX()); + int beginHeight = (int) (renderTargets.getResolution() * renderPass.viewportScale.viewportY()); + RenderSystem.viewport(beginWidth, beginHeight, (int) scaledWidth, (int) scaledHeight); renderPass.framebuffer.bind(); renderPass.program.use(); diff --git a/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java b/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java index 15ca2aef30..bf0a0c3f67 100644 --- a/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java +++ b/src/main/java/net/coderbot/iris/uniforms/IrisExclusiveUniforms.java @@ -33,6 +33,8 @@ public static void addIrisExclusiveUniforms(UniformHolder uniforms) { uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerHealth", IrisExclusiveUniforms::getMaxHealth); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerHunger", IrisExclusiveUniforms::getCurrentHunger); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerHunger", () -> 20); + uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerArmor", IrisExclusiveUniforms::getCurrentArmor); + uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerArmor", () -> 50); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "currentPlayerAir", IrisExclusiveUniforms::getCurrentAir); uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerAir", IrisExclusiveUniforms::getMaxAir); uniforms.uniform1b(UniformUpdateFrequency.PER_FRAME, "firstPersonCamera", IrisExclusiveUniforms::isFirstPersonCamera); @@ -92,6 +94,14 @@ private static float getCurrentAir() { return (float) Minecraft.getInstance().player.getAirSupply() / (float) Minecraft.getInstance().player.getMaxAirSupply(); } + private static float getCurrentArmor() { + if (Minecraft.getInstance().player == null || !Minecraft.getInstance().gameMode.getPlayerMode().isSurvival()) { + return -1; + } + + return (float) (Minecraft.getInstance().player.getArmorValue() / 50.0f); + } + private static float getMaxAir() { if (Minecraft.getInstance().player == null || !Minecraft.getInstance().gameMode.getPlayerMode().isSurvival()) { return -1; @@ -108,6 +118,8 @@ private static float getMaxHealth() { return Minecraft.getInstance().player.getMaxHealth(); } + + private static boolean isFirstPersonCamera() { // If camera type is not explicitly third-person, assume it's first-person. switch (Minecraft.getInstance().options.getCameraType()) { diff --git a/src/main/java/net/coderbot/iris/vertices/ImmediateState.java b/src/main/java/net/coderbot/iris/vertices/ImmediateState.java index 2762c6bda0..7e13ce2970 100644 --- a/src/main/java/net/coderbot/iris/vertices/ImmediateState.java +++ b/src/main/java/net/coderbot/iris/vertices/ImmediateState.java @@ -1,9 +1,10 @@ package net.coderbot.iris.vertices; /** - * Some annoying global state needed for the extended vertex format disabling optimization. + * Some annoying global state needed for rendering. */ public class ImmediateState { public static boolean isRenderingLevel = false; + public static boolean usingTessellation = false; public static boolean renderWithExtendedVertexFormat = true; } diff --git a/src/main/resources/assets/iris/lang/en_us.json b/src/main/resources/assets/iris/lang/en_us.json index 68b913611a..7993e00d00 100644 --- a/src/main/resources/assets/iris/lang/en_us.json +++ b/src/main/resources/assets/iris/lang/en_us.json @@ -11,6 +11,7 @@ "iris.shaders.ssbofailure": "The shader requested a specific feature (SSBO) that is not supported by your GPU, it may not work correctly.", "iris.keybind.reload": "Reload Shaders", "iris.keybind.shaderPackSelection": "Shaderpack Selection Screen", + "iris.keybind.wireframe": "Wireframe (SP only)", "iris.keybind.toggleShaders": "Toggle Shaders", "iris.keybinds": "Iris", "iris.shaders.reloaded.failure": "Failed to reload shaders! Reason: %s", diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java index 56bcd1cd3e..521440be24 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkProgramOverrides.java @@ -83,6 +83,56 @@ private GlShader createGeometryShader(IrisTerrainPass pass, SodiumTerrainPipelin "sodium-terrain-" + pass.toString().toLowerCase(Locale.ROOT) + ".gsh"), source); } + private GlShader createTessControlShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { + Optional irisTessControlShader; + + if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { + irisTessControlShader = pipeline.getShadowTessControlShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + irisTessControlShader = pipeline.getTerrainSolidTessControlShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + irisTessControlShader = pipeline.getTerrainCutoutTessControlShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { + irisTessControlShader = pipeline.getTranslucentTessControlShaderSource(); + } else { + throw new IllegalArgumentException("Unknown pass type " + pass); + } + + String source = irisTessControlShader.orElse(null); + + if (source == null) { + return null; + } + + return new GlShader(IrisShaderTypes.TESS_CONTROL, new ResourceLocation("iris", + "sodium-terrain-" + pass.toString().toLowerCase(Locale.ROOT) + ".tcs"), source); + } + + private GlShader createTessEvalShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { + Optional irisTessEvalShader; + + if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) { + irisTessEvalShader = pipeline.getShadowTessEvalShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_SOLID) { + irisTessEvalShader = pipeline.getTerrainSolidTessEvalShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_CUTOUT) { + irisTessEvalShader = pipeline.getTerrainCutoutTessEvalShaderSource(); + } else if (pass == IrisTerrainPass.GBUFFER_TRANSLUCENT) { + irisTessEvalShader = pipeline.getTranslucentTessEvalShaderSource(); + } else { + throw new IllegalArgumentException("Unknown pass type " + pass); + } + + String source = irisTessEvalShader.orElse(null); + + if (source == null) { + return null; + } + + return new GlShader(IrisShaderTypes.TESS_EVAL, new ResourceLocation("iris", + "sodium-terrain-" + pass.toString().toLowerCase(Locale.ROOT) + ".tes"), source); + } + private GlShader createFragmentShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline) { Optional irisFragmentShader; @@ -142,6 +192,8 @@ private List getBufferBlendOverride(IrisTerrainPass pass, S private GlProgram createShader(IrisTerrainPass pass, SodiumTerrainPipeline pipeline, ChunkVertexType vertexType) { GlShader vertShader = createVertexShader(pass, pipeline); GlShader geomShader = createGeometryShader(pass, pipeline); + GlShader tessCShader = createTessControlShader(pass, pipeline); + GlShader tessEShader = createTessEvalShader(pass, pipeline); GlShader fragShader = createFragmentShader(pass, pipeline); BlendModeOverride blendOverride = getBlendOverride(pass, pipeline); List bufferOverrides = getBufferBlendOverride(pass, pipeline); @@ -156,6 +208,14 @@ private GlProgram createShader(IrisTerrainPass pass, S geomShader.delete(); } + if (tessCShader != null) { + tessCShader.delete(); + } + + if (tessEShader != null) { + tessEShader.delete(); + } + if (fragShader != null) { fragShader.delete(); } @@ -171,6 +231,12 @@ private GlProgram createShader(IrisTerrainPass pass, S if (geomShader != null) { builder.attachShader(geomShader); } + if (tessCShader != null) { + builder.attachShader(tessCShader); + } + if (tessEShader != null) { + builder.attachShader(tessEShader); + } return builder.attachShader(vertShader) .attachShader(fragShader) @@ -190,13 +256,19 @@ private GlProgram createShader(IrisTerrainPass pass, S ShaderBindingContextExt contextExt = (ShaderBindingContextExt) shader; return new IrisChunkShaderInterface(handle, contextExt, pipeline, new ChunkShaderOptions(ChunkFogMode.SMOOTH, pass.toTerrainPass()), - pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT, blendOverride, bufferOverrides, alpha, pipeline.getCustomUniforms()); + tessCShader != null || tessEShader != null, pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT, blendOverride, bufferOverrides, alpha, pipeline.getCustomUniforms()); }); } finally { vertShader.delete(); if (geomShader != null) { geomShader.delete(); } + if (tessCShader != null) { + tessCShader.delete(); + } + if (tessEShader != null) { + tessEShader.delete(); + } fragShader.delete(); } } diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java index f09ea414ba..3966b9b4cf 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisChunkShaderInterface.java @@ -23,6 +23,7 @@ import net.coderbot.iris.samplers.IrisSamplers; import net.coderbot.iris.uniforms.CapturedRenderingState; import net.coderbot.iris.uniforms.custom.CustomUniforms; +import net.coderbot.iris.vertices.ImmediateState; import org.jetbrains.annotations.Nullable; import org.joml.Matrix3f; import org.joml.Matrix4f; @@ -56,10 +57,11 @@ public class IrisChunkShaderInterface extends ChunkShaderInterface { private final ProgramImages irisProgramImages; private final List bufferBlendOverrides; private final boolean hasOverrides; + private final boolean isTess; private CustomUniforms customUniforms; public IrisChunkShaderInterface(int handle, ShaderBindingContextExt contextExt, SodiumTerrainPipeline pipeline, ChunkShaderOptions options, - boolean isShadowPass, BlendModeOverride blendModeOverride, List bufferOverrides, float alpha, CustomUniforms customUniforms) { + boolean isTess, boolean isShadowPass, BlendModeOverride blendModeOverride, List bufferOverrides, float alpha, CustomUniforms customUniforms) { super(new ShaderBindingContext() { @Override public > U bindUniform(String s, IntFunction intFunction) { @@ -79,6 +81,7 @@ public GlUniformBlock bindUniformBlock(String s, int i) { this.uniformNormalMatrix = contextExt.bindUniformIfPresent("iris_NormalMatrix", GlUniformMatrix3f::new); this.uniformBlockDrawParameters = contextExt.bindUniformBlockIfPresent("ubo_DrawParameters", 0); this.customUniforms = customUniforms; + this.isTess = isTess; this.alpha = alpha; @@ -108,6 +111,8 @@ public void setupState() { blendModeOverride.apply(); } + ImmediateState.usingTessellation = isTess; + if (hasOverrides) { bufferBlendOverrides.forEach(BufferBlendOverride::apply); } @@ -121,6 +126,8 @@ public void setupState() { } public void restore() { + ImmediateState.usingTessellation = false; + if (blendModeOverride != null || hasOverrides) { BlendModeOverride.restore(); } diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java index ef30b90648..18c8980d2c 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/impl/shader_overrides/IrisShaderTypes.java @@ -7,4 +7,6 @@ */ public class IrisShaderTypes { public static ShaderType GEOMETRY; + public static ShaderType TESS_CONTROL; + public static ShaderType TESS_EVAL; } diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkProgram.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkProgram.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkRenderShaderBackend.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinChunkRenderShaderBackend.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java index 8c7603e187..9fdb33ff51 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlProgram.java @@ -8,10 +8,12 @@ import net.coderbot.iris.compat.sodium.impl.shader_overrides.ShaderBindingContextExt; import net.coderbot.iris.gl.IrisRenderSystem; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; import java.util.function.IntFunction; -@Mixin(GlProgram.class) +@Mixin(value = GlProgram.class, remap = false) public class MixinGlProgram extends GlObject implements ShaderBindingContextExt { public > U bindUniformIfPresent(String name, IntFunction factory) { int index = GlStateManager._glGetUniformLocation(this.handle(), name); @@ -22,6 +24,16 @@ public > U bindUniformIfPresent(String name, IntFunction< } } + @Redirect(method = "bind", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL20C;glUseProgram(I)V")) + private void iris$useGlStateManager(int i) { + GlStateManager._glUseProgram(i); + } + + @Redirect(method = "unbind", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL20C;glUseProgram(I)V")) + private void iris$useGlStateManager2(int i) { + GlStateManager._glUseProgram(i); + } + public GlUniformBlock bindUniformBlockIfPresent(String name, int bindingPoint) { int index = IrisRenderSystem.getUniformBlockIndex(this.handle(), name); if (index < 0) { diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlRenderDevice.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlRenderDevice.java new file mode 100644 index 0000000000..ca9dd80f2b --- /dev/null +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinGlRenderDevice.java @@ -0,0 +1,18 @@ +package net.coderbot.iris.compat.sodium.mixin.shader_overrides; + +import me.jellysquid.mods.sodium.client.gl.tessellation.GlPrimitiveType; +import net.coderbot.iris.vertices.ImmediateState; +import org.lwjgl.opengl.GL43C; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(targets = "me.jellysquid.mods.sodium.client.gl.device.GLRenderDevice$ImmediateDrawCommandList", remap = false) +public class MixinGlRenderDevice { + @Redirect(method = "multiDrawElementsBaseVertex", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gl/tessellation/GlPrimitiveType;getId()I")) + private int replaceId(GlPrimitiveType instance) { + if (ImmediateState.usingTessellation) return GL43C.GL_PATCHES; + + return instance.getId(); + } +} diff --git a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java index 56af4d60d0..0b42012993 100644 --- a/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java +++ b/src/sodiumCompatibility/java/net/coderbot/iris/compat/sodium/mixin/shader_overrides/MixinShaderType.java @@ -4,6 +4,7 @@ import net.coderbot.iris.compat.sodium.impl.shader_overrides.IrisShaderTypes; import org.apache.commons.lang3.ArrayUtils; import org.lwjgl.opengl.GL32C; +import org.lwjgl.opengl.GL42C; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -22,7 +23,11 @@ public class MixinShaderType { IrisShaderTypes.GEOMETRY = ShaderTypeAccessor.createShaderType("GEOMETRY", baseOrdinal, GL32C.GL_GEOMETRY_SHADER); + IrisShaderTypes.TESS_CONTROL + = ShaderTypeAccessor.createShaderType("TESS_CONTROL", baseOrdinal + 1, GL42C.GL_TESS_CONTROL_SHADER); + IrisShaderTypes.TESS_EVAL + = ShaderTypeAccessor.createShaderType("TESS_EVAL", baseOrdinal + 2, GL42C.GL_TESS_EVALUATION_SHADER); - $VALUES = ArrayUtils.addAll($VALUES, IrisShaderTypes.GEOMETRY); + $VALUES = ArrayUtils.addAll($VALUES, IrisShaderTypes.GEOMETRY, IrisShaderTypes.TESS_CONTROL, IrisShaderTypes.TESS_EVAL); } } diff --git a/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json b/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json index 63a981bf6c..85dd77b9c2 100644 --- a/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json +++ b/src/sodiumCompatibility/resources/mixins.iris.compat.sodium.json @@ -29,6 +29,7 @@ "font.MixinGlyphRenderer", "pbr_animation.MixinSpriteContents", "shader_overrides.MixinGlProgram", + "shader_overrides.MixinGlRenderDevice", "shader_overrides.MixinRegionChunkRenderer", "shader_overrides.MixinShaderChunkRenderer", "shader_overrides.MixinBlockRenderPass",