fix texture overwrite and z-fighting for non-ctm voidstone blocks

This commit is contained in:
danyadev committed 2025-11-20 22:12:50 +03:00
1 parent e969289b22
commit 12323be015
3 files changed
+120 -40

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,166 @@ 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;
shiftBoundary(ForgeDirection.WEST);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.WEST.ordinal()));
super.renderFaceXNeg(block, x, y, z, null);
clearOverrideBlockTexture();
resetBoundary(ForgeDirection.WEST);
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);
shiftBoundary(ForgeDirection.EAST);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.EAST.ordinal()));
renderMaxX -= 0.005;
super.renderFaceXPos(block, x, y, z, null);
clearOverrideBlockTexture();
resetBoundary(ForgeDirection.EAST);
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);
shiftBoundary(ForgeDirection.DOWN);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.DOWN.ordinal()));
renderMinY += 0.005;
super.renderFaceYNeg(block, x, y, z, null);
clearOverrideBlockTexture();
resetBoundary(ForgeDirection.DOWN);
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);
shiftBoundary(ForgeDirection.UP);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.UP.ordinal()));
renderMaxY -= 0.005;
super.renderFaceYPos(block, x, y, z, null);
clearOverrideBlockTexture();
resetBoundary(ForgeDirection.UP);
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);
shiftBoundary(ForgeDirection.NORTH);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.NORTH.ordinal()));
renderMinZ += 0.005;
super.renderFaceZNeg(block, x, y, z, null);
clearOverrideBlockTexture();
resetBoundary(ForgeDirection.NORTH);
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);
shiftBoundary(ForgeDirection.SOUTH);
setOverrideBlockTexture(getBase(x, y, z, ForgeDirection.SOUTH.ordinal()));
renderMaxZ -= 0.005;
super.renderFaceZPos(block, x, y, z, null);
clearOverrideBlockTexture();
resetBoundary(ForgeDirection.SOUTH);
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);
}
private void shiftBoundary(ForgeDirection direction) {
// When rendering a CTM overlay texture over a base block texture the base texture starts to z-fight.
// This method makes the base texture render slightly below the overlay.
// This submap check makes sure that we only apply this hack for blocks with CTM overlays
if (submap == null) {
return;
}
float epsilon = 0.0005F;
switch (direction) {
case WEST -> {
renderMinX += epsilon;
renderMinX += epsilon;
}
case EAST -> {
renderMinX -= epsilon;
renderMaxX -= epsilon;
}
case DOWN -> {
renderMinY += epsilon;
renderMaxY += epsilon;
}
case UP -> {
renderMinY -= epsilon;
renderMaxY -= epsilon;
}
case NORTH -> {
renderMinZ += epsilon;
renderMaxZ += epsilon;
}
case SOUTH -> {
renderMinZ -= epsilon;
renderMaxZ -= epsilon;
}
}
}
private void resetBoundary(ForgeDirection direction) {
if (submap == null) {
return;
}
float epsilon = 0.0005F;
switch (direction) {
case WEST -> {
renderMinX -= epsilon;
renderMaxX -= epsilon;
}
case EAST -> {
renderMinX += epsilon;
renderMaxX += epsilon;
}
case DOWN -> {
renderMinY -= epsilon;
renderMaxY -= epsilon;
}
case UP -> {
renderMinY += epsilon;
renderMaxY += epsilon;
}
case NORTH -> {
renderMinZ -= epsilon;
renderMaxZ -= epsilon;
}
case SOUTH -> {
renderMinZ += epsilon;
renderMaxZ += epsilon;
}
}
}
}
@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 +208,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;
}
}