Simplify SBB

- SBB -> ModelTransformer
 - Shader binding the minecraft way
 - Engines are responsible for ending batches
This commit is contained in:
Jozufozu 2021-12-16 23:10:24 -08:00
parent a668a7c7ac
commit 3049601e4a
15 changed files with 112 additions and 404 deletions

View file

@ -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);
}

View file

@ -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);
}
/**

View file

@ -35,7 +35,15 @@ public class BatchedMaterialGroup implements MaterialGroup {
VertexConsumer buffer = source.getBuffer(state);
if (buffer instanceof DirectBufferBuilder direct) {
DirectVertexConsumer consumer = direct.intoDirectConsumer(calculateNeededVertices());
renderParallel(stack, pool, direct);
} else {
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()) {
@ -45,8 +53,11 @@ public class BatchedMaterialGroup implements MaterialGroup {
instancer.submitTasks(stack, pool, consumer);
}
}
} else {
renderInto(stack, buffer, FormatContext.defaultContext());
}
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);
}

View file

@ -65,6 +65,8 @@ public class BatchingEngine implements Engine {
}
stack.popPose();
event.buffers.bufferSource().endBatch();
}
@Override

View file

@ -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;
}
if (context.usesOverlay()) {
defaultParams.overlay();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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()

View file

@ -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

View file

@ -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();
}
}

View file

@ -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;
}
}
}
}
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -16,6 +16,7 @@
"RenderHooksMixin",
"RenderTexturesMixin",
"ShaderCloseMixin",
"ShaderInstanceAccessor",
"atlas.AtlasDataMixin",
"atlas.SheetDataAccessor",
"light.LightUpdateMixin",