Skip to content

Commit 1ebcb0f

Browse files
authored
URenderPipeline: Fix blend state with default/mc shaders on 1.17-1.20.6, third try
There another bug in GlBlendState which cause the GlBlendState which we apply by enabling the shader to not actually be stored as the `activeBlendState`. See code comments for details. Since we now necessarily have access to the GlBlendState of the shader, this commit also simplifies our dummy call to merely enable that particular GlBlendState instead of binding and unbinding the entire shader. Linear: EM-3512 GitHub: #121
1 parent dfc84bd commit 1ebcb0f

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

src/main/kotlin/gg/essential/universal/render/URenderPipeline.kt

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ import net.minecraft.client.renderer.WorldVertexBufferUploader
5151
//$$ import net.minecraft.client.render.Shader
5252
//$$ import java.util.function.Supplier
5353
//#endif
54+
//#if MC<12100
55+
//$$ import net.minecraft.client.gl.GlBlendState
56+
//$$ import java.lang.invoke.MethodHandles
57+
//#endif
5458
//#else
5559
import gg.essential.universal.shader.GlShader
5660
import net.minecraft.client.renderer.vertex.VertexFormatElement
@@ -129,9 +133,23 @@ class URenderPipeline private constructor(
129133
// (On 1.21+, MC's `GlBlendState` is still broken, but `ShaderProgram` no longer applies it)
130134
//#if MC>=11700 && MC<12100
131135
//$$ RenderSystem.getShader()?.let { shaderProgram ->
136+
//$$ // Capture actual desired blend state to restore afterwards
132137
//$$ val prevBlendState = BlendState.active()
133-
//$$ shaderProgram.bind()
134-
//$$ shaderProgram.unbind()
138+
//$$ // This seemingly pointless change of active blend state here is necessary because of another bug in
139+
//$$ // GlBlendState: It'll only update its global `activeBlendState` when the blend state is enabled or disabled
140+
//$$ // but not when merely the blend function or one of its parameters is changed. So we need to make sure
141+
//$$ // we enable a blend state which is the opposite of the blend state of the shader before we enable that one.
142+
//$$ // We need to do two calls because we don't know the state of the current `activeBlendState`.
143+
//$$ if (shaderProgram.glBlendState.isBlendDisabled) {
144+
//$$ BlendState.DISABLED.mc.enable()
145+
//$$ BlendState.ALPHA.mc.enable()
146+
//$$ } else {
147+
//$$ BlendState.ALPHA.mc.enable()
148+
//$$ BlendState.DISABLED.mc.enable()
149+
//$$ }
150+
//$$ // Enable shader's GlBlendState so it becomes the `GlBlendState.activeBlendState`
151+
//$$ shaderProgram.glBlendState.enable()
152+
//$$ // Restore desired blend state
135153
//$$ prevBlendState.activateWithoutChangingMcBlendState()
136154
//$$ }
137155
//#endif
@@ -522,6 +540,22 @@ class URenderPipeline private constructor(
522540
val isRequired = false
523541
//#endif
524542

543+
//#if MC>=11700 && MC<12100
544+
//$$ private val Shader_glBlendState: (Shader) -> GlBlendState by lazy {
545+
//$$ try {
546+
//$$ val field = Shader::class.java.declaredFields
547+
//$$ .first { it.type == GlBlendState::class.java }
548+
//$$ field.isAccessible = true
549+
//$$ val handle = MethodHandles.lookup().unreflectGetter(field)
550+
//$$ return@lazy { shader: Shader -> handle.invoke(shader) as GlBlendState }
551+
//$$ } catch (e: Exception) {
552+
//$$ e.printStackTrace()
553+
//$$ return@lazy { GlBlendState() }
554+
//$$ }
555+
//$$ }
556+
//$$ private val Shader.glBlendState: GlBlendState get() = Shader_glBlendState(this)
557+
//#endif
558+
525559
//#if !STANDALONE
526560
//#if MC>=12105
527561
//$$ @JvmStatic

0 commit comments

Comments
 (0)