mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-01-05 20:06:30 +01:00
prepare for fast actor rendering
This commit is contained in:
parent
697a7df59c
commit
11f9c7459c
11 changed files with 421 additions and 167 deletions
|
@ -10,90 +10,39 @@ import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
||||||
|
|
||||||
public class ContraptionBuffer extends TemplateBuffer {
|
public class ContraptionBuffer extends GPUBuffer {
|
||||||
public static final VertexFormat FORMAT = new VertexFormat(InstanceBuffer.FORMAT, RGBA);
|
public static final VertexFormat FORMAT = new VertexFormat(InstanceBuffer.FORMAT, RGBA);
|
||||||
|
|
||||||
protected int vao, ebo, vbo;
|
|
||||||
|
|
||||||
public ContraptionBuffer(BufferBuilder buf) {
|
public ContraptionBuffer(BufferBuilder buf) {
|
||||||
super(buf);
|
super(buf);
|
||||||
if (vertexCount > 0) setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
@Override
|
||||||
if (vertexCount > 0) {
|
protected void copyVertex(ByteBuffer to, int vertex) {
|
||||||
RenderWork.enqueue(() -> {
|
to.putFloat(getX(template, vertex));
|
||||||
GL15.glDeleteBuffers(vbo);
|
to.putFloat(getY(template, vertex));
|
||||||
GL15.glDeleteBuffers(ebo);
|
to.putFloat(getZ(template, vertex));
|
||||||
GL30.glDeleteVertexArrays(vao);
|
|
||||||
});
|
to.put(getNX(template, vertex));
|
||||||
}
|
to.put(getNY(template, vertex));
|
||||||
|
to.put(getNZ(template, vertex));
|
||||||
|
|
||||||
|
to.putFloat(getU(template, vertex));
|
||||||
|
to.putFloat(getV(template, vertex));
|
||||||
|
|
||||||
|
to.put(getR(template, vertex));
|
||||||
|
to.put(getG(template, vertex));
|
||||||
|
to.put(getB(template, vertex));
|
||||||
|
to.put(getA(template, vertex));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render() {
|
@Override
|
||||||
if (vertexCount == 0) return;
|
protected VertexFormat getModelFormat() {
|
||||||
GL30.glBindVertexArray(vao);
|
return FORMAT;
|
||||||
|
}
|
||||||
for (int i = 0; i <= 3; i++) {
|
|
||||||
GL40.glEnableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawCall() {
|
||||||
GL40.glDrawElements(GL11.GL_QUADS, vertexCount, GL11.GL_UNSIGNED_SHORT, 0);
|
GL40.glDrawElements(GL11.GL_QUADS, vertexCount, GL11.GL_UNSIGNED_SHORT, 0);
|
||||||
|
|
||||||
for (int i = 0; i <= FORMAT.getNumAttributes(); i++) {
|
|
||||||
GL40.glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
GL30.glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setup() {
|
|
||||||
int stride = FORMAT.getStride();
|
|
||||||
int invariantSize = vertexCount * stride;
|
|
||||||
|
|
||||||
vao = GL30.glGenVertexArrays();
|
|
||||||
ebo = GlStateManager.genBuffers();
|
|
||||||
vbo = GlStateManager.genBuffers();
|
|
||||||
|
|
||||||
GL30.glBindVertexArray(vao);
|
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
|
||||||
|
|
||||||
// allocate the buffer on the gpu
|
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
// mirror it in system memory so we can write to it
|
|
||||||
ByteBuffer constant = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
|
||||||
|
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
|
||||||
constant.putFloat(getX(template, i));
|
|
||||||
constant.putFloat(getY(template, i));
|
|
||||||
constant.putFloat(getZ(template, i));
|
|
||||||
|
|
||||||
constant.put(getNX(template, i));
|
|
||||||
constant.put(getNY(template, i));
|
|
||||||
constant.put(getNZ(template, i));
|
|
||||||
|
|
||||||
constant.putFloat(getU(template, i));
|
|
||||||
constant.putFloat(getV(template, i));
|
|
||||||
|
|
||||||
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);
|
|
||||||
// Deselect (bind to 0) the VAO
|
|
||||||
GL30.glBindVertexArray(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
package com.simibubi.create.foundation.render;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
import com.simibubi.create.foundation.render.instancing.VertexFormat;
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
import org.lwjgl.opengl.GL40;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public abstract class GPUBuffer extends TemplateBuffer {
|
||||||
|
|
||||||
|
protected int vao, ebo, invariantVBO;
|
||||||
|
|
||||||
|
public GPUBuffer(BufferBuilder buf) {
|
||||||
|
super(buf);
|
||||||
|
if (vertexCount > 0) setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setup() {
|
||||||
|
int stride = getModelFormat().getStride();
|
||||||
|
|
||||||
|
int invariantSize = vertexCount * stride;
|
||||||
|
|
||||||
|
vao = GL30.glGenVertexArrays();
|
||||||
|
ebo = GlStateManager.genBuffers();
|
||||||
|
invariantVBO = GlStateManager.genBuffers();
|
||||||
|
|
||||||
|
GL30.glBindVertexArray(vao);
|
||||||
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, invariantVBO);
|
||||||
|
|
||||||
|
// allocate the buffer on the gpu
|
||||||
|
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// mirror it in system memory so we can write to it
|
||||||
|
ByteBuffer constant = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
copyVertex(constant, i);
|
||||||
|
}
|
||||||
|
constant.rewind();
|
||||||
|
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
buildEBO(ebo);
|
||||||
|
|
||||||
|
getModelFormat().informAttributes(0);
|
||||||
|
|
||||||
|
GlStateManager.bindBuffers(GL15.GL_ARRAY_BUFFER, 0);
|
||||||
|
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
// Deselect (bind to 0) the VAO
|
||||||
|
GL30.glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void copyVertex(ByteBuffer to, int index);
|
||||||
|
|
||||||
|
protected abstract VertexFormat getModelFormat();
|
||||||
|
|
||||||
|
protected int getTotalShaderAttributeCount() {
|
||||||
|
return getModelFormat().getShaderAttributeCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void drawCall();
|
||||||
|
|
||||||
|
protected void preDrawTask() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render() {
|
||||||
|
if (vao == 0) return;
|
||||||
|
|
||||||
|
GL30.glBindVertexArray(vao);
|
||||||
|
preDrawTask();
|
||||||
|
|
||||||
|
int numAttributes = getTotalShaderAttributeCount();
|
||||||
|
for (int i = 0; i <= numAttributes; i++) {
|
||||||
|
GL40.glEnableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
|
|
||||||
|
drawCall();
|
||||||
|
|
||||||
|
for (int i = 0; i <= numAttributes; i++) {
|
||||||
|
GL40.glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
GL30.glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
if (vertexCount > 0) {
|
||||||
|
RenderWork.enqueue(this::deleteInternal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteInternal() {
|
||||||
|
GL15.glDeleteBuffers(invariantVBO);
|
||||||
|
GL15.glDeleteBuffers(ebo);
|
||||||
|
GL30.glDeleteVertexArrays(vao);
|
||||||
|
vao = 0;
|
||||||
|
ebo = 0;
|
||||||
|
invariantVBO = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.simibubi.create.foundation.render.instancing;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import org.lwjgl.opengl.*;
|
||||||
|
|
||||||
|
public abstract class DynamicInstanceBuffer<S extends InstanceData, D extends InstanceData> extends InstanceBuffer<S> {
|
||||||
|
|
||||||
|
protected int dynamicVBO;
|
||||||
|
|
||||||
|
protected int dynamicBufferSize = -1;
|
||||||
|
|
||||||
|
public DynamicInstanceBuffer(BufferBuilder buf) {
|
||||||
|
super(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setup() {
|
||||||
|
super.setup();
|
||||||
|
dynamicVBO = GL20.glGenBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract VertexFormat getDynamicFormat();
|
||||||
|
|
||||||
|
protected abstract D newDynamicPart();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getTotalShaderAttributeCount() {
|
||||||
|
return super.getTotalShaderAttributeCount() + getDynamicFormat().getShaderAttributeCount();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package com.simibubi.create.foundation.render.instancing;
|
||||||
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
import com.simibubi.create.foundation.render.GPUBuffer;
|
||||||
import com.simibubi.create.foundation.render.RenderMath;
|
import com.simibubi.create.foundation.render.RenderMath;
|
||||||
import com.simibubi.create.foundation.render.RenderWork;
|
import com.simibubi.create.foundation.render.RenderWork;
|
||||||
import com.simibubi.create.foundation.render.TemplateBuffer;
|
import com.simibubi.create.foundation.render.TemplateBuffer;
|
||||||
|
@ -14,12 +15,13 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
||||||
|
|
||||||
public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuffer {
|
public abstract class InstanceBuffer<D extends InstanceData> extends GPUBuffer {
|
||||||
public static final VertexFormat FORMAT = new VertexFormat(POSITION, NORMAL, UV);
|
public static final VertexFormat FORMAT = new VertexFormat(POSITION, NORMAL, UV);
|
||||||
|
|
||||||
protected int vao, ebo, invariantVBO, instanceVBO, instanceCount;
|
protected int instanceVBO;
|
||||||
|
protected int instanceCount;
|
||||||
|
|
||||||
protected int bufferSize = -1;
|
protected int instanceBufferSize = -1;
|
||||||
|
|
||||||
protected final ArrayList<D> data = new ArrayList<>();
|
protected final ArrayList<D> data = new ArrayList<>();
|
||||||
protected boolean rebuffer = false;
|
protected boolean rebuffer = false;
|
||||||
|
@ -27,51 +29,31 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
||||||
|
|
||||||
public InstanceBuffer(BufferBuilder buf) {
|
public InstanceBuffer(BufferBuilder buf) {
|
||||||
super(buf);
|
super(buf);
|
||||||
if (vertexCount > 0) setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setup() {
|
@Override
|
||||||
int stride = FORMAT.getStride();
|
protected void setup() {
|
||||||
|
super.setup();
|
||||||
int invariantSize = vertexCount * stride;
|
|
||||||
|
|
||||||
vao = GL30.glGenVertexArrays();
|
|
||||||
ebo = GlStateManager.genBuffers();
|
|
||||||
invariantVBO = GlStateManager.genBuffers();
|
|
||||||
instanceVBO = GlStateManager.genBuffers();
|
instanceVBO = GlStateManager.genBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
GL30.glBindVertexArray(vao);
|
@Override
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, invariantVBO);
|
protected VertexFormat getModelFormat() {
|
||||||
|
return FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate the buffer on the gpu
|
@Override
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
protected void copyVertex(ByteBuffer constant, int i) {
|
||||||
|
constant.putFloat(getX(template, i));
|
||||||
|
constant.putFloat(getY(template, i));
|
||||||
|
constant.putFloat(getZ(template, i));
|
||||||
|
|
||||||
// mirror it in system memory so we can write to it
|
constant.put(getNX(template, i));
|
||||||
ByteBuffer constant = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
constant.put(getNY(template, i));
|
||||||
|
constant.put(getNZ(template, i));
|
||||||
|
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
constant.putFloat(getU(template, i));
|
||||||
constant.putFloat(getX(template, i));
|
constant.putFloat(getV(template, i));
|
||||||
constant.putFloat(getY(template, i));
|
|
||||||
constant.putFloat(getZ(template, i));
|
|
||||||
|
|
||||||
constant.put(getNX(template, i));
|
|
||||||
constant.put(getNY(template, i));
|
|
||||||
constant.put(getNZ(template, i));
|
|
||||||
|
|
||||||
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);
|
|
||||||
// Deselect (bind to 0) the VAO
|
|
||||||
GL30.glBindVertexArray(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract VertexFormat getInstanceFormat();
|
protected abstract VertexFormat getInstanceFormat();
|
||||||
|
@ -93,20 +75,16 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
||||||
if (shouldBuild) rebuffer = true;
|
if (shouldBuild) rebuffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
protected void deleteInternal() {
|
||||||
if (vertexCount > 0) {
|
GL15.glDeleteBuffers(invariantVBO);
|
||||||
RenderWork.enqueue(() -> {
|
GL15.glDeleteBuffers(instanceVBO);
|
||||||
GL15.glDeleteBuffers(invariantVBO);
|
GL15.glDeleteBuffers(ebo);
|
||||||
GL15.glDeleteBuffers(instanceVBO);
|
GL30.glDeleteVertexArrays(vao);
|
||||||
GL15.glDeleteBuffers(ebo);
|
vao = 0;
|
||||||
GL30.glDeleteVertexArrays(vao);
|
ebo = 0;
|
||||||
vao = 0;
|
invariantVBO = 0;
|
||||||
ebo = 0;
|
instanceVBO = 0;
|
||||||
invariantVBO = 0;
|
instanceBufferSize = -1;
|
||||||
instanceVBO = 0;
|
|
||||||
bufferSize = -1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract D newInstance();
|
protected abstract D newInstance();
|
||||||
|
@ -120,30 +98,16 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
||||||
data.add(instanceData);
|
data.add(instanceData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render() {
|
protected int getTotalShaderAttributeCount() {
|
||||||
if (vao == 0) return;
|
return getInstanceFormat().getShaderAttributeCount() + FORMAT.getShaderAttributeCount();
|
||||||
|
|
||||||
GL30.glBindVertexArray(vao);
|
|
||||||
finishBuffering();
|
|
||||||
|
|
||||||
int numAttributes = getInstanceFormat().getNumAttributes() + FORMAT.getNumAttributes();
|
|
||||||
for (int i = 0; i <= numAttributes; i++) {
|
|
||||||
GL40.glEnableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
|
||||||
|
|
||||||
GL40.glDrawElementsInstanced(GL11.GL_QUADS, vertexCount, GL11.GL_UNSIGNED_SHORT, 0, instanceCount);
|
|
||||||
|
|
||||||
for (int i = 0; i <= numAttributes; i++) {
|
|
||||||
GL40.glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
GL30.glBindVertexArray(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishBuffering() {
|
@Override
|
||||||
|
protected void drawCall() {
|
||||||
|
GL40.glDrawElementsInstanced(GL11.GL_QUADS, vertexCount, GL11.GL_UNSIGNED_SHORT, 0, instanceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void preDrawTask() {
|
||||||
if (!rebuffer || data.isEmpty()) return;
|
if (!rebuffer || data.isEmpty()) return;
|
||||||
|
|
||||||
instanceCount = data.size();
|
instanceCount = data.size();
|
||||||
|
@ -155,9 +119,9 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
||||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, instanceVBO);
|
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, instanceVBO);
|
||||||
|
|
||||||
// this changes enough that it's not worth reallocating the entire buffer every time.
|
// this changes enough that it's not worth reallocating the entire buffer every time.
|
||||||
if (instanceSize > bufferSize) {
|
if (instanceSize > instanceBufferSize) {
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, instanceSize, GL15.GL_STATIC_DRAW);
|
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, instanceSize, GL15.GL_STATIC_DRAW);
|
||||||
bufferSize = instanceSize;
|
instanceBufferSize = instanceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer buffer = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
ByteBuffer buffer = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
||||||
|
@ -166,10 +130,10 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
int staticAttributes = FORMAT.getNumAttributes();
|
int staticAttributes = FORMAT.getShaderAttributeCount();
|
||||||
instanceFormat.informAttributes(staticAttributes);
|
instanceFormat.informAttributes(staticAttributes);
|
||||||
|
|
||||||
for (int i = 0; i < instanceFormat.getNumAttributes(); i++) {
|
for (int i = 0; i < instanceFormat.getShaderAttributeCount(); i++) {
|
||||||
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
|
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,13 @@ import java.nio.ByteBuffer;
|
||||||
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
||||||
|
|
||||||
public class RotatingData extends BasicData<RotatingData> {
|
public class RotatingData extends BasicData<RotatingData> {
|
||||||
public static VertexFormat FORMAT = new VertexFormat(BasicData.FORMAT, FLOAT, FLOAT, VEC3);
|
public static VertexFormat FORMAT = new VertexFormat(BasicData.FORMAT, FLOAT, FLOAT, NORMAL);
|
||||||
|
|
||||||
private float rotationalSpeed;
|
private float rotationalSpeed;
|
||||||
private float rotationOffset;
|
private float rotationOffset;
|
||||||
private float rotationAxisX;
|
private byte rotationAxisX;
|
||||||
private float rotationAxisY;
|
private byte rotationAxisY;
|
||||||
private float rotationAxisZ;
|
private byte rotationAxisZ;
|
||||||
|
|
||||||
public RotatingData setRotationalSpeed(float rotationalSpeed) {
|
public RotatingData setRotationalSpeed(float rotationalSpeed) {
|
||||||
this.rotationalSpeed = rotationalSpeed;
|
this.rotationalSpeed = rotationalSpeed;
|
||||||
|
@ -26,16 +26,14 @@ public class RotatingData extends BasicData<RotatingData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RotatingData setRotationAxis(Vector3f axis) {
|
public RotatingData setRotationAxis(Vector3f axis) {
|
||||||
this.rotationAxisX = axis.getX();
|
setRotationAxis(axis.getX(), axis.getY(), axis.getZ());
|
||||||
this.rotationAxisY = axis.getY();
|
|
||||||
this.rotationAxisZ = axis.getZ();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RotatingData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
|
public RotatingData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
|
||||||
this.rotationAxisX = rotationAxisX;
|
this.rotationAxisX = (byte) (rotationAxisX * 127);
|
||||||
this.rotationAxisY = rotationAxisY;
|
this.rotationAxisY = (byte) (rotationAxisY * 127);
|
||||||
this.rotationAxisZ = rotationAxisZ;
|
this.rotationAxisZ = (byte) (rotationAxisZ * 127);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class VertexFormat {
|
||||||
this.stride = stride;
|
this.stride = stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumAttributes() {
|
public int getShaderAttributeCount() {
|
||||||
return numAttributes;
|
return numAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.simibubi.create.foundation.render.instancing.actors;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.instancing.InstanceData;
|
||||||
|
import com.simibubi.create.foundation.render.instancing.VertexFormat;
|
||||||
|
import net.minecraft.client.renderer.Vector3f;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
||||||
|
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.NORMAL;
|
||||||
|
|
||||||
|
public class DynamicRotatingActorData extends InstanceData {
|
||||||
|
public static VertexFormat FORMAT = new VertexFormat(NORMAL);
|
||||||
|
|
||||||
|
private byte relativeMotionX;
|
||||||
|
private byte relativeMotionY;
|
||||||
|
private byte relativeMotionZ;
|
||||||
|
|
||||||
|
public DynamicRotatingActorData setRelativeMotion(Vector3f axis) {
|
||||||
|
setRelativeMotion(axis.getX(), axis.getY(), axis.getZ());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DynamicRotatingActorData setRelativeMotion(float relativeMotionX, float relativeMotionY, float relativeMotionZ) {
|
||||||
|
this.relativeMotionX = (byte) (relativeMotionX * 127);
|
||||||
|
this.relativeMotionY = (byte) (relativeMotionY * 127);
|
||||||
|
this.relativeMotionZ = (byte) (relativeMotionZ * 127);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuffer buf) {
|
||||||
|
putVec3(buf, relativeMotionX, relativeMotionY, relativeMotionZ);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.simibubi.create.foundation.render.instancing.actors;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.instancing.DynamicInstanceBuffer;
|
||||||
|
import com.simibubi.create.foundation.render.instancing.VertexFormat;
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
|
||||||
|
public class RotatingActorBuffer extends DynamicInstanceBuffer<StaticRotatingActorData, DynamicRotatingActorData> {
|
||||||
|
public RotatingActorBuffer(BufferBuilder buf) {
|
||||||
|
super(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected VertexFormat getDynamicFormat() {
|
||||||
|
return DynamicRotatingActorData.FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DynamicRotatingActorData newDynamicPart() {
|
||||||
|
return new DynamicRotatingActorData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected VertexFormat getInstanceFormat() {
|
||||||
|
return StaticRotatingActorData.FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected StaticRotatingActorData newInstance() {
|
||||||
|
return new StaticRotatingActorData();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.simibubi.create.foundation.render.instancing.actors;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.instancing.InstanceData;
|
||||||
|
import com.simibubi.create.foundation.render.instancing.RotatingData;
|
||||||
|
import com.simibubi.create.foundation.render.instancing.VertexFormat;
|
||||||
|
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 StaticRotatingActorData extends InstanceData {
|
||||||
|
public static VertexFormat FORMAT = new VertexFormat(POSITION, FLOAT, NORMAL, NORMAL);
|
||||||
|
|
||||||
|
private float x;
|
||||||
|
private float y;
|
||||||
|
private float z;
|
||||||
|
private float rotationOffset;
|
||||||
|
private byte rotationAxisX;
|
||||||
|
private byte rotationAxisY;
|
||||||
|
private byte rotationAxisZ;
|
||||||
|
private byte localOrientationX;
|
||||||
|
private byte localOrientationY;
|
||||||
|
private byte localOrientationZ;
|
||||||
|
|
||||||
|
public StaticRotatingActorData setPosition(BlockPos pos) {
|
||||||
|
this.x = pos.getX();
|
||||||
|
this.y = pos.getY();
|
||||||
|
this.z = pos.getZ();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticRotatingActorData setRotationOffset(float rotationOffset) {
|
||||||
|
this.rotationOffset = rotationOffset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticRotatingActorData setRotationAxis(Vector3f axis) {
|
||||||
|
setRotationAxis(axis.getX(), axis.getY(), axis.getZ());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticRotatingActorData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
|
||||||
|
this.rotationAxisX = (byte) (rotationAxisX * 127);
|
||||||
|
this.rotationAxisY = (byte) (rotationAxisY * 127);
|
||||||
|
this.rotationAxisZ = (byte) (rotationAxisZ * 127);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticRotatingActorData setLocalOrientation(Vector3f axis) {
|
||||||
|
setRotationAxis(axis.getX(), axis.getY(), axis.getZ());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticRotatingActorData setLocalOrientation(float localOrientationX, float localOrientationY, float localOrientationZ) {
|
||||||
|
this.localOrientationX = (byte) (localOrientationX * 127);
|
||||||
|
this.localOrientationY = (byte) (localOrientationY * 127);
|
||||||
|
this.localOrientationZ = (byte) (localOrientationZ * 127);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuffer buf) {
|
||||||
|
putVec3(buf, x, y, z);
|
||||||
|
put(buf, rotationOffset);
|
||||||
|
putVec3(buf, rotationAxisX, rotationAxisY, rotationAxisZ);
|
||||||
|
putVec3(buf, localOrientationX, localOrientationY, localOrientationZ);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ public enum Shader {
|
||||||
CONTRAPTION_STRUCTURE("shader/contraption.vert", "shader/contraption.frag"),
|
CONTRAPTION_STRUCTURE("shader/contraption.vert", "shader/contraption.frag"),
|
||||||
CONTRAPTION_ROTATING("shader/contraption_rotating.vert", "shader/contraption.frag"),
|
CONTRAPTION_ROTATING("shader/contraption_rotating.vert", "shader/contraption.frag"),
|
||||||
CONTRAPTION_BELT("shader/contraption_belt.vert", "shader/contraption.frag"),
|
CONTRAPTION_BELT("shader/contraption_belt.vert", "shader/contraption.frag"),
|
||||||
|
//CONTRAPTION_ACTOR("shader/contraption_actor.vert", "shader/contraption.frag"),
|
||||||
;
|
;
|
||||||
|
|
||||||
public final String vert;
|
public final String vert;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#version 330 core
|
||||||
|
#define PI 3.1415926538
|
||||||
|
// model data
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aNormal;
|
||||||
|
layout (location = 2) in vec2 aTexCoords;
|
||||||
|
|
||||||
|
// instance data
|
||||||
|
layout (location = 3) in vec3 instancePos;
|
||||||
|
layout (location = 4) in float rotationOffset;
|
||||||
|
layout (location = 5) in vec3 localRotationAxis;
|
||||||
|
layout (location = 6) in vec3 localOrientation;
|
||||||
|
|
||||||
|
// dynamic data
|
||||||
|
layout (location = 7) in vec3 relativeMotion;
|
||||||
|
|
||||||
|
out float Diffuse;
|
||||||
|
out vec2 TexCoords;
|
||||||
|
out vec4 Color;
|
||||||
|
out vec3 BoxCoord;
|
||||||
|
|
||||||
|
uniform vec3 lightBoxSize;
|
||||||
|
uniform vec3 lightBoxMin;
|
||||||
|
uniform mat4 model;
|
||||||
|
|
||||||
|
uniform float time;
|
||||||
|
uniform int ticks;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform int debug;
|
||||||
|
|
||||||
|
mat4 rotate(vec3 axis, float angle) {
|
||||||
|
float s = sin(angle);
|
||||||
|
float c = cos(angle);
|
||||||
|
float oc = 1.0 - c;
|
||||||
|
|
||||||
|
return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.,
|
||||||
|
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.,
|
||||||
|
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.,
|
||||||
|
0., 0., 0., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 kineticRotation() {
|
||||||
|
float degrees = rotationOffset + time * speed * -3./10.;
|
||||||
|
float angle = fract(degrees / 360.) * PI * 2.;
|
||||||
|
|
||||||
|
return rotate(normalize(localRotationAxis), angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
float diffuse(vec3 normal) {
|
||||||
|
float x = normal.x;
|
||||||
|
float y = normal.y;
|
||||||
|
float z = normal.z;
|
||||||
|
return min(x * x * 0.6f + y * y * ((3f + y) / 4f) + z * z * 0.8f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
mat4 kineticRotation = kineticRotation();
|
||||||
|
vec4 localPos = kineticRotation * vec4(aPos - 0.5, 1f) + vec4(instancePos + 0.5, 0);
|
||||||
|
|
||||||
|
vec4 worldPos = model * localPos;
|
||||||
|
|
||||||
|
BoxCoord = (worldPos.xyz - lightBoxMin) / lightBoxSize;
|
||||||
|
Diffuse = diffuse(normalize(model * kineticRotation * vec4(aNormal, 0.)).xyz);
|
||||||
|
Color = vec4(1.);
|
||||||
|
TexCoords = aTexCoords;
|
||||||
|
gl_Position = projection * view * worldPos;
|
||||||
|
}
|
Loading…
Reference in a new issue