fix vertex attribute data types

blockcolors and ao now work in contraptions
be smarter about allocating buffers
use gl buffer mapping, more to come
This commit is contained in:
JozsefA 2021-01-15 16:17:13 -08:00
parent 5ea0fa788f
commit 37e64e4c1d
14 changed files with 177 additions and 137 deletions

View file

@ -126,7 +126,7 @@ dependencies {
//runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")
//runtimeOnly fg.deobf("vazkii.quark:Quark:r2.0-212.984")
annotationProcessor 'org.spongepowered:mixin:0.8:processor'
//annotationProcessor 'org.spongepowered:mixin:0.8:processor'
}
jar {

View file

@ -6,7 +6,9 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -16,6 +18,8 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(World.class)
public class OnRemoveTileMixin {
@Shadow @Final public boolean isRemote;
/**
* JUSTIFICATION: This method is called whenever a tile entity is removed due
* to a change in block state, even on the client. By hooking into this method,
@ -23,6 +27,6 @@ public class OnRemoveTileMixin {
*/
@Inject(at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/World;getTileEntity(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/tileentity/TileEntity;"), method = "removeTileEntity", locals = LocalCapture.CAPTURE_FAILHARD)
private void onRemoveTile(BlockPos pos, CallbackInfo ci, TileEntity te) {
FastRenderDispatcher.markForRebuild(te);
if (isRemote) FastRenderDispatcher.markForRebuild(te);
}
}

View file

@ -6,6 +6,8 @@ import com.simibubi.create.foundation.render.instancing.VertexFormat;
import net.minecraft.client.renderer.BufferBuilder;
import org.lwjgl.opengl.*;
import java.nio.ByteBuffer;
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
public class ContraptionBuffer extends TemplateBuffer {
@ -15,19 +17,21 @@ public class ContraptionBuffer extends TemplateBuffer {
public ContraptionBuffer(BufferBuilder buf) {
super(buf);
setup();
if (vertexCount > 0) setup();
}
public void delete() {
RenderWork.enqueue(() -> {
GL15.glDeleteBuffers(vbo);
GL15.glDeleteBuffers(ebo);
GL30.glDeleteVertexArrays(vao);
});
if (vertexCount > 0) {
RenderWork.enqueue(() -> {
GL15.glDeleteBuffers(vbo);
GL15.glDeleteBuffers(ebo);
GL30.glDeleteVertexArrays(vao);
});
}
}
public void render() {
if (vertexCount == 0) return;
GL30.glBindVertexArray(vao);
for (int i = 0; i <= 3; i++) {
@ -54,39 +58,38 @@ public class ContraptionBuffer extends TemplateBuffer {
ebo = GlStateManager.genBuffers();
vbo = GlStateManager.genBuffers();
try (SafeDirectBuffer constant = new SafeDirectBuffer(invariantSize)) {
constant.order(template.order());
constant.limit(invariantSize);
GL30.glBindVertexArray(vao);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
for (int i = 0; i < vertexCount; i++) {
constant.putFloat(getX(template, i));
constant.putFloat(getY(template, i));
constant.putFloat(getZ(template, i));
// allocate the buffer on the gpu
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
constant.put(getNX(template, i));
constant.put(getNY(template, i));
constant.put(getNZ(template, i));
// mirror it in system memory so we can write to it
ByteBuffer constant = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
constant.putFloat(getU(template, i));
constant.putFloat(getV(template, i));
for (int i = 0; i < vertexCount; i++) {
constant.putFloat(getX(template, i));
constant.putFloat(getY(template, i));
constant.putFloat(getZ(template, i));
constant.put(getR(template, i));
constant.put(getG(template, i));
constant.put(getB(template, i));
constant.put(getA(template, i));
}
constant.rewind();
constant.put(getNX(template, i));
constant.put(getNY(template, i));
constant.put(getNZ(template, i));
GL30.glBindVertexArray(vao);
constant.putFloat(getU(template, i));
constant.putFloat(getV(template, i));
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, vbo);
GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, constant.getBacking(), GL15.GL_STATIC_DRAW);
buildEBO(ebo);
FORMAT.informAttributes(0);
} catch (Exception e) {
e.printStackTrace();
constant.put(getR(template, i));
constant.put(getG(template, i));
constant.put(getB(template, i));
constant.put(getA(template, i));
}
constant.rewind();
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
buildEBO(ebo);
FORMAT.informAttributes(0);
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0);
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

View file

@ -8,6 +8,10 @@ import net.minecraft.world.LightType;
import net.minecraft.world.World;
import org.lwjgl.opengl.*;
import java.nio.ByteBuffer;
import static com.simibubi.create.foundation.render.RenderMath.nextPowerOf2;
public class ContraptionLighter {
private int minX;
@ -45,11 +49,6 @@ public class ContraptionLighter {
update(contraption);
}
public static int nextPowerOf2(int a) {
int h = Integer.highestOneBit(a);
return (h == a) ? h : (h << 1);
}
public int getSizeX() {
return sizeX;
}

View file

@ -0,0 +1,8 @@
package com.simibubi.create.foundation.render;
public class RenderMath {
public static int nextPowerOf2(int a) {
int h = Integer.highestOneBit(a);
return (h == a) ? h : (h << 1);
}
}

View file

@ -32,20 +32,20 @@ public class TemplateBuffer {
((Buffer)template).rewind();
}
protected void buildEBO(int ebo) throws Exception {
protected void buildEBO(int ebo){
int indicesSize = vertexCount * VertexFormatElement.Type.USHORT.getSize();
try (SafeDirectBuffer indices = new SafeDirectBuffer(indicesSize)) {
indices.order(template.order());
indices.limit(indicesSize);
for (int i = 0; i < vertexCount; i++) {
indices.putShort((short) i);
}
indices.rewind();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesSize, GL15.GL_STATIC_DRAW);
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
GlStateManager.bufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices.getBacking(), GL15.GL_STATIC_DRAW);
ByteBuffer indices = GL15.glMapBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
for (int i = 0; i < vertexCount; i++) {
indices.putShort((short) i);
}
indices.rewind();
GL15.glUnmapBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER);
}
public boolean isEmpty() {

View file

@ -2,10 +2,11 @@ package com.simibubi.create.foundation.render.instancing;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.render.SafeDirectBuffer;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.util.math.BlockPos;
import java.nio.ByteBuffer;
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
public class BasicData<D extends BasicData<D>> extends InstanceData {
@ -17,16 +18,16 @@ public class BasicData<D extends BasicData<D>> extends InstanceData {
private float x;
private float y;
private float z;
private float blockLight;
private float skyLight;
private byte blockLight;
private byte skyLight;
public D setBlockLight(int blockLight) {
this.blockLight = blockLight / 15f;
this.blockLight = (byte) ((blockLight & 0xF) << 4);
return (D) this;
}
public D setSkyLight(int skyLight) {
this.skyLight = skyLight / 15f;
this.skyLight = (byte) ((skyLight & 0xF) << 4);
return (D) this;
}
@ -61,10 +62,8 @@ public class BasicData<D extends BasicData<D>> extends InstanceData {
}
@Override
public void write(SafeDirectBuffer buf) {
buf.put(r);
buf.put(g);
buf.put(b);
public void write(ByteBuffer buf) {
putVec3(buf, r, g, b);
putVec3(buf, x, y, z);

View file

@ -1,9 +1,10 @@
package com.simibubi.create.foundation.render.instancing;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.render.SafeDirectBuffer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import java.nio.ByteBuffer;
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
public class BeltData extends BasicData<BeltData> {
@ -53,16 +54,16 @@ public class BeltData extends BasicData<BeltData> {
}
@Override
public void write(SafeDirectBuffer buf) {
public void write(ByteBuffer buf) {
super.write(buf);
putVec3(buf, rotX, rotY, rotZ);
putFloat(buf, rotationalSpeed);
put(buf, rotationalSpeed);
putVec2(buf, sourceU, sourceV);
putVec4(buf, minU, minV, maxU, maxV);
putFloat(buf, scrollMult);
put(buf, scrollMult);
}
}

View file

@ -2,12 +2,14 @@ package com.simibubi.create.foundation.render.instancing;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.render.RenderMath;
import com.simibubi.create.foundation.render.RenderWork;
import com.simibubi.create.foundation.render.SafeDirectBuffer;
import com.simibubi.create.foundation.render.TemplateBuffer;
import net.minecraft.client.renderer.BufferBuilder;
import org.lwjgl.opengl.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.function.Consumer;
@ -18,13 +20,15 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
protected int vao, ebo, invariantVBO, instanceVBO, instanceCount;
protected int bufferSize = -1;
protected final ArrayList<D> data = new ArrayList<>();
protected boolean rebuffer = false;
protected boolean shouldBuild = true;
public InstanceBuffer(BufferBuilder buf) {
super(buf);
setup();
if (vertexCount > 0) setup();
}
private void setup() {
@ -37,35 +41,33 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
invariantVBO = GlStateManager.genBuffers();
instanceVBO = GlStateManager.genBuffers();
try (SafeDirectBuffer constant = new SafeDirectBuffer(invariantSize)) {
constant.order(template.order());
constant.limit(invariantSize);
GL30.glBindVertexArray(vao);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, invariantVBO);
for (int i = 0; i < vertexCount; i++) {
constant.putFloat(getX(template, i));
constant.putFloat(getY(template, i));
constant.putFloat(getZ(template, i));
// allocate the buffer on the gpu
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
constant.put(getNX(template, i));
constant.put(getNY(template, i));
constant.put(getNZ(template, i));
// mirror it in system memory so we can write to it
ByteBuffer constant = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
constant.putFloat(getU(template, i));
constant.putFloat(getV(template, i));
}
constant.rewind();
for (int i = 0; i < vertexCount; i++) {
constant.putFloat(getX(template, i));
constant.putFloat(getY(template, i));
constant.putFloat(getZ(template, i));
GL30.glBindVertexArray(vao);
constant.put(getNX(template, i));
constant.put(getNY(template, i));
constant.put(getNZ(template, i));
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, invariantVBO);
GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, constant.getBacking(), GL15.GL_STATIC_DRAW);
buildEBO(ebo);
FORMAT.informAttributes(0);
} catch (Exception e) {
delete();
constant.putFloat(getU(template, i));
constant.putFloat(getV(template, i));
}
constant.rewind();
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
buildEBO(ebo);
FORMAT.informAttributes(0);
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0);
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
@ -93,16 +95,19 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
}
public void delete() {
RenderWork.enqueue(() -> {
GL15.glDeleteBuffers(invariantVBO);
GL15.glDeleteBuffers(instanceVBO);
GL15.glDeleteBuffers(ebo);
GL30.glDeleteVertexArrays(vao);
vao = 0;
ebo = 0;
invariantVBO = 0;
instanceVBO = 0;
});
if (vertexCount > 0) {
RenderWork.enqueue(() -> {
GL15.glDeleteBuffers(invariantVBO);
GL15.glDeleteBuffers(instanceVBO);
GL15.glDeleteBuffers(ebo);
GL30.glDeleteVertexArrays(vao);
vao = 0;
ebo = 0;
invariantVBO = 0;
instanceVBO = 0;
bufferSize = -1;
});
}
}
protected abstract D newInstance();
@ -146,26 +151,27 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
VertexFormat instanceFormat = getInstanceFormat();
int instanceSize = instanceCount * instanceFormat.getStride();
int instanceSize = RenderMath.nextPowerOf2(instanceCount * instanceFormat.getStride());
try (SafeDirectBuffer buffer = new SafeDirectBuffer(instanceSize)) {
buffer.order(template.order());
buffer.limit(instanceSize);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, instanceVBO);
data.forEach(instanceData -> instanceData.write(buffer));
buffer.rewind();
// this changes enough that it's not worth reallocating the entire buffer every time.
if (instanceSize > bufferSize) {
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, instanceSize, GL15.GL_STATIC_DRAW);
bufferSize = instanceSize;
}
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, instanceVBO);
GlStateManager.bufferData(GL15.GL_ARRAY_BUFFER, buffer.getBacking(), GL15.GL_STATIC_DRAW);
ByteBuffer buffer = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
int staticAttributes = FORMAT.getNumAttributes();
instanceFormat.informAttributes(staticAttributes);
data.forEach(instanceData -> instanceData.write(buffer));
buffer.rewind();
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
for (int i = 0; i < instanceFormat.getNumAttributes(); i++) {
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
}
} catch (Exception e) {
e.printStackTrace();
int staticAttributes = FORMAT.getNumAttributes();
instanceFormat.informAttributes(staticAttributes);
for (int i = 0; i < instanceFormat.getNumAttributes(); i++) {
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
}
// Deselect (bind to 0) the VBO

View file

@ -1,30 +1,45 @@
package com.simibubi.create.foundation.render.instancing;
import com.simibubi.create.foundation.render.SafeDirectBuffer;
import java.nio.ByteBuffer;
public abstract class InstanceData {
public abstract void write(SafeDirectBuffer buf);
public abstract void write(ByteBuffer buf);
public void putVec4(SafeDirectBuffer buf, float x, float y, float z, float w) {
putFloat(buf, x);
putFloat(buf, y);
putFloat(buf, z);
putFloat(buf, w);
public void putVec4(ByteBuffer buf, float x, float y, float z, float w) {
put(buf, x);
put(buf, y);
put(buf, z);
put(buf, w);
}
public void putVec3(SafeDirectBuffer buf, float x, float y, float z) {
putFloat(buf, x);
putFloat(buf, y);
putFloat(buf, z);
public void putVec3(ByteBuffer buf, float x, float y, float z) {
put(buf, x);
put(buf, y);
put(buf, z);
}
public void putVec2(SafeDirectBuffer buf, float x, float y) {
putFloat(buf, x);
putFloat(buf, y);
public void putVec2(ByteBuffer buf, float x, float y) {
put(buf, x);
put(buf, y);
}
public void putFloat(SafeDirectBuffer buf, float f) {
public void putVec3(ByteBuffer buf, byte x, byte y, byte z) {
put(buf, x);
put(buf, y);
put(buf, z);
}
public void putVec2(ByteBuffer buf, byte x, byte y) {
put(buf, x);
put(buf, y);
}
public void put(ByteBuffer buf, byte b) {
buf.put(b);
}
public void put(ByteBuffer buf, float f) {
buf.putFloat(f);
}
}

View file

@ -1,8 +1,9 @@
package com.simibubi.create.foundation.render.instancing;
import com.simibubi.create.foundation.render.SafeDirectBuffer;
import net.minecraft.client.renderer.Vector3f;
import java.nio.ByteBuffer;
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
public class RotatingData extends BasicData<RotatingData> {
@ -39,10 +40,10 @@ public class RotatingData extends BasicData<RotatingData> {
}
@Override
public void write(SafeDirectBuffer buf) {
public void write(ByteBuffer buf) {
super.write(buf);
putFloat(buf, rotationalSpeed);
putFloat(buf, rotationOffset);
put(buf, rotationalSpeed);
put(buf, rotationOffset);
putVec3(buf, rotationAxisX, rotationAxisY, rotationAxisZ);
}

View file

@ -12,10 +12,10 @@ public class VertexAttribute {
public static final VertexAttribute POSITION = VEC3;
public static final VertexAttribute NORMAL = new VertexAttribute(VertexFormatElement.Type.BYTE, 3, true);
public static final VertexAttribute RGBA = new VertexAttribute(VertexFormatElement.Type.BYTE, 4, true);
public static final VertexAttribute RGB = new VertexAttribute(VertexFormatElement.Type.BYTE, 3, true);
public static final VertexAttribute RGBA = new VertexAttribute(VertexFormatElement.Type.UBYTE, 4, true);
public static final VertexAttribute RGB = new VertexAttribute(VertexFormatElement.Type.UBYTE, 3, true);
public static final VertexAttribute UV = VEC2;
public static final VertexAttribute LIGHT = new VertexAttribute(VertexFormatElement.Type.FLOAT, 2);
public static final VertexAttribute LIGHT = new VertexAttribute(VertexFormatElement.Type.UBYTE, 2, true);
private final VertexFormatElement.Type type;
private final int count;

View file

@ -43,8 +43,8 @@ void main() {
vec4 worldPos = model * vec4(aPos, 1);
BoxCoord = (worldPos.xyz - lightBoxMin) / lightBoxSize;
Diffuse = diffuse(normalize(model * vec4(aNormal, 0.)).xyz);
Color = vec4(1);//aColor;
Diffuse = diffuse((model * vec4(aNormal, 0.)).xyz);
Color = aColor / diffuse(aNormal);
TexCoords = aTexCoords;
gl_Position = projection * view * worldPos;
}

View file

@ -49,13 +49,17 @@ void main() {
renderPos += vec4(instancePos + vec3(0.5), 0);
Diffuse = diffuse(normalize((rotation * vec4(aNormal, 0.)).xyz));
vec3 norm = (rotation * vec4(aNormal, 0.)).xyz;
Diffuse = diffuse(norm);
TexCoords = aTexCoords;
gl_Position = projection * view * renderPos;
Light = light;
if (debug == 1) {
Color = vec4(networkTint, 1);
} else if (debug == 2) {
Color = vec4(norm, 1);
} else {
Color = vec4(1);
}