Instead of using a stencil and rendering in the forgelastdraw event, we now you a mixin to render right before the sold block layer. The main purpose of this was to allow for LODs to be drawn behind transparent objects; however as a happy accident it seems to have also improved the lighting, I'm not sure if it is perfect, but it is much better.
This commit is contained in:
@@ -5,7 +5,8 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import com.backsun.lod.renderer.RenderGlobalHook;
|
import com.backsun.lod.LodMain;
|
||||||
|
import com.backsun.lod.util.LodConfig;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
@@ -14,9 +15,22 @@ import net.minecraft.client.renderer.WorldRenderer;
|
|||||||
@Mixin(WorldRenderer.class)
|
@Mixin(WorldRenderer.class)
|
||||||
public class MixinWorldRenderer
|
public class MixinWorldRenderer
|
||||||
{
|
{
|
||||||
@Inject(at = @At("HEAD"), method = "renderBlockLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V", cancellable = false)
|
private static float previousPartialTicks = 0;
|
||||||
private void renderBlockLayer(RenderType blockLayerIn, MatrixStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V", cancellable = false)
|
||||||
|
private void renderSky(MatrixStack matrixStackIn, float partialTicks, CallbackInfo callback)
|
||||||
{
|
{
|
||||||
RenderGlobalHook.startRenderingStencil(blockLayerIn);
|
// get the partial ticks since renderBlockLayer doesn't
|
||||||
|
// have access to them
|
||||||
|
previousPartialTicks = partialTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(at = @At("HEAD"), method = "renderBlockLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V", cancellable = false)
|
||||||
|
private void renderBlockLayer(RenderType renderType, MatrixStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
||||||
|
{
|
||||||
|
// only render if LODs are enabled and
|
||||||
|
// only render before solid blocks
|
||||||
|
if (LodConfig.CLIENT.drawLODs.get() && renderType == RenderType.getSolid())
|
||||||
|
LodMain.client_proxy.renderLods(previousPartialTicks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
package com.backsun.lod.proxy;
|
package com.backsun.lod.proxy;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
|
|
||||||
import com.backsun.lod.builders.LodBuilder;
|
import com.backsun.lod.builders.LodBuilder;
|
||||||
import com.backsun.lod.objects.LodChunk;
|
import com.backsun.lod.objects.LodChunk;
|
||||||
import com.backsun.lod.objects.LodDimension;
|
import com.backsun.lod.objects.LodDimension;
|
||||||
import com.backsun.lod.objects.LodRegion;
|
import com.backsun.lod.objects.LodRegion;
|
||||||
import com.backsun.lod.objects.LodWorld;
|
import com.backsun.lod.objects.LodWorld;
|
||||||
import com.backsun.lod.renderer.LodRenderer;
|
import com.backsun.lod.renderer.LodRenderer;
|
||||||
import com.backsun.lod.renderer.RenderGlobalHook;
|
|
||||||
import com.backsun.lod.util.LodConfig;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
|
||||||
import net.minecraftforge.event.world.BlockEvent;
|
import net.minecraftforge.event.world.BlockEvent;
|
||||||
import net.minecraftforge.event.world.ChunkEvent;
|
import net.minecraftforge.event.world.ChunkEvent;
|
||||||
import net.minecraftforge.event.world.WorldEvent;
|
import net.minecraftforge.event.world.WorldEvent;
|
||||||
@@ -49,25 +44,13 @@ public class ClientProxy
|
|||||||
// render event //
|
// render event //
|
||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
@SubscribeEvent
|
|
||||||
public void renderWorldLast(RenderWorldLastEvent event)
|
|
||||||
{
|
|
||||||
RenderGlobalHook.endRenderingStencil();
|
|
||||||
GL11.glStencilFunc(GL11.GL_EQUAL, 0, 0xFF);
|
|
||||||
|
|
||||||
if (LodConfig.CLIENT.drawLODs.get())
|
|
||||||
renderLods(event.getPartialTicks());
|
|
||||||
|
|
||||||
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do any setup that is required to draw LODs
|
* Do any setup that is required to draw LODs
|
||||||
* and then tell the LodRenderer to draw.
|
* and then tell the LodRenderer to draw.
|
||||||
*/
|
*/
|
||||||
public void renderLods(float partialTicks)
|
public void renderLods(float partialTicks)
|
||||||
{
|
{
|
||||||
// update the
|
// update each regions' width to match the new render distance
|
||||||
int newWidth = Math.max(4, (mc.gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE);
|
int newWidth = Math.max(4, (mc.gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE);
|
||||||
if (lodWorld != null && lodBuilder.regionWidth != newWidth)
|
if (lodWorld != null && lodBuilder.regionWidth != newWidth)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -241,18 +241,27 @@ public class LodRenderer
|
|||||||
// set the required open GL settings
|
// set the required open GL settings
|
||||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
GL11.glDisable(GL11.GL_TEXTURE_2D); // TODO store the default values of each of these so they can be reset correctly
|
||||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
// disable the lights Minecraft uses
|
||||||
|
GL11.glDisable(GL11.GL_LIGHT0);
|
||||||
|
GL11.glDisable(GL11.GL_LIGHT1);
|
||||||
|
|
||||||
Matrix4f modelViewMatrix = generateModelViewMatrix(partialTicks);
|
Matrix4f modelViewMatrix = generateModelViewMatrix(partialTicks);
|
||||||
|
|
||||||
setupProjectionMatrix(partialTicks);
|
setupProjectionMatrix(partialTicks);
|
||||||
setupLighting(partialTicks);
|
setupLighting(partialTicks);
|
||||||
|
|
||||||
NearFarFogSetting fogSetting = determineFogSettings();
|
NearFarFogSetting fogSetting = determineFogSettings();
|
||||||
|
|
||||||
|
// determine the current fog settings so they can be
|
||||||
|
// reset after drawing the LODs
|
||||||
|
float defaultFogStartDist = GL11.glGetFloat(GL11.GL_FOG_START);
|
||||||
|
float defaultFogEndDist = GL11.glGetFloat(GL11.GL_FOG_END);
|
||||||
|
int defaultFogMode = GL11.glGetInteger(GL11.GL_FOG_MODE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -278,19 +287,26 @@ public class LodRenderer
|
|||||||
|
|
||||||
profiler.endStartSection("LOD cleanup");
|
profiler.endStartSection("LOD cleanup");
|
||||||
|
|
||||||
// this must be done otherwise other parts of the screen may be drawn with a fog effect
|
|
||||||
// IE the GUI
|
|
||||||
FogRenderer.resetFog();
|
|
||||||
RenderSystem.disableFog();
|
|
||||||
|
|
||||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||||
GL11.glDisable(LOD_GL_LIGHT_NUMBER);
|
GL11.glDisable(LOD_GL_LIGHT_NUMBER);
|
||||||
|
// re-enable the lights Minecraft uses
|
||||||
|
GL11.glEnable(GL11.GL_LIGHT0);
|
||||||
|
GL11.glEnable(GL11.GL_LIGHT1);
|
||||||
|
// TODO record the light states before to make sure they are being reset correctly
|
||||||
|
RenderSystem.disableLighting();
|
||||||
|
|
||||||
// this can't be called until after the buffers are built
|
// this can't be called until after the buffers are built
|
||||||
// because otherwise the buffers may be set to the wrong size
|
// because otherwise the buffers may be set to the wrong size
|
||||||
previousChunkRenderDistance = mc.gameSettings.renderDistanceChunks;
|
previousChunkRenderDistance = mc.gameSettings.renderDistanceChunks;
|
||||||
|
|
||||||
|
// reset the fog settings so the normal chunks
|
||||||
|
// will be drawn correctly
|
||||||
|
RenderSystem.fogStart(defaultFogStartDist);
|
||||||
|
RenderSystem.fogEnd(defaultFogEndDist);
|
||||||
|
RenderSystem.fogMode(defaultFogMode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// end of profiler tracking
|
// end of profiler tracking
|
||||||
profiler.endSection();
|
profiler.endSection();
|
||||||
@@ -478,7 +494,7 @@ public class LodRenderer
|
|||||||
{
|
{
|
||||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.world.getSunBrightness(partialTicks) : 0.2f;
|
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.world.getSunBrightness(partialTicks) : 0.2f;
|
||||||
float gammaMultiplyer = (float)mc.gameSettings.gamma - 0.5f;
|
float gammaMultiplyer = (float)mc.gameSettings.gamma - 0.5f;
|
||||||
float lightStrength = sunBrightness - 0.7f + (gammaMultiplyer * 0.2f);
|
float lightStrength = sunBrightness - 0.4f + (gammaMultiplyer * 0.2f);
|
||||||
|
|
||||||
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
|
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
|
||||||
|
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
package com.backsun.lod.renderer;
|
|
||||||
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This code is used for drawing
|
|
||||||
* to the stencil buffer.
|
|
||||||
*
|
|
||||||
* @author James Seibel
|
|
||||||
* @version 02-17-2021
|
|
||||||
*/
|
|
||||||
public class RenderGlobalHook
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* this variable should be the same as the method name below.
|
|
||||||
* It is used when transforming the RenderGlobal class'
|
|
||||||
* renderBlockLayer method.
|
|
||||||
*/
|
|
||||||
public static final String START_STENCIL_METHOD_NAME = "startRenderingStencil";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method tells OpenGL to start drawing everything to the stencil.
|
|
||||||
* This is done to prevent LODs from being rendered on top of the world.
|
|
||||||
* <br><br>
|
|
||||||
* Called in the order (as of minecraft 1.16.4): <br>
|
|
||||||
* RenderType.getSolid() <br>
|
|
||||||
* RenderType.getCutoutMipped() <br>
|
|
||||||
* RenderType.getCutout() <br>
|
|
||||||
* RenderType.getTranslucent() <br>
|
|
||||||
* RenderType.getTripwire() <br>
|
|
||||||
*/
|
|
||||||
public static void startRenderingStencil(RenderType blockLayerIn)
|
|
||||||
{
|
|
||||||
// we only enable drawing to the stencil once since
|
|
||||||
// we want to skip the rendering of the out of world fog
|
|
||||||
// but catch everything else
|
|
||||||
if (blockLayerIn == RenderType.getSolid())
|
|
||||||
{
|
|
||||||
// solid is the first layer rendered
|
|
||||||
// clear the buffer so we can start fresh.
|
|
||||||
// if this isn't cleared first we will have overlap with the fog
|
|
||||||
// outside the world
|
|
||||||
GL11.glClearStencil(0);
|
|
||||||
GL11.glStencilMask(0x11111111);
|
|
||||||
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
|
|
||||||
|
|
||||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
|
||||||
GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0x11111111);
|
|
||||||
GL11.glStencilMask(0b11111111);
|
|
||||||
GL11.glStencilOp(GL11.GL_KEEP, // this doesn't mater since GL_ALWAYS is being used
|
|
||||||
GL11.GL_KEEP, // stencil test passes
|
|
||||||
GL11.GL_REPLACE); // stencil + depth pass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* this variable should be the same as the method name below.
|
|
||||||
* It is used when transforming the RenderGlobal class'
|
|
||||||
* renderBlockLayer method.
|
|
||||||
*/
|
|
||||||
public static final String END_STENCIL_METHOD_NAME = "endRenderingStencil";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currently this method isn't used in any transformations since we end
|
|
||||||
* the stencil drawing in the ClientProxy right before we draw the LODs.
|
|
||||||
*/
|
|
||||||
public static void endRenderingStencil(RenderType blockLayerIn)
|
|
||||||
{
|
|
||||||
GL11.glStencilOp(GL11.GL_KEEP, // this doesn't mater since GL_ALWAYS is being used
|
|
||||||
GL11.GL_KEEP, // stencil test passes
|
|
||||||
GL11.GL_KEEP); // stencil + depth pass
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void endRenderingStencil()
|
|
||||||
{
|
|
||||||
endRenderingStencil(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user