Skip to content

Commit

Permalink
z-fighting fix shaders compat
Browse files Browse the repository at this point in the history
  • Loading branch information
FalsePattern committed Dec 31, 2024
1 parent f2b0570 commit a0b70d9
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ public class TranslucentBlockLayersConfig {
@Config.DefaultDouble(0.001)
public static double TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON;

@Config.Comment({
"Runtime toggle for enabling the matrix transforms.",
"This does not affect the mixin loading, use the toggle in the modules section for that."
})
@Config.Name(value = "enabled")
@Config.LangKey
@Config.DefaultBoolean(true)
public static boolean ENABLED;

static {
ConfigurationManager.selfInit();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,85 +23,104 @@

package com.falsepattern.falsetweaks.mixin.mixins.client.misc;

import lombok.val;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import com.falsepattern.falsetweaks.modules.misc.TranslucentBlockLayers;
import org.spongepowered.asm.mixin.Dynamic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.entity.EntityLivingBase;

import java.nio.FloatBuffer;

import static com.falsepattern.falsetweaks.config.TranslucentBlockLayersConfig.TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON;
import static com.falsepattern.falsetweaks.config.TranslucentBlockLayersConfig.ENABLED;


/**
* Allows translucent layers of blocks to render on the same plane as opaque.
*/
@Mixin(RenderGlobal.class)
public abstract class TranslucentBlockLayers_RenderGlobalMixin {
private FloatBuffer fltw$matrixBuffer;
private TranslucentBlockLayers ft$tbl;

private boolean doResetMatrix;

/**
* Moves the Z-Clip towards the camera by the {@link com.falsepattern.falsetweaks.config.TranslucentBlockLayersConfig#TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON epsilon} value when rendering translucent blocks.
*
* @param entityLivingBase Entity
* @param renderPass Render pass
* @param partialTick Partial tick
* @param cir Mixin callback
* Vanilla hook
*/
@Inject(method = "sortAndRender",
at = @At("HEAD"),
require = 1)
private void offsetProjection(EntityLivingBase entityLivingBase, int renderPass, double partialTick, CallbackInfoReturnable<Integer> cir) {
if (renderPass != 1) {
return;
}
ft$offsetProjection(renderPass);
}

if (fltw$matrixBuffer == null) {
fltw$matrixBuffer = BufferUtils.createFloatBuffer(16);
}
/**
* OptiFine hook
*/
@Dynamic
@Inject(method = "renderAllSortedRenderers",
at = @At("HEAD"),
remap = false,
require = 0,
expect = 0)
private void offsetProjection(int renderPass, double partialTick, CallbackInfoReturnable<Integer> cir) {
ft$offsetProjection(renderPass);
}

val lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE);
GL11.glMatrixMode(GL11.GL_PROJECTION);
/**
* Vanilla hook
*/
@Inject(method = "sortAndRender",
at = @At("RETURN"),
require = 1)
private void resetProjection(EntityLivingBase entityLivingBase, int renderPass, double partialTick, CallbackInfoReturnable<Integer> cir) {
ft$resetProjection();
}

GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, fltw$matrixBuffer);
/**
* OptiFine hook
*/
@Dynamic
@Inject(method = "renderAllSortedRenderers",
at = @At("RETURN"),
remap = false,
require = 0,
expect = 0)
private void resetProjection(int renderPass, double partialTick, CallbackInfoReturnable<Integer> cir) {
ft$resetProjection();
}

GL11.glPushMatrix();
/**
* Moves the Z-Clip towards the camera by the {@link com.falsepattern.falsetweaks.config.TranslucentBlockLayersConfig#TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON epsilon} value when rendering translucent blocks.
*/
@Unique
private void ft$offsetProjection(int renderPass) {
if (!ENABLED || renderPass != 1) {
doResetMatrix = false;
return;
}

GL11.glLoadIdentity();
GL11.glScalef(1F, 1F, 1F / (1F - (float) TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON));
GL11.glTranslatef(0F, 0F, -(float) TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON);
GL11.glMultMatrix(fltw$matrixBuffer);
doResetMatrix = true;

GL11.glMatrixMode(lastMatrixMode);
if (ft$tbl == null) {
ft$tbl = new TranslucentBlockLayers();
}
ft$tbl.offsetProjection();
}

/**
* Resets the projection after rendering translucent blocks.
*
* @param entityLivingBase Entity
* @param renderPass Render pass
* @param partialTick Partial tick
* @param cir Mixin callback
*/
@Inject(method = "sortAndRender",
at = @At("RETURN"),
require = 1)
private void resetProjection(EntityLivingBase entityLivingBase, int renderPass, double partialTick, CallbackInfoReturnable<Integer> cir) {
if (renderPass != 1) {
@Unique
private void ft$resetProjection() {
if (!doResetMatrix) {
return;
}

val lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE);

GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPopMatrix();
doResetMatrix = false;

GL11.glMatrixMode(lastMatrixMode);
ft$tbl.resetProjection();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* This file is part of FalseTweaks.
*
* Copyright (C) 2022-2024 FalsePattern
* All Rights Reserved
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* FalseTweaks is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FalseTweaks is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FalseTweaks. If not, see <https://www.gnu.org/licenses/>.
*/

package com.falsepattern.falsetweaks.modules.misc;

import com.falsepattern.falsetweaks.Compat;
import lombok.val;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import shadersmod.client.SMath;
import shadersmod.client.Shaders;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.FloatBuffer;

import static com.falsepattern.falsetweaks.config.TranslucentBlockLayersConfig.TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON;

public class TranslucentBlockLayers {
private final FloatBuffer matrixBufferIn = BufferUtils.createFloatBuffer(16);
private final FloatBuffer matrixBufferOut = BufferUtils.createFloatBuffer(16);
private final Matrix4f matrixA = new Matrix4f();
private final Matrix4f matrixB = new Matrix4f();
public void offsetProjection() {
val bufIn = matrixBufferIn;
val bufOut = matrixBufferOut;
val lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE);
GL11.glMatrixMode(GL11.GL_PROJECTION);
bufIn.position(0);
GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, bufIn);
transform();
GL11.glPushMatrix();
bufOut.position(0);
GL11.glLoadMatrix(bufOut);
GL11.glMatrixMode(lastMatrixMode);
if (Compat.isShaders()) {
ShadersCompat.fetchFromShaders(bufIn);
transform();
ShadersCompat.setToShaders(bufOut);
}
}

private void transform() {
val matA = matrixA;
val matB = matrixB;
matB.set(0, matrixBufferIn);
float epsilon = (float) -TRANSLUCENT_BLOCK_LAYERS_FIX_EPSILON;
matA.scaling(1F, 1F, 1F / (1F + epsilon));
matA.translate(0F, 0F, epsilon);
matA.mul(matB);
matA.get(0, matrixBufferOut);
}

public void resetProjection() {
val lastMatrixMode = GL11.glGetInteger(GL11.GL_MATRIX_MODE);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glPopMatrix();
GL11.glMatrixMode(lastMatrixMode);
if (Compat.isShaders()) {
ShadersCompat.setToShaders(matrixBufferIn);
}
}

private static class ShadersCompat {
private static final FloatBuffer projection;
private static final FloatBuffer projectionInverse;
private static final float[] faProjection;
private static final float[] faProjectionInverse;
private static final Method invertMat4FBFA;
static {
try {
val fProjection = Shaders.class.getDeclaredField("projection");
val fProjectionInverse = Shaders.class.getDeclaredField("projectionInverse");
val ffaProjection = Shaders.class.getDeclaredField("faProjection");
val ffaProjectionInverse = Shaders.class.getDeclaredField("faProjectionInverse");
invertMat4FBFA = SMath.class.getDeclaredMethod("invertMat4FBFA", FloatBuffer.class, FloatBuffer.class, float[].class, float[].class);
invertMat4FBFA.setAccessible(true);
fProjection.setAccessible(true);
fProjectionInverse.setAccessible(true);
ffaProjection.setAccessible(true);
ffaProjectionInverse.setAccessible(true);
projection = (FloatBuffer) fProjection.get(null);
projectionInverse = (FloatBuffer) fProjectionInverse.get(null);
faProjection = (float[]) ffaProjection.get(null);
faProjectionInverse = (float[]) ffaProjectionInverse.get(null);
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
private static void fetchFromShaders(FloatBuffer buf) {
buf.position(0);
projection.position(0);
buf.put(projection);
buf.position(0);
projection.position(0);
}

private static void setToShaders(FloatBuffer buf) {
buf.position(0);
projection.position(0);
projection.put(buf);
buf.position(0);
projection.position(0);
try {
invertMat4FBFA.invoke(null, (FloatBuffer)projectionInverse.position(0), (FloatBuffer)projection.position(0), faProjectionInverse, faProjection);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
Shaders.setProgramUniformMatrix4ARB("gbufferProjection", false, projection);
Shaders.setProgramUniformMatrix4ARB("gbufferProjectionInverse", false, projectionInverse);
}
}
}

0 comments on commit a0b70d9

Please sign in to comment.