minecraft-src/net/minecraft/client/renderer/chunk/CompiledSectionMesh.java
2025-09-18 12:27:44 +00:00

220 lines
6.8 KiB
Java

package net.minecraft.client.renderer.chunk;
import com.mojang.blaze3d.buffers.GpuBuffer;
import com.mojang.blaze3d.systems.CommandEncoder;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.ByteBufferBuilder;
import com.mojang.blaze3d.vertex.MeshData;
import java.nio.ByteBuffer;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.core.Direction;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class CompiledSectionMesh implements SectionMesh {
public static final SectionMesh UNCOMPILED = new SectionMesh() {
@Override
public boolean facesCanSeeEachother(Direction face1, Direction face2) {
return false;
}
};
public static final SectionMesh EMPTY = new SectionMesh() {
@Override
public boolean facesCanSeeEachother(Direction face1, Direction face2) {
return true;
}
};
private final List<BlockEntity> renderableBlockEntities;
private final VisibilitySet visibilitySet;
@Nullable
private final MeshData.SortState transparencyState;
@Nullable
private TranslucencyPointOfView translucencyPointOfView;
private final Map<ChunkSectionLayer, SectionBuffers> buffers = new EnumMap(ChunkSectionLayer.class);
public CompiledSectionMesh(TranslucencyPointOfView translucencyPointOfView, SectionCompiler.Results results) {
this.translucencyPointOfView = translucencyPointOfView;
this.visibilitySet = results.visibilitySet;
this.renderableBlockEntities = results.blockEntities;
this.transparencyState = results.transparencyState;
}
public void setTranslucencyPointOfView(TranslucencyPointOfView translucencyPointOfView) {
this.translucencyPointOfView = translucencyPointOfView;
}
@Override
public boolean isDifferentPointOfView(TranslucencyPointOfView pointOfView) {
return !pointOfView.equals(this.translucencyPointOfView);
}
@Override
public boolean hasRenderableLayers() {
return !this.buffers.isEmpty();
}
@Override
public boolean isEmpty(ChunkSectionLayer layer) {
return !this.buffers.containsKey(layer);
}
@Override
public List<BlockEntity> getRenderableBlockEntities() {
return this.renderableBlockEntities;
}
@Override
public boolean facesCanSeeEachother(Direction face1, Direction face2) {
return this.visibilitySet.visibilityBetween(face1, face2);
}
@Nullable
@Override
public SectionBuffers getBuffers(ChunkSectionLayer layer) {
return (SectionBuffers)this.buffers.get(layer);
}
public void uploadMeshLayer(ChunkSectionLayer layer, MeshData meshData, long sectionNode) {
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
SectionBuffers sectionBuffers = this.getBuffers(layer);
if (sectionBuffers != null) {
if (sectionBuffers.getVertexBuffer().size() < meshData.vertexBuffer().remaining()) {
sectionBuffers.getVertexBuffer().close();
sectionBuffers.setVertexBuffer(
RenderSystem.getDevice()
.createBuffer(
() -> "Section vertex buffer - layer: "
+ layer.label()
+ "; cords: "
+ SectionPos.x(sectionNode)
+ ", "
+ SectionPos.y(sectionNode)
+ ", "
+ SectionPos.z(sectionNode),
40,
meshData.vertexBuffer()
)
);
} else if (!sectionBuffers.getVertexBuffer().isClosed()) {
commandEncoder.writeToBuffer(sectionBuffers.getVertexBuffer().slice(), meshData.vertexBuffer());
}
ByteBuffer byteBuffer = meshData.indexBuffer();
if (byteBuffer != null) {
if (sectionBuffers.getIndexBuffer() != null && sectionBuffers.getIndexBuffer().size() >= byteBuffer.remaining()) {
if (!sectionBuffers.getIndexBuffer().isClosed()) {
commandEncoder.writeToBuffer(sectionBuffers.getIndexBuffer().slice(), byteBuffer);
}
} else {
if (sectionBuffers.getIndexBuffer() != null) {
sectionBuffers.getIndexBuffer().close();
}
sectionBuffers.setIndexBuffer(
RenderSystem.getDevice()
.createBuffer(
() -> "Section index buffer - layer: "
+ layer.label()
+ "; cords: "
+ SectionPos.x(sectionNode)
+ ", "
+ SectionPos.y(sectionNode)
+ ", "
+ SectionPos.z(sectionNode),
72,
byteBuffer
)
);
}
} else if (sectionBuffers.getIndexBuffer() != null) {
sectionBuffers.getIndexBuffer().close();
sectionBuffers.setIndexBuffer(null);
}
sectionBuffers.setIndexCount(meshData.drawState().indexCount());
sectionBuffers.setIndexType(meshData.drawState().indexType());
} else {
GpuBuffer gpuBuffer = RenderSystem.getDevice()
.createBuffer(
() -> "Section vertex buffer - layer: "
+ layer.label()
+ "; cords: "
+ SectionPos.x(sectionNode)
+ ", "
+ SectionPos.y(sectionNode)
+ ", "
+ SectionPos.z(sectionNode),
40,
meshData.vertexBuffer()
);
ByteBuffer byteBuffer2 = meshData.indexBuffer();
GpuBuffer gpuBuffer2 = byteBuffer2 != null
? RenderSystem.getDevice()
.createBuffer(
() -> "Section index buffer - layer: "
+ layer.label()
+ "; cords: "
+ SectionPos.x(sectionNode)
+ ", "
+ SectionPos.y(sectionNode)
+ ", "
+ SectionPos.z(sectionNode),
72,
byteBuffer2
)
: null;
SectionBuffers sectionBuffers2 = new SectionBuffers(gpuBuffer, gpuBuffer2, meshData.drawState().indexCount(), meshData.drawState().indexType());
this.buffers.put(layer, sectionBuffers2);
}
}
public void uploadLayerIndexBuffer(ChunkSectionLayer layer, ByteBufferBuilder.Result result, long sectionNode) {
SectionBuffers sectionBuffers = this.getBuffers(layer);
if (sectionBuffers != null) {
if (sectionBuffers.getIndexBuffer() == null) {
sectionBuffers.setIndexBuffer(
RenderSystem.getDevice()
.createBuffer(
() -> "Section index buffer - layer: "
+ layer.label()
+ "; cords: "
+ SectionPos.x(sectionNode)
+ ", "
+ SectionPos.y(sectionNode)
+ ", "
+ SectionPos.z(sectionNode),
72,
result.byteBuffer()
)
);
} else {
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
if (!sectionBuffers.getIndexBuffer().isClosed()) {
commandEncoder.writeToBuffer(sectionBuffers.getIndexBuffer().slice(), result.byteBuffer());
}
}
}
}
@Override
public boolean hasTranslucentGeometry() {
return this.buffers.containsKey(ChunkSectionLayer.TRANSLUCENT);
}
@Nullable
public MeshData.SortState getTransparencyState() {
return this.transparencyState;
}
@Override
public void close() {
this.buffers.values().forEach(SectionBuffers::close);
this.buffers.clear();
}
}