Move Render helper methods into RenderUtil

Also refactor said methods along with ClientApit
This commit is contained in:
James Seibel
2022-08-21 22:37:09 -05:00
parent c69b7d14bf
commit 9c669c2fe6
3 changed files with 137 additions and 78 deletions
@@ -34,6 +34,7 @@ import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.render.GLProxy;
import com.seibel.lod.core.render.LodFogConfig;
import com.seibel.lod.core.render.LodRenderProgram;
import com.seibel.lod.core.render.RenderUtil;
import com.seibel.lod.core.render.objects.GLState;
import com.seibel.lod.core.render.objects.GLVertexBuffer;
import com.seibel.lod.core.render.objects.QuadElementBuffer;
@@ -54,7 +55,7 @@ import java.util.concurrent.TimeUnit;
* This is where LODs are draw to the world.
*
* @author James Seibel
* @version 12-12-2021
* @version 2022-8-21
*/
public class a7LodRenderer
{
@@ -125,18 +126,7 @@ public class a7LodRenderer
EVENT_LOGGER.error("drawLODs() called after close()!");
return;
}
//=================================//
// determine if LODs should render //
//=================================//
if (MC_RENDER.playerHasBlindnessEffect())
{
// if the player is blind, don't render LODs,
// and don't change minecraft's fog
// which blindness relies on.
return;
}
if (MC_RENDER.getLightmapWrapper() == null)
return;
// get MC's shader program
// Save all MC render state
@@ -203,24 +193,14 @@ public class a7LodRenderer
//LightmapTexture lightmapTexture = new LightmapTexture();
/*---------Get required data--------*/
// Get the matrixs for rendering
int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
int lodChunkDist = Config.Client.Graphics.Quality.lodChunkRenderDistance.get();
int farPlaneBlockDistance;
// required for setupFog and setupProjectionMatrix
if (MC.getWrappedClientWorld().getDimensionType().hasCeiling())
farPlaneBlockDistance = Math.min(lodChunkDist, LodUtil.CEILED_DIMENSION_MAX_RENDER_DISTANCE) * LodUtil.CHUNK_WIDTH;
else
farPlaneBlockDistance = lodChunkDist * LodUtil.CHUNK_WIDTH;
Mat4f combinedMatrix = createCombinedMatrix(baseProjectionMatrix, baseModelViewMatrix,
vanillaBlockRenderedDistance, farPlaneBlockDistance, partialTicks);
Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks);
/*---------Fill uniform data--------*/
// Fill the uniform data. Note: GL33.GL_TEXTURE0 == texture bindpoint 0
shaderProgram.fillUniformData(combinedMatrix,
shaderProgram.fillUniformData(modelViewProjectionMatrix,
MC_RENDER.isFogStateSpecial() ? getSpecialFogColor(partialTicks) : getFogColor(partialTicks),
0, MC.getWrappedClientWorld().getHeight(), MC.getWrappedClientWorld().getMinHeight(), farPlaneBlockDistance,
0, MC.getWrappedClientWorld().getHeight(), MC.getWrappedClientWorld().getMinHeight(), RenderUtil.getFarClipPlaneDistanceInBlocks(),
vanillaBlockRenderedDistance, MC_RENDER.isFogStateSpecial());
// Note: Since lightmapTexture is changing every frame, it's faster to recreate it than to reuse the old one.
@@ -272,6 +252,8 @@ public class a7LodRenderer
tickLogger.incLogTries();
}
//=================//
// Setup Functions //
//=================//
@@ -313,44 +295,7 @@ public class a7LodRenderer
return MC_RENDER.getSpecialFogColor(partialTicks);
}
private static float calculateNearClipPlane(float distance, float partialTicks) {
double fov = MC_RENDER.getFov(partialTicks);
double aspectRatio = (double)MC_RENDER.getScreenWidth()/MC_RENDER.getScreenHeight();
return (float) (distance
/ Math.sqrt(1d + LodUtil.pow2(Math.tan(fov/180d*Math.PI/2d))
* (LodUtil.pow2(aspectRatio) + 1d)));
}
/**
* create and return a new projection matrix based on MC's projection matrix
* @param projMat this is Minecraft's current projection matrix
* @param modelMat this is Minecraft's current model matrix
* @param vanillaBlockRenderedDistance Minecraft's vanilla far plane distance
*/
private static Mat4f createCombinedMatrix(Mat4f projMat, Mat4f modelMat, float vanillaBlockRenderedDistance,
int farPlaneBlockDistance, float partialTicks)
{
//Create a copy of the current matrix, so the current matrix isn't modified.
Mat4f lodProj = projMat.copy();
float nearClipPlane;
if (Config.Client.Advanced.lodOnlyMode.get()) {
nearClipPlane = 0.1f;
} else if (Config.Client.Graphics.AdvancedGraphics.useExtendedNearClipPlane.get()) {
nearClipPlane = Math.min((vanillaBlockRenderedDistance-16f),8f*16f);
} else {
nearClipPlane = 16f;
}
//Set new far and near clip plane values.
lodProj.setClipPlanes(
calculateNearClipPlane(nearClipPlane, partialTicks),
(float)((farPlaneBlockDistance+LodUtil.REGION_WIDTH) * Math.sqrt(2)));
lodProj.multiply(modelMat);
return lodProj;
}
//======================//
// Cleanup Functions //
@@ -32,6 +32,7 @@ import com.seibel.lod.core.logging.SpamReducedLogger;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.render.GLProxy;
import com.seibel.lod.core.render.RenderSystemTest;
import com.seibel.lod.core.render.RenderUtil;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
@@ -52,7 +53,7 @@ import java.util.concurrent.TimeUnit;
* Specifically for the client.
*
* @author James Seibel
* @version 2022-8-20
* @version 2022-8-21
*/
public class ClientApi
{
@@ -231,19 +232,13 @@ public class ClientApi
profiler.push("DH-RenderLevel");
try
{
if (!MC.playerExists())
return;
if (levelWrapper == null)
return;
DhWorld dhWorld = SharedApi.currentWorld;
if (dhWorld == null)
return;
if (!(SharedApi.currentWorld instanceof IClientWorld))
if (!RenderUtil.shouldLodsRender(levelWrapper))
return;
//FIXME: Improve class hierarchy of DhWorld, IClientWorld, IServerWorld to fix all this hard casting
// (also in RenderUtil)
DhWorld dhWorld = SharedApi.currentWorld;
IClientLevel level = (IClientLevel) dhWorld.getOrLoadLevel(levelWrapper);
if (level == null)
return; //Level is not ready yet.
if (prefLoggerEnabled)
{
@@ -19,25 +19,38 @@
package com.seibel.lod.core.render;
import com.seibel.lod.core.a7.level.IClientLevel;
import com.seibel.lod.core.a7.world.DhWorld;
import com.seibel.lod.core.a7.world.IClientWorld;
import com.seibel.lod.core.api.internal.a7.SharedApi;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.objects.DHBlockPos;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
/**
* This holds miscellaneous helper code
* to be used in the rendering process.
*
* @author James Seibel
* @version 10-19-2021
* @version 2022-8-21
*/
public class RenderUtil
{
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
//=================//
// culling methods //
//=================//
/**
* Returns if the given ChunkPos is in the loaded area of the world.
* @param center the center of the loaded world (probably the player's ChunkPos)
@@ -64,7 +77,6 @@ public class RenderUtil
&& z <= centerCoordinate + MC_RENDER.getRenderDistance());
}
/**
* Find the coordinates that are in the center half of the given
* 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius).
@@ -80,7 +92,6 @@ public class RenderUtil
&& j <= lodRadius + halfRadius);
}
/**
* Returns true if one of the region's 4 corners is in front
* of the camera.
@@ -118,4 +129,112 @@ public class RenderUtil
// flickering or odd disappearances
return objectVector.dotProduct(cameraDir) > -0.1;
}
//=====================//
// matrix manipulation //
//=====================//
/**
* create and return a new projection matrix based on MC's modelView and projection matrices
* @param mcProjMat Minecraft's current projection matrix
*/
public static Mat4f createLodProjectionMatrix(Mat4f mcProjMat, float partialTicks)
{
int farPlaneDistanceInBlocks = RenderUtil.getFarClipPlaneDistanceInBlocks();
// Create a copy of the current matrix, so it won't be modified.
Mat4f lodProj = mcProjMat.copy();
// Set new far and near clip plane values.
lodProj.setClipPlanes(
getNearClipPlaneDistanceInBlocks(partialTicks),
(float)((farPlaneDistanceInBlocks+LodUtil.REGION_WIDTH) * Math.sqrt(2)));
return lodProj;
}
/** create and return a new projection matrix based on MC's modelView and projection matrices */
public static Mat4f createLodModelViewMatrix(Mat4f mcModelViewMat)
{
// nothing beyond copying needs to be done to MC's MVM currently,
// this method is just here in case that changes in the future
return mcModelViewMat.copy();
}
/**
* create and return a new combined modelView/projection matrix based on MC's modelView and projection matrices
* @param mcProjMat Minecraft's current projection matrix
* @param mcModelViewMat Minecraft's current model view matrix
*/
public static Mat4f createCombinedModelViewProjectionMatrix(Mat4f mcProjMat, Mat4f mcModelViewMat, float partialTicks)
{
Mat4f lodProj = createLodProjectionMatrix(mcProjMat, partialTicks);
lodProj.multiply(createLodModelViewMatrix(mcModelViewMat));
return lodProj;
}
public static float getNearClipPlaneDistanceInBlocks(float partialTicks)
{
int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
float nearClipPlane;
if (Config.Client.Advanced.lodOnlyMode.get()) {
nearClipPlane = 0.1f;
} else if (Config.Client.Graphics.AdvancedGraphics.useExtendedNearClipPlane.get()) {
nearClipPlane = Math.min(vanillaBlockRenderedDistance - LodUtil.CHUNK_WIDTH, (float) 8 * LodUtil.CHUNK_WIDTH); // allow a max near clip plane of 8 chunks
} else {
nearClipPlane = 16f;
}
// modify the based on the player's FOV
double fov = MC_RENDER.getFov(partialTicks);
double aspectRatio = (double) MC_RENDER.getScreenWidth() / MC_RENDER.getScreenHeight();
return (float) (nearClipPlane
/ Math.sqrt(1d + LodUtil.pow2(Math.tan(fov / 180d * Math.PI / 2d))
* (LodUtil.pow2(aspectRatio) + 1d)));
}
public static int getFarClipPlaneDistanceInBlocks()
{
int lodChunkDist = Config.Client.Graphics.Quality.lodChunkRenderDistance.get();
return lodChunkDist * LodUtil.CHUNK_WIDTH;
}
/** @return false if LODs shouldn't be rendered for any reason */
public static boolean shouldLodsRender(ILevelWrapper levelWrapper)
{
if (!MC.playerExists())
return false;
if (levelWrapper == null)
return false;
DhWorld dhWorld = SharedApi.currentWorld;
if (dhWorld == null)
return false;
if (!(SharedApi.currentWorld instanceof IClientWorld))
return false; // don't attempt to render server worlds
//FIXME: Improve class hierarchy of DhWorld, IClientWorld, IServerWorld to fix all this hard casting
// (also in ClientApi)
IClientLevel level = (IClientLevel) dhWorld.getOrLoadLevel(levelWrapper);
if (level == null)
return false; //Level is not ready yet.
if (MC_RENDER.playerHasBlindnessEffect())
{
// if the player is blind, don't render LODs,
// and don't change minecraft's fog
// which blindness relies on.
return false;
}
if (MC_RENDER.getLightmapWrapper() == null)
return false;
return true;
}
}