diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4ecc7c9b2f..b288bab853 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: run: chmod +x gradlew - name: Build the mod run: ./gradlew --no-daemon build - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: Oculus-Artifacts path: build/libs \ No newline at end of file diff --git a/DistantHorizons-forge-2.0.4-a-dev-1.20.1.jar b/DistantHorizons-forge-2.0.4-a-dev-1.20.1.jar deleted file mode 100644 index 4577e2e7da..0000000000 Binary files a/DistantHorizons-forge-2.0.4-a-dev-1.20.1.jar and /dev/null differ diff --git a/build.gradle b/build.gradle index 96a5eb0397..9312e4c2b2 100644 --- a/build.gradle +++ b/build.gradle @@ -110,7 +110,7 @@ dependencies { forge "net.neoforged:forge:${minecraft_version}-${forge_version}" modImplementation "org.embeddedt:embeddium-${minecraft_version}:${embeddium_version}" - modCompileOnly(files("DistantHorizons-forge-2.0.4-a-dev-1.20.1.jar")) + modCompileOnly("maven.modrinth:distanthorizonsapi:3.0.0") forgeRuntimeLibrary(implementation(shadow(project(path: ":glsl-relocated", configuration: "bundledJar")))) { transitive = false diff --git a/src/main/java/net/irisshaders/iris/Iris.java b/src/main/java/net/irisshaders/iris/Iris.java index 324184b3d5..28ef05acd5 100644 --- a/src/main/java/net/irisshaders/iris/Iris.java +++ b/src/main/java/net/irisshaders/iris/Iris.java @@ -45,6 +45,7 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.fml.loading.FMLPaths; +import net.minecraftforge.fml.loading.LoadingModList; import net.minecraftforge.network.NetworkConstants; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; @@ -105,6 +106,8 @@ public class Iris { private static String IRIS_VERSION; private static boolean fallback; + private static boolean loadPackWhenPossible = false; + private static boolean renderSystemInit = false; public Iris() { try { @@ -119,6 +122,14 @@ public Iris() { } } + public static void loadShaderpackWhenPossible() { + loadPackWhenPossible = true; + } + + public static boolean isPackInUseQuick() { + return pipelineManager.getPipelineNullable() instanceof IrisRenderingPipeline; + } + public void onKeyRegister(RegisterKeyMappingsEvent event) { event.register(reloadKeybind); event.register(toggleShadersKeybind); @@ -141,8 +152,12 @@ public static void onRenderSystemInit() { PBRTextureManager.INSTANCE.init(); + renderSystemInit = true; + // Only load the shader pack when we can access OpenGL - loadShaderpack(); + if (LoadingModList.get().getModFileById("distanthorizons") == null) { + loadShaderpack(); + } } public static void duringRenderSystemInit() { @@ -630,6 +645,19 @@ public static PipelineManager getPipelineManager() { pipelineManager = new PipelineManager(Iris::createPipeline); } + if (loadPackWhenPossible && renderSystemInit) { + loadPackWhenPossible = false; + try { + reload(); + } catch (IOException e) { + logger.error("Error while reloading Shaders for " + MODNAME + "!", e); + + if (Minecraft.getInstance().player != null) { + Minecraft.getInstance().player.displayClientMessage(Component.translatable("iris.shaders.reloaded.failure", Throwables.getRootCause(e).getMessage()).withStyle(ChatFormatting.RED), false); + } + } + } + return pipelineManager; } diff --git a/src/main/java/net/irisshaders/iris/compat/dh/DHCompat.java b/src/main/java/net/irisshaders/iris/compat/dh/DHCompat.java index b062136cfb..bb5b4021c4 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/DHCompat.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/DHCompat.java @@ -16,7 +16,6 @@ public class DHCompat { private static boolean dhPresent = true; private static boolean lastIncompatible; - private static MethodHandle setupEventHandlers; private static MethodHandle deletePipeline; private static MethodHandle incompatible; private static MethodHandle getDepthTex; @@ -59,7 +58,7 @@ public static void run() { try { if (LoadingModList.get().getModFileById("distanthorizons") != null) { deletePipeline = MethodHandles.lookup().findVirtual(Class.forName("net.irisshaders.iris.compat.dh.DHCompatInternal"), "clear", MethodType.methodType(void.class)); - setupEventHandlers = MethodHandles.lookup().findStatic(Class.forName("net.irisshaders.iris.compat.dh.LodRendererEvents"), "setupEventHandlers", MethodType.methodType(void.class)); + MethodHandle setupEventHandlers = MethodHandles.lookup().findStatic(Class.forName("net.irisshaders.iris.compat.dh.LodRendererEvents"), "setupEventHandlers", MethodType.methodType(void.class)); getDepthTex = MethodHandles.lookup().findVirtual(Class.forName("net.irisshaders.iris.compat.dh.DHCompatInternal"), "getStoredDepthTex", MethodType.methodType(int.class)); getRenderDistance = MethodHandles.lookup().findStatic(Class.forName("net.irisshaders.iris.compat.dh.DHCompatInternal"), "getRenderDistance", MethodType.methodType(int.class)); incompatible = MethodHandles.lookup().findVirtual(Class.forName("net.irisshaders.iris.compat.dh.DHCompatInternal"), "incompatiblePack", MethodType.methodType(boolean.class)); @@ -79,7 +78,7 @@ public static void run() { if (e instanceof ExceptionInInitializerError eiie) { throw new RuntimeException("Failure loading DH compat.", eiie.getCause()); } else { - throw new RuntimeException("DH 2.0 not found, yet Fabric claims it's there. Curious.", e); + throw new RuntimeException("DH found, but one or more API methods are missing. Iris requires DH [2.0.4] or DH API version [1.1.0] or newer. Please make sure you are on the latest version of DH and Iris.", e); } } else { Iris.logger.info("DH not found, and classes not found."); diff --git a/src/main/java/net/irisshaders/iris/compat/dh/DHCompatInternal.java b/src/main/java/net/irisshaders/iris/compat/dh/DHCompatInternal.java index 6f23e344c4..b8cc8e8d3e 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/DHCompatInternal.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/DHCompatInternal.java @@ -3,16 +3,17 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.seibel.distanthorizons.api.DhApi; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import net.irisshaders.iris.Iris; -import net.irisshaders.iris.api.v0.IrisApi; import net.irisshaders.iris.gl.IrisRenderSystem; import net.irisshaders.iris.gl.framebuffer.GlFramebuffer; import net.irisshaders.iris.gl.texture.DepthBufferFormat; import net.irisshaders.iris.gl.texture.DepthCopyStrategy; import net.irisshaders.iris.pipeline.IrisRenderingPipeline; import net.irisshaders.iris.shaderpack.programs.ProgramSource; +import net.irisshaders.iris.shaderpack.properties.CloudSetting; import net.irisshaders.iris.targets.Blaze3dRenderTargetExt; import net.irisshaders.iris.targets.DepthTexture; import net.irisshaders.iris.uniforms.CapturedRenderingState; @@ -28,7 +29,9 @@ public class DHCompatInternal { private final IrisRenderingPipeline pipeline; public boolean shouldOverrideShadow; public boolean shouldOverride; + private GlFramebuffer dhGenericFramebuffer; private IrisLodRenderProgram solidProgram; + private IrisGenericRenderProgram genericShader; private IrisLodRenderProgram translucentProgram; private IrisLodRenderProgram shadowProgram; private GlFramebuffer dhTerrainFramebuffer; @@ -54,6 +57,7 @@ public DHCompatInternal(IrisRenderingPipeline pipeline, boolean dhShadowEnabled) incompatible = true; return; } + cachedVersion = ((Blaze3dRenderTargetExt) Minecraft.getInstance().getMainRenderTarget()).iris$getDepthBufferVersion(); createDepthTex(Minecraft.getInstance().getMainRenderTarget().width, Minecraft.getInstance().getMainRenderTarget().height); @@ -62,6 +66,10 @@ public DHCompatInternal(IrisRenderingPipeline pipeline, boolean dhShadowEnabled) ProgramSource terrain = pipeline.getDHTerrainShader().get(); solidProgram = IrisLodRenderProgram.createProgram(terrain.getName(), false, false, terrain, pipeline.getCustomUniforms(), pipeline); + ProgramSource generic = pipeline.getDHGenericShader().get(); + genericShader = IrisGenericRenderProgram.createProgram(generic.getName() + "_g", false, false, generic, pipeline.getCustomUniforms(), pipeline); + dhGenericFramebuffer = pipeline.createDHFramebuffer(generic, false); + if (pipeline.getDHWaterShader().isPresent()) { ProgramSource water = pipeline.getDHWaterShader().get(); translucentProgram = IrisLodRenderProgram.createProgram(water.getName(), false, true, water, pipeline.getCustomUniforms(), pipeline); @@ -129,13 +137,10 @@ public static boolean checkFrame() { guiScale = Minecraft.getInstance().options.guiScale().get(); } - // TODO fix early initialization - if (DhApi.Delayed.configs == null) { - return true; - } + if (DhApi.Delayed.configs == null) return dhEnabled; if ((dhEnabled != DhApi.Delayed.configs.graphics().renderingEnabled().getValue() || guiScale != Minecraft.getInstance().options.guiScale().get()) - && IrisApi.getInstance().isShaderPackInUse()) { + && Iris.getPipelineManager().getPipelineNullable() instanceof IrisRenderingPipeline) { guiScale = Minecraft.getInstance().options.guiScale().get(); dhEnabled = DhApi.Delayed.configs.graphics().renderingEnabled().getValue(); try { @@ -163,6 +168,9 @@ public void reconnectDHTextures(int depthTex) { if (dhWaterFramebuffer != null) { dhWaterFramebuffer.addDepthAttachment(depthTex); } + if (dhGenericFramebuffer != null) { + dhGenericFramebuffer.addDepthAttachment(depthTex); + } } } @@ -199,12 +207,13 @@ public void clear() { translucentDepthDirty = true; OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, dhTerrainFramebufferWrapper); + OverrideInjector.INSTANCE.unbind(IDhApiGenericObjectShaderProgram.class, genericShader); OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, dhShadowFramebufferWrapper); dhTerrainFramebufferWrapper = null; dhShadowFramebufferWrapper = null; } - public void setModelPos(Vec3f modelPos) { + public void setModelPos(DhApiVec3f modelPos) { solidProgram.bind(); solidProgram.setModelPos(modelPos); translucentProgram.bind(); @@ -262,9 +271,21 @@ public GlFramebuffer getTranslucentFB() { return dhWaterFramebuffer; } + public GlFramebuffer getGenericFB() { + return dhGenericFramebuffer; + } + public int getDepthTexNoTranslucent() { if (depthTexNoTranslucent == null) return 0; return depthTexNoTranslucent.getTextureId(); } + + public IDhApiGenericObjectShaderProgram getGenericShader() { + return genericShader; + } + + public boolean avoidRenderingClouds() { + return pipeline != null && (pipeline.getDHCloudSetting() == CloudSetting.OFF || (pipeline.getDHCloudSetting() == CloudSetting.DEFAULT && pipeline.getCloudSetting() == CloudSetting.OFF)); + } } diff --git a/src/main/java/net/irisshaders/iris/compat/dh/DhFrameBufferWrapper.java b/src/main/java/net/irisshaders/iris/compat/dh/DhFrameBufferWrapper.java index dd34a05ef1..e7bbb0504d 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/DhFrameBufferWrapper.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/DhFrameBufferWrapper.java @@ -36,8 +36,7 @@ public int getId() { @Override public int getStatus() { this.bind(); - int status = GL32.glCheckFramebufferStatus(GL32.GL_FRAMEBUFFER); - return status; + return GL32.glCheckFramebufferStatus(GL32.GL_FRAMEBUFFER); } @Override diff --git a/src/main/java/net/irisshaders/iris/compat/dh/IrisGenericRenderProgram.java b/src/main/java/net/irisshaders/iris/compat/dh/IrisGenericRenderProgram.java new file mode 100644 index 0000000000..3933b372d2 --- /dev/null +++ b/src/main/java/net/irisshaders/iris/compat/dh/IrisGenericRenderProgram.java @@ -0,0 +1,348 @@ +package net.irisshaders.iris.compat.dh; + +import com.google.common.primitives.Ints; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; +import net.irisshaders.iris.Iris; +import net.irisshaders.iris.gl.IrisRenderSystem; +import net.irisshaders.iris.gl.blending.BlendModeOverride; +import net.irisshaders.iris.gl.blending.BufferBlendOverride; +import net.irisshaders.iris.gl.program.ProgramImages; +import net.irisshaders.iris.gl.program.ProgramSamplers; +import net.irisshaders.iris.gl.program.ProgramUniforms; +import net.irisshaders.iris.gl.shader.GlShader; +import net.irisshaders.iris.gl.shader.ShaderType; +import net.irisshaders.iris.gl.state.FogMode; +import net.irisshaders.iris.gl.texture.TextureType; +import net.irisshaders.iris.pipeline.IrisRenderingPipeline; +import net.irisshaders.iris.pipeline.transform.PatchShaderType; +import net.irisshaders.iris.pipeline.transform.ShaderPrinter; +import net.irisshaders.iris.pipeline.transform.TransformPatcher; +import net.irisshaders.iris.samplers.IrisSamplers; +import net.irisshaders.iris.shaderpack.programs.ProgramSource; +import net.irisshaders.iris.uniforms.CommonUniforms; +import net.irisshaders.iris.uniforms.builtin.BuiltinReplacementUniforms; +import net.irisshaders.iris.uniforms.custom.CustomUniforms; +import net.minecraft.client.Minecraft; +import org.joml.Matrix3f; +import org.joml.Matrix4f; +import org.lwjgl.opengl.GL30C; +import org.lwjgl.opengl.GL32; +import org.lwjgl.opengl.GL32C; +import org.lwjgl.opengl.GL43C; +import org.lwjgl.system.MemoryStack; + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class IrisGenericRenderProgram implements IDhApiGenericObjectShaderProgram { + // Uniforms + public final int modelViewUniform; + public final int modelViewInverseUniform; + public final int projectionUniform; + public final int projectionInverseUniform; + public final int normalMatrix3fUniform; + // Fog/Clip Uniforms + private final int id; + private final ProgramUniforms uniforms; + private final CustomUniforms customUniforms; + private final ProgramSamplers samplers; + private final ProgramImages images; + private final BlendModeOverride blend; + private final BufferBlendOverride[] bufferBlendOverrides; + + private final int instancedShaderOffsetChunkUniform; + private final int instancedShaderOffsetSubChunkUniform; + private final int instancedShaderCameraChunkPosUniform; + private final int instancedShaderCameraSubChunkPosUniform; + private final int instancedShaderProjectionModelViewMatrixUniform; + private final int va; + private final int uBlockLight; + private final int uSkyLight; + + // This will bind AbstractVertexAttribute + private IrisGenericRenderProgram(String name, boolean isShadowPass, boolean translucent, BlendModeOverride override, BufferBlendOverride[] bufferBlendOverrides, String vertex, String tessControl, String tessEval, String geometry, String fragment, CustomUniforms customUniforms, IrisRenderingPipeline pipeline) { + id = GL43C.glCreateProgram(); + + GL32.glBindAttribLocation(this.id, 0, "vPosition"); + + this.bufferBlendOverrides = bufferBlendOverrides; + + GlShader vert = new GlShader(ShaderType.VERTEX, name + ".vsh", vertex); + GL43C.glAttachShader(id, vert.getHandle()); + + GlShader tessCont = null; + if (tessControl != null) { + tessCont = new GlShader(ShaderType.TESSELATION_CONTROL, name + ".tcs", tessControl); + GL43C.glAttachShader(id, tessCont.getHandle()); + } + + GlShader tessE = null; + if (tessEval != null) { + tessE = new GlShader(ShaderType.TESSELATION_EVAL, name + ".tes", tessEval); + GL43C.glAttachShader(id, tessE.getHandle()); + } + + GlShader geom = null; + if (geometry != null) { + geom = new GlShader(ShaderType.GEOMETRY, name + ".gsh", geometry); + GL43C.glAttachShader(id, geom.getHandle()); + } + + GlShader frag = new GlShader(ShaderType.FRAGMENT, name + ".fsh", fragment); + GL43C.glAttachShader(id, frag.getHandle()); + + GL32.glLinkProgram(this.id); + int status = GL32.glGetProgrami(this.id, 35714); + if (status != 1) { + String message = "Shader link error in Iris DH program! Details: " + GL32.glGetProgramInfoLog(this.id); + this.free(); + throw new RuntimeException(message); + } else { + GL32.glUseProgram(this.id); + } + + vert.destroy(); + frag.destroy(); + + if (tessCont != null) tessCont.destroy(); + if (tessE != null) tessE.destroy(); + if (geom != null) geom.destroy(); + + blend = override; + ProgramUniforms.Builder uniformBuilder = ProgramUniforms.builder(name, id); + ProgramSamplers.Builder samplerBuilder = ProgramSamplers.builder(id, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS); + CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_VERTEX); + customUniforms.assignTo(uniformBuilder); + BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniformBuilder); + ProgramImages.Builder builder = ProgramImages.builder(id); + pipeline.addGbufferOrShadowSamplers(samplerBuilder, builder, isShadowPass ? pipeline::getFlippedBeforeShadow : () -> translucent ? pipeline.getFlippedAfterTranslucent() : pipeline.getFlippedAfterPrepare(), isShadowPass, false, true, false); + customUniforms.mapholderToPass(uniformBuilder, this); + this.uniforms = uniformBuilder.buildUniforms(); + this.customUniforms = customUniforms; + samplers = samplerBuilder.build(); + images = builder.build(); + + this.va = GlStateManager._glGenVertexArrays(); + GlStateManager._glBindVertexArray(va); + GL32.glVertexAttribPointer(0, 3, GL32.GL_FLOAT, false, 0, 0); + GL32.glEnableVertexAttribArray(0); + + projectionUniform = tryGetUniformLocation2("iris_ProjectionMatrix"); + projectionInverseUniform = tryGetUniformLocation2("iris_ProjectionMatrixInverse"); + modelViewUniform = tryGetUniformLocation2("iris_ModelViewMatrix"); + modelViewInverseUniform = tryGetUniformLocation2("iris_ModelViewMatrixInverse"); + normalMatrix3fUniform = tryGetUniformLocation2("iris_NormalMatrix"); + + this.instancedShaderOffsetChunkUniform = this.tryGetUniformLocation2("uOffsetChunk"); + this.instancedShaderOffsetSubChunkUniform = this.tryGetUniformLocation2("uOffsetSubChunk"); + this.instancedShaderCameraChunkPosUniform = this.tryGetUniformLocation2("uCameraPosChunk"); + this.instancedShaderCameraSubChunkPosUniform = this.tryGetUniformLocation2("uCameraPosSubChunk"); + this.instancedShaderProjectionModelViewMatrixUniform = this.tryGetUniformLocation2("uProjectionMvm"); + this.uBlockLight = this.tryGetUniformLocation2("uBlockLight"); + this.uSkyLight = this.tryGetUniformLocation2("uSkyLight"); + } + + public static IrisGenericRenderProgram createProgram(String name, boolean isShadowPass, boolean translucent, ProgramSource source, CustomUniforms uniforms, IrisRenderingPipeline pipeline) { + Map transformed = TransformPatcher.patchDHGeneric( + name, + source.getVertexSource().orElseThrow(RuntimeException::new), + source.getTessControlSource().orElse(null), + source.getTessEvalSource().orElse(null), + source.getGeometrySource().orElse(null), + source.getFragmentSource().orElseThrow(RuntimeException::new), + pipeline.getTextureMap()); + String vertex = transformed.get(PatchShaderType.VERTEX); + String tessControl = transformed.get(PatchShaderType.TESS_CONTROL); + String tessEval = transformed.get(PatchShaderType.TESS_EVAL); + String geometry = transformed.get(PatchShaderType.GEOMETRY); + String fragment = transformed.get(PatchShaderType.FRAGMENT); + ShaderPrinter.printProgram(name + "_g") + .addSources(transformed) + .setName("dh_" + name + "_g") + .print(); + + List bufferOverrides = new ArrayList<>(); + + source.getDirectives().getBufferBlendOverrides().forEach(information -> { + int index = Ints.indexOf(source.getDirectives().getDrawBuffers(), information.index()); + if (index > -1) { + bufferOverrides.add(new BufferBlendOverride(index, information.blendMode())); + } + }); + + return new IrisGenericRenderProgram(name, isShadowPass, translucent, source.getDirectives().getBlendModeOverride().orElse(null), bufferOverrides.toArray(BufferBlendOverride[]::new), vertex, tessControl, tessEval, geometry, fragment, uniforms, pipeline); + } + + // Noise Uniforms + + private static int getChunkPosFromDouble(double value) { + return (int) Math.floor(value / 16); + } + + private static float getSubChunkPosFromDouble(double value) { + double chunkPos = Math.floor(value / 16); + return (float) (value - chunkPos * 16); + } + + public int tryGetUniformLocation2(CharSequence name) { + return GL32.glGetUniformLocation(this.id, name); + } + + public void setUniform(int index, Matrix4f matrix) { + if (index == -1 || matrix == null) return; + + try (MemoryStack stack = MemoryStack.stackPush()) { + FloatBuffer buffer = stack.callocFloat(16); + matrix.get(buffer); + buffer.rewind(); + + RenderSystem.glUniformMatrix4(index, false, buffer); + } + } + + public void setUniform(int index, Matrix3f matrix) { + if (index == -1) return; + + try (MemoryStack stack = MemoryStack.stackPush()) { + FloatBuffer buffer = stack.callocFloat(9); + matrix.get(buffer); + buffer.rewind(); + + RenderSystem.glUniformMatrix3(index, false, buffer); + } + } + + // Override ShaderProgram.bind() + public void bind(DhApiRenderParam renderParam) { + GlStateManager._glBindVertexArray(va); + GL32C.glUseProgram(id); + if (blend != null) blend.apply(); + + for (BufferBlendOverride override : bufferBlendOverrides) { + override.apply(); + } + + setUniform(modelViewUniform, toJOML(renderParam.dhModelViewMatrix)); + setUniform(modelViewInverseUniform, toJOML(renderParam.dhModelViewMatrix).invert()); + setUniform(projectionUniform, toJOML(renderParam.dhProjectionMatrix)); + setUniform(projectionInverseUniform, toJOML(renderParam.dhModelViewMatrix).invert()); + setUniform(normalMatrix3fUniform, toJOML(renderParam.dhModelViewMatrix).invert().transpose3x3(new Matrix3f())); + Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer(); + IrisRenderSystem.bindTextureToUnit(TextureType.TEXTURE_2D.getGlType(), IrisSamplers.LIGHTMAP_TEXTURE_UNIT, RenderSystem.getShaderTexture(2)); + this.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, toJOML(renderParam.dhProjectionMatrix).mul(toJOML(renderParam.dhModelViewMatrix))); + + samplers.update(); + uniforms.update(); + + customUniforms.push(this); + + images.update(); + } + + public void unbind() { + GlStateManager._glBindVertexArray(0); + GL43C.glUseProgram(0); + ProgramUniforms.clearActiveUniforms(); + ProgramSamplers.clearActiveSamplers(); + BlendModeOverride.restore(); + } + + @Override + public void bindVertexBuffer(int i) { + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, i); + GL32.glVertexAttribPointer(0, 3, GL32.GL_FLOAT, false, 12, 0); + } + + @Override + public boolean overrideThisFrame() { + return Iris.getPipelineManager().getPipelineNullable() instanceof IrisRenderingPipeline; + } + + @Override + public int getId() { + return id; + } + + public void free() { + GL43C.glDeleteProgram(id); + } + + public void fillIndirectUniformData(DhApiRenderParam dhApiRenderParam, DhApiRenderableBoxGroupShading dhApiRenderableBoxGroupShading, IDhApiRenderableBoxGroup boxGroup, DhApiVec3d camPos) { + bind(dhApiRenderParam); + RenderSystem.enableDepthTest(); + RenderSystem.depthFunc(GL30C.GL_LEQUAL); + this.setUniform(this.instancedShaderOffsetChunkUniform, + new DhApiVec3i( + getChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + getChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + getChunkPosFromDouble(boxGroup.getOriginBlockPos().z) + )); + this.setUniform(this.instancedShaderOffsetSubChunkUniform, + new DhApiVec3f( + getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z) + )); + + this.setUniform(this.instancedShaderCameraChunkPosUniform, + new DhApiVec3i( + getChunkPosFromDouble(camPos.x), + getChunkPosFromDouble(camPos.y), + getChunkPosFromDouble(camPos.z) + )); + this.setUniform(this.instancedShaderCameraSubChunkPosUniform, + new DhApiVec3f( + getSubChunkPosFromDouble(camPos.x), + getSubChunkPosFromDouble(camPos.y), + getSubChunkPosFromDouble(camPos.z) + )); + this.setUniform(this.uBlockLight, + boxGroup.getBlockLight()); + this.setUniform(this.uSkyLight, + boxGroup.getSkyLight()); + + } + + @Override + public void fillSharedDirectUniformData(DhApiRenderParam dhApiRenderParam, DhApiRenderableBoxGroupShading dhApiRenderableBoxGroupShading, IDhApiRenderableBoxGroup iDhApiRenderableBoxGroup, DhApiVec3d dhApiVec3d) { + throw new IllegalStateException("Only indirect is supported with Iris."); + } + + @Override + public void fillDirectUniformData(DhApiRenderParam dhApiRenderParam, IDhApiRenderableBoxGroup iDhApiRenderableBoxGroup, DhApiRenderableBox dhApiRenderableBox, DhApiVec3d dhApiVec3d) { + throw new IllegalStateException("Only indirect is supported with Iris."); + } + + private Matrix4f toJOML(DhApiMat4f mat4f) { + return new Matrix4f().setTransposed(mat4f.getValuesAsArray()); + } + + private void setUniform(int index, int value) { + GL43C.glUniform1i(index, value); + } + + private void setUniform(int index, float value) { + GL43C.glUniform1f(index, value); + } + + private void setUniform(int index, DhApiVec3f pos) { + GL43C.glUniform3f(index, pos.x, pos.y, pos.z); + } + + private void setUniform(int index, DhApiVec3i pos) { + GL43C.glUniform3i(index, pos.x, pos.y, pos.z); + } + +} diff --git a/src/main/java/net/irisshaders/iris/compat/dh/IrisLodRenderProgram.java b/src/main/java/net/irisshaders/iris/compat/dh/IrisLodRenderProgram.java index 3a37048d69..5aa1dd9f90 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/IrisLodRenderProgram.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/IrisLodRenderProgram.java @@ -3,8 +3,7 @@ import com.google.common.primitives.Ints; import com.mojang.blaze3d.systems.RenderSystem; import com.seibel.distanthorizons.api.DhApi; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; -import net.irisshaders.iris.Iris; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import net.irisshaders.iris.gl.IrisRenderSystem; import net.irisshaders.iris.gl.blending.BlendModeOverride; import net.irisshaders.iris.gl.blending.BufferBlendOverride; @@ -27,6 +26,7 @@ import net.minecraft.client.Minecraft; import org.joml.Matrix3f; import org.joml.Matrix4f; +import org.joml.Matrix4fc; import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL43C; import org.lwjgl.system.MemoryStack; @@ -135,7 +135,7 @@ private IrisLodRenderProgram(String name, boolean isShadowPass, boolean transluc } public static IrisLodRenderProgram createProgram(String name, boolean isShadowPass, boolean translucent, ProgramSource source, CustomUniforms uniforms, IrisRenderingPipeline pipeline) { - Map transformed = TransformPatcher.patchDH( + Map transformed = TransformPatcher.patchDHTerrain( name, source.getVertexSource().orElseThrow(RuntimeException::new), source.getTessControlSource().orElse(null), @@ -171,7 +171,7 @@ public int tryGetUniformLocation2(CharSequence name) { return GL32.glGetUniformLocation(this.id, name); } - public void setUniform(int index, Matrix4f matrix) { + public void setUniform(int index, Matrix4fc matrix) { if (index == -1 || matrix == null) return; try (MemoryStack stack = MemoryStack.stackPush()) { @@ -216,7 +216,7 @@ public void free() { GL43C.glDeleteProgram(id); } - public void fillUniformData(Matrix4f projection, Matrix4f modelView, int worldYOffset, float partialTicks) { + public void fillUniformData(Matrix4fc projection, Matrix4fc modelView, int worldYOffset, float partialTicks) { GL43C.glUseProgram(id); Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer(); @@ -249,11 +249,11 @@ private void setUniform(int index, float value) { GL43C.glUniform1f(index, value); } - public void setModelPos(Vec3f modelPos) { + public void setModelPos(DhApiVec3f modelPos) { setUniform(modelOffsetUniform, modelPos); } - private void setUniform(int index, Vec3f pos) { + private void setUniform(int index, DhApiVec3f pos) { GL43C.glUniform3f(index, pos.x, pos.y, pos.z); } diff --git a/src/main/java/net/irisshaders/iris/compat/dh/LodRendererEvents.java b/src/main/java/net/irisshaders/iris/compat/dh/LodRendererEvents.java index 5185f28008..541262e153 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/LodRendererEvents.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/LodRendererEvents.java @@ -5,11 +5,14 @@ import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeApplyShaderRenderEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeBufferRenderEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDeferredRenderEvent; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericObjectRenderEvent; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericRenderSetupEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderCleanupEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderPassEvent; @@ -19,15 +22,15 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import net.irisshaders.iris.Iris; -import net.irisshaders.iris.api.v0.IrisApi; import net.irisshaders.iris.pipeline.WorldRenderingPipeline; import net.irisshaders.iris.shadows.ShadowRenderer; import net.irisshaders.iris.shadows.ShadowRenderingState; import net.irisshaders.iris.uniforms.CapturedRenderingState; import org.joml.Matrix4f; +import org.joml.Matrix4fc; import org.lwjgl.opengl.GL43C; import org.lwjgl.opengl.GL46C; @@ -51,8 +54,11 @@ public static void setupEventHandlers() { public void afterDistantHorizonsInit(DhApiEventParam event) { Iris.logger.info("DH Ready, binding Iris event handlers..."); + Iris.loadShaderpackWhenPossible(); + setupSetDeferredBeforeRenderingEvent(); setupReconnectDepthTextureEvent(); + setupGenericEvent(); setupCreateDepthTextureEvent(); setupTransparentRendererEventCancling(); setupBeforeBufferClearEvent(); @@ -80,7 +86,7 @@ private static void setupSetDeferredBeforeRenderingEvent() { @Override public void beforeRender(DhApiCancelableEventParam event) { - DhApi.Delayed.renderProxy.setDeferTransparentRendering(IrisApi.getInstance().isShaderPackInUse() && getInstance().shouldOverride); + DhApi.Delayed.renderProxy.setDeferTransparentRendering(Iris.isPackInUseQuick() && getInstance().shouldOverride); DhApi.Delayed.configs.graphics().fog().drawMode().setValue(getInstance().shouldOverride ? EDhApiFogDrawMode.FOG_DISABLED : EDhApiFogDrawMode.FOG_ENABLED); } }; @@ -103,6 +109,31 @@ public void beforeClear(DhApiCancelableEventParam event) { DhApi.events.bind(DhApiBeforeTextureClearEvent.class, beforeRenderEvent); } + private static void setupGenericEvent() { + DhApiBeforeGenericRenderSetupEvent beforeRenderEvent = new DhApiBeforeGenericRenderSetupEvent() { + @Override + public void beforeSetup(DhApiEventParam dhApiEventParam) { + if (getInstance().getGenericFB() != null) { + getInstance().getGenericFB().bind(); + } + } + }; + + DhApiBeforeGenericObjectRenderEvent beforeDrawEvent = new DhApiBeforeGenericObjectRenderEvent() { + @Override + public void beforeRender(DhApiCancelableEventParam dhApiCancelableEventParam) { + if (dhApiCancelableEventParam.value.resourceLocationPath.equalsIgnoreCase("Clouds")) { + if (getInstance().avoidRenderingClouds()) { + dhApiCancelableEventParam.cancelEvent(); + } + } + } + }; + + DhApi.events.bind(DhApiBeforeGenericRenderSetupEvent.class, beforeRenderEvent); + DhApi.events.bind(DhApiBeforeGenericObjectRenderEvent.class, beforeDrawEvent); + } + private static DHCompatInternal getInstance() { return (DHCompatInternal) Iris.getPipelineManager().getPipeline().map(WorldRenderingPipeline::getDHCompat).map(DHCompat::getInstance).orElse(DHCompatInternal.SHADERLESS); } @@ -182,7 +213,7 @@ private static void beforeBufferRenderEvent() { public void beforeRender(DhApiEventParam input) { DHCompatInternal instance = getInstance(); if (instance.shouldOverride) { - Vec3f modelPos = input.value.modelPos; + DhApiVec3f modelPos = input.value.modelPos; if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) { instance.getShadowShader().bind(); instance.getShadowShader().setModelPos(modelPos); @@ -209,8 +240,13 @@ public void beforeSetup(DhApiEventParam event) { OverrideInjector.INSTANCE.unbind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM); OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getShadowFBWrapper()); OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getSolidFBWrapper()); + OverrideInjector.INSTANCE.unbind(IDhApiGenericObjectShaderProgram.class, instance.getGenericShader()); if (instance.shouldOverride) { + if (instance.getGenericShader() != null) { + OverrideInjector.INSTANCE.bind(IDhApiGenericObjectShaderProgram.class, instance.getGenericShader()); + } + if (ShadowRenderingState.areShadowsCurrentlyBeingRendered() && instance.shouldOverrideShadow) { OverrideInjector.INSTANCE.bind(IDhApiFramebuffer.class, instance.getShadowFBWrapper()); OverrideInjector.INSTANCE.bind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM); @@ -268,7 +304,7 @@ public void beforeRender(DhApiEventParam event) { -1000, //MC.getWrappedClientLevel().getMinHeight(), partialTicks); } else { - Matrix4f projection = CapturedRenderingState.INSTANCE.getGbufferProjection(); + Matrix4fc projection = CapturedRenderingState.INSTANCE.getGbufferProjection(); //float nearClip = DhApi.Delayed.renderProxy.getNearClipPlaneDistanceInBlocks(partialTicks); //float farClip = (float) ((double) (DHCompatInternal.getDhBlockRenderDistance() + 512) * Math.sqrt(2.0)); @@ -301,7 +337,7 @@ public void beforeRender(DhApiEventParam event) { if (instance.shouldOverride && instance.getTranslucentFB() != null) { instance.copyTranslucents(textureWidth, textureHeight); instance.getTranslucentShader().bind(); - Matrix4f projection = CapturedRenderingState.INSTANCE.getGbufferProjection(); + Matrix4fc projection = CapturedRenderingState.INSTANCE.getGbufferProjection(); //float nearClip = DhApi.Delayed.renderProxy.getNearClipPlaneDistanceInBlocks(partialTicks); //float farClip = (float) ((double) (DHCompatInternal.getDhBlockRenderDistance() + 512) * Math.sqrt(2.0)); GL46C.glDisable(GL46C.GL_CULL_FACE); @@ -330,7 +366,7 @@ private static void setupBeforeApplyShaderEvent() { DhApiBeforeApplyShaderRenderEvent beforeApplyShaderEvent = new DhApiBeforeApplyShaderRenderEvent() { @Override public void beforeRender(DhApiCancelableEventParam event) { - if (IrisApi.getInstance().isShaderPackInUse()) { + if (Iris.isPackInUseQuick()) { DHCompatInternal instance = getInstance(); OverrideInjector.INSTANCE.unbind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM); diff --git a/src/main/java/net/irisshaders/iris/compat/dh/mixin/AdvancedShadowCullingFrustumMixin.java b/src/main/java/net/irisshaders/iris/compat/dh/mixin/AdvancedShadowCullingFrustumMixin.java index dee303bd68..1d9b17a996 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/mixin/AdvancedShadowCullingFrustumMixin.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/mixin/AdvancedShadowCullingFrustumMixin.java @@ -1,7 +1,7 @@ package net.irisshaders.iris.compat.dh.mixin; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; import net.irisshaders.iris.shadows.frustum.advanced.AdvancedShadowCullingFrustum; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -18,7 +18,7 @@ public int isVisible(double minX, double minY, double minZ, double maxX, double } @Override - public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection) { + public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) { this.worldMinYDH = worldMinBlockY; this.worldMaxYDH = worldMaxBlockY; } diff --git a/src/main/java/net/irisshaders/iris/compat/dh/mixin/BoxCullingFrustumMixin.java b/src/main/java/net/irisshaders/iris/compat/dh/mixin/BoxCullingFrustumMixin.java index 3caf41da79..719c2ccc0d 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/mixin/BoxCullingFrustumMixin.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/mixin/BoxCullingFrustumMixin.java @@ -1,7 +1,7 @@ package net.irisshaders.iris.compat.dh.mixin; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; import net.irisshaders.iris.shadows.frustum.BoxCuller; import net.irisshaders.iris.shadows.frustum.fallback.BoxCullingFrustum; import org.spongepowered.asm.mixin.Final; @@ -19,7 +19,7 @@ public class BoxCullingFrustumMixin implements IDhApiShadowCullingFrustum { private int worldMaxYDH; @Override - public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection) { + public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) { this.worldMinYDH = worldMinBlockY; this.worldMaxYDH = worldMaxBlockY; } diff --git a/src/main/java/net/irisshaders/iris/compat/dh/mixin/CullEverythingFrustumMixin.java b/src/main/java/net/irisshaders/iris/compat/dh/mixin/CullEverythingFrustumMixin.java index 1c2de107aa..1cf73501f5 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/mixin/CullEverythingFrustumMixin.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/mixin/CullEverythingFrustumMixin.java @@ -1,14 +1,14 @@ package net.irisshaders.iris.compat.dh.mixin; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; import net.irisshaders.iris.shadows.frustum.CullEverythingFrustum; import org.spongepowered.asm.mixin.Mixin; @Mixin(value = CullEverythingFrustum.class, remap = false) public class CullEverythingFrustumMixin implements IDhApiShadowCullingFrustum { @Override - public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection) { + public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) { } diff --git a/src/main/java/net/irisshaders/iris/compat/dh/mixin/NonCullingFrustumMixin.java b/src/main/java/net/irisshaders/iris/compat/dh/mixin/NonCullingFrustumMixin.java index e942502a13..b7b267d785 100644 --- a/src/main/java/net/irisshaders/iris/compat/dh/mixin/NonCullingFrustumMixin.java +++ b/src/main/java/net/irisshaders/iris/compat/dh/mixin/NonCullingFrustumMixin.java @@ -1,14 +1,14 @@ package net.irisshaders.iris.compat.dh.mixin; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; import net.irisshaders.iris.shadows.frustum.fallback.NonCullingFrustum; import org.spongepowered.asm.mixin.Mixin; @Mixin(value = NonCullingFrustum.class, remap = false) public class NonCullingFrustumMixin implements IDhApiShadowCullingFrustum { @Override - public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection) { + public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection) { } diff --git a/src/main/java/net/irisshaders/iris/features/FeatureFlags.java b/src/main/java/net/irisshaders/iris/features/FeatureFlags.java index 89ca843804..000525f7b6 100644 --- a/src/main/java/net/irisshaders/iris/features/FeatureFlags.java +++ b/src/main/java/net/irisshaders/iris/features/FeatureFlags.java @@ -14,7 +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), + TESSELLATION_SHADERS(() -> true, IrisRenderSystem::supportsTesselation), ENTITY_TRANSLUCENT(() -> true, () -> true), REVERSED_CULLING(() -> true, () -> true), BLOCK_EMISSION_ATTRIBUTE(() -> true, () -> true), diff --git a/src/main/java/net/irisshaders/iris/gl/IrisLimits.java b/src/main/java/net/irisshaders/iris/gl/IrisLimits.java index 0687f5462f..287ce4f223 100644 --- a/src/main/java/net/irisshaders/iris/gl/IrisLimits.java +++ b/src/main/java/net/irisshaders/iris/gl/IrisLimits.java @@ -9,4 +9,5 @@ public class IrisLimits { * is implemented. */ public static final int MAX_COLOR_BUFFERS = 16; + public static final boolean VK_CONFORMANCE = false; } diff --git a/src/main/java/net/irisshaders/iris/pipeline/IrisRenderingPipeline.java b/src/main/java/net/irisshaders/iris/pipeline/IrisRenderingPipeline.java index ab442a8395..6212a6e93e 100644 --- a/src/main/java/net/irisshaders/iris/pipeline/IrisRenderingPipeline.java +++ b/src/main/java/net/irisshaders/iris/pipeline/IrisRenderingPipeline.java @@ -181,6 +181,7 @@ public class IrisRenderingPipeline implements WorldRenderingPipeline, ShaderRend private int currentNormalTexture; private int currentSpecularTexture; private ColorSpace currentColorSpace; + private CloudSetting dhCloudSetting; public IrisRenderingPipeline(ProgramSet programSet) { ShaderPrinter.resetPrintState(); @@ -195,6 +196,7 @@ public IrisRenderingPipeline(ProgramSet programSet) { this.separateHardwareSamplers = programSet.getPack().hasFeature(FeatureFlags.SEPARATE_HARDWARE_SAMPLERS); this.shadowDirectives = packDirectives.getShadowDirectives(); this.cloudSetting = programSet.getPackDirectives().getCloudSetting(); + this.dhCloudSetting = programSet.getPackDirectives().getDHCloudSetting(); this.shouldRenderSun = programSet.getPackDirectives().shouldRenderSun(); this.shouldRenderMoon = programSet.getPackDirectives().shouldRenderMoon(); this.allowConcurrentCompute = programSet.getPackDirectives().getConcurrentCompute(); @@ -1259,10 +1261,18 @@ public Optional getDHTerrainShader() { return resolver.resolve(ProgramId.DhTerrain); } + public Optional getDHGenericShader() { + return resolver.resolve(ProgramId.DhGeneric); + } + public Optional getDHWaterShader() { return resolver.resolve(ProgramId.DhWater); } + public CloudSetting getDHCloudSetting() { + return dhCloudSetting; + } + public Optional getDHShadowShader() { return resolver.resolve(ProgramId.DhShadow); } diff --git a/src/main/java/net/irisshaders/iris/pipeline/transform/Patch.java b/src/main/java/net/irisshaders/iris/pipeline/transform/Patch.java index 174ed952ea..5273c94755 100644 --- a/src/main/java/net/irisshaders/iris/pipeline/transform/Patch.java +++ b/src/main/java/net/irisshaders/iris/pipeline/transform/Patch.java @@ -2,7 +2,8 @@ public enum Patch { VANILLA, - DH, + DH_TERRAIN, + DH_GENERIC, SODIUM, COMPOSITE, COMPUTE diff --git a/src/main/java/net/irisshaders/iris/pipeline/transform/TransformPatcher.java b/src/main/java/net/irisshaders/iris/pipeline/transform/TransformPatcher.java index 158c8e9529..6e42ab0584 100644 --- a/src/main/java/net/irisshaders/iris/pipeline/transform/TransformPatcher.java +++ b/src/main/java/net/irisshaders/iris/pipeline/transform/TransformPatcher.java @@ -16,12 +16,14 @@ import io.github.douira.glsl_transformer.util.LRUCache; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.irisshaders.iris.Iris; +import net.irisshaders.iris.gl.IrisLimits; import net.irisshaders.iris.gl.blending.AlphaTest; import net.irisshaders.iris.gl.shader.ShaderCompileException; import net.irisshaders.iris.gl.state.ShaderAttributeInputs; import net.irisshaders.iris.gl.texture.TextureType; import net.irisshaders.iris.helpers.Tri; import net.irisshaders.iris.pipeline.transform.parameter.ComputeParameters; +import net.irisshaders.iris.pipeline.transform.parameter.DHParameters; import net.irisshaders.iris.pipeline.transform.parameter.Parameters; import net.irisshaders.iris.pipeline.transform.parameter.SodiumParameters; import net.irisshaders.iris.pipeline.transform.parameter.TextureStageParameters; @@ -30,7 +32,8 @@ import net.irisshaders.iris.pipeline.transform.transformer.CompatibilityTransformer; import net.irisshaders.iris.pipeline.transform.transformer.CompositeCoreTransformer; import net.irisshaders.iris.pipeline.transform.transformer.CompositeTransformer; -import net.irisshaders.iris.pipeline.transform.transformer.DHTransformer; +import net.irisshaders.iris.pipeline.transform.transformer.DHGenericTransformer; +import net.irisshaders.iris.pipeline.transform.transformer.DHTerrainTransformer; import net.irisshaders.iris.pipeline.transform.transformer.SodiumCoreTransformer; import net.irisshaders.iris.pipeline.transform.transformer.SodiumTransformer; import net.irisshaders.iris.pipeline.transform.transformer.TextureTransformer; @@ -97,7 +100,7 @@ public TranslationUnit parseTranslationUnit(Root rootInstance, String input) { Matcher matcher = versionPattern.matcher(input); if (!matcher.find()) { throw new IllegalArgumentException( - "No #version directive found in source code! See debugging.md for more information."); + "No #version directive found in source code! See debugging.md for more information."); } transformer.getLexer().version = Version.fromNumber(Integer.parseInt(matcher.group(1))); @@ -140,8 +143,8 @@ public TranslationUnit parseTranslationUnit(Root rootInstance, String input) { if (profile == Profile.CORE || version.number >= 150 && profile == null || isLine) { // patch the version number to at least 330 - if (version.number < 330) { - versionStatement.version = Version.GLSL33; + if (version.number < 410) { + versionStatement.version = Version.GLSL41; } switch (parameters.patch) { @@ -164,8 +167,8 @@ public TranslationUnit parseTranslationUnit(Root rootInstance, String input) { } } else { // patch the version number to at least 330 - if (version.number < 330) { - versionStatement.version = Version.GLSL33; + if (version.number < 410) { + versionStatement.version = Version.GLSL41; } versionStatement.profile = Profile.CORE; @@ -180,8 +183,11 @@ public TranslationUnit parseTranslationUnit(Root rootInstance, String input) { case VANILLA: VanillaTransformer.transform(transformer, tree, root, (VanillaParameters) parameters); break; - case DH: - DHTransformer.transform(transformer, tree, root, parameters); + case DH_TERRAIN: + DHTerrainTransformer.transform(transformer, tree, root, parameters); + break; + case DH_GENERIC: + DHGenericTransformer.transform(transformer, tree, root, parameters); break; default: throw new UnsupportedOperationException("Unknown patch type: " + parameters.patch); @@ -289,16 +295,19 @@ public static Map patchVanilla( } - public static Map patchDH( + public static Map patchDHTerrain( String name, String vertex, String tessControl, String tessEval, String geometry, String fragment, Object2ObjectMap, String> textureMap) { return transform(name, vertex, geometry, tessControl, tessEval, fragment, - new Parameters(Patch.DH, textureMap) { - @Override - public TextureStage getTextureStage() { - return TextureStage.GBUFFERS_AND_SHADOW; - } - }); + new DHParameters(Patch.DH_TERRAIN, textureMap)); + } + + + public static Map patchDHGeneric( + String name, String vertex, String tessControl, String tessEval, String geometry, String fragment, + Object2ObjectMap, String> textureMap) { + return transform(name, vertex, geometry, tessControl, tessEval, fragment, + new DHParameters(Patch.DH_GENERIC, textureMap)); } public static Map patchSodium(String name, String vertex, String geometry, String tessControl, String tessEval, String fragment, diff --git a/src/main/java/net/irisshaders/iris/pipeline/transform/parameter/DHParameters.java b/src/main/java/net/irisshaders/iris/pipeline/transform/parameter/DHParameters.java new file mode 100644 index 0000000000..a9b40c371a --- /dev/null +++ b/src/main/java/net/irisshaders/iris/pipeline/transform/parameter/DHParameters.java @@ -0,0 +1,20 @@ +package net.irisshaders.iris.pipeline.transform.parameter; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import net.irisshaders.iris.gl.texture.TextureType; +import net.irisshaders.iris.helpers.Tri; +import net.irisshaders.iris.pipeline.transform.Patch; +import net.irisshaders.iris.shaderpack.texture.TextureStage; + +public class DHParameters extends Parameters { + public DHParameters(Patch patch, Object2ObjectMap, String> textureMap) { + super(patch, textureMap); + } + + @Override + public TextureStage getTextureStage() { + return TextureStage.GBUFFERS_AND_SHADOW; + } + + +} diff --git a/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/CommonTransformer.java b/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/CommonTransformer.java index e9e294f358..dd8e764f04 100644 --- a/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/CommonTransformer.java +++ b/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/CommonTransformer.java @@ -70,7 +70,9 @@ public class CommonTransformer { private static final List replaceExpressions = new ArrayList<>(); private static final List replaceIndexes = new ArrayList<>(); private static final Template inputDeclarationTemplate = Template.withExternalDeclaration( - "uniform int __name;"); + "uniform int __name;"); + private static final Template inputDeclarationTemplateLayout = Template.withExternalDeclaration( + "layout (location = __index) uniform int __name;"); static { fragDataDeclaration.markLocalReplacement("__index", ReferenceExpression.class); @@ -83,6 +85,13 @@ public class CommonTransformer { inputDeclarationTemplate.markLocalReplacement( inputDeclarationTemplate.getSourceRoot().nodeIndex.getOne(BuiltinNumericTypeSpecifier.class)); inputDeclarationTemplate.markIdentifierReplacement("__name"); + + inputDeclarationTemplateLayout.markLocalReplacement("__index", ReferenceExpression.class); + inputDeclarationTemplateLayout.markLocalReplacement( + inputDeclarationTemplateLayout.getSourceRoot().nodeIndex.getOne(StorageQualifier.class)); + inputDeclarationTemplateLayout.markLocalReplacement( + inputDeclarationTemplateLayout.getSourceRoot().nodeIndex.getOne(BuiltinNumericTypeSpecifier.class)); + inputDeclarationTemplateLayout.markIdentifierReplacement("__name"); } static void renameFunctionCall(Root root, String oldName, String newName) { @@ -391,6 +400,18 @@ public static void addIfNotExists(Root root, ASTParser t, TranslationUnit tree, } } + public static void addIfNotExists(Root root, ASTParser t, TranslationUnit tree, String name, Type type, + StorageType storageType, int location) { + if (root.externalDeclarationIndex.getStream(name) + .noneMatch((entry) -> entry.declaration() instanceof DeclarationExternalDeclaration)) { + tree.injectNode(ASTInjectionPoint.BEFORE_DECLARATIONS, inputDeclarationTemplateLayout.getInstanceFor(root, + new LiteralExpression(Type.INT32, location), + new StorageQualifier(storageType), + new BuiltinNumericTypeSpecifier(type), + new Identifier(name))); + } + } + private record RenameTargetResult(DeclarationExternalDeclaration samplerDeclaration, DeclarationMember samplerDeclarationMember, Stream targets) { } diff --git a/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHGenericTransformer.java b/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHGenericTransformer.java new file mode 100644 index 0000000000..eb8474edfe --- /dev/null +++ b/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHGenericTransformer.java @@ -0,0 +1,149 @@ +package net.irisshaders.iris.pipeline.transform.transformer; + +import io.github.douira.glsl_transformer.ast.node.TranslationUnit; +import io.github.douira.glsl_transformer.ast.node.type.qualifier.StorageQualifier; +import io.github.douira.glsl_transformer.ast.query.Root; +import io.github.douira.glsl_transformer.ast.transform.ASTInjectionPoint; +import io.github.douira.glsl_transformer.ast.transform.ASTParser; +import io.github.douira.glsl_transformer.util.Type; +import net.irisshaders.iris.Iris; +import net.irisshaders.iris.gl.shader.ShaderType; +import net.irisshaders.iris.pipeline.transform.parameter.Parameters; + +import static net.irisshaders.iris.pipeline.transform.transformer.CommonTransformer.addIfNotExists; + +public class DHGenericTransformer { + public static void transform( + ASTParser t, + TranslationUnit tree, + Root root, Parameters parameters) { + CommonTransformer.transform(t, tree, root, parameters, false); + + + root.replaceExpressionMatches(t, CommonTransformer.glTextureMatrix0, "mat4(1.0)"); + root.replaceExpressionMatches(t, CommonTransformer.glTextureMatrix1, "mat4(1.0)"); + root.rename("gl_ProjectionMatrix", "iris_ProjectionMatrix"); + + if (parameters.type.glShaderType == ShaderType.VERTEX) { + // Alias of gl_MultiTexCoord1 on 1.15+ for OptiFine + // See https://github.com/IrisShaders/Iris/issues/1149 + root.rename("gl_MultiTexCoord2", "gl_MultiTexCoord1"); + + root.replaceReferenceExpressions(t, "gl_MultiTexCoord0", + "vec4(0.0, 0.0, 0.0, 1.0)"); + + root.replaceReferenceExpressions(t, "gl_MultiTexCoord1", + "vec4(_vert_tex_light_coord, 0.0, 1.0)"); + + + // gl_MultiTexCoord0 and gl_MultiTexCoord1 are the only valid inputs (with + // gl_MultiTexCoord2 and gl_MultiTexCoord3 as aliases), other texture + // coordinates are not valid inputs. + CommonTransformer.replaceGlMultiTexCoordBounded(t, root, 4, 7); + } + + root.rename("gl_Color", "_vert_color"); + + if (parameters.type.glShaderType == ShaderType.VERTEX) { + root.replaceReferenceExpressions(t, "gl_Normal", "_vert_normal"); + + } + + // TODO: Should probably add the normal matrix as a proper uniform that's + // computed on the CPU-side of things + root.replaceReferenceExpressions(t, "gl_NormalMatrix", + "iris_NormalMatrix"); + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "uniform mat3 iris_NormalMatrix;"); + + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "uniform mat4 iris_ModelViewMatrixInverse;"); + + tree.parseAndInjectNode(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "uniform mat4 iris_ProjectionMatrixInverse;"); + + Iris.logger.warn("Type is " + parameters.type); + + // TODO: All of the transformed variants of the input matrices, preferably + // computed on the CPU side... + root.rename("gl_ModelViewMatrix", "iris_ModelViewMatrix"); + root.rename("gl_ModelViewMatrixInverse", "iris_ModelViewMatrixInverse"); + root.rename("gl_ProjectionMatrixInverse", "iris_ProjectionMatrixInverse"); + + if (parameters.type.glShaderType == ShaderType.VERTEX) { + // TODO: Vaporwave-Shaderpack expects that vertex positions will be aligned to + // chunks. + if (root.identifierIndex.has("ftransform")) { + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_FUNCTIONS, + "vec4 ftransform() { return gl_ModelViewProjectionMatrix * gl_Vertex; }"); + } + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "uniform mat4 iris_ProjectionMatrix;", + "uniform mat4 iris_ModelViewMatrix;", + // _draw_translation replaced with Chunks[_draw_id].offset.xyz + "vec4 getVertexPosition() { return vec4(_vert_position, 1.0); }"); + root.replaceReferenceExpressions(t, "gl_Vertex", "getVertexPosition()"); + + // inject here so that _vert_position is available to the above. (injections + // inject in reverse order if performed piece-wise but in correct order if + // performed as an array of injections) + injectVertInit(t, tree, root, parameters); + } else { + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_DECLARATIONS, + "uniform mat4 iris_ModelViewMatrix;", + "uniform mat4 iris_ProjectionMatrix;"); + } + + root.replaceReferenceExpressions(t, "gl_ModelViewProjectionMatrix", + "(iris_ProjectionMatrix * iris_ModelViewMatrix)"); + + CommonTransformer.applyIntelHd4000Workaround(root); + } + + public static void injectVertInit( + ASTParser t, + TranslationUnit tree, + Root root, + Parameters parameters) { + tree.parseAndInjectNodes(t, ASTInjectionPoint.BEFORE_FUNCTIONS, + // translated from sodium's chunk_vertex.glsl + "vec3 _vert_position;", + "vec2 _vert_tex_light_coord;", + "int dhMaterialId;", + "vec4 _vert_color;", + "vec3 _vert_normal;", + "uniform ivec3 uOffsetChunk;", + "uniform vec3 uOffsetSubChunk;", + "uniform ivec3 uCameraPosChunk;", + "uniform vec3 uCameraPosSubChunk;", + "uniform int uSkyLight;", + "uniform int uBlockLight;", + "const vec3 irisNormals[6] = vec3[](vec3(0,0,-1),vec3(0,0,1),vec3(-1,0,0),vec3(1,0,0),vec3(0,-1,0),vec3(0,1,0));", + """ + void _vert_init() { + vec3 trans = (aTranslateChunk + uOffsetChunk - uCameraPosChunk) * 16.0f; + trans += (aTranslateSubChunk + uOffsetSubChunk - uCameraPosSubChunk); + mat4 transform = mat4( + aScale.x, 0.0, 0.0, 0.0, + 0.0, aScale.y, 0.0, 0.0, + 0.0, 0.0, aScale.z, 0.0, + trans.x, trans.y, trans.z, 1.0 + ); + _vert_position = (transform * vec4(vPosition, 1.0)).xyz; + _vert_normal = irisNormals[int(floor(float(gl_VertexID) / 4))]; + float blockLight = (float(uBlockLight)+0.5) / 16.0; + float skyLight = (float(uSkyLight)+0.5) / 16.0; + _vert_tex_light_coord = vec2(blockLight, skyLight); + dhMaterialId = aMaterial; + _vert_color = iris_color; + } + """); + addIfNotExists(root, t, tree, "iris_color", Type.F32VEC4, StorageQualifier.StorageType.IN, 1); + addIfNotExists(root, t, tree, "aScale", Type.F32VEC3, StorageQualifier.StorageType.IN, 2); + addIfNotExists(root, t, tree, "aTranslateChunk", Type.I32VEC3, StorageQualifier.StorageType.IN, 3); + addIfNotExists(root, t, tree, "aTranslateSubChunk", Type.F32VEC3, StorageQualifier.StorageType.IN, 4); + addIfNotExists(root, t, tree, "aMaterial", Type.INT32, StorageQualifier.StorageType.IN, 5); + addIfNotExists(root, t, tree, "vPosition", Type.F32VEC3, StorageQualifier.StorageType.IN, 0); + tree.prependMainFunctionBody(t, "_vert_init();"); + } +} diff --git a/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHTransformer.java b/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHTerrainTransformer.java similarity index 99% rename from src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHTransformer.java rename to src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHTerrainTransformer.java index 6413ce5132..b962ac2440 100644 --- a/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHTransformer.java +++ b/src/main/java/net/irisshaders/iris/pipeline/transform/transformer/DHTerrainTransformer.java @@ -12,7 +12,7 @@ import static net.irisshaders.iris.pipeline.transform.transformer.CommonTransformer.addIfNotExists; -public class DHTransformer { +public class DHTerrainTransformer { public static void transform( ASTParser t, TranslationUnit tree, diff --git a/src/main/java/net/irisshaders/iris/shaderpack/ShaderPack.java b/src/main/java/net/irisshaders/iris/shaderpack/ShaderPack.java index d4104b73da..3790b70b9e 100644 --- a/src/main/java/net/irisshaders/iris/shaderpack/ShaderPack.java +++ b/src/main/java/net/irisshaders/iris/shaderpack/ShaderPack.java @@ -166,6 +166,9 @@ public ShaderPack(Path root, Map changedConfigs, ImmutableList finalEnvironmentDefines = new ArrayList<>(List.copyOf(environmentDefines)); for (FeatureFlags flag : FeatureFlags.values()) { if (flag.isUsable()) { + if (flag == FeatureFlags.TESSELLATION_SHADERS) { + finalEnvironmentDefines.add(new StringPair("IRIS_FEATURE_TESSELATION_SHADERS", "")); + } finalEnvironmentDefines.add(new StringPair("IRIS_FEATURE_" + flag.name(), "")); } } diff --git a/src/main/java/net/irisshaders/iris/shaderpack/loading/ProgramId.java b/src/main/java/net/irisshaders/iris/shaderpack/loading/ProgramId.java index 71651358f6..9af15fb0ec 100644 --- a/src/main/java/net/irisshaders/iris/shaderpack/loading/ProgramId.java +++ b/src/main/java/net/irisshaders/iris/shaderpack/loading/ProgramId.java @@ -45,6 +45,7 @@ public enum ProgramId { Water(ProgramGroup.Gbuffers, "water", Terrain), HandWater(ProgramGroup.Gbuffers, "hand_water", Hand), DhTerrain(ProgramGroup.Dh, "terrain"), + DhGeneric(ProgramGroup.Dh, "generic", DhTerrain), DhWater(ProgramGroup.Dh, "water", DhTerrain), DhShadow(ProgramGroup.Dh, "shadow"), diff --git a/src/main/java/net/irisshaders/iris/shaderpack/programs/ProgramSet.java b/src/main/java/net/irisshaders/iris/shaderpack/programs/ProgramSet.java index d7bedc0027..b5dda712f8 100644 --- a/src/main/java/net/irisshaders/iris/shaderpack/programs/ProgramSet.java +++ b/src/main/java/net/irisshaders/iris/shaderpack/programs/ProgramSet.java @@ -85,7 +85,7 @@ 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); + boolean readTesselation = pack.hasFeature(FeatureFlags.TESSELLATION_SHADERS); this.shadow = readProgramSource(directory, sourceProvider, "shadow", this, shaderProperties, BlendModeOverride.OFF, readTesselation); diff --git a/src/main/java/net/irisshaders/iris/shaderpack/properties/PackDirectives.java b/src/main/java/net/irisshaders/iris/shaderpack/properties/PackDirectives.java index d1b7e3a51b..132a7e95b7 100644 --- a/src/main/java/net/irisshaders/iris/shaderpack/properties/PackDirectives.java +++ b/src/main/java/net/irisshaders/iris/shaderpack/properties/PackDirectives.java @@ -30,6 +30,7 @@ public class PackDirectives { private float eyeBrightnessHalfLife; private float centerDepthHalfLife; private CloudSetting cloudSetting; + private CloudSetting dhCloudSetting; private boolean underwaterOverlay; private boolean vignette; private boolean sun; @@ -67,6 +68,7 @@ private PackDirectives(Set supportedRenderTargets, PackShadowDirectives public PackDirectives(Set supportedRenderTargets, ShaderProperties properties) { this(supportedRenderTargets, new PackShadowDirectives(properties)); cloudSetting = properties.getCloudSetting(); + dhCloudSetting = properties.getDHCloudSetting(); underwaterOverlay = properties.getUnderwaterOverlay().orElse(false); vignette = properties.getVignette().orElse(false); sun = properties.getSun().orElse(true); @@ -142,6 +144,10 @@ public CloudSetting getCloudSetting() { return cloudSetting; } + public CloudSetting getDHCloudSetting() { + return dhCloudSetting; + } + public boolean underwaterOverlay() { return underwaterOverlay; } diff --git a/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java b/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java index be492d5c51..67faf6aa21 100644 --- a/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java +++ b/src/main/java/net/irisshaders/iris/shaderpack/properties/ShaderProperties.java @@ -76,6 +76,7 @@ public class ShaderProperties { CustomUniforms.Builder customUniforms = new CustomUniforms.Builder(); private int customTexAmount; private CloudSetting cloudSetting = CloudSetting.DEFAULT; + private CloudSetting dhCloudSetting = CloudSetting.DEFAULT; private OptionalBoolean oldHandLight = OptionalBoolean.DEFAULT; private OptionalBoolean dynamicHandLight = OptionalBoolean.DEFAULT; private OptionalBoolean supportsColorCorrection = OptionalBoolean.DEFAULT; @@ -159,6 +160,20 @@ public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, It } else { Iris.logger.error("Unrecognized clouds setting: " + value); } + + if (dhCloudSetting == CloudSetting.DEFAULT) { + dhCloudSetting = cloudSetting; + } + } + + if ("dhClouds".equals(key)) { + if ("off".equals(value)) { + dhCloudSetting = CloudSetting.OFF; + } else if ("on".equals(value) || "fancy".equals(value)) { + dhCloudSetting = CloudSetting.FANCY; + } else { + Iris.logger.error("Unrecognized DH clouds setting (need off, on): " + value); + } } if ("shadow.culling".equals(key)) { @@ -932,4 +947,8 @@ public OptionalBoolean supportsColorCorrection() { public CustomUniforms.Builder getCustomUniforms() { return customUniforms; } + + public CloudSetting getDHCloudSetting() { + return dhCloudSetting; + } }