Skip to content

Commit 5f02456

Browse files
authored
URenderPipeline: Fix blend state with default/mc shaders on 1.17-1.20.6
On these versions, the blend state configured for the URenderPipeline would under specific circumstances (depending on bugs in MC's GlBlendState and previous setup of global state) not be honored. See code comment for how this commit fixes / works around this issue. GitHub: #117
1 parent cfb963c commit 5f02456

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,29 @@ class URenderPipeline private constructor(
112112

113113
internal fun bind() {
114114
shader?.bind(glState.blendState)
115+
116+
// These seemingly pointless calls are used to bypass the builtin `GlBlendState` applied by Minecraft's
117+
// `ShaderProgram` class right before the actual draw call (so no way for us to change it afterwards) on these
118+
// versions.
119+
// This is so we can apply the BlendState of this URenderPipeline, even when using a pre-existing ShaderProgram
120+
// (such as all the default programs) which has a different builtin `GlBlendState`.
121+
// This works by exploiting one of the (many) bugs of `GlBlendState`, namely that it is lazy in that it does
122+
// not update anything if the previously active blend state matches the new one. In general that behavior is
123+
// wrong because there's plenty other things which update the global GL state but we use this to our advantage
124+
// here: We'll apply its GlBlendState now, and then revert the global GL state to our expected state, so that
125+
// later when MC calls `ShaderProgram.bind` right before the actual draw, its `GlBlendState.enable` call will
126+
// no-op and our desired blend state will stay active.
127+
// (Prior to 1.17, we only support the fixed-function pipeline and our own shader class which we call with
128+
// `skipBlendState = true`, so it doesn't mess with the global blend state at all)
129+
// (On 1.21+, MC's `GlBlendState` is still broken, but `ShaderProgram` no longer applies it)
130+
//#if MC>=11700 && MC<12100
131+
//$$ RenderSystem.getShader()?.let { shaderProgram ->
132+
//$$ val prevBlendState = BlendState.active()
133+
//$$ shaderProgram.bind()
134+
//$$ shaderProgram.unbind()
135+
//$$ UGraphics.Globals.blendState(prevBlendState)
136+
//$$ }
137+
//#endif
115138
}
116139

117140
internal fun unbind() {

0 commit comments

Comments
 (0)