From e4bfd6f303d8bc6b73f471829eb4974dfd899183 Mon Sep 17 00:00:00 2001 From: MCTian-mi <35869948+MCTian-mi@users.noreply.github.com> Date: Wed, 13 Aug 2025 18:56:55 +0800 Subject: [PATCH 1/7] feat: vbo world scene renderer --- .../renderer/scene/VBOWorldSceneRenderer.java | 133 ++++++++++++++++++ .../renderer/scene/WorldSceneRenderer.java | 74 +++++----- .../MultiblockInfoRecipeWrapper.java | 3 +- 3 files changed, 175 insertions(+), 35 deletions(-) create mode 100644 src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java diff --git a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java new file mode 100644 index 00000000000..d3bdb417f06 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java @@ -0,0 +1,133 @@ +package gregtech.client.renderer.scene; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.renderer.vertex.VertexBuffer; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.client.MinecraftForgeClient; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.opengl.GL11; + +import java.nio.ByteBuffer; +import java.util.Collection; + +@SideOnly(Side.CLIENT) +public class VBOWorldSceneRenderer extends ImmediateWorldSceneRenderer { + + protected final VertexBuffer[] vbos = new VertexBuffer[BlockRenderLayer.values().length]; + protected boolean isDirty = true; + + public VBOWorldSceneRenderer(World world) { + super(world); + } + + private void uploadVBO() { + BlockRenderLayer oldRenderLayer = MinecraftForgeClient.getRenderLayer(); + + try { // render block in each layer + for (BlockRenderLayer layer : BlockRenderLayer.values()) { + + var vbo = this.vbos[layer.ordinal()] = new VertexBuffer(DefaultVertexFormats.BLOCK); + + renderBlockLayer(layer); + + // Get the buffer again + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + buffer.finishDrawing(); + buffer.reset(); + + ByteBuffer data = buffer.getByteBuffer(); + vbo.bufferData(data); + } + } finally { + ForgeHooksClient.setRenderLayer(oldRenderLayer); + } + this.isDirty = false; + } + + @Override + protected void drawWorld() { + if (this.isDirty) { + uploadVBO(); + } + + Minecraft mc = Minecraft.getMinecraft(); + GlStateManager.enableCull(); + GlStateManager.enableRescaleNormal(); + RenderHelper.disableStandardItemLighting(); + mc.entityRenderer.disableLightmap(); + mc.renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); + GlStateManager.disableLighting(); + GlStateManager.enableTexture2D(); + GlStateManager.enableAlpha(); + + var oldRenderLayer = MinecraftForgeClient.getRenderLayer(); + for (var layer : BlockRenderLayer.values()) { + + ForgeHooksClient.setRenderLayer(layer); + + int pass = layer == BlockRenderLayer.TRANSLUCENT ? 1 : 0; + setDefaultPassRenderState(pass); + + GlStateManager.pushMatrix(); + { + var vbo = this.vbos[layer.ordinal()]; + vbo.bindBuffer(); + setupClientStates(); + setupArrayPointers(); + vbo.drawArrays(GL11.GL_QUADS); + resetClientStates(); + vbo.unbindBuffer(); + } + GlStateManager.popMatrix(); + } + ForgeHooksClient.setRenderLayer(oldRenderLayer); + + renderTESR(); // Handles TileEntities + + GlStateManager.shadeModel(GL11.GL_SMOOTH); + RenderHelper.enableStandardItemLighting(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.depthMask(true); + } + + @Override + public WorldSceneRenderer addRenderedBlocks(Collection blocks) { + this.isDirty = true; + return super.addRenderedBlocks(blocks); + } + + protected void setupClientStates() { + GlStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + GlStateManager.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit); + GlStateManager.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + GlStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY); + } + + protected void resetClientStates() { + GlStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY); + GlStateManager.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + GlStateManager.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + GlStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY); + } + + protected void setupArrayPointers() { + // 28 == DefaultVertexFormats.BLOCK.getSize(); + GlStateManager.glVertexPointer(3, GL11.GL_FLOAT, 28, 0); + GlStateManager.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 28, 12); + GlStateManager.glTexCoordPointer(2, GL11.GL_FLOAT, 28, 16); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit); + GlStateManager.glTexCoordPointer(2, GL11.GL_SHORT, 28, 24); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + } +} diff --git a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java index cb0dacd1c63..cd7aefc5080 100644 --- a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java @@ -1,10 +1,11 @@ package gregtech.client.renderer.scene; +import codechicken.lib.vec.Vector3; import gregtech.api.util.Position; import gregtech.api.util.PositionedRect; import gregtech.api.util.Size; import gregtech.client.utils.RenderUtil; - +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -23,13 +24,11 @@ import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; - -import codechicken.lib.vec.Vector3; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.GLU; +import javax.vecmath.Vector3f; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; @@ -37,8 +36,6 @@ import java.util.Collection; import java.util.function.Consumer; -import javax.vecmath.Vector3f; - /** * Created with IntelliJ IDEA. * @@ -237,23 +234,8 @@ protected void drawWorld() { try { // render block in each layer for (BlockRenderLayer layer : BlockRenderLayer.values()) { - ForgeHooksClient.setRenderLayer(layer); - int pass = layer == BlockRenderLayer.TRANSLUCENT ? 1 : 0; - setDefaultPassRenderState(pass); - - BufferBuilder buffer = Tessellator.getInstance().getBuffer(); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - BlockRendererDispatcher blockrendererdispatcher = mc.getBlockRendererDispatcher(); - - for (BlockPos pos : renderedBlocks) { - IBlockState state = world.getBlockState(pos); - Block block = state.getBlock(); - if (block == Blocks.AIR) continue; - state = state.getActualState(world, pos); - if (block.canRenderInLayer(state, layer)) { - blockrendererdispatcher.renderBlock(state, pos, world, buffer); - } - } + + renderBlockLayer(layer); Tessellator.getInstance().draw(); Tessellator.getInstance().getBuffer().setTranslation(0, 0, 0); @@ -262,14 +244,44 @@ protected void drawWorld() { ForgeHooksClient.setRenderLayer(oldRenderLayer); } - RenderHelper.enableStandardItemLighting(); - GlStateManager.enableLighting(); + renderTESR(); // Handles TileEntities + + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.depthMask(true); + + if (afterRender != null) { + afterRender.accept(this); + } + } - // render TESR + protected void renderBlockLayer(BlockRenderLayer layer) { + ForgeHooksClient.setRenderLayer(layer); + int pass = layer == BlockRenderLayer.TRANSLUCENT ? 1 : 0; + setDefaultPassRenderState(pass); + + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + BlockRendererDispatcher blockrendererdispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); + + for (BlockPos pos : renderedBlocks) { + IBlockState state = world.getBlockState(pos); + Block block = state.getBlock(); + state = state.getActualState(world, pos); + if (block == Blocks.AIR) continue; + if (block.canRenderInLayer(state, layer)) { + blockrendererdispatcher.renderBlock(state, pos, world, buffer); + } + } + } + + protected void renderTESR() { + RenderHelper.enableStandardItemLighting(); for (int pass = 0; pass < 2; pass++) { ForgeHooksClient.setRenderPass(pass); setDefaultPassRenderState(pass); - for (BlockPos pos : renderedBlocks) { + + for (BlockPos pos : renderedBlocks) { // This TileEntity tile = world.getTileEntity(pos); if (tile != null) { if (tile.shouldRenderInPass(pass)) { @@ -279,13 +291,7 @@ protected void drawWorld() { } } ForgeHooksClient.setRenderPass(-1); - GlStateManager.enableDepth(); - GlStateManager.disableBlend(); - GlStateManager.depthMask(true); - - if (afterRender != null) { - afterRender.accept(this); - } + RenderHelper.disableStandardItemLighting(); } public static void setDefaultPassRenderState(int pass) { diff --git a/src/main/java/gregtech/integration/jei/multiblock/MultiblockInfoRecipeWrapper.java b/src/main/java/gregtech/integration/jei/multiblock/MultiblockInfoRecipeWrapper.java index 1e5dd465b99..2bca0ef6bf1 100644 --- a/src/main/java/gregtech/integration/jei/multiblock/MultiblockInfoRecipeWrapper.java +++ b/src/main/java/gregtech/integration/jei/multiblock/MultiblockInfoRecipeWrapper.java @@ -13,6 +13,7 @@ import gregtech.api.util.GregFakePlayer; import gregtech.api.util.ItemStackHashStrategy; import gregtech.client.renderer.scene.ImmediateWorldSceneRenderer; +import gregtech.client.renderer.scene.VBOWorldSceneRenderer; import gregtech.client.renderer.scene.WorldSceneRenderer; import gregtech.client.utils.RenderUtil; import gregtech.client.utils.TrackedDummyWorld; @@ -585,7 +586,7 @@ private MBPattern initializePattern(@NotNull MultiblockShapeInfo shapeInfo, @Not } TrackedDummyWorld world = new TrackedDummyWorld(); - ImmediateWorldSceneRenderer worldSceneRenderer = new ImmediateWorldSceneRenderer(world); + ImmediateWorldSceneRenderer worldSceneRenderer = new VBOWorldSceneRenderer(world); worldSceneRenderer.setClearColor(ConfigHolder.client.multiblockPreviewColor); world.addBlocks(blockMap); From 65b24ea46f76a3f1275ffa64a09d7f8dd3ca2ead Mon Sep 17 00:00:00 2001 From: MCTian-mi <35869948+MCTian-mi@users.noreply.github.com> Date: Wed, 13 Aug 2025 19:32:36 +0800 Subject: [PATCH 2/7] fix: pre/after renders --- .../client/renderer/scene/VBOWorldSceneRenderer.java | 7 +++++++ .../gregtech/client/renderer/scene/WorldSceneRenderer.java | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java index d3bdb417f06..b1da32f6235 100644 --- a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java @@ -56,6 +56,9 @@ protected void drawWorld() { if (this.isDirty) { uploadVBO(); } + if (beforeRender != null) { + beforeRender.accept(this); + } Minecraft mc = Minecraft.getMinecraft(); GlStateManager.enableCull(); @@ -96,6 +99,10 @@ protected void drawWorld() { GlStateManager.enableDepth(); GlStateManager.disableBlend(); GlStateManager.depthMask(true); + + if (afterRender != null) { + afterRender.accept(this); + } } @Override diff --git a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java index cd7aefc5080..849de4a56df 100644 --- a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java @@ -59,8 +59,8 @@ public abstract class WorldSceneRenderer { public final World world; public final Collection renderedBlocks = new ObjectOpenHashSet<>(); - private Consumer beforeRender; - private Consumer afterRender; + protected Consumer beforeRender; + protected Consumer afterRender; private Consumer onLookingAt; private int clearColor; private RayTraceResult lastTraceResult; From 10fe768d273840009d29f4d4d8c1b79c6658614e Mon Sep 17 00:00:00 2001 From: MCTian-mi <35869948+MCTian-mi@users.noreply.github.com> Date: Fri, 15 Aug 2025 08:23:21 +0800 Subject: [PATCH 3/7] fix & format --- .../renderer/scene/VBOWorldSceneRenderer.java | 42 ++++++++++++------- .../renderer/scene/WorldSceneRenderer.java | 13 +++--- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java index b1da32f6235..f6a93b6113d 100644 --- a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java @@ -5,6 +5,7 @@ import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.VertexBuffer; +import net.minecraft.client.renderer.vertex.VertexFormatElement; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -12,15 +13,15 @@ import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; + import org.lwjgl.opengl.GL11; -import java.nio.ByteBuffer; import java.util.Collection; @SideOnly(Side.CLIENT) public class VBOWorldSceneRenderer extends ImmediateWorldSceneRenderer { - protected final VertexBuffer[] vbos = new VertexBuffer[BlockRenderLayer.values().length]; + protected static final VertexBuffer[] VBOS = new VertexBuffer[BlockRenderLayer.values().length]; protected boolean isDirty = true; public VBOWorldSceneRenderer(World world) { @@ -33,8 +34,6 @@ private void uploadVBO() { try { // render block in each layer for (BlockRenderLayer layer : BlockRenderLayer.values()) { - var vbo = this.vbos[layer.ordinal()] = new VertexBuffer(DefaultVertexFormats.BLOCK); - renderBlockLayer(layer); // Get the buffer again @@ -42,8 +41,10 @@ private void uploadVBO() { buffer.finishDrawing(); buffer.reset(); - ByteBuffer data = buffer.getByteBuffer(); - vbo.bufferData(data); + int i = layer.ordinal(); + var vbo = VBOS[i]; + if (vbo == null) vbo = VBOS[i] = new VertexBuffer(DefaultVertexFormats.BLOCK); + vbo.bufferData(buffer.getByteBuffer()); } } finally { ForgeHooksClient.setRenderLayer(oldRenderLayer); @@ -80,19 +81,20 @@ protected void drawWorld() { GlStateManager.pushMatrix(); { - var vbo = this.vbos[layer.ordinal()]; + int i = layer.ordinal(); + var vbo = VBOS[i]; vbo.bindBuffer(); - setupClientStates(); + enableClientStates(); setupArrayPointers(); vbo.drawArrays(GL11.GL_QUADS); - resetClientStates(); + disableClientStates(); vbo.unbindBuffer(); } GlStateManager.popMatrix(); } ForgeHooksClient.setRenderLayer(oldRenderLayer); - renderTESR(); // Handles TileEntities + renderTileEntities(); // Handle TileEntities GlStateManager.shadeModel(GL11.GL_SMOOTH); RenderHelper.enableStandardItemLighting(); @@ -111,7 +113,7 @@ public WorldSceneRenderer addRenderedBlocks(Collection blocks) { return super.addRenderedBlocks(blocks); } - protected void setupClientStates() { + protected void enableClientStates() { GlStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY); OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); GlStateManager.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY); @@ -121,11 +123,19 @@ protected void setupClientStates() { GlStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY); } - protected void resetClientStates() { - GlStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY); - GlStateManager.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY); - GlStateManager.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY); - GlStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY); + protected void disableClientStates() { + for (VertexFormatElement element : DefaultVertexFormats.BLOCK.getElements()) { + switch (element.getUsage()) { + case POSITION -> GlStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY); + case COLOR -> GlStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY); + case UV -> { + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit + element.getIndex()); + GlStateManager.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + } + default -> {} + } + } } protected void setupArrayPointers() { diff --git a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java index 849de4a56df..bdebbfa1c08 100644 --- a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java @@ -1,11 +1,10 @@ package gregtech.client.renderer.scene; -import codechicken.lib.vec.Vector3; import gregtech.api.util.Position; import gregtech.api.util.PositionedRect; import gregtech.api.util.Size; import gregtech.client.utils.RenderUtil; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -24,11 +23,13 @@ import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; + +import codechicken.lib.vec.Vector3; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.GLU; -import javax.vecmath.Vector3f; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; @@ -36,6 +37,8 @@ import java.util.Collection; import java.util.function.Consumer; +import javax.vecmath.Vector3f; + /** * Created with IntelliJ IDEA. * @@ -244,7 +247,7 @@ protected void drawWorld() { ForgeHooksClient.setRenderLayer(oldRenderLayer); } - renderTESR(); // Handles TileEntities + renderTileEntities(); // Handle TileEntities GlStateManager.enableDepth(); GlStateManager.disableBlend(); @@ -275,7 +278,7 @@ protected void renderBlockLayer(BlockRenderLayer layer) { } } - protected void renderTESR() { + protected void renderTileEntities() { RenderHelper.enableStandardItemLighting(); for (int pass = 0; pass < 2; pass++) { ForgeHooksClient.setRenderPass(pass); From 28b93c69093fc78c12a0ff6ddea83676599c3fa5 Mon Sep 17 00:00:00 2001 From: MCTian-mi <35869948+MCTian-mi@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:21:18 +0800 Subject: [PATCH 4/7] fix: optifine shader compat --- .../net/optifine/shaders/ShadersRender.java | 14 +++++++++ .../renderer/scene/VBOWorldSceneRenderer.java | 30 ++++++++++++++----- .../gregtech/client/utils/OptiFineHelper.java | 26 ++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 src/api/java/net/optifine/shaders/ShadersRender.java create mode 100644 src/main/java/gregtech/client/utils/OptiFineHelper.java diff --git a/src/api/java/net/optifine/shaders/ShadersRender.java b/src/api/java/net/optifine/shaders/ShadersRender.java new file mode 100644 index 00000000000..ceedfee366b --- /dev/null +++ b/src/api/java/net/optifine/shaders/ShadersRender.java @@ -0,0 +1,14 @@ +package net.optifine.shaders; + +import net.minecraft.util.BlockRenderLayer; + +/// Adapted and minimized from OptiFine +public class ShadersRender { + + public static void preRenderChunkLayer(BlockRenderLayer blockLayerIn) {} + + public static void postRenderChunkLayer(BlockRenderLayer blockLayerIn) {} + + public static void setupArrayPointersVbo() {} + +} diff --git a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java index f6a93b6113d..63bda60fb97 100644 --- a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java @@ -1,5 +1,8 @@ package gregtech.client.renderer.scene; +import gregtech.api.util.Mods; +import gregtech.client.utils.OptiFineHelper; + import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.texture.TextureMap; @@ -13,6 +16,7 @@ import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import net.optifine.shaders.ShadersRender; import org.lwjgl.opengl.GL11; @@ -34,6 +38,8 @@ private void uploadVBO() { try { // render block in each layer for (BlockRenderLayer layer : BlockRenderLayer.values()) { + OptiFineHelper.preRenderChunkLayer(layer); + renderBlockLayer(layer); // Get the buffer again @@ -45,6 +51,8 @@ private void uploadVBO() { var vbo = VBOS[i]; if (vbo == null) vbo = VBOS[i] = new VertexBuffer(DefaultVertexFormats.BLOCK); vbo.bufferData(buffer.getByteBuffer()); + + OptiFineHelper.postRenderChunkLayer(layer); } } finally { ForgeHooksClient.setRenderLayer(oldRenderLayer); @@ -79,6 +87,8 @@ protected void drawWorld() { int pass = layer == BlockRenderLayer.TRANSLUCENT ? 1 : 0; setDefaultPassRenderState(pass); + OptiFineHelper.preRenderChunkLayer(layer); + GlStateManager.pushMatrix(); { int i = layer.ordinal(); @@ -91,6 +101,8 @@ protected void drawWorld() { vbo.unbindBuffer(); } GlStateManager.popMatrix(); + + OptiFineHelper.postRenderChunkLayer(layer); } ForgeHooksClient.setRenderLayer(oldRenderLayer); @@ -139,12 +151,16 @@ protected void disableClientStates() { } protected void setupArrayPointers() { - // 28 == DefaultVertexFormats.BLOCK.getSize(); - GlStateManager.glVertexPointer(3, GL11.GL_FLOAT, 28, 0); - GlStateManager.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 28, 12); - GlStateManager.glTexCoordPointer(2, GL11.GL_FLOAT, 28, 16); - OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit); - GlStateManager.glTexCoordPointer(2, GL11.GL_SHORT, 28, 24); - OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + if (Mods.Optifine.isModLoaded()) { + ShadersRender.setupArrayPointersVbo(); + } else { + // 28 == DefaultVertexFormats.BLOCK.getSize(); + GlStateManager.glVertexPointer(3, GL11.GL_FLOAT, 28, 0); + GlStateManager.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 28, 12); + GlStateManager.glTexCoordPointer(2, GL11.GL_FLOAT, 28, 16); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit); + GlStateManager.glTexCoordPointer(2, GL11.GL_SHORT, 28, 24); + OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit); + } } } diff --git a/src/main/java/gregtech/client/utils/OptiFineHelper.java b/src/main/java/gregtech/client/utils/OptiFineHelper.java new file mode 100644 index 00000000000..8d1dc7ffc10 --- /dev/null +++ b/src/main/java/gregtech/client/utils/OptiFineHelper.java @@ -0,0 +1,26 @@ +package gregtech.client.utils; + +import gregtech.api.util.Mods; + +import net.minecraft.util.BlockRenderLayer; +import net.optifine.shaders.ShadersRender; + +public class OptiFineHelper { + + public static BlockRenderLayer getOFSafeLayer(BlockRenderLayer layer) { + if (!Mods.Optifine.isModLoaded()) return layer; + return layer == BloomEffectUtil.getBloomLayer() ? BloomEffectUtil.getEffectiveBloomLayer() : layer; + } + + public static void preRenderChunkLayer(BlockRenderLayer layer) { + if (Mods.Optifine.isModLoaded()) { + ShadersRender.preRenderChunkLayer(getOFSafeLayer(layer)); + } + } + + public static void postRenderChunkLayer(BlockRenderLayer layer) { + if (Mods.Optifine.isModLoaded()) { + ShadersRender.postRenderChunkLayer(getOFSafeLayer(layer)); + } + } +} From db9c1505644967f5b3c47856fb6cab670c7bbbc8 Mon Sep 17 00:00:00 2001 From: MCTian-mi <35869948+MCTian-mi@users.noreply.github.com> Date: Tue, 26 Aug 2025 10:51:32 +0800 Subject: [PATCH 5/7] feat: optimize tileEntity querying by caching them --- .../renderer/scene/WorldSceneRenderer.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java index bdebbfa1c08..69d2401fb31 100644 --- a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java @@ -1,5 +1,7 @@ package gregtech.client.renderer.scene; +import gregtech.api.metatileentity.IFastRenderMetaTileEntity; +import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.util.Position; import gregtech.api.util.PositionedRect; import gregtech.api.util.Size; @@ -25,6 +27,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import codechicken.lib.vec.Vector3; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; @@ -35,6 +38,7 @@ import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.Collection; +import java.util.Map; import java.util.function.Consumer; import javax.vecmath.Vector3f; @@ -60,6 +64,8 @@ public abstract class WorldSceneRenderer { protected static final FloatBuffer OBJECT_POS_BUFFER = ByteBuffer.allocateDirect(3 * 4) .order(ByteOrder.nativeOrder()).asFloatBuffer(); + // In most cases this would be empty + protected static final Map TILE_ENTITIES = new Object2ObjectArrayMap<>(); public final World world; public final Collection renderedBlocks = new ObjectOpenHashSet<>(); protected Consumer beforeRender; @@ -88,6 +94,15 @@ public WorldSceneRenderer setAfterWorldRender(Consumer callb public WorldSceneRenderer addRenderedBlocks(@Nullable Collection blocks) { if (blocks != null) { this.renderedBlocks.addAll(blocks); + TILE_ENTITIES.clear(); + blocks.forEach(pos -> { + TileEntity tile = world.getTileEntity(pos); + if (tile != null && (!(tile instanceof IGregTechTileEntity gtte) || + // Put MTEs only when it has FastRenderer + gtte.getMetaTileEntity() instanceof IFastRenderMetaTileEntity)) { + TILE_ENTITIES.put(pos, tile); + } + }); } return this; } @@ -280,18 +295,17 @@ protected void renderBlockLayer(BlockRenderLayer layer) { protected void renderTileEntities() { RenderHelper.enableStandardItemLighting(); + var dispatcher = TileEntityRendererDispatcher.instance; for (int pass = 0; pass < 2; pass++) { ForgeHooksClient.setRenderPass(pass); setDefaultPassRenderState(pass); - for (BlockPos pos : renderedBlocks) { // This - TileEntity tile = world.getTileEntity(pos); - if (tile != null) { - if (tile.shouldRenderInPass(pass)) { - TileEntityRendererDispatcher.instance.render(tile, pos.getX(), pos.getY(), pos.getZ(), 0); - } + int finalPass = pass; + TILE_ENTITIES.forEach((pos, tile) -> { + if (tile.shouldRenderInPass(finalPass)) { + dispatcher.render(tile, pos.getX(), pos.getY(), pos.getZ(), 0); } - } + }); } ForgeHooksClient.setRenderPass(-1); RenderHelper.disableStandardItemLighting(); From a28af9c5afce7619da7bc4f4a2ab2f03fc7de264 Mon Sep 17 00:00:00 2001 From: MCTian-mi <35869948+MCTian-mi@users.noreply.github.com> Date: Tue, 28 Oct 2025 10:28:41 +0800 Subject: [PATCH 6/7] fix: alson's review --- .../java/gregtech/client/renderer/scene/WorldSceneRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java index 69d2401fb31..b3716c07929 100644 --- a/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/WorldSceneRenderer.java @@ -285,8 +285,8 @@ protected void renderBlockLayer(BlockRenderLayer layer) { for (BlockPos pos : renderedBlocks) { IBlockState state = world.getBlockState(pos); Block block = state.getBlock(); - state = state.getActualState(world, pos); if (block == Blocks.AIR) continue; + state = state.getActualState(world, pos); if (block.canRenderInLayer(state, layer)) { blockrendererdispatcher.renderBlock(state, pos, world, buffer); } From 5f6805b0d55069475b0ec177a9ff50d13f233e5e Mon Sep 17 00:00:00 2001 From: MCTian-mi <35869948+MCTian-mi@users.noreply.github.com> Date: Tue, 25 Nov 2025 11:48:35 +0800 Subject: [PATCH 7/7] fix upstream merging --- .../client/renderer/scene/VBOWorldSceneRenderer.java | 2 +- src/main/java/gregtech/client/utils/OptiFineHelper.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java index 63bda60fb97..b4524ab576e 100644 --- a/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java +++ b/src/main/java/gregtech/client/renderer/scene/VBOWorldSceneRenderer.java @@ -151,7 +151,7 @@ protected void disableClientStates() { } protected void setupArrayPointers() { - if (Mods.Optifine.isModLoaded()) { + if (Mods.ShadersMod.isModLoaded()) { ShadersRender.setupArrayPointersVbo(); } else { // 28 == DefaultVertexFormats.BLOCK.getSize(); diff --git a/src/main/java/gregtech/client/utils/OptiFineHelper.java b/src/main/java/gregtech/client/utils/OptiFineHelper.java index 8d1dc7ffc10..f09b0f304d2 100644 --- a/src/main/java/gregtech/client/utils/OptiFineHelper.java +++ b/src/main/java/gregtech/client/utils/OptiFineHelper.java @@ -8,18 +8,18 @@ public class OptiFineHelper { public static BlockRenderLayer getOFSafeLayer(BlockRenderLayer layer) { - if (!Mods.Optifine.isModLoaded()) return layer; + if (!Mods.ShadersMod.isModLoaded()) return layer; return layer == BloomEffectUtil.getBloomLayer() ? BloomEffectUtil.getEffectiveBloomLayer() : layer; } public static void preRenderChunkLayer(BlockRenderLayer layer) { - if (Mods.Optifine.isModLoaded()) { + if (Mods.ShadersMod.isModLoaded()) { ShadersRender.preRenderChunkLayer(getOFSafeLayer(layer)); } } public static void postRenderChunkLayer(BlockRenderLayer layer) { - if (Mods.Optifine.isModLoaded()) { + if (Mods.ShadersMod.isModLoaded()) { ShadersRender.postRenderChunkLayer(getOFSafeLayer(layer)); } }