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.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 net.minecraft.client.renderer.RenderType;
|
||||
@@ -14,9 +15,22 @@ import net.minecraft.client.renderer.WorldRenderer;
|
||||
@Mixin(WorldRenderer.class)
|
||||
public class MixinWorldRenderer
|
||||
{
|
||||
@Inject(at = @At("HEAD"), method = "renderBlockLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V", cancellable = false)
|
||||
private void renderBlockLayer(RenderType blockLayerIn, MatrixStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
||||
private static float previousPartialTicks = 0;
|
||||
|
||||
@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;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.backsun.lod.builders.LodBuilder;
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.LodRegion;
|
||||
import com.backsun.lod.objects.LodWorld;
|
||||
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.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
@@ -49,25 +44,13 @@ public class ClientProxy
|
||||
// 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
|
||||
* and then tell the LodRenderer to draw.
|
||||
*/
|
||||
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);
|
||||
if (lodWorld != null && lodBuilder.regionWidth != newWidth)
|
||||
{
|
||||
|
||||
@@ -241,18 +241,27 @@ public class LodRenderer
|
||||
// set the required open GL settings
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
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_COLOR_MATERIAL);
|
||||
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);
|
||||
|
||||
setupProjectionMatrix(partialTicks);
|
||||
setupLighting(partialTicks);
|
||||
|
||||
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");
|
||||
|
||||
// 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.glEnable(GL11.GL_TEXTURE_2D);
|
||||
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
|
||||
// because otherwise the buffers may be set to the wrong size
|
||||
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
|
||||
profiler.endSection();
|
||||
@@ -478,7 +494,7 @@ public class LodRenderer
|
||||
{
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.world.getSunBrightness(partialTicks) : 0.2f;
|
||||
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};
|
||||
|
||||
|
||||
@@ -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