221 lines
5.6 KiB
Java
221 lines
5.6 KiB
Java
package com.mojang.blaze3d.vertex;
|
|
|
|
import com.mojang.blaze3d.platform.GlStateManager;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import java.nio.ByteBuffer;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.renderer.ShaderInstance;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.joml.Matrix4f;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class VertexBuffer implements AutoCloseable {
|
|
private final VertexBuffer.Usage usage;
|
|
private int vertexBufferId;
|
|
private int indexBufferId;
|
|
private int arrayObjectId;
|
|
@Nullable
|
|
private VertexFormat format;
|
|
@Nullable
|
|
private RenderSystem.AutoStorageIndexBuffer sequentialIndices;
|
|
private VertexFormat.IndexType indexType;
|
|
private int indexCount;
|
|
private VertexFormat.Mode mode;
|
|
|
|
public VertexBuffer(VertexBuffer.Usage usage) {
|
|
this.usage = usage;
|
|
RenderSystem.assertOnRenderThread();
|
|
this.vertexBufferId = GlStateManager._glGenBuffers();
|
|
this.indexBufferId = GlStateManager._glGenBuffers();
|
|
this.arrayObjectId = GlStateManager._glGenVertexArrays();
|
|
}
|
|
|
|
public void upload(MeshData meshData) {
|
|
MeshData var2 = meshData;
|
|
|
|
label40: {
|
|
try {
|
|
if (this.isInvalid()) {
|
|
break label40;
|
|
}
|
|
|
|
RenderSystem.assertOnRenderThread();
|
|
MeshData.DrawState drawState = meshData.drawState();
|
|
this.format = this.uploadVertexBuffer(drawState, meshData.vertexBuffer());
|
|
this.sequentialIndices = this.uploadIndexBuffer(drawState, meshData.indexBuffer());
|
|
this.indexCount = drawState.indexCount();
|
|
this.indexType = drawState.indexType();
|
|
this.mode = drawState.mode();
|
|
} catch (Throwable var6) {
|
|
if (meshData != null) {
|
|
try {
|
|
var2.close();
|
|
} catch (Throwable var5) {
|
|
var6.addSuppressed(var5);
|
|
}
|
|
}
|
|
|
|
throw var6;
|
|
}
|
|
|
|
if (meshData != null) {
|
|
meshData.close();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (meshData != null) {
|
|
meshData.close();
|
|
}
|
|
}
|
|
|
|
public void uploadIndexBuffer(ByteBufferBuilder.Result result) {
|
|
ByteBufferBuilder.Result var2 = result;
|
|
|
|
label40: {
|
|
try {
|
|
if (this.isInvalid()) {
|
|
break label40;
|
|
}
|
|
|
|
RenderSystem.assertOnRenderThread();
|
|
GlStateManager._glBindBuffer(34963, this.indexBufferId);
|
|
RenderSystem.glBufferData(34963, result.byteBuffer(), this.usage.id);
|
|
this.sequentialIndices = null;
|
|
} catch (Throwable var6) {
|
|
if (result != null) {
|
|
try {
|
|
var2.close();
|
|
} catch (Throwable var5) {
|
|
var6.addSuppressed(var5);
|
|
}
|
|
}
|
|
|
|
throw var6;
|
|
}
|
|
|
|
if (result != null) {
|
|
result.close();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (result != null) {
|
|
result.close();
|
|
}
|
|
}
|
|
|
|
private VertexFormat uploadVertexBuffer(MeshData.DrawState drawState, @Nullable ByteBuffer buffer) {
|
|
boolean bl = false;
|
|
if (!drawState.format().equals(this.format)) {
|
|
if (this.format != null) {
|
|
this.format.clearBufferState();
|
|
}
|
|
|
|
GlStateManager._glBindBuffer(34962, this.vertexBufferId);
|
|
drawState.format().setupBufferState();
|
|
bl = true;
|
|
}
|
|
|
|
if (buffer != null) {
|
|
if (!bl) {
|
|
GlStateManager._glBindBuffer(34962, this.vertexBufferId);
|
|
}
|
|
|
|
RenderSystem.glBufferData(34962, buffer, this.usage.id);
|
|
}
|
|
|
|
return drawState.format();
|
|
}
|
|
|
|
@Nullable
|
|
private RenderSystem.AutoStorageIndexBuffer uploadIndexBuffer(MeshData.DrawState drawState, @Nullable ByteBuffer buffer) {
|
|
if (buffer != null) {
|
|
GlStateManager._glBindBuffer(34963, this.indexBufferId);
|
|
RenderSystem.glBufferData(34963, buffer, this.usage.id);
|
|
return null;
|
|
} else {
|
|
RenderSystem.AutoStorageIndexBuffer autoStorageIndexBuffer = RenderSystem.getSequentialBuffer(drawState.mode());
|
|
if (autoStorageIndexBuffer != this.sequentialIndices || !autoStorageIndexBuffer.hasStorage(drawState.indexCount())) {
|
|
autoStorageIndexBuffer.bind(drawState.indexCount());
|
|
}
|
|
|
|
return autoStorageIndexBuffer;
|
|
}
|
|
}
|
|
|
|
public void bind() {
|
|
BufferUploader.invalidate();
|
|
GlStateManager._glBindVertexArray(this.arrayObjectId);
|
|
}
|
|
|
|
public static void unbind() {
|
|
BufferUploader.invalidate();
|
|
GlStateManager._glBindVertexArray(0);
|
|
}
|
|
|
|
public void draw() {
|
|
RenderSystem.drawElements(this.mode.asGLMode, this.indexCount, this.getIndexType().asGLType);
|
|
}
|
|
|
|
private VertexFormat.IndexType getIndexType() {
|
|
RenderSystem.AutoStorageIndexBuffer autoStorageIndexBuffer = this.sequentialIndices;
|
|
return autoStorageIndexBuffer != null ? autoStorageIndexBuffer.type() : this.indexType;
|
|
}
|
|
|
|
public void drawWithShader(Matrix4f modelViewMatrix, Matrix4f projectionMatrix, ShaderInstance shader) {
|
|
if (!RenderSystem.isOnRenderThread()) {
|
|
RenderSystem.recordRenderCall(() -> this._drawWithShader(new Matrix4f(modelViewMatrix), new Matrix4f(projectionMatrix), shader));
|
|
} else {
|
|
this._drawWithShader(modelViewMatrix, projectionMatrix, shader);
|
|
}
|
|
}
|
|
|
|
private void _drawWithShader(Matrix4f modelViewMatrix, Matrix4f projectionMatrix, ShaderInstance shader) {
|
|
shader.setDefaultUniforms(this.mode, modelViewMatrix, projectionMatrix, Minecraft.getInstance().getWindow());
|
|
shader.apply();
|
|
this.draw();
|
|
shader.clear();
|
|
}
|
|
|
|
public void close() {
|
|
if (this.vertexBufferId >= 0) {
|
|
RenderSystem.glDeleteBuffers(this.vertexBufferId);
|
|
this.vertexBufferId = -1;
|
|
}
|
|
|
|
if (this.indexBufferId >= 0) {
|
|
RenderSystem.glDeleteBuffers(this.indexBufferId);
|
|
this.indexBufferId = -1;
|
|
}
|
|
|
|
if (this.arrayObjectId >= 0) {
|
|
RenderSystem.glDeleteVertexArrays(this.arrayObjectId);
|
|
this.arrayObjectId = -1;
|
|
}
|
|
}
|
|
|
|
public VertexFormat getFormat() {
|
|
return this.format;
|
|
}
|
|
|
|
public boolean isInvalid() {
|
|
return this.arrayObjectId == -1;
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static enum Usage {
|
|
STATIC(35044),
|
|
DYNAMIC(35048);
|
|
|
|
final int id;
|
|
|
|
private Usage(final int id) {
|
|
this.id = id;
|
|
}
|
|
}
|
|
}
|