diff --git a/src/main/java/com/simibubi/create/foundation/render/ContraptionBuffer.java b/src/main/java/com/simibubi/create/foundation/render/ContraptionBuffer.java index d3c77a3a5..89e76292a 100644 --- a/src/main/java/com/simibubi/create/foundation/render/ContraptionBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/ContraptionBuffer.java @@ -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); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/GPUBuffer.java b/src/main/java/com/simibubi/create/foundation/render/GPUBuffer.java new file mode 100644 index 000000000..854b814e8 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/GPUBuffer.java @@ -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; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/DynamicInstanceBuffer.java b/src/main/java/com/simibubi/create/foundation/render/instancing/DynamicInstanceBuffer.java new file mode 100644 index 000000000..0abba029c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/DynamicInstanceBuffer.java @@ -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 extends InstanceBuffer { + + 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(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/InstanceBuffer.java b/src/main/java/com/simibubi/create/foundation/render/instancing/InstanceBuffer.java index 0f88d52a3..67a6ddcbf 100644 --- a/src/main/java/com/simibubi/create/foundation/render/instancing/InstanceBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/InstanceBuffer.java @@ -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 extends TemplateBuffer { +public abstract class InstanceBuffer 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 data = new ArrayList<>(); protected boolean rebuffer = false; @@ -27,51 +29,31 @@ public abstract class InstanceBuffer 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 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 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 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 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); } diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/RotatingData.java b/src/main/java/com/simibubi/create/foundation/render/instancing/RotatingData.java index 1aa62c4a5..c905d93e9 100644 --- a/src/main/java/com/simibubi/create/foundation/render/instancing/RotatingData.java +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/RotatingData.java @@ -7,13 +7,13 @@ import java.nio.ByteBuffer; import static com.simibubi.create.foundation.render.instancing.VertexAttribute.*; public class RotatingData extends BasicData { - 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 { } 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; } diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/VertexFormat.java b/src/main/java/com/simibubi/create/foundation/render/instancing/VertexFormat.java index 856fcdd7f..55003dc2e 100644 --- a/src/main/java/com/simibubi/create/foundation/render/instancing/VertexFormat.java +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/VertexFormat.java @@ -34,7 +34,7 @@ public class VertexFormat { this.stride = stride; } - public int getNumAttributes() { + public int getShaderAttributeCount() { return numAttributes; } diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/actors/DynamicRotatingActorData.java b/src/main/java/com/simibubi/create/foundation/render/instancing/actors/DynamicRotatingActorData.java new file mode 100644 index 000000000..613ff90bd --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/actors/DynamicRotatingActorData.java @@ -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); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/actors/RotatingActorBuffer.java b/src/main/java/com/simibubi/create/foundation/render/instancing/actors/RotatingActorBuffer.java new file mode 100644 index 000000000..6e33fc9f4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/actors/RotatingActorBuffer.java @@ -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 { + 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(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/instancing/actors/StaticRotatingActorData.java b/src/main/java/com/simibubi/create/foundation/render/instancing/actors/StaticRotatingActorData.java new file mode 100644 index 000000000..48c71e91b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/instancing/actors/StaticRotatingActorData.java @@ -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); + + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/shader/Shader.java b/src/main/java/com/simibubi/create/foundation/render/shader/Shader.java index 2be9e5c96..38d0df8a9 100644 --- a/src/main/java/com/simibubi/create/foundation/render/shader/Shader.java +++ b/src/main/java/com/simibubi/create/foundation/render/shader/Shader.java @@ -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; diff --git a/src/main/resources/assets/create/shader/contraption_actor.vert b/src/main/resources/assets/create/shader/contraption_actor.vert new file mode 100644 index 000000000..1c30f9d71 --- /dev/null +++ b/src/main/resources/assets/create/shader/contraption_actor.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; +} \ No newline at end of file