smooth belts

This commit is contained in:
JozsefA 2021-01-05 01:59:32 -08:00
parent 7deb72baa1
commit 566a370e3b
8 changed files with 120 additions and 78 deletions

View file

@ -55,9 +55,9 @@ public class AllSpriteShifts {
CREATIVE_FLUID_TANK = getCT(CTType.CROSS, "creative_fluid_tank"); CREATIVE_FLUID_TANK = getCT(CTType.CROSS, "creative_fluid_tank");
public static final SpriteShiftEntry public static final SpriteShiftEntry
BELT = SpriteShifter.get("block/belt", "block/belt_animated"), BELT = SpriteShifter.get("block/belt", "block/belt_scroll"),
BELT_OFFSET = SpriteShifter.get("block/belt_offset", "block/belt_animated"), BELT_OFFSET = SpriteShifter.get("block/belt_offset", "block/belt_offset_scroll"),
BELT_DIAGONAL = SpriteShifter.get("block/belt_diagonal", "block/belt_diagonal_animated"), BELT_DIAGONAL = SpriteShifter.get("block/belt_diagonal", "block/belt_diagonal_scroll"),
ANDESIDE_BELT_CASING = SpriteShifter.get("block/brass_casing_belt", "block/andesite_casing_belt"), ANDESIDE_BELT_CASING = SpriteShifter.get("block/brass_casing_belt", "block/andesite_casing_belt"),
CRAFTER_THINGIES = SpriteShifter.get("block/crafter_thingies", "block/crafter_thingies"); CRAFTER_THINGIES = SpriteShifter.get("block/crafter_thingies", "block/crafter_thingies");

View file

@ -66,17 +66,6 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
boolean sideways = beltSlope == BeltSlope.SIDEWAYS; boolean sideways = beltSlope == BeltSlope.SIDEWAYS;
boolean alongX = facing.getAxis() == Axis.X; boolean alongX = facing.getAxis() == Axis.X;
MatrixStacker msr = MatrixStacker.of(ms);
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
float renderTick = AnimationTickHolder.getRenderTick();
ms.push();
msr.centre();
msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0));
msr.rotateZ(sideways ? 90 : 0);
msr.rotateX(!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0);
msr.unCentre();
if (downward || beltSlope == BeltSlope.VERTICAL && axisDirection == AxisDirection.POSITIVE) { if (downward || beltSlope == BeltSlope.VERTICAL && axisDirection == AxisDirection.POSITIVE) {
boolean b = start; boolean b = start;
start = end; start = end;
@ -98,34 +87,29 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
SpriteShiftEntry spriteShift = SpriteShiftEntry spriteShift =
diagonal ? AllSpriteShifts.BELT_DIAGONAL : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT; diagonal ? AllSpriteShifts.BELT_DIAGONAL : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT;
int cycleLength = diagonal ? 12 : 16;
int cycleOffset = bottom ? 8 : 0;
// UV shift
beltBuffer.setupInstance(data -> { beltBuffer.setupInstance(data -> {
float speed = te.getSpeed(); float speed = te.getSpeed();
if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX
|| sideways && axisDirection == AxisDirection.NEGATIVE) || sideways && axisDirection == AxisDirection.NEGATIVE)
speed = -speed; speed = -speed;
Matrix4f m = new Matrix4f(); float horizontalAngle = facing.getHorizontalAngle();
m.loadIdentity();
m.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0)));
m.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(sideways ? 90 : 0));
m.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0));
data.setPosition(te.getPos()) data.setPosition(te.getPos())
.setModel(m) .setRotation(
!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0,
horizontalAngle + (upward ? 180 : 0) + (sideways ? 270 : 0),
sideways ? 90 : 0
)
.setPackedLight(light) .setPackedLight(light)
.setRotationalSpeed(speed); .setRotationalSpeed(speed)
.setScrollTexture(spriteShift)
.setScrollMult(diagonal ? 3f / 8f : 0.5f);
}); });
// Diagonal belt do not have a separate bottom model // Diagonal belt do not have a separate bottom model
if (diagonal) if (diagonal)
break; break;
} }
ms.pop();
if (te.hasPulley()) { if (te.hasPulley()) {
// TODO 1.15 find a way to cache this model matrix computation // TODO 1.15 find a way to cache this model matrix computation
@ -134,7 +118,7 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
.rotateY(); .rotateY();
if (sideways) if (sideways)
dir = Direction.UP; dir = Direction.UP;
msr = MatrixStacker.of(modelTransform); MatrixStacker msr = MatrixStacker.of(modelTransform);
msr.centre(); msr.centre();
if (dir.getAxis() == Axis.X) if (dir.getAxis() == Axis.X)
msr.rotateY(90); msr.rotateY(90);
@ -143,9 +127,9 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
msr.rotateX(90); msr.rotateX(90);
msr.unCentre(); msr.unCentre();
RotatingBuffer superBuffer = CreateClient.kineticRenderer RotatingBuffer rotatingBuffer = CreateClient.kineticRenderer
.renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); .renderDirectionalPartialInstanced(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform);
KineticTileEntityRenderer.renderRotatingBuffer(te, superBuffer, light); KineticTileEntityRenderer.renderRotatingBuffer(te, rotatingBuffer, light);
} }
renderItems(te, partialTicks, ms, buffer, light, overlay); renderItems(te, partialTicks, ms, buffer, light, overlay);

