Skip to content

Conversation

@danyadev
Copy link
Member

@danyadev danyadev commented Nov 20, 2025

fixes GTNewHorizons/GT-New-Horizons-Modpack#21220

Before
image

After
image

Before After
image image

There are two parts of the problem and two commits to resolve them for good

Fix z-fighting for regular blocks

I just changed the order of rendering: now I first render animated base texture and then overlay texture. This way overlay always wins and renders above the base

I also tried to fix z-fighting for CTM blocks by adding shiftBoundary and resetBoundary methods, but epsilon-based approach is always unstable so you could still encounter micro-tears in minecraft material space on edges in some cases and z-fighting when the block is far away enough from you

Fix z-fighting for CTM blocks

Regular blocks got fixed because vertices have the same coordinates and minecraft have only one way left to decide what texture to render first: by using order in which they were added. Unfortunately, for CTM textures this isn't the case. Let's look at their rendering process:

  1. First, we render animated base texture using minecraft's RenderBlocks.renderFace*() method
  2. Then, we render an overlay texture using RenderBlocksCTM.renderFace*() method

These methods are very different: the native one creates only 4 vertices per side, but the RenderBlocksCTM one create 16 vertices per side, 4 per a quarter of the side. Vertices are different, calculations don't match, imperfections occur and z-fight begins (Why do I even write it, you already know what z-fighting is and why it happens)

So, what if we choose just one method to render both textures, just as it works for regular blocks? Finally, this is the only attempt that actually worked. Obviously we're going to use CTM rendering in both cases to keep connected textures

Before super.renderFace*() call there is a setOverrideBlockTexture() call which sets a base texture we want to render. The super.renderFace* method have two branches: in first it renders given face the vanilla way, and in second it renders it the CTM way. There were two main reasons to render the vanilla way: hasOverrideBlockTexture() and submap == null. Now we want to render the CTM way when hasOverrideBlockTexture() is true, but we'll still render the vanilla way when submap == null, which basically means that we don't have a CTM texture

The last part of solution is to handle the CTM rendering itself. If we leave it as is, it will render the full texture in every corner 4 times. To solve this problem we need to change UVs to render only a desired quarter of the texture in every corner

@danyadev danyadev force-pushed the cursed-voidstone-rendering branch from 2cd9642 to 20110c2 Compare November 20, 2025 19:12
@danyadev danyadev requested a review from a team December 27, 2025 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Some chisel blocks reveal their inner content when looking at them from distance

3 participants