Fix LOD rendering on Mac

This commit is contained in:
James Seibel
2026-03-15 15:57:57 -05:00
parent 9bd946a41c
commit 667dd85aef
7 changed files with 155 additions and 98 deletions
@@ -492,15 +492,7 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
profiler.push(boxGroup.getResourceLocationNamespace());
profiler.push(boxGroup.getResourceLocationPath());
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
this::getRenderPassName,
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
/*optionalClearColorAsInt*/ OptionalInt.empty(),
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
{
this.renderBoxGroupInstanced(renderPass, renderEventParam, boxGroup, profiler);
}
this.renderBoxGroupInstanced(renderEventParam, boxGroup, profiler);
profiler.pop(); // resource path
profiler.pop(); // resource namespace
@@ -537,46 +529,54 @@ public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
//region
private void renderBoxGroupInstanced(
RenderPass renderPass, RenderParams renderEventParam,
RenderParams renderEventParam,
RenderableBoxGroup boxGroup,
IProfilerWrapper profiler)
{
// update instance data //
profiler.push("vertex setup");
BlazeGenericObjectVertexContainer container = (BlazeGenericObjectVertexContainer) boxGroup.vertexBufferContainer;
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
BlazeTextureViewWrapper lightmapTextureViewWrapper = lightMapWrapper.getTextureViewWrapper();
renderPass.bindTexture("uLightMap", lightmapTextureViewWrapper.textureView, lightmapTextureViewWrapper.textureSampler);
// Bind instance data //
profiler.popPush("binding");
renderPass.setUniform("vertUniformBlock", this.vertUniformBuffer);
// set pipeline
renderPass.setPipeline(this.pipeline);
renderPass.setIndexBuffer(container.indexGpuBuffer, VertexFormat.IndexType.INT);
renderPass.setVertexBuffer(0, container.vboGpuBuffer);
// Draw instanced
profiler.popPush("render");
if (container.uploadedBoxCount > 0)
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
this::getRenderPassName,
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
/*optionalClearColorAsInt*/ OptionalInt.empty(),
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
{
renderPass.drawIndexed(
/*indexStart*/ 0,
/*firstIndex*/0,
/*indexCount*/container.uploadedBoxCount * 36, // 36 = 6 faces * 6 verticies per face
/*instanceCount*/1);
// update instance data //
profiler.push("vertex setup");
BlazeGenericObjectVertexContainer container = (BlazeGenericObjectVertexContainer) boxGroup.vertexBufferContainer;
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
BlazeTextureViewWrapper lightmapTextureViewWrapper = lightMapWrapper.getTextureViewWrapper();
renderPass.bindTexture("uLightMap", lightmapTextureViewWrapper.textureView, lightmapTextureViewWrapper.textureSampler);
// Bind instance data //
profiler.popPush("binding");
renderPass.setUniform("vertUniformBlock", this.vertUniformBuffer);
// set pipeline
renderPass.setPipeline(this.pipeline);
renderPass.setIndexBuffer(container.indexGpuBuffer, VertexFormat.IndexType.INT);
renderPass.setVertexBuffer(0, container.vboGpuBuffer);
// Draw instanced
profiler.popPush("render");
if (container.uploadedBoxCount > 0)
{
renderPass.drawIndexed(
/*indexStart*/ 0,
/*firstIndex*/0,
/*indexCount*/container.uploadedBoxCount * 36, // 36 = 6 faces * 6 verticies per face
/*instanceCount*/1);
}
}
profiler.pop();
}
@@ -68,8 +68,6 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
private RenderPipeline transparentPipeline;
private boolean init = false;
private GpuBuffer indexBuffer;
private GpuBuffer fragUniformBuffer;
private GpuBuffer vertSharedUniformBuffer;
@@ -261,30 +259,6 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
}
// create index buffer
{
if (this.indexBuffer == null)
{
ByteBuffer buffer = MemoryUtil.memAlloc(LodQuadBuilder.getMaxBufferByteSize() * GLEnums.getTypeSize(GL32.GL_UNSIGNED_INT) * 6);
GlQuadIndexBuffer.buildBuffer(LodQuadBuilder.getMaxBufferByteSize(), buffer, GL32.GL_UNSIGNED_INT);
// create buffer if needed
if (this.indexBuffer == null
|| this.indexBuffer.size() < buffer.capacity())
{
int usage = GpuBuffer.USAGE_COPY_DST
| GpuBuffer.USAGE_VERTEX
| GpuBuffer.USAGE_INDEX
| GpuBuffer.USAGE_UNIFORM;
this.indexBuffer = GPU_DEVICE.createBuffer(this::getIndexBufferName, usage, buffer.capacity());
}
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.indexBuffer, /*offset*/ 0, buffer.capacity());
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
}
}
// render pass setup
@@ -292,25 +266,20 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
profiler.popPush("setup");
// create a render pass
OptionalInt optionalClearColorAsInt = OptionalInt.empty();
OptionalDouble optionalDepthValueAsDouble = OptionalDouble.empty();
try(RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
this::getRenderPassName,
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
optionalClearColorAsInt,
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView, optionalDepthValueAsDouble)
/*optionalClearColorAsInt*/ OptionalInt.empty(),
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
/*optionalDepthValueAsDouble*/ OptionalDouble.empty())
)
{
// bind MC Lightmap
//renderPass.bindTexture("uLightMap", this.mcLightTextureViewWrapper.textureView, this.mcLightTextureViewWrapper.textureSampler);
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
BlazeTextureViewWrapper lightmapTextureViewWrapper = lightMapWrapper.getTextureViewWrapper();
renderPass.bindTexture("uLightMap", lightmapTextureViewWrapper.textureView, lightmapTextureViewWrapper.textureSampler);
// set pipeline
renderPass.setPipeline(opaquePass ? this.opaquePipeline : this.transparentPipeline);
renderPass.setIndexBuffer(this.indexBuffer, VertexFormat.IndexType.INT);
// shared uniforms
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
@@ -367,6 +336,7 @@ public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos));
}
renderPass.setIndexBuffer(bufferWrapper.indexBuffer, VertexFormat.IndexType.INT);
renderPass.setVertexBuffer(0, bufferWrapper.vboGpuBuffer); // vertex buffer can only be "0" lol
if (!bufferWrapper.vboGpuBuffer.isClosed())
@@ -215,8 +215,15 @@ public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertex
{
int totalVertexByteSize = this.vertexBufferSize();
if (this.vboGpuBuffer == null
|| this.vboGpuBuffer.size() < totalVertexByteSize)
// recreating if the size changes is always necessary (even if we only need a smaller amount)
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|| this.vboGpuBuffer.size() != totalVertexByteSize)
{
if (this.vboGpuBuffer != null)
{
this.vboGpuBuffer.close();
}
int usage = GpuBuffer.USAGE_COPY_DST
| GpuBuffer.USAGE_VERTEX;
this.vboGpuBuffer = GPU_DEVICE.createBuffer(this::getVertexBufferName, usage, totalVertexByteSize);
@@ -230,12 +237,17 @@ public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertex
{
int totalVertexByteSize = this.indexBufferSize();
if (this.indexGpuBuffer == null
|| this.indexGpuBuffer.size() < totalVertexByteSize)
// recreating if the size changes is always necessary (even if we only need a smaller amount)
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|| this.indexGpuBuffer.size() != totalVertexByteSize)
{
if (this.indexGpuBuffer != null)
{
this.indexGpuBuffer.close();
}
int usage = GpuBuffer.USAGE_COPY_DST
| GpuBuffer.USAGE_VERTEX
| GpuBuffer.USAGE_INDEX
| GpuBuffer.USAGE_UNIFORM;
| GpuBuffer.USAGE_INDEX;
this.indexGpuBuffer = GPU_DEVICE.createBuffer(this::getIndexBufferName, usage, totalVertexByteSize);
}
@@ -10,9 +10,15 @@ import com.mojang.blaze3d.buffers.GpuBufferSlice;
import com.mojang.blaze3d.systems.CommandEncoder;
import com.mojang.blaze3d.systems.GpuDevice;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GlQuadIndexBuffer;
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.GLEnums;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
import org.lwjgl.opengl.GL32;
import org.lwjgl.system.MemoryUtil;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class BlazeVertexBufferWrapper implements IVertexBufferWrapper
{
@@ -24,6 +30,8 @@ public class BlazeVertexBufferWrapper implements IVertexBufferWrapper
public String getName() { return this.name; }
public GpuBuffer vboGpuBuffer = null;
public GpuBuffer indexBuffer = null;
public int vertexCount = -1;
public int indexCount = -1;
public boolean uploaded = false;
@@ -47,22 +55,60 @@ public class BlazeVertexBufferWrapper implements IVertexBufferWrapper
//region
@Override
public void upload(ByteBuffer buffer, int vertexCount)
public void upload(ByteBuffer vertexBuffer, int vertexCount)
{
int oldVertexCount = this.vertexCount;
this.vertexCount = vertexCount;
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
this.indexCount = (int)(vertexCount * 1.5);
this.uploaded = true;
int usage = GpuBuffer.USAGE_COPY_DST
| GpuBuffer.USAGE_VERTEX;
int byteSize = (buffer.limit() - buffer.position());
this.vboGpuBuffer = GPU_DEVICE.createBuffer(this::getName, usage, byteSize);
if (this.vboGpuBuffer == null
// recreating if the size changes is always necessary (even if we only need a smaller amount)
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|| oldVertexCount != vertexCount)
{
if (this.vboGpuBuffer != null)
{
this.vboGpuBuffer.close();
}
int usage = GpuBuffer.USAGE_COPY_DST
| GpuBuffer.USAGE_VERTEX;
int byteSize = (vertexBuffer.limit() - vertexBuffer.position());
this.vboGpuBuffer = GPU_DEVICE.createBuffer(this::getName, usage, byteSize);
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vboGpuBuffer, /*offset*/0, byteSize);
COMMAND_ENCODER.writeToBuffer(bufferSlice, vertexBuffer);
}
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vboGpuBuffer, /*offset*/0, byteSize);
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
if (this.indexBuffer == null
// recreating if the size changes is always necessary (even if we only need a smaller amount)
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|| oldVertexCount != vertexCount)
{
if (this.indexBuffer != null)
{
this.indexBuffer.close();
}
int quadCount = (this.vertexCount / 4);
ByteBuffer indexBuffer = MemoryUtil.memAlloc(quadCount * 6 * GLEnums.getTypeSize(GL32.GL_UNSIGNED_INT));
indexBuffer.order(ByteOrder.nativeOrder());
GlQuadIndexBuffer.buildBuffer(quadCount, indexBuffer, GL32.GL_UNSIGNED_INT);
int usage = GpuBuffer.USAGE_COPY_DST
| GpuBuffer.USAGE_INDEX;
this.indexBuffer = GPU_DEVICE.createBuffer(this::getIndexBufferName, usage, indexBuffer.capacity());
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.indexBuffer, /*offset*/ 0, indexBuffer.capacity());
COMMAND_ENCODER.writeToBuffer(bufferSlice, indexBuffer);
}
}
private String getIndexBufferName() { return "distantHorizons:LodIndexBuffer"; }
//endregion
@@ -106,7 +106,6 @@ public class GlDhMetaRenderer implements IDhMetaRenderer
this.setGLState(renderParams, firstPass);
GlDhTerrainShaderProgram.INSTANCE.quadIBO.bind();
this.bindLightmap(renderParams.lightmap);
}
private void setGLState(
@@ -242,9 +241,6 @@ public class GlDhMetaRenderer implements IDhMetaRenderer
LOGGER.info("Setting up renderer");
GlDhTerrainShaderProgram.INSTANCE.quadIBO = new GlQuadIndexBuffer();
GlDhTerrainShaderProgram.INSTANCE.quadIBO.reserve(LodQuadBuilder.getMaxBufferByteSize());
// create or get the frame buffer
if (AbstractOptifineAccessor.optifinePresent())
@@ -362,7 +358,6 @@ public class GlDhMetaRenderer implements IDhMetaRenderer
this.unbindLightmap();
GlDhTerrainShaderProgram.INSTANCE.quadIBO.unbind();
this.shaderProgramForThisFrame.unbind();
}
@@ -52,7 +52,6 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
private boolean init = false;
public GlQuadIndexBuffer quadIBO = null;
public GlAbstractVertexAttribute vao;
// uniforms //
@@ -351,12 +350,16 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
int indexCount = (int)(vbo.getVertexCount() * 1.5);
vbo.bind();
vbo.quadIBO.bind();
GlDhMetaRenderer.INSTANCE.shaderProgramForThisFrame.bindVertexBuffer(vbo.getId());
GL32.glDrawElements(
GL32.GL_TRIANGLES,
indexCount,
this.quadIBO.getType(), 0);
vbo.quadIBO.getType(), 0);
vbo.unbind();
vbo.quadIBO.unbind();
}
}
}
@@ -20,13 +20,17 @@
package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import com.seibel.distanthorizons.common.render.openGl.GlDhTerrainShaderProgram;
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.GLEnums;
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
import org.lwjgl.opengl.GL32;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import org.lwjgl.system.MemoryUtil;
/**
* This is a container for a OpenGL
@@ -44,6 +48,8 @@ public class GLVertexBuffer extends GLBuffer implements IVertexBufferWrapper
protected int vertexCount = 0;
public int getVertexCount() { return this.vertexCount; }
public GlQuadIndexBuffer quadIBO = null;
//=============//
@@ -89,12 +95,36 @@ public class GLVertexBuffer extends GLBuffer implements IVertexBufferWrapper
// If size is zero, just ignore it.
if (byteBuffer.limit() - byteBuffer.position() != 0)
{
boolean useBuffStorage = uploadMethod.useBufferStorage;
super.uploadBuffer(byteBuffer, uploadMethod, maxExpansionSize, useBuffStorage ? 0 : GL32.GL_STATIC_DRAW);
// vertex data
{
super.uploadBuffer(byteBuffer, uploadMethod, maxExpansionSize, uploadMethod.useBufferStorage ? 0 : GL32.GL_STATIC_DRAW);
}
// index data
{
if (this.quadIBO != null)
{
this.quadIBO.close();
}
int quadCount = (vertexCount / 4);
this.quadIBO = new GlQuadIndexBuffer();
this.quadIBO.reserve(quadCount);
}
}
this.vertexCount = vertexCount;
}
//endregion
//================//
// base overrides //
//================//
//region
@Override
public void close() { this.destroyAsync(); }
@@ -102,6 +132,7 @@ public class GLVertexBuffer extends GLBuffer implements IVertexBufferWrapper
public void destroyAsync()
{
super.destroyAsync();
this.quadIBO.destroyAsync();
this.vertexCount = 0;
}