View file

@ -1,10 +1,11 @@
package com.simibubi.create.foundation.utility.render; package com.simibubi.create.foundation.utility.render;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GLAllocation; import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormatElement; import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
@ -34,7 +35,7 @@ public class BeltBuffer extends InstancedBuffer<BeltBuffer.BeltData> {
protected void finishBufferingInternal() { protected void finishBufferingInternal() {
int floatSize = VertexFormatElement.Type.FLOAT.getSize(); int floatSize = VertexFormatElement.Type.FLOAT.getSize();
int intSize = VertexFormatElement.Type.INT.getSize(); int intSize = VertexFormatElement.Type.INT.getSize();
int stride = floatSize * 22; int stride = floatSize * 16;
int instanceSize = instanceCount * stride; int instanceSize = instanceCount * stride;
@ -51,16 +52,21 @@ public class BeltBuffer extends InstancedBuffer<BeltBuffer.BeltData> {
// render position // render position
GL20.glVertexAttribPointer(3, 3, GL11.GL_FLOAT, false, stride, 0); GL20.glVertexAttribPointer(3, 3, GL11.GL_FLOAT, false, stride, 0);
// model matrix // render rotation
for (int i = 0; i < 4; i++) { GL20.glVertexAttribPointer(4, 3, GL11.GL_FLOAT, false, stride, floatSize * 3L);
GL20.glVertexAttribPointer(4 + i, 4, GL11.GL_FLOAT, false, stride, floatSize * (4 * i + 3));
}
// light map // light map
GL20.glVertexAttribPointer(8, 2, GL11.GL_FLOAT, false, stride, floatSize * 16L); GL20.glVertexAttribPointer(5, 2, GL11.GL_FLOAT, false, stride, floatSize * 6L);
// rotational speed and offset // speed
GL20.glVertexAttribPointer(9, 1, GL11.GL_FLOAT, false, stride, floatSize * 18L); GL20.glVertexAttribPointer(6, 1, GL11.GL_FLOAT, false, stride, floatSize * 8L);
// uv data
GL20.glVertexAttribPointer(7, 2, GL11.GL_FLOAT, false, stride, floatSize * 9L);
GL20.glVertexAttribPointer(8, 4, GL11.GL_FLOAT, false, stride, floatSize * 11L);
GL20.glVertexAttribPointer(9, 1, GL11.GL_FLOAT, false, stride, floatSize * 15L);
for (int i = 3; i <= numAttributes(); i++) { for (int i = 3; i <= numAttributes(); i++) {
GL40.glVertexAttribDivisor(i, 1); GL40.glVertexAttribDivisor(i, 1);
@ -74,9 +80,18 @@ public class BeltBuffer extends InstancedBuffer<BeltBuffer.BeltData> {
private float x; private float x;
private float y; private float y;
private float z; private float z;
private Matrix4f model; private float rotX;
private float rotY;
private float rotZ;
private int packedLight; private int packedLight;
private float rotationalSpeed; private float rotationalSpeed;
private float sourceU;
private float sourceV;
private float minU;
private float minV;
private float maxU;
private float maxV;
private float scrollMult;
public BeltData setPosition(BlockPos pos) { public BeltData setPosition(BlockPos pos) {
this.x = pos.getX(); this.x = pos.getX();
@ -85,8 +100,10 @@ public class BeltBuffer extends InstancedBuffer<BeltBuffer.BeltData> {
return this; return this;
} }
public BeltData setModel(Matrix4f model) { public BeltData setRotation(float rotX, float rotY, float rotZ) {
this.model = model; this.rotX = rotX;
this.rotY = rotY;
this.rotZ = rotZ;
return this; return this;
} }
@ -100,6 +117,25 @@ public class BeltBuffer extends InstancedBuffer<BeltBuffer.BeltData> {
return this; return this;
} }
public BeltData setScrollTexture(SpriteShiftEntry spriteShift) {
TextureAtlasSprite source = spriteShift.getOriginal();
TextureAtlasSprite target = spriteShift.getTarget();
this.sourceU = source.getMinU();
this.sourceV = source.getMinV();
this.minU = target.getMinU();
this.minV = target.getMinV();
this.maxU = target.getMaxU();
this.maxV = target.getMaxV();
return this;
}
public BeltData setScrollMult(float scrollMult) {
this.scrollMult = scrollMult;
return this;
}
void buffer(ByteBuffer buf) { void buffer(ByteBuffer buf) {
float blockLightCoordinates = LightTexture.getBlockLightCoordinates(packedLight) / (float) 0xF; float blockLightCoordinates = LightTexture.getBlockLightCoordinates(packedLight) / (float) 0xF;
float skyLightCoordinates = LightTexture.getSkyLightCoordinates(packedLight) / (float) 0xF; float skyLightCoordinates = LightTexture.getSkyLightCoordinates(packedLight) / (float) 0xF;
@ -108,14 +144,22 @@ public class BeltBuffer extends InstancedBuffer<BeltBuffer.BeltData> {
buf.putFloat(y); buf.putFloat(y);
buf.putFloat(z); buf.putFloat(z);
InstancedBuffer.MATRIX_BUF.rewind(); buf.putFloat(rotX);
model.write(InstancedBuffer.MATRIX_BUF.asFloatBuffer()); buf.putFloat(rotY);
InstancedBuffer.MATRIX_BUF.rewind(); buf.putFloat(rotZ);
buf.put(InstancedBuffer.MATRIX_BUF);
buf.putFloat(blockLightCoordinates); buf.putFloat(blockLightCoordinates);
buf.putFloat(skyLightCoordinates); buf.putFloat(skyLightCoordinates);
buf.putFloat(rotationalSpeed); buf.putFloat(rotationalSpeed);
buf.putFloat(sourceU);
buf.putFloat(sourceV);
buf.putFloat(minU);
buf.putFloat(minV);
buf.putFloat(maxU);
buf.putFloat(maxV);
buf.putFloat(scrollMult);
} }
} }
} }

View file

@ -50,17 +50,17 @@ public class FastKineticRenderer {
} }
public void tick() { public void tick() {
for (Cache<Object, RotatingBuffer> cache : rotating.values()) { // for (Cache<Object, RotatingBuffer> cache : rotating.values()) {
for (RotatingBuffer renderer : cache.asMap().values()) { // for (RotatingBuffer renderer : cache.asMap().values()) {
renderer.clearInstanceData(); // renderer.clearInstanceData();
} // }
} // }
//
for (Cache<Object, BeltBuffer> cache : belts.values()) { // for (Cache<Object, BeltBuffer> cache : belts.values()) {
for (BeltBuffer renderer : cache.asMap().values()) { // for (BeltBuffer renderer : cache.asMap().values()) {
renderer.clearInstanceData(); // renderer.clearInstanceData();
} // }
} // }
} }
public void enqueue(Runnable run) { public void enqueue(Runnable run) {
@ -219,5 +219,10 @@ public class FastKineticRenderer {
cache.asMap().values().forEach(InstancedBuffer::invalidate); cache.asMap().values().forEach(InstancedBuffer::invalidate);
cache.invalidateAll(); cache.invalidateAll();
}); });
belts.values().forEach(cache -> {
cache.asMap().values().forEach(InstancedBuffer::invalidate);
cache.invalidateAll();
});
} }
} }

