mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-11 04:22:00 +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.*;
|
||||
|
||||
public class ContraptionBuffer extends TemplateBuffer {
|
||||
public class ContraptionBuffer extends GPUBuffer {
|
||||
public static final VertexFormat FORMAT = new VertexFormat(InstanceBuffer.FORMAT, RGBA);
|
||||
|
||||
protected int vao, ebo, vbo;
|
||||
|
||||
public ContraptionBuffer(BufferBuilder buf) {
|
||||
super(buf);
|
||||
if (vertexCount > 0) setup();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
if (vertexCount > 0) {
|
||||
RenderWork.enqueue(() -> {
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GL15.glDeleteBuffers(ebo);
|
||||
GL30.glDeleteVertexArrays(vao);
|
||||
});
|
||||
}
|
||||
@Override
|
||||
protected void copyVertex(ByteBuffer to, int vertex) {
|
||||
to.putFloat(getX(template, vertex));
|
||||
to.putFloat(getY(template, vertex));
|
||||
to.putFloat(getZ(template, vertex));
|
||||
|
||||
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() {
|
||||
if (vertexCount == 0) return;
|
||||
GL30.glBindVertexArray(vao);
|
||||
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
GL40.glEnableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
GlStateManager.bindBuffers(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
@Override
|
||||
protected VertexFormat getModelFormat() {
|
||||
return FORMAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCall() {
|
||||
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.simibubi.create.foundation.render.GPUBuffer;
|
||||
import com.simibubi.create.foundation.render.RenderMath;
|
||||
import com.simibubi.create.foundation.render.RenderWork;
|
||||
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.*;
|
||||
|
||||
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);
|
||||
|
||||
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 boolean rebuffer = false;
|
||||
|
@ -27,51 +29,31 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
|||
|
||||
public InstanceBuffer(BufferBuilder buf) {
|
||||
super(buf);
|
||||
if (vertexCount > 0) setup();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
int stride = FORMAT.getStride();
|
||||
|
||||
int invariantSize = vertexCount * stride;
|
||||
|
||||
vao = GL30.glGenVertexArrays();
|
||||
ebo = GlStateManager.genBuffers();
|
||||
invariantVBO = GlStateManager.genBuffers();
|
||||
@Override
|
||||
protected void setup() {
|
||||
super.setup();
|
||||
instanceVBO = GlStateManager.genBuffers();
|
||||
}
|
||||
|
||||
GL30.glBindVertexArray(vao);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, invariantVBO);
|
||||
@Override
|
||||
protected VertexFormat getModelFormat() {
|
||||
return FORMAT;
|
||||
}
|
||||
|
||||
// allocate the buffer on the gpu
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
||||
@Override
|
||||
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
|
||||
ByteBuffer constant = GL15.glMapBuffer(GL15.GL_ARRAY_BUFFER, GL15.GL_WRITE_ONLY);
|
||||
constant.put(getNX(template, i));
|
||||
constant.put(getNY(template, i));
|
||||
constant.put(getNZ(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(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);
|
||||
constant.putFloat(getU(template, i));
|
||||
constant.putFloat(getV(template, i));
|
||||
}
|
||||
|
||||
protected abstract VertexFormat getInstanceFormat();
|
||||
|
@ -93,20 +75,16 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
|||
if (shouldBuild) rebuffer = true;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
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 void deleteInternal() {
|
||||
GL15.glDeleteBuffers(invariantVBO);
|
||||
GL15.glDeleteBuffers(instanceVBO);
|
||||
GL15.glDeleteBuffers(ebo);
|
||||
GL30.glDeleteVertexArrays(vao);
|
||||
vao = 0;
|
||||
ebo = 0;
|
||||
invariantVBO = 0;
|
||||
instanceVBO = 0;
|
||||
instanceBufferSize = -1;
|
||||
}
|
||||
|
||||
protected abstract D newInstance();
|
||||
|
@ -120,30 +98,16 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
|||
data.add(instanceData);
|
||||
}
|
||||
|
||||
public void render() {
|
||||
if (vao == 0) return;
|
||||
|
||||
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);
|
||||
protected int getTotalShaderAttributeCount() {
|
||||
return getInstanceFormat().getShaderAttributeCount() + FORMAT.getShaderAttributeCount();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
instanceCount = data.size();
|
||||
|
@ -155,9 +119,9 @@ public abstract class InstanceBuffer<D extends InstanceData> extends TemplateBuf
|
|||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, instanceVBO);
|
||||
|
||||
// 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);
|
||||
bufferSize = instanceSize;
|
||||
instanceBufferSize = instanceSize;
|
||||
}
|
||||
|
||||
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();
|
||||
GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER);
|
||||
|
||||
int staticAttributes = FORMAT.getNumAttributes();
|
||||
int staticAttributes = FORMAT.getShaderAttributeCount();
|
||||
instanceFormat.informAttributes(staticAttributes);
|
||||
|
||||
for (int i = 0; i < instanceFormat.getNumAttributes(); i++) {
|
||||
for (int i = 0; i < instanceFormat.getShaderAttributeCount(); i++) {
|
||||
GL33.glVertexAttribDivisor(i + staticAttributes, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,13 @@ import java.nio.ByteBuffer;
|
|||
import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*;
|
||||
|
||||
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 rotationOffset;
|
||||
private float rotationAxisX;
|
||||
private float rotationAxisY;
|
||||
private float rotationAxisZ;
|
||||
private byte rotationAxisX;
|
||||
private byte rotationAxisY;
|
||||
private byte rotationAxisZ;
|
||||
|
||||
public RotatingData setRotationalSpeed(float rotationalSpeed) {
|
||||
this.rotationalSpeed = rotationalSpeed;
|
||||
|
@ -26,16 +26,14 @@ public class RotatingData extends BasicData<RotatingData> {
|
|||
}
|
||||
|
||||
public RotatingData setRotationAxis(Vector3f axis) {
|
||||
this.rotationAxisX = axis.getX();
|
||||
this.rotationAxisY = axis.getY();
|
||||
this.rotationAxisZ = axis.getZ();
|
||||
setRotationAxis(axis.getX(), axis.getY(), axis.getZ());
|
||||
return this;
|
||||
}
|
||||
|
||||
public RotatingData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) {
|
||||
this.rotationAxisX = rotationAxisX;
|
||||
this.rotationAxisY = rotationAxisY;
|
||||
this.rotationAxisZ = rotationAxisZ;
|
||||
this.rotationAxisX = (byte) (rotationAxisX * 127);
|
||||
this.rotationAxisY = (byte) (rotationAxisY * 127);
|
||||
this.rotationAxisZ = (byte) (rotationAxisZ * 127);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public class VertexFormat {
|
|||
this.stride = stride;
|
||||
}
|
||||
|
||||
public int getNumAttributes() {
|
||||
public int getShaderAttributeCount() {
|
||||
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_ROTATING("shader/contraption_rotating.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;
|
||||
|
|
|
@ -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