mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-28 16:06:28 +01:00
Simplify SBB
- SBB -> ModelTransformer - Shader binding the minecraft way - Engines are responsible for ending batches
This commit is contained in:
parent
a668a7c7ac
commit
3049601e4a
15 changed files with 112 additions and 404 deletions
|
@ -1,9 +1,9 @@
|
|||
package com.jozufozu.flywheel.api.struct;
|
||||
|
||||
import com.jozufozu.flywheel.core.model.SuperByteBuffer;
|
||||
import com.jozufozu.flywheel.core.model.ModelTransformer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BatchingTransformer<S> {
|
||||
|
||||
void transform(S s, SuperByteBuffer.Params b);
|
||||
void transform(S s, ModelTransformer.Params b);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import static org.lwjgl.opengl.GL20.glDeleteProgram;
|
|||
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
|
||||
import static org.lwjgl.opengl.GL20.glUniform1i;
|
||||
import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
|
||||
import static org.lwjgl.opengl.GL20.glUseProgram;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
|
@ -12,6 +11,8 @@ import org.lwjgl.system.MemoryStack;
|
|||
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||
import com.jozufozu.flywheel.mixin.ShaderInstanceAccessor;
|
||||
import com.mojang.blaze3d.shaders.ProgramManager;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -28,11 +29,14 @@ public abstract class GlProgram extends GlObject {
|
|||
}
|
||||
|
||||
public void bind() {
|
||||
glUseProgram(handle());
|
||||
int handle = handle();
|
||||
ProgramManager.glUseProgram(handle);
|
||||
ShaderInstanceAccessor.setLastProgramId(handle);
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
glUseProgram(0);
|
||||
ProgramManager.glUseProgram(0);
|
||||
ShaderInstanceAccessor.setLastProgramId(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,18 +35,29 @@ public class BatchedMaterialGroup implements MaterialGroup {
|
|||
VertexConsumer buffer = source.getBuffer(state);
|
||||
|
||||
if (buffer instanceof DirectBufferBuilder direct) {
|
||||
DirectVertexConsumer consumer = direct.intoDirectConsumer(calculateNeededVertices());
|
||||
FormatContext context = new FormatContext(consumer.hasOverlay());
|
||||
|
||||
for (BatchedMaterial<?> material : materials.values()) {
|
||||
for (CPUInstancer<?> instancer : material.models.values()) {
|
||||
instancer.setup(context);
|
||||
|
||||
instancer.submitTasks(stack, pool, consumer);
|
||||
}
|
||||
}
|
||||
renderParallel(stack, pool, direct);
|
||||
} else {
|
||||
renderInto(stack, buffer, FormatContext.defaultContext());
|
||||
renderSerial(stack, buffer, FormatContext.defaultContext());
|
||||
}
|
||||
}
|
||||
|
||||
private void renderParallel(PoseStack stack, Executor pool, DirectBufferBuilder direct) {
|
||||
int vertexCount = calculateNeededVertices();
|
||||
DirectVertexConsumer consumer = direct.intoDirectConsumer(vertexCount);
|
||||
FormatContext context = new FormatContext(consumer.hasOverlay());
|
||||
|
||||
for (BatchedMaterial<?> material : materials.values()) {
|
||||
for (CPUInstancer<?> instancer : material.models.values()) {
|
||||
instancer.setup(context);
|
||||
|
||||
instancer.submitTasks(stack, pool, consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderSerial(PoseStack stack, VertexConsumer consumer, FormatContext context) {
|
||||
for (BatchedMaterial<?> value : materials.values()) {
|
||||
value.render(stack, consumer, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,12 +72,6 @@ public class BatchedMaterialGroup implements MaterialGroup {
|
|||
return total;
|
||||
}
|
||||
|
||||
private void renderInto(PoseStack stack, VertexConsumer consumer, FormatContext context) {
|
||||
for (BatchedMaterial<?> value : materials.values()) {
|
||||
value.render(stack, consumer, context);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
materials.values().forEach(BatchedMaterial::clear);
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ public class BatchingEngine implements Engine {
|
|||
}
|
||||
|
||||
stack.popPose();
|
||||
|
||||
event.buffers.bufferSource().endBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,7 +8,7 @@ import com.jozufozu.flywheel.api.struct.StructType;
|
|||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.model.DirectVertexConsumer;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
import com.jozufozu.flywheel.core.model.SuperByteBuffer;
|
||||
import com.jozufozu.flywheel.core.model.ModelTransformer;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
|
||||
|
@ -16,14 +16,14 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
|
||||
private final BatchingTransformer<D> transform;
|
||||
|
||||
private final SuperByteBuffer sbb;
|
||||
private final SuperByteBuffer.Params defaultParams;
|
||||
private final ModelTransformer sbb;
|
||||
private final ModelTransformer.Params defaultParams;
|
||||
|
||||
public CPUInstancer(StructType<D> type, Model modelData) {
|
||||
super(type, modelData);
|
||||
|
||||
sbb = new SuperByteBuffer(modelData);
|
||||
defaultParams = SuperByteBuffer.Params.defaultParams();
|
||||
sbb = new ModelTransformer(modelData);
|
||||
defaultParams = ModelTransformer.Params.defaultParams();
|
||||
transform = type.asBatched()
|
||||
.getTransformer();
|
||||
|
||||
|
@ -37,7 +37,7 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
|
||||
while (instances > 0) {
|
||||
int end = instances;
|
||||
instances -= 100;
|
||||
instances -= 512;
|
||||
int start = Math.max(instances, 0);
|
||||
|
||||
int verts = getModelVertexCount() * (end - start);
|
||||
|
@ -54,7 +54,7 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
}
|
||||
|
||||
private void drawRange(PoseStack stack, VertexConsumer buffer, int from, int to) {
|
||||
SuperByteBuffer.Params params = defaultParams.copy();
|
||||
ModelTransformer.Params params = defaultParams.copy();
|
||||
|
||||
for (D d : data.subList(from, to)) {
|
||||
transform.transform(d, params);
|
||||
|
@ -66,7 +66,7 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
}
|
||||
|
||||
void drawAll(PoseStack stack, VertexConsumer buffer) {
|
||||
SuperByteBuffer.Params params = defaultParams.copy();
|
||||
ModelTransformer.Params params = defaultParams.copy();
|
||||
for (D d : data) {
|
||||
transform.transform(d, params);
|
||||
|
||||
|
@ -77,18 +77,15 @@ public class CPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
}
|
||||
|
||||
void setup(FormatContext context) {
|
||||
renderSetup();
|
||||
|
||||
if (context.usesOverlay()) {
|
||||
defaultParams.entityMode();
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderSetup() {
|
||||
if (anyToRemove) {
|
||||
removeDeletedInstances();
|
||||
anyToRemove = false;
|
||||
}
|
||||
|
||||
anyToRemove = false;
|
||||
|
||||
if (context.usesOverlay()) {
|
||||
defaultParams.overlay();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.jozufozu.flywheel.backend.model;
|
||||
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
@ -22,8 +23,9 @@ public class DirectVertexConsumer implements VertexConsumer {
|
|||
private int uv2 = -1;
|
||||
|
||||
private long vertexBase;
|
||||
private final long end;
|
||||
|
||||
public DirectVertexConsumer(ByteBuffer buffer, VertexFormat format) {
|
||||
public DirectVertexConsumer(ByteBuffer buffer, VertexFormat format, int maxVertices) {
|
||||
this.format = format;
|
||||
startPos = buffer.position();
|
||||
stride = format.getVertexSize();
|
||||
|
@ -48,9 +50,10 @@ public class DirectVertexConsumer implements VertexConsumer {
|
|||
}
|
||||
|
||||
this.vertexBase = MemoryUtil.memAddress(buffer, startPos);
|
||||
this.end = vertexBase + (long) maxVertices * stride;
|
||||
}
|
||||
|
||||
private DirectVertexConsumer(DirectVertexConsumer parent) {
|
||||
private DirectVertexConsumer(DirectVertexConsumer parent, int maxVertices) {
|
||||
this.format = parent.format;
|
||||
this.stride = parent.stride;
|
||||
this.startPos = parent.startPos;
|
||||
|
@ -62,6 +65,7 @@ public class DirectVertexConsumer implements VertexConsumer {
|
|||
this.uv2 = parent.uv2;
|
||||
|
||||
this.vertexBase = parent.vertexBase;
|
||||
this.end = parent.vertexBase + (long) maxVertices * this.stride;
|
||||
}
|
||||
|
||||
public boolean hasOverlay() {
|
||||
|
@ -76,7 +80,7 @@ public class DirectVertexConsumer implements VertexConsumer {
|
|||
public DirectVertexConsumer split(int vertexCount) {
|
||||
int bytes = vertexCount * stride;
|
||||
|
||||
DirectVertexConsumer head = new DirectVertexConsumer(this);
|
||||
DirectVertexConsumer head = new DirectVertexConsumer(this, vertexCount);
|
||||
|
||||
this.vertexBase += bytes;
|
||||
|
||||
|
@ -85,6 +89,7 @@ public class DirectVertexConsumer implements VertexConsumer {
|
|||
|
||||
@Override
|
||||
public VertexConsumer vertex(double x, double y, double z) {
|
||||
checkOverflow();
|
||||
if (position < 0) return this;
|
||||
long base = vertexBase + position;
|
||||
MemoryUtil.memPutFloat(base, (float) x);
|
||||
|
@ -97,6 +102,8 @@ public class DirectVertexConsumer implements VertexConsumer {
|
|||
public VertexConsumer color(int r, int g, int b, int a) {
|
||||
if (color < 0) return this;
|
||||
long base = vertexBase + color;
|
||||
int color = ((r & 0xFF)) | ((g & 0xFF) << 8) | ((b & 0xFF) << 16) | ((a & 0xFF) << 24);
|
||||
//MemoryUtil.memPutInt(base, color);
|
||||
MemoryUtil.memPutByte(base, (byte) r);
|
||||
MemoryUtil.memPutByte(base + 1, (byte) g);
|
||||
MemoryUtil.memPutByte(base + 2, (byte) b);
|
||||
|
@ -155,4 +162,10 @@ public class DirectVertexConsumer implements VertexConsumer {
|
|||
public void unsetDefaultColor() {
|
||||
|
||||
}
|
||||
|
||||
private void checkOverflow() {
|
||||
if (vertexBase >= end) {
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
package com.jozufozu.flywheel.core.materials.model;
|
||||
|
||||
import com.jozufozu.flywheel.core.materials.BasicData;
|
||||
import com.jozufozu.flywheel.core.model.SuperByteBuffer;
|
||||
import com.jozufozu.flywheel.util.transform.Rotate;
|
||||
import com.jozufozu.flywheel.util.transform.Scale;
|
||||
import com.jozufozu.flywheel.util.transform.Transform;
|
||||
import com.jozufozu.flywheel.util.transform.Translate;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix3f;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
|
|
@ -6,28 +6,19 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
|||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.*;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2IntMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.client.model.pipeline.LightUtil;
|
||||
|
||||
public class SuperByteBuffer {
|
||||
public class ModelTransformer {
|
||||
|
||||
private final Model model;
|
||||
private final ModelReader template;
|
||||
private final ModelReader reader;
|
||||
|
||||
// Temporary
|
||||
private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap();
|
||||
|
||||
public SuperByteBuffer(Model model) {
|
||||
public ModelTransformer(Model model) {
|
||||
this.model = model;
|
||||
template = model.getReader();
|
||||
reader = model.getReader();
|
||||
}
|
||||
|
||||
public void renderInto(Params params, PoseStack input, VertexConsumer builder) {
|
||||
|
@ -36,7 +27,6 @@ public class SuperByteBuffer {
|
|||
|
||||
Vector4f pos = new Vector4f();
|
||||
Vector3f normal = new Vector3f();
|
||||
Vector4f lightPos = new Vector4f();
|
||||
|
||||
Matrix4f modelMat = input.last()
|
||||
.pose()
|
||||
|
@ -52,23 +42,18 @@ public class SuperByteBuffer {
|
|||
normalMat = params.normal.copy();
|
||||
}
|
||||
|
||||
if (params.useWorldLight) {
|
||||
WORLD_LIGHT_CACHE.clear();
|
||||
}
|
||||
|
||||
float f = .5f;
|
||||
int vertexCount = template.getVertexCount();
|
||||
int vertexCount = reader.getVertexCount();
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
float x = template.getX(i);
|
||||
float y = template.getY(i);
|
||||
float z = template.getZ(i);
|
||||
float x = reader.getX(i);
|
||||
float y = reader.getY(i);
|
||||
float z = reader.getZ(i);
|
||||
pos.set(x, y, z, 1F);
|
||||
pos.transform(modelMat);
|
||||
builder.vertex(pos.x(), pos.y(), pos.z());
|
||||
|
||||
float normalX = template.getNX(i);
|
||||
float normalY = template.getNY(i);
|
||||
float normalZ = template.getNZ(i);
|
||||
float normalX = reader.getNX(i);
|
||||
float normalY = reader.getNY(i);
|
||||
float normalZ = reader.getNZ(i);
|
||||
|
||||
normal.set(normalX, normalY, normalZ);
|
||||
normal.transform(normalMat);
|
||||
|
@ -80,13 +65,13 @@ public class SuperByteBuffer {
|
|||
float instanceDiffuse = LightUtil.diffuseLight(nx, ny, nz);
|
||||
|
||||
switch (params.colorMode) {
|
||||
case MODEL_ONLY -> builder.color(template.getR(i), template.getG(i), template.getB(i), template.getA(i));
|
||||
case MODEL_ONLY -> builder.color(reader.getR(i), reader.getG(i), reader.getB(i), reader.getA(i));
|
||||
case DIFFUSE_ONLY -> builder.color(instanceDiffuse, instanceDiffuse, instanceDiffuse, 1f);
|
||||
case MODEL_DIFFUSE -> {
|
||||
int r = Byte.toUnsignedInt(template.getR(i));
|
||||
int g = Byte.toUnsignedInt(template.getG(i));
|
||||
int b = Byte.toUnsignedInt(template.getB(i));
|
||||
int a = Byte.toUnsignedInt(template.getA(i));
|
||||
int r = Byte.toUnsignedInt(reader.getR(i));
|
||||
int g = Byte.toUnsignedInt(reader.getG(i));
|
||||
int b = Byte.toUnsignedInt(reader.getB(i));
|
||||
int a = Byte.toUnsignedInt(reader.getA(i));
|
||||
|
||||
float diffuse = switch (params.diffuseMode) {
|
||||
case NONE -> 1f;
|
||||
|
@ -118,8 +103,8 @@ public class SuperByteBuffer {
|
|||
//builder.color(Math.max(0, (int) (nx * 255)), Math.max(0, (int) (ny * 255)), Math.max(0, (int) (nz * 255)), 0xFF);
|
||||
//builder.color(Math.max(0, (int) (normalX * 255)), Math.max(0, (int) (normalY * 255)), Math.max(0, (int) (normalZ * 255)), 0xFF);
|
||||
|
||||
float u = template.getU(i);
|
||||
float v = template.getV(i);
|
||||
float u = reader.getU(i);
|
||||
float v = reader.getV(i);
|
||||
if (params.spriteShiftFunc != null) {
|
||||
params.spriteShiftFunc.shift(builder, u, v);
|
||||
} else {
|
||||
|
@ -130,29 +115,7 @@ public class SuperByteBuffer {
|
|||
builder.overlayCoords(params.overlay);
|
||||
}
|
||||
|
||||
int light;
|
||||
if (params.useWorldLight) {
|
||||
lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F);
|
||||
lightPos.transform(params.model);
|
||||
if (params.lightTransform != null) {
|
||||
lightPos.transform(params.lightTransform);
|
||||
}
|
||||
|
||||
light = getLight(Minecraft.getInstance().level, lightPos);
|
||||
if (params.hasCustomLight) {
|
||||
light = maxLight(light, params.packedLightCoords);
|
||||
}
|
||||
} else if (params.hasCustomLight) {
|
||||
light = params.packedLightCoords;
|
||||
} else {
|
||||
light = template.getLight(i);
|
||||
}
|
||||
|
||||
if (params.hybridLight) {
|
||||
builder.uv2(maxLight(light, template.getLight(i)));
|
||||
} else {
|
||||
builder.uv2(light);
|
||||
}
|
||||
builder.uv2(params.hasCustomLight ? params.packedLightCoords : reader.getLight(i));
|
||||
|
||||
builder.normal(nx, ny, nz);
|
||||
|
||||
|
@ -161,7 +124,7 @@ public class SuperByteBuffer {
|
|||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return template.isEmpty();
|
||||
return reader.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -173,19 +136,6 @@ public class SuperByteBuffer {
|
|||
return Mth.clamp((int) (component * scale), 0, 255);
|
||||
}
|
||||
|
||||
public static int maxLight(int packedLight1, int packedLight2) {
|
||||
int blockLight1 = LightTexture.block(packedLight1);
|
||||
int skyLight1 = LightTexture.sky(packedLight1);
|
||||
int blockLight2 = LightTexture.block(packedLight2);
|
||||
int skyLight2 = LightTexture.sky(packedLight2);
|
||||
return LightTexture.pack(Math.max(blockLight1, blockLight2), Math.max(skyLight1, skyLight2));
|
||||
}
|
||||
|
||||
private static int getLight(Level world, Vector4f lightPos) {
|
||||
BlockPos pos = new BlockPos(lightPos.x(), lightPos.y(), lightPos.z());
|
||||
return WORLD_LIGHT_CACHE.computeIfAbsent(pos.asLong(), $ -> LevelRenderer.getLightColor(world, pos));
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SpriteShiftFunc {
|
||||
void shift(VertexConsumer builder, float u, float v);
|
||||
|
@ -207,12 +157,12 @@ public class SuperByteBuffer {
|
|||
|
||||
public static class Params implements Transform<Params> {
|
||||
// Vertex Position
|
||||
public final Matrix4f model = new Matrix4f();
|
||||
public final Matrix3f normal = new Matrix3f();
|
||||
public final Matrix4f model;
|
||||
public final Matrix3f normal;
|
||||
|
||||
// Vertex Coloring
|
||||
public ColorMode colorMode = ColorMode.DIFFUSE_ONLY;
|
||||
public DiffuseMode diffuseMode = DiffuseMode.INSTANCE;
|
||||
public ColorMode colorMode;
|
||||
public DiffuseMode diffuseMode;
|
||||
public int r;
|
||||
public int g;
|
||||
public int b;
|
||||
|
@ -223,18 +173,20 @@ public class SuperByteBuffer {
|
|||
|
||||
// Vertex Overlay Color
|
||||
public boolean hasOverlay;
|
||||
public int overlay = OverlayTexture.NO_OVERLAY;
|
||||
public int overlay;
|
||||
|
||||
// Vertex Lighting
|
||||
public boolean useWorldLight;
|
||||
public Matrix4f lightTransform;
|
||||
public boolean hasCustomLight;
|
||||
public int packedLightCoords;
|
||||
public boolean hybridLight;
|
||||
|
||||
// Vertex Normals
|
||||
public boolean fullNormalTransform;
|
||||
|
||||
public Params() {
|
||||
model = new Matrix4f();
|
||||
normal = new Matrix3f();
|
||||
}
|
||||
|
||||
public void load(Params from) {
|
||||
model.load(from.model);
|
||||
normal.load(from.normal);
|
||||
|
@ -247,11 +199,8 @@ public class SuperByteBuffer {
|
|||
spriteShiftFunc = from.spriteShiftFunc;
|
||||
hasOverlay = from.hasOverlay;
|
||||
overlay = from.overlay;
|
||||
useWorldLight = from.useWorldLight;
|
||||
lightTransform = from.lightTransform;
|
||||
hasCustomLight = from.hasCustomLight;
|
||||
packedLightCoords = from.packedLightCoords;
|
||||
hybridLight = from.hybridLight;
|
||||
fullNormalTransform = from.fullNormalTransform;
|
||||
}
|
||||
|
||||
|
@ -307,23 +256,11 @@ public class SuperByteBuffer {
|
|||
/**
|
||||
* Transforms normals not only by the local matrix stack, but also by the passed matrix stack.
|
||||
*/
|
||||
public Params entityMode() {
|
||||
public void entityMode() {
|
||||
this.hasOverlay = true;
|
||||
this.fullNormalTransform = true;
|
||||
this.diffuseMode = DiffuseMode.NONE;
|
||||
this.colorMode = ColorMode.RECOLOR;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Params light() {
|
||||
this.useWorldLight = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Params light(Matrix4f lightTransform) {
|
||||
this.useWorldLight = true;
|
||||
this.lightTransform = lightTransform;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Params light(int packedLightCoords) {
|
||||
|
@ -332,24 +269,10 @@ public class SuperByteBuffer {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Params light(Matrix4f lightTransform, int packedLightCoords) {
|
||||
light(lightTransform);
|
||||
light(packedLightCoords);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses max light from calculated light (world light or custom light) and vertex light for the final light value.
|
||||
* Ineffective if any other light method was not called.
|
||||
*/
|
||||
public Params hybridLight() {
|
||||
hybridLight = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Params multiply(Quaternion quaternion) {
|
||||
model.multiply(quaternion);
|
||||
normal.mul(quaternion);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -404,11 +327,8 @@ public class SuperByteBuffer {
|
|||
out.spriteShiftFunc = null;
|
||||
out.hasOverlay = false;
|
||||
out.overlay = OverlayTexture.NO_OVERLAY;
|
||||
out.useWorldLight = false;
|
||||
out.lightTransform = null;
|
||||
out.hasCustomLight = false;
|
||||
out.packedLightCoords = 0;
|
||||
out.hybridLight = false;
|
||||
out.packedLightCoords = LightTexture.FULL_BRIGHT;
|
||||
out.fullNormalTransform = false;
|
||||
return out;
|
||||
}
|
|
@ -42,7 +42,7 @@ public abstract class BufferBuilderMixin implements DirectBufferBuilder {
|
|||
int bytes = vertexCount * format.getVertexSize();
|
||||
ensureCapacity(bytes);
|
||||
|
||||
DirectVertexConsumer consumer = new DirectVertexConsumer(this.buffer, this.format);
|
||||
DirectVertexConsumer consumer = new DirectVertexConsumer(this.buffer, this.format, vertexCount);
|
||||
|
||||
this.vertices += vertexCount;
|
||||
this.currentElement = format.getElements()
|
||||
|
|
|
@ -60,10 +60,6 @@ public class RenderHooksMixin {
|
|||
RenderBuffers renderBuffers = this.renderBuffers;
|
||||
|
||||
MinecraftForge.EVENT_BUS.post(new RenderLayerEvent(level, type, stack, renderBuffers, camX, camY, camZ));
|
||||
|
||||
if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0);
|
||||
|
||||
renderBuffers.bufferSource().endBatch(type);
|
||||
}
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "allChanged")
|
||||
|
@ -84,8 +80,6 @@ public class RenderHooksMixin {
|
|||
Vec3 cameraPos = info.getPosition();
|
||||
|
||||
CrumblingRenderer.renderBreaking(new RenderLayerEvent(level, null, stack, null, cameraPos.x, cameraPos.y, cameraPos.z));
|
||||
|
||||
if (!OptifineHandler.usingShaders()) GL20.glUseProgram(0);
|
||||
}
|
||||
|
||||
// Instancing
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
|
||||
@Mixin(ShaderInstance.class)
|
||||
public interface ShaderInstanceAccessor {
|
||||
@Accessor("lastProgramId")
|
||||
static void setLastProgramId(int id) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
|
@ -1,219 +0,0 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||
import com.mojang.math.Vector3f;
|
||||
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
|
||||
public class BakedQuadWrapper {
|
||||
private final FormatCache formatCache = new FormatCache();
|
||||
private BakedQuad quad;
|
||||
private int[] vertexData;
|
||||
|
||||
public BakedQuadWrapper() {
|
||||
}
|
||||
|
||||
public BakedQuadWrapper(BakedQuad quad) {
|
||||
this.quad = quad;
|
||||
this.vertexData = quad.getVertices();
|
||||
}
|
||||
|
||||
public void setQuad(BakedQuad quad) {
|
||||
this.quad = quad;
|
||||
this.vertexData = this.quad.getVertices();
|
||||
}
|
||||
|
||||
public static BakedQuadWrapper of(BakedQuad quad) {
|
||||
return new BakedQuadWrapper(quad);
|
||||
}
|
||||
|
||||
public void refreshFormat() {
|
||||
formatCache.refresh();
|
||||
}
|
||||
|
||||
public BakedQuad getQuad() {
|
||||
return quad;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
quad = null;
|
||||
vertexData = null;
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
public float getPosX(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.position]);
|
||||
}
|
||||
|
||||
public float getPosY(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.position + 1]);
|
||||
}
|
||||
|
||||
public float getPosZ(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.position + 2]);
|
||||
}
|
||||
|
||||
public Vector3f getPos(int vertexIndex) {
|
||||
return new Vector3f(getPosX(vertexIndex), getPosY(vertexIndex), getPosZ(vertexIndex));
|
||||
}
|
||||
|
||||
public void copyPos(int vertexIndex, Vector3f pos) {
|
||||
pos.set(getPosX(vertexIndex), getPosY(vertexIndex), getPosZ(vertexIndex));
|
||||
}
|
||||
|
||||
public int getColor(int vertexIndex) {
|
||||
return vertexData[vertexIndex * formatCache.vertexSize + formatCache.color];
|
||||
}
|
||||
|
||||
public float getTexU(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.texture]);
|
||||
}
|
||||
|
||||
public float getTexV(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.texture + 1]);
|
||||
}
|
||||
|
||||
public Vec2 getTex(int vertexIndex) {
|
||||
return new Vec2(getTexU(vertexIndex), getTexV(vertexIndex));
|
||||
}
|
||||
|
||||
public int getLight(int vertexIndex) {
|
||||
return vertexData[vertexIndex * formatCache.vertexSize + formatCache.light];
|
||||
}
|
||||
|
||||
public float getNormalX(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.normal]);
|
||||
}
|
||||
|
||||
public float getNormalY(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.normal + 1]);
|
||||
}
|
||||
|
||||
public float getNormalZ(int vertexIndex) {
|
||||
return Float.intBitsToFloat(vertexData[vertexIndex * formatCache.vertexSize + formatCache.normal + 2]);
|
||||
}
|
||||
|
||||
public Vector3f getNormal(int vertexIndex) {
|
||||
return new Vector3f(getNormalX(vertexIndex), getNormalY(vertexIndex), getNormalZ(vertexIndex));
|
||||
}
|
||||
|
||||
public void copyNormal(int vertexIndex, Vector3f normal) {
|
||||
normal.set(getNormalX(vertexIndex), getNormalY(vertexIndex), getNormalZ(vertexIndex));
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
public void setPosX(int vertexIndex, float x) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.position] = Float.floatToRawIntBits(x);
|
||||
}
|
||||
|
||||
public void setPosY(int vertexIndex, float y) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.position + 1] = Float.floatToRawIntBits(y);
|
||||
}
|
||||
|
||||
public void setPosZ(int vertexIndex, float z) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.position + 2] = Float.floatToRawIntBits(z);
|
||||
}
|
||||
|
||||
public void setPos(int vertexIndex, float x, float y, float z) {
|
||||
setPosX(vertexIndex, x);
|
||||
setPosY(vertexIndex, y);
|
||||
setPosZ(vertexIndex, z);
|
||||
}
|
||||
|
||||
public void setPos(int vertexIndex, Vector3f pos) {
|
||||
setPos(vertexIndex, pos.x(), pos.y(), pos.z());
|
||||
}
|
||||
|
||||
public void setColor(int vertexIndex, int color) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.color] = color;
|
||||
}
|
||||
|
||||
public void setTexU(int vertexIndex, float u) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.texture] = Float.floatToRawIntBits(u);
|
||||
}
|
||||
|
||||
public void setTexV(int vertexIndex, float v) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.texture + 1] = Float.floatToRawIntBits(v);
|
||||
}
|
||||
|
||||
public void setTex(int vertexIndex, float u, float v) {
|
||||
setTexU(vertexIndex, u);
|
||||
setTexV(vertexIndex, v);
|
||||
}
|
||||
|
||||
public void setTex(int vertexIndex, Vec2 tex) {
|
||||
setTex(vertexIndex, tex.x, tex.y);
|
||||
}
|
||||
|
||||
public void setLight(int vertexIndex, int light) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.light] = light;
|
||||
}
|
||||
|
||||
public void setNormalX(int vertexIndex, float normalX) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.normal] = Float.floatToRawIntBits(normalX);
|
||||
}
|
||||
|
||||
public void setNormalY(int vertexIndex, float normalY) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.normal + 1] = Float.floatToRawIntBits(normalY);
|
||||
}
|
||||
|
||||
public void setNormalZ(int vertexIndex, float normalZ) {
|
||||
vertexData[vertexIndex * formatCache.vertexSize + formatCache.normal + 2] = Float.floatToRawIntBits(normalZ);
|
||||
}
|
||||
|
||||
public void setNormal(int vertexIndex, float normalX, float normalY, float normalZ) {
|
||||
setNormalX(vertexIndex, normalX);
|
||||
setNormalY(vertexIndex, normalY);
|
||||
setNormalZ(vertexIndex, normalZ);
|
||||
}
|
||||
|
||||
public void setNormal(int vertexIndex, Vector3f normal) {
|
||||
setNormal(vertexIndex, normal.x(), normal.y(), normal.z());
|
||||
}
|
||||
|
||||
private static class FormatCache {
|
||||
private static final VertexFormat FORMAT = DefaultVertexFormat.BLOCK;
|
||||
|
||||
public FormatCache() {
|
||||
refresh();
|
||||
}
|
||||
|
||||
// Integer size
|
||||
public int vertexSize;
|
||||
|
||||
// Element integer offsets
|
||||
public int position;
|
||||
public int color;
|
||||
public int texture;
|
||||
public int light;
|
||||
public int normal;
|
||||
|
||||
public void refresh() {
|
||||
vertexSize = FORMAT.getIntegerSize();
|
||||
for (int elementId = 0; elementId < FORMAT.getElements()
|
||||
.size(); elementId++) {
|
||||
VertexFormatElement element = FORMAT.getElements()
|
||||
.get(elementId);
|
||||
int intOffset = FORMAT.getOffset(elementId) / Integer.BYTES;
|
||||
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
|
||||
position = intOffset;
|
||||
} else if (element.getUsage() == VertexFormatElement.Usage.COLOR) {
|
||||
color = intOffset;
|
||||
} else if (element.getUsage() == VertexFormatElement.Usage.UV) {
|
||||
if (element.getIndex() == 0) {
|
||||
texture = intOffset;
|
||||
} else if (element.getIndex() == 2) {
|
||||
light = intOffset;
|
||||
}
|
||||
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
|
||||
normal = intOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
|
||||
public class ChunkUtil {
|
||||
|
||||
public static boolean isValidSection(@Nullable LevelChunk chunk, int sectionY) {
|
||||
if (chunk == null) return false;
|
||||
|
||||
// TODO: 1.17
|
||||
LevelChunkSection[] sections = chunk.getSections();
|
||||
|
||||
return sectionY >= 0 && sectionY < sections.length;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.jozufozu.flywheel.util.transform;
|
||||
|
||||
import com.jozufozu.flywheel.core.model.SuperByteBuffer;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix3f;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"RenderHooksMixin",
|
||||
"RenderTexturesMixin",
|
||||
"ShaderCloseMixin",
|
||||
"ShaderInstanceAccessor",
|
||||
"atlas.AtlasDataMixin",
|
||||
"atlas.SheetDataAccessor",
|
||||
"light.LightUpdateMixin",
|
||||
|
|
Loading…
Reference in a new issue