View file

@ -15,8 +15,6 @@ import java.util.function.Consumer;
public abstract class InstancedBuffer<T> extends TemplateBuffer { public abstract class InstancedBuffer<T> extends TemplateBuffer {
protected static ByteBuffer MATRIX_BUF = GLAllocation.createDirectByteBuffer(16 << 2);
protected int vao, ebo, invariantVBO, instanceVBO, instanceCount; protected int vao, ebo, invariantVBO, instanceVBO, instanceCount;
protected final ArrayList<T> data = new ArrayList<>(); protected final ArrayList<T> data = new ArrayList<>();
@ -112,11 +110,6 @@ public abstract class InstancedBuffer<T> extends TemplateBuffer {
}); });
} }
protected void addData(T instance) {
data.add(instance);
instanceCount++;
}
protected abstract T newInstance(); protected abstract T newInstance();
protected abstract int numAttributes(); protected abstract int numAttributes();
@ -127,7 +120,8 @@ public abstract class InstancedBuffer<T> extends TemplateBuffer {
T instanceData = newInstance(); T instanceData = newInstance();
setup.accept(instanceData); setup.accept(instanceData);
addData(instanceData); data.add(instanceData);
instanceCount++;
} }
public void render() { public void render() {

View file

@ -6,9 +6,12 @@ layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords; layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 instancePos; layout (location = 3) in vec3 instancePos;
layout (location = 4) in mat4 model; layout (location = 4) in vec3 rotationDegrees;
layout (location = 8) in vec2 light; layout (location = 5) in vec2 light;
layout (location = 9) in float speed; layout (location = 6) in float speed;
layout (location = 7) in vec2 sourceUV;
layout (location = 8) in vec4 scrollTexture;
layout (location = 9) in float scrollMult;
out vec2 TexCoords; out vec2 TexCoords;
out vec2 Light; out vec2 Light;
@ -18,18 +21,30 @@ uniform int ticks;
uniform mat4 projection; uniform mat4 projection;
uniform mat4 view; uniform mat4 view;
mat4 rotate(vec3 axis, float angle)
{
float s = sin(angle);
float c = cos(angle);
float oc = 1.0 - c;
void main() { 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.,
// float textureIndex = fract((speed * time / 36 + cycle[1]) / cycle[0]) * cycle[0]; oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.,
// if (textureIndex < 0) { oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.,
// textureIndex += cycle[0]; 0., 0., 0., 1.);
// } }
//
// vec2 scrollPos = vec2(fract(textureIndex / 4), floor(textureIndex / 16));
vec4 renderPos = model * vec4(aPos - vec3(0.5), 1f); void main()
{
vec3 rot = fract(rotationDegrees / 360.) * PI * 2.;
vec4 renderPos = rotate(vec3(1, 0, 0), rot.x) * rotate(vec3(0, 0, 1), rot.z) * rotate(vec3(0, 1, 0), rot.y) * vec4(aPos - vec3(0.5), 1f);
renderPos += vec4(instancePos + vec3(0.5), 0); renderPos += vec4(instancePos + vec3(0.5), 0);
TexCoords = aTexCoords; float scrollSize = scrollTexture.w - scrollTexture.y;
float scroll = fract(speed * time / (36. * 16.)) * scrollSize * scrollMult;
Light = light;
TexCoords = aTexCoords - sourceUV + scrollTexture.xy + vec2(0., scroll);
gl_Position = projection * view * renderPos; gl_Position = projection * view * renderPos;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B