From c5b4e20787c14b125b1b42b1a017b97568a5ce7e Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 21 Aug 2021 13:05:32 -0500 Subject: [PATCH] Add simple partially functioning frustum culling --- .../com/seibel/lod/render/LodRenderer.java | 39 +++++++++++++--- .../com/seibel/lod/render/RenderUtil.java | 44 ++++++++++++++++++- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index f2b3204ec..f7e92bae2 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -39,6 +39,7 @@ import com.seibel.lod.handlers.ReflectionHandler; import com.seibel.lod.objects.LevelPos; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.NearFarFogSettings; +import com.seibel.lod.objects.RegionPos; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.util.LodUtil; @@ -67,7 +68,7 @@ import net.minecraft.util.math.vector.Vector3f; * This is where LODs are draw to the world. * * @author James Seibel - * @version 8-20-2021 + * @version 8-21-2021 */ public class LodRenderer { @@ -318,14 +319,39 @@ public class LodRenderer if (vbos != null) { + int rendered = 0; + int skipped = 0; + + Vector3d cameraDir = mc.cameraEntity.getLookAngle(); + + // used to determine what type of fog to render + int halfWidth = vbos.length/2; + int quarterWidth = vbos.length/4; + for (int i = 0; i < vbos.length; i++) { for (int j = 0; j < vbos.length; j++) { - setupFog(fogSettings.near.distance, fogSettings.near.quality); - sendLodsToGpuAndDraw(vbos[i][j], modelViewMatrix); + RegionPos vboPos = new RegionPos(i + lodDim.getCenterX() - lodDim.getWidth()/2, j + lodDim.getCenterZ() - lodDim.getWidth()/2); + if (RenderUtil.isRegionInViewFrustum(player.blockPosition(), cameraDir, vboPos.blockPos())) + { + if ((i > halfWidth - quarterWidth && i < halfWidth + quarterWidth) && (j > halfWidth - quarterWidth && j < halfWidth + quarterWidth)) + setupFog(fogSettings.near.distance, fogSettings.near.quality); + else + setupFog(fogSettings.far.distance, fogSettings.far.quality); + + + sendLodsToGpuAndDraw(vbos[i][j], modelViewMatrix); + rendered++; + } + else + { + skipped++; + } } } + + ClientProxy.LOGGER.info(rendered + " - " + skipped); } @@ -361,9 +387,10 @@ public class LodRenderer // end of internal LOD profiling profiler.pop(); } - - - /** + + + + /** * This is where the actual drawing happens. * * @param buffers the buffers sent to the GPU to draw diff --git a/src/main/java/com/seibel/lod/render/RenderUtil.java b/src/main/java/com/seibel/lod/render/RenderUtil.java index a99d449d6..49108b987 100644 --- a/src/main/java/com/seibel/lod/render/RenderUtil.java +++ b/src/main/java/com/seibel/lod/render/RenderUtil.java @@ -22,14 +22,16 @@ import com.seibel.lod.handlers.LodConfig; import com.seibel.lod.util.LodUtil; import net.minecraft.client.Minecraft; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.vector.Vector3d; /** * This holds miscellaneous helper code * to be used in the rendering process. * * @author James Seibel - * @version 8-17-2021 + * @version 8-21-2021 */ public class RenderUtil { @@ -105,4 +107,44 @@ public class RenderUtil return numbLodsWide / (2 * mc.options.renderDistance); } + + + /** + * Returns true if one of the regions 4 corners is in front + * of the camera. + */ + public static boolean isRegionInViewFrustum(BlockPos playerBlockPos, Vector3d cameraDir, BlockPos vboCenterPos) + { + // convert the vbo position into a direction vector + // starting from the player's position + Vector3d vboVec = new Vector3d(playerBlockPos.getX(), 0, playerBlockPos.getZ()); + Vector3d playerVec = new Vector3d(vboCenterPos.getX(), vboCenterPos.getY(), vboCenterPos.getZ()); + Vector3d vboCenterVec = playerVec.subtract(vboVec); + + + int halfRegionWidth = LodUtil.REGION_WIDTH; + + Vector3d vboSeVec = new Vector3d(vboCenterVec.x + halfRegionWidth, 0, vboCenterVec.z + halfRegionWidth).normalize(); + Vector3d vboSwVec = new Vector3d(vboCenterVec.x - halfRegionWidth, 0, vboCenterVec.z + halfRegionWidth).normalize(); + Vector3d vboNwVec = new Vector3d(vboCenterVec.x - halfRegionWidth, 0, vboCenterVec.z - halfRegionWidth).normalize(); + Vector3d vboNeVec = new Vector3d(vboCenterVec.x + halfRegionWidth, 0, vboCenterVec.z - halfRegionWidth).normalize(); + + return isNormalizedVectorInViewFrustum(vboSeVec, cameraDir) || + isNormalizedVectorInViewFrustum(vboSwVec, cameraDir) || + isNormalizedVectorInViewFrustum(vboNwVec, cameraDir) || + isNormalizedVectorInViewFrustum(vboNeVec, cameraDir); + +// return isNormalizedVectorInViewFrustum(vboCenterVec.normalize(), cameraDir); + } + + /** + * Currently takes the dot product of the two vectors, + * but in the future could do more complicated frustum culling tests. + */ + private static boolean isNormalizedVectorInViewFrustum(Vector3d objectVector, Vector3d cameraDir) + { + // take the dot product + double dot = objectVector.dot(cameraDir); + return dot >= 0; + } }