[fabric-renderer-api] Mesh with a BlendMode of TRANSLUCENT is hiding crumbling particles
natanfudge opened this issue · 16 comments
For example this mesh (sorry for Kotlin)
private fun hologramCubeMesh(): Mesh {
val baseColor = 0xFF_FF_FF_FF.toInt()
val renderer = RendererAccess.INSTANCE.renderer
val mb = renderer.meshBuilder()
val qe = mb.emitter
val mat = renderer.materialFinder().blendMode(0, BlendMode.TRANSLUCENT).find()
val atlas = MinecraftClient.getInstance().getSpriteAtlas(PlayerContainer.field_21668)
val spriteBase = atlas.apply(Texture)
qe.material(mat).square(Direction.UP, 0f, 0f, 1f, 1f, 0f)
.spriteBake(0, spriteBase, MutableQuadView.BAKE_LOCK_UV or MutableQuadView.BAKE_NORMALIZED)
.spriteColor(0, baseColor, baseColor, baseColor, baseColor).emit()
qe.material(mat).square(Direction.DOWN, 0f, 0f, 1f, 1f, 0f)
.spriteBake(0, spriteBase, MutableQuadView.BAKE_LOCK_UV or MutableQuadView.BAKE_NORMALIZED)
.spriteColor(0, baseColor, baseColor, baseColor, baseColor).emit()
qe.material(mat).square(Direction.EAST, 0f, 0f, 1f, 1f, 0f)
.spriteBake(0, spriteBase, MutableQuadView.BAKE_LOCK_UV or MutableQuadView.BAKE_NORMALIZED)
.spriteColor(0, baseColor, baseColor, baseColor, baseColor).emit()
qe.material(mat).square(Direction.WEST, 0f, 0f, 1f, 1f, 0f)
.spriteBake(0, spriteBase, MutableQuadView.BAKE_LOCK_UV or MutableQuadView.BAKE_NORMALIZED)
.spriteColor(0, baseColor, baseColor, baseColor, baseColor).emit()
qe.material(mat).square(Direction.NORTH, 0f, 0f, 1f, 1f, 0f)
.spriteBake(0, spriteBase, MutableQuadView.BAKE_LOCK_UV or MutableQuadView.BAKE_NORMALIZED)
.spriteColor(0, baseColor, baseColor, baseColor, baseColor).emit()
qe.material(mat).square(Direction.SOUTH, 0f, 0f, 1f, 1f, 0f)
.spriteBake(0, spriteBase, MutableQuadView.BAKE_LOCK_UV or MutableQuadView.BAKE_NORMALIZED)
.spriteColor(0, baseColor, baseColor, baseColor, baseColor).emit()
return mb.build()
}
If you place a block behind the block that uses the mesh and break it, you won't be able to see the particles.
It depends. When CUTOUT is used, pixels from the texture will only be rendered if the pixel's alpha value is > 0.5. If your texture is designed for translucency (alpha < 0.5) then this is a correct render.
Mojang may fix the breaking particle issue, or they may not. Translucent rendering is tricky because it generally requires that quads be depth-sorted from the perspective of the viewer, which changes rapidly. This is feasible for static terrain quads, but for things like particles it can be prohibitive.
There are various tricks for dealing with it that don't require exotic algorithms but they all have trade-offs.
There has to be some workaround, because my mod emits particles INSIDE the holograms, and if I make it translucent you can't see the particles...
I can relate. I had the same issue issue in 1.14 for the Alchemical crafting blocks in DoomTree and eventually I resorted to using cutout particles.
Mojang doesn’t have good choices here. If translucent block quads update the depth buffer then translucent particles will always render behind terrain. (Seems to be what happens now). If they don’t update the depth buffer then translucent particles will always render in front of terrain.
If they don’t update the depth buffer for translucent terrain then it comes down to render order. If they render terrain first, then particles are always in front. If they render particles first, then particles are always in back.
If they depth sort the particles each frame and then interleave the rendering of terrain and particles according to depth, then performance suffers. More esoteric algorithms may be available but likely aren’t suitable or would be difficult to adapt to such a dynamic game with its unique run constraints.
Cutout particles don’t have this problem because they render before translucent and update the depth buffer. Translucent quads pixels “behind” the depth buffer are culled.
Writing to the depth buffer from non-opaque draws is always wrong, it doesn't fix anything outside some corner cases. It generally leads to worse results as more opaque objects are likely to follow.
Fixing or changing this seems out of fabric-api's scope though, if it persists and someone actually confirmed it is happening, we may want to consider offering a blend layer without depth writes.
Correct or not, it's what Mojang does. I was guessing before, but confirmed it just now:
Appears depth mask is also enabled for translucent terrain.
This is definitely out of API scope. A blend layer without depth writes would unfortunately solve nothing - unless something much more involved was also done. Even if the existing terrain and particles were changed to use the "corrected" material, that would simply mean that whatever renders last goes on top. Terrain quads would still be OK relative to themselves but translucent particles would always be either in front of or in back of terrain and their own draw order would be non-deterministic unless they are also sorted each frame.
There's no fix for this that isn't monstrously ambitious.
As an aside, Mojang gets away with this cheat by tightly controlling the draw order of opaque vs translucent polygons. All solid and cutout quads are drawn first, and only then are translucent terrain and particles drawn. This is done in back-to-front order by render chunk. It's been that way for as long as I can remember.
This appears to be a vanilla bug. Same thing happens with vanilla stained glass without API loaded.
try in pre2 @natanfudge ?
Should be closed IMO.
Note the fabulous mode introduced in 1.16 mostly fixes this. (And was, indeed "monstrously ambitious".)
Translucent layers do still update the depth buffer (and must, given how their rendering works) and afaik particles or translucent entities behind translucent terrain will still be hidden if fabulous mode is off.