Fix z-fighting for voidstone blocks (#71)

Co-authored-by: Martin Robertz <dream-master@gmx.net>
This commit is contained in:
danyadevandMartin Robertz authored and GitHub committed 2025-12-29 23:37:43 +00:00
1 parent c3e1675ac8
commit 6efa21100b
4 files changed
+100 -65

No files matched your search

+1
View File
@@ -28,3 +28,4 @@ whitelist.json
src/main/resources/mixins.*.json
*.bat
layout.json
.DS_Store
+1 -1
View File
@@ -41,7 +41,7 @@ developmentEnvironmentUserName = Developer
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
# See https://github.com/bsideup/jabel for details on how this works.
enableModernJavaSyntax = false
enableModernJavaSyntax = true
# Enables injecting missing generics into the decompiled source code for a better coding experience.
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
@@ -21,91 +21,81 @@ public class SubmapManagerVoidstone extends SubmapManagerBase {
// TODO there must be a better more generic way to do this...
@SideOnly(Side.CLIENT)
private class RenderBlocksVoidstone extends RenderBlocksCTM {
private static class RenderBlocksVoidstone extends RenderBlocksCTM {
@Override
public void renderFaceXNeg(Block block, double x, double y, double z, IIcon icon) {
super.renderFaceXNeg(block, x, y, z, icon);
renderMinX += 0.005;
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.WEST.ordinal()));
super.renderFaceXNeg(block, x, y, z, null);
clearOverrideBlockTexture();
super.renderFaceXNeg(block, x, y, z, icon);
}
@Override
public void renderFaceXPos(Block block, double x, double y, double z, IIcon icon) {
super.renderFaceXPos(block, x, y, z, icon);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.EAST.ordinal()));
renderMaxX -= 0.005;
super.renderFaceXPos(block, x, y, z, null);
clearOverrideBlockTexture();
super.renderFaceXPos(block, x, y, z, icon);
}
@Override
public void renderFaceYNeg(Block block, double x, double y, double z, IIcon icon) {
super.renderFaceYNeg(block, x, y, z, icon);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.DOWN.ordinal()));
renderMinY += 0.005;
super.renderFaceYNeg(block, x, y, z, null);
clearOverrideBlockTexture();
super.renderFaceYNeg(block, x, y, z, icon);
}
@Override
public void renderFaceYPos(Block block, double x, double y, double z, IIcon icon) {
super.renderFaceYPos(block, x, y, z, icon);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.UP.ordinal()));
renderMaxY -= 0.005;
super.renderFaceYPos(block, x, y, z, null);
clearOverrideBlockTexture();
super.renderFaceYPos(block, x, y, z, icon);
}
@Override
public void renderFaceZNeg(Block block, double x, double y, double z, IIcon icon) {
super.renderFaceZNeg(block, x, y, z, icon);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.NORTH.ordinal()));
renderMinZ += 0.005;
super.renderFaceZNeg(block, x, y, z, null);
clearOverrideBlockTexture();
super.renderFaceZNeg(block, x, y, z, icon);
}
@Override
public void renderFaceZPos(Block block, double x, double y, double z, IIcon icon) {
super.renderFaceZPos(block, x, y, z, icon);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.SOUTH.ordinal()));
renderMaxZ -= 0.005;
super.renderFaceZPos(block, x, y, z, null);
clearOverrideBlockTexture();
super.renderFaceZPos(block, x, y, z, icon);
}
public void reset() {
this.submap = null;
private IIcon getBase(double x, double y, double z, int side) {
return TextureType.getVIcon(
TextureType.V4,
base,
MathHelper.floor_double(x),
MathHelper.floor_double(y),
MathHelper.floor_double(z),
side);
}
}
@SideOnly(Side.CLIENT)
private static ThreadLocal<RenderBlocksVoidstone> renderBlocksThreadLocal;
private static void initStatics() {
if (renderBlocksThreadLocal == null) {
renderBlocksThreadLocal = new ThreadLocal<>();
}
}
private ISubmapManager overlay;
private TextureSubmap base;
private static TextureSubmap base;
private IIcon getBase(double x, double y, double z, int side) {
return TextureType.getVIcon(
TextureType.V4,
base,
MathHelper.floor_double(x),
MathHelper.floor_double(y),
MathHelper.floor_double(z),
side);
}
private String texture;
private int meta;
private final String texture;
private final int meta;
public SubmapManagerVoidstone(String texture, int meta) {
this.texture = texture;
@@ -133,18 +123,22 @@ public class SubmapManagerVoidstone extends SubmapManagerBase {
@Override
@SideOnly(Side.CLIENT)
public RenderBlocks createRenderContext(RenderBlocks rendererOld, Block block, IBlockAccess world) {
initStatics();
if (renderBlocksThreadLocal == null) {
renderBlocksThreadLocal = ThreadLocal.withInitial(RenderBlocksVoidstone::new);
}
RenderBlocksVoidstone rb = renderBlocksThreadLocal.get();
if (rb == null) {
rb = new RenderBlocksVoidstone();
renderBlocksThreadLocal.set(rb);
} else rb.reset();
RenderBlocks ctx = overlay.createRenderContext(rendererOld, block, world);
rb.setRenderBoundsFromBlock(block);
if (ctx instanceof RenderBlocksCTM) {
rb.submap = ((RenderBlocksCTM) ctx).submap;
rb.submapSmall = ((RenderBlocksCTM) ctx).submapSmall;
} else {
rb.submap = null;
rb.submapSmall = null;
}
return rb;
}
}
@@ -361,6 +361,61 @@ public class RenderBlocksCTM extends RenderBlocks {
protected void side(Block block, SubSide side, int iconIndex) {
// If we have an overridden texture when we're supposed to render a CTM texture,
// we'll treat it as a normal block texture but still render it the CTM way: quarter of a texture at a time.
// This way has one benefit: if an overridden texture is a base block texture and a CTM texture (that is being
// rendered next) is an overlay texture above the base, we're avoiding any z-fighting issues because we
// create identical vertices and now only order of rendering dictates which texture will be rendered above
if (hasOverrideBlockTexture()) {
IIcon icon = overrideBlockTexture;
double u0 = icon.getMinU();
double u1 = icon.getMaxU();
double v0 = icon.getMinV();
double v1 = icon.getMaxV();
double uMid = (u0 + u1) / 2;
double vMid = (v0 + v1) / 2;
// Map all LB-style subsides to bottom-left quarter, RB to bottom-right, RT to top-right, LT to top-left
switch (side) {
// bottom-left quarter
case XNEG_LB, XPOS_LB, YNEG_LB, YPOS_LB, ZNEG_LB, ZPOS_LB -> {
minU = u0;
maxU = uMid;
minV = vMid;
maxV = v1;
}
// bottom-right quarter
case XNEG_RB, XPOS_RB, YNEG_RB, YPOS_RB, ZNEG_RB, ZPOS_RB -> {
minU = uMid;
maxU = u1;
minV = vMid;
maxV = v1;
}
// top-right quarter
case XNEG_RT, XPOS_RT, YNEG_RT, YPOS_RT, ZNEG_RT, ZPOS_RT -> {
minU = uMid;
maxU = u1;
minV = v0;
maxV = vMid;
}
// top-left quarter
case XNEG_LT, XPOS_LT, YNEG_LT, YPOS_LT, ZNEG_LT, ZPOS_LT -> {
minU = u0;
maxU = uMid;
minV = v0;
maxV = vMid;
}
}
side.render(this);
return;
}
IIcon icon;
TextureSubmap map;
if (iconIndex >= 16) {
@@ -378,25 +433,10 @@ public class RenderBlocksCTM extends RenderBlocks {
icon = map.getSubIcon(x, y);
}
double umax = icon.getMaxU();
double umin = icon.getMinU();
double vmax = icon.getMaxV();
double vmin = icon.getMinV();
minU = umin;
maxU = umax;
minV = vmin;
maxV = vmax;
// uCache[0] = umin;
// uCache[1] = umax;
// uCache[2] = umax;
// uCache[3] = umin;
//
// vCache[0] = vmax;
// vCache[1] = vmax;
// vCache[2] = vmin;
// vCache[3] = vmin;
minU = icon.getMinU();
maxU = icon.getMaxU();
minV = icon.getMinV();
maxV = icon.getMaxV();
side.render(this);
}
@@ -404,7 +444,7 @@ public class RenderBlocksCTM extends RenderBlocks {
@Override
public void renderFaceXNeg(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.WEST);
if (!inWorld || hasOverrideBlockTexture() || submap == null) {
if (!inWorld || submap == null) {
super.renderFaceXNeg(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 4);
@@ -429,7 +469,7 @@ public class RenderBlocksCTM extends RenderBlocks {
@Override
public void renderFaceXPos(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.EAST);
if (!inWorld || hasOverrideBlockTexture() || submap == null) {
if (!inWorld || submap == null) {
super.renderFaceXPos(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 5);
@@ -454,7 +494,7 @@ public class RenderBlocksCTM extends RenderBlocks {
@Override
public void renderFaceZNeg(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.NORTH);
if (!inWorld || hasOverrideBlockTexture() || submap == null) {
if (!inWorld || submap == null) {
super.renderFaceZNeg(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 2);
@@ -479,7 +519,7 @@ public class RenderBlocksCTM extends RenderBlocks {
@Override
public void renderFaceZPos(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.SOUTH);
if (!inWorld || hasOverrideBlockTexture() || submap == null) {
if (!inWorld || submap == null) {
super.renderFaceZPos(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 3);
@@ -504,7 +544,7 @@ public class RenderBlocksCTM extends RenderBlocks {
@Override
public void renderFaceYNeg(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.DOWN);
if (!inWorld || hasOverrideBlockTexture() || submap == null) {
if (!inWorld || submap == null) {
super.renderFaceYNeg(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 0);
@@ -529,7 +569,7 @@ public class RenderBlocksCTM extends RenderBlocks {
@Override
public void renderFaceYPos(Block block, double x, double y, double z, IIcon icon) {
pre(ForgeDirection.UP);
if (!inWorld || hasOverrideBlockTexture() || submap == null) {
if (!inWorld || submap == null) {
super.renderFaceYPos(block, 0, 0, 0, icon);
} else {
int tex[] = ctm.getSubmapIndices(blockAccess, bx, by, bz, 1);