mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
Merge remote-tracking branch 'origin/1.18/dev' into 1.18/fabric/dev
Conflicts: src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertex.java src/main/java/com/jozufozu/flywheel/core/vertex/BlockVertexList.java src/main/java/com/jozufozu/flywheel/util/RenderMath.java
This commit is contained in:
commit
f5b15f3dff
22 changed files with 456 additions and 130 deletions
|
@ -0,0 +1,5 @@
|
|||
package com.jozufozu.flywheel.api.vertex;
|
||||
|
||||
public interface ShadedVertexList extends VertexList {
|
||||
boolean isShaded(int index);
|
||||
}
|
|
@ -44,7 +44,7 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
|||
.onAMDWindows()) {
|
||||
this.allocator = FallbackAllocator.INSTANCE;
|
||||
} else {
|
||||
this.allocator = new ModelPool(Formats.POS_TEX_NORMAL, 2048);
|
||||
this.allocator = new ModelPool(Formats.POS_TEX_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ import com.mojang.blaze3d.vertex.VertexFormat;
|
|||
*/
|
||||
public interface BufferBuilderExtension {
|
||||
|
||||
int flywheel$getVertices();
|
||||
|
||||
/**
|
||||
* Frees the internal ByteBuffer, if it exists.
|
||||
*/
|
||||
|
@ -24,4 +26,12 @@ public interface BufferBuilderExtension {
|
|||
* @param vertexCount The number of vertices in the buffer.
|
||||
*/
|
||||
void flywheel$injectForRender(ByteBuffer buffer, VertexFormat format, int vertexCount);
|
||||
|
||||
/**
|
||||
* Appends the remaining bytes from the given buffer to this BufferBuilder.
|
||||
* @param buffer The buffer from which to copy bytes.
|
||||
* @throws IllegalStateException If this BufferBuilder is not started or is the process of writing a vertex
|
||||
* @throws IllegalArgumentException If the given buffer does not contain a whole number of vertices
|
||||
*/
|
||||
void flywheel$appendBufferUnsafe(ByteBuffer buffer);
|
||||
}
|
||||
|
|
|
@ -35,16 +35,14 @@ public class ModelPool implements ModelAllocator {
|
|||
* Create a new model pool.
|
||||
*
|
||||
* @param vertexType The vertex type of the models that will be stored in the pool.
|
||||
* @param initialSize The initial size of the pool, in vertices.
|
||||
*/
|
||||
public ModelPool(VertexType vertexType, int initialSize) {
|
||||
public ModelPool(VertexType vertexType) {
|
||||
this.vertexType = vertexType;
|
||||
int stride = vertexType.getStride();
|
||||
|
||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
|
||||
vbo.bind();
|
||||
vbo.ensureCapacity((long) stride * initialSize);
|
||||
vbo.setGrowthMargin(stride * 64);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.core.compile.FragmentTemplateData;
|
||||
import com.jozufozu.flywheel.core.compile.InstancingTemplateData;
|
||||
import com.jozufozu.flywheel.core.compile.OneShotTemplateData;
|
||||
import com.jozufozu.flywheel.core.compile.Template;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.Resolver;
|
||||
|
||||
public class Templates {
|
||||
|
||||
public static final FileResolution DIFFUSE_FILE = Resolver.INSTANCE.get(Flywheel.rl("core/diffuse.glsl"));
|
||||
|
||||
public static final Template<InstancingTemplateData> INSTANCING = new Template<>(GLSLVersion.V330, InstancingTemplateData::new);
|
||||
public static final Template<OneShotTemplateData> ONE_SHOT = new Template<>(GLSLVersion.V150, OneShotTemplateData::new);
|
||||
public static final Template<FragmentTemplateData> FRAGMENT = new Template<>(GLSLVersion.V150, FragmentTemplateData::new);
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Objects;
|
|||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||
import com.jozufozu.flywheel.core.Templates;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
import com.jozufozu.flywheel.core.source.FileIndexImpl;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
|
@ -40,6 +41,7 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
|||
|
||||
FileIndexImpl index = new FileIndexImpl();
|
||||
|
||||
Templates.DIFFUSE_FILE.getFile().generateFinalSource(index, finalSource);
|
||||
header.getFile().generateFinalSource(index, finalSource);
|
||||
|
||||
key.file.generateFinalSource(index, finalSource);
|
||||
|
|
|
@ -16,7 +16,7 @@ import com.jozufozu.flywheel.core.QuadConverter;
|
|||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* IModel model = ...;
|
||||
* Model model = ...;
|
||||
* VecBuffer into = ...;
|
||||
*
|
||||
* int initial = VecBuffer.unwrap().position();
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.util.function.IntPredicate;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.util.DiffuseLightCalculator;
|
||||
import com.jozufozu.flywheel.util.transform.Transform;
|
||||
|
@ -19,12 +22,18 @@ public class ModelTransformer {
|
|||
|
||||
private final Model model;
|
||||
private final VertexList reader;
|
||||
private final IntPredicate shadedPredicate;
|
||||
|
||||
public final Context context = new Context();
|
||||
|
||||
public ModelTransformer(Model model) {
|
||||
this.model = model;
|
||||
reader = model.getReader();
|
||||
if (reader instanceof ShadedVertexList shaded) {
|
||||
shadedPredicate = shaded::isShaded;
|
||||
} else {
|
||||
shadedPredicate = index -> true;
|
||||
}
|
||||
}
|
||||
|
||||
public void renderInto(Params params, PoseStack input, VertexConsumer builder) {
|
||||
|
@ -82,7 +91,7 @@ public class ModelTransformer {
|
|||
a = reader.getA(i);
|
||||
}
|
||||
if (context.outputColorDiffuse) {
|
||||
float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz);
|
||||
float instanceDiffuse = diffuseCalculator.getDiffuse(nx, ny, nz, shadedPredicate.test(i));
|
||||
int colorR = transformColor(r, instanceDiffuse);
|
||||
int colorG = transformColor(g, instanceDiffuse);
|
||||
int colorB = transformColor(b, instanceDiffuse);
|
||||
|
|
|
@ -30,25 +30,53 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
|
||||
public class ModelUtil {
|
||||
public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) {
|
||||
|
||||
private static final ThreadLocal<ThreadLocalObjects> THREAD_LOCAL_OBJECTS = ThreadLocal.withInitial(ThreadLocalObjects::new);
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||
return getBufferBuilder(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, poseStack);
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilder(BlockAndTintGetter renderWorld, BakedModel model, BlockState referenceState, PoseStack poseStack) {
|
||||
ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer();
|
||||
BufferBuilder builder = new BufferBuilder(512);
|
||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||
|
||||
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
||||
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512);
|
||||
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
|
||||
|
||||
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
shadeSeparatingWrapper.prepare(builder, unshadedBuilder);
|
||||
model = DefaultLayerFilteringBakedModel.wrap(model);
|
||||
blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder,
|
||||
false, new Random(), 42, OverlayTexture.NO_OVERLAY);
|
||||
model = shadeSeparatingWrapper.wrapModel(model);
|
||||
blockRenderer.tesselateBlock(renderWorld, model, referenceState, BlockPos.ZERO, poseStack, shadeSeparatingWrapper,
|
||||
false, objects.random, 42, OverlayTexture.NO_OVERLAY);
|
||||
shadeSeparatingWrapper.clear();
|
||||
unshadedBuilder.end();
|
||||
builder.appendUnshadedVertices(unshadedBuilder);
|
||||
builder.end();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static BufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
||||
BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer();
|
||||
ModelBlockRenderer modelRenderer = dispatcher.getModelRenderer();
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
||||
return getBufferBuilderFromTemplate(renderWorld, layer, blocks, new PoseStack());
|
||||
}
|
||||
|
||||
public static ShadeSeparatedBufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, PoseStack poseStack) {
|
||||
BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer();
|
||||
ModelBlockRenderer modelRenderer = dispatcher.getModelRenderer();
|
||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||
|
||||
Random random = objects.random;
|
||||
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
||||
ShadeSeparatedBufferBuilder builder = new ShadeSeparatedBufferBuilder(512);
|
||||
BufferBuilder unshadedBuilder = objects.unshadedBuilder;
|
||||
|
||||
PoseStack ms = new PoseStack();
|
||||
Random random = new Random();
|
||||
BufferBuilder builder = new BufferBuilder(512);
|
||||
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
unshadedBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
shadeSeparatingWrapper.prepare(builder, unshadedBuilder);
|
||||
|
||||
ModelBlockRenderer.enableCaching();
|
||||
for (StructureTemplate.StructureBlockInfo info : blocks) {
|
||||
|
@ -65,19 +93,24 @@ public class ModelUtil {
|
|||
} else {
|
||||
model = CullingBakedModel.wrap(model);
|
||||
model = LayerFilteringBakedModel.wrap(model, layer);
|
||||
model = shadeSeparatingWrapper.wrapModel(model);
|
||||
}
|
||||
|
||||
BlockPos pos = info.pos;
|
||||
|
||||
ms.pushPose();
|
||||
ms.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||
modelRenderer.tesselateBlock(renderWorld, model, state, pos, ms, builder,
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||
modelRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper,
|
||||
true, random, 42, OverlayTexture.NO_OVERLAY);
|
||||
ms.popPose();
|
||||
poseStack.popPose();
|
||||
}
|
||||
ModelBlockRenderer.clearCache();
|
||||
|
||||
shadeSeparatingWrapper.clear();
|
||||
unshadedBuilder.end();
|
||||
builder.appendUnshadedVertices(unshadedBuilder);
|
||||
builder.end();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
@ -91,4 +124,10 @@ public class ModelUtil {
|
|||
return stack;
|
||||
};
|
||||
}
|
||||
|
||||
private static class ThreadLocalObjects {
|
||||
public final Random random = new Random();
|
||||
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
||||
public final BufferBuilder unshadedBuilder = new BufferBuilder(512);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.backend.model.BufferBuilderExtension;
|
||||
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
public class ShadeSeparatedBufferBuilder extends BufferBuilder {
|
||||
protected int unshadedStartVertex;
|
||||
|
||||
public ShadeSeparatedBufferBuilder(int capacity) {
|
||||
super(capacity);
|
||||
}
|
||||
|
||||
public void appendUnshadedVertices(BufferBuilder unshadedBuilder) {
|
||||
Pair<DrawState, ByteBuffer> data = unshadedBuilder.popNextBuffer();
|
||||
ByteBuffer buffer = data.getSecond();
|
||||
BufferBuilderHelper.fixByteOrder(unshadedBuilder, buffer);
|
||||
unshadedStartVertex = ((BufferBuilderExtension) this).flywheel$getVertices();
|
||||
((BufferBuilderExtension) this).flywheel$appendBufferUnsafe(buffer);
|
||||
}
|
||||
|
||||
public int getUnshadedStartVertex() {
|
||||
return unshadedStartVertex;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.jozufozu.flywheel.fabric.model.FabricModelUtil;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
|
||||
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
|
||||
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext.QuadTransform;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class ShadeSeparatingVertexConsumer implements VertexConsumer {
|
||||
private final ShadeSeparatingBakedModel modelWrapper = new ShadeSeparatingBakedModel();
|
||||
protected VertexConsumer shadedConsumer;
|
||||
protected VertexConsumer unshadedConsumer;
|
||||
protected VertexConsumer activeConsumer;
|
||||
|
||||
public void prepare(VertexConsumer shadedConsumer, VertexConsumer unshadedConsumer) {
|
||||
this.shadedConsumer = shadedConsumer;
|
||||
this.unshadedConsumer = unshadedConsumer;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
shadedConsumer = null;
|
||||
unshadedConsumer = null;
|
||||
activeConsumer = null;
|
||||
}
|
||||
|
||||
public BakedModel wrapModel(BakedModel model) {
|
||||
modelWrapper.setWrapped(model);
|
||||
return modelWrapper;
|
||||
}
|
||||
|
||||
protected void setActiveConsumer(boolean shaded) {
|
||||
activeConsumer = shaded ? shadedConsumer : unshadedConsumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBulkData(PoseStack.Pose poseEntry, BakedQuad quad, float[] colorMuls, float red, float green, float blue, int[] combinedLights, int combinedOverlay, boolean mulColor) {
|
||||
if (quad.isShade()) {
|
||||
shadedConsumer.putBulkData(poseEntry, quad, colorMuls, red, green, blue, combinedLights, combinedOverlay, mulColor);
|
||||
} else {
|
||||
unshadedConsumer.putBulkData(poseEntry, quad, colorMuls, red, green, blue, combinedLights, combinedOverlay, mulColor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer vertex(double x, double y, double z) {
|
||||
activeConsumer.vertex(x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer color(int red, int green, int blue, int alpha) {
|
||||
activeConsumer.color(red, green, blue, alpha);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer uv(float u, float v) {
|
||||
activeConsumer.uv(u, v);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer overlayCoords(int u, int v) {
|
||||
activeConsumer.overlayCoords(u, v);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer uv2(int u, int v) {
|
||||
activeConsumer.uv2(u, v);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexConsumer normal(float x, float y, float z) {
|
||||
activeConsumer.normal(x, y, z);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVertex() {
|
||||
activeConsumer.endVertex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defaultColor(int red, int green, int blue, int alpha) {
|
||||
activeConsumer.defaultColor(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetDefaultColor() {
|
||||
activeConsumer.unsetDefaultColor();
|
||||
}
|
||||
|
||||
private class ShadeSeparatingBakedModel extends ForwardingBakedModel {
|
||||
private final QuadTransform quadTransform = quad -> {
|
||||
ShadeSeparatingVertexConsumer.this.setActiveConsumer(FabricModelUtil.isShaded(quad));
|
||||
return true;
|
||||
};
|
||||
|
||||
private void setWrapped(BakedModel model) {
|
||||
wrapped = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emitBlockQuads(BlockAndTintGetter blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
|
||||
context.pushTransform(quadTransform);
|
||||
super.emitBlockQuads(blockView, state, pos, randomSupplier, context);
|
||||
context.popTransform();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import com.jozufozu.flywheel.api.vertex.VertexList;
|
|||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
|
||||
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
|
@ -58,6 +59,10 @@ Vertex FLWCreateVertex() {
|
|||
""";
|
||||
}
|
||||
|
||||
public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
|
||||
return new BlockVertexListUnsafe.Shaded(buffer, vertexCount, unshadedStartVertex);
|
||||
}
|
||||
|
||||
public VertexList createReader(BufferBuilder bufferBuilder) {
|
||||
// TODO: try to avoid virtual model rendering
|
||||
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
|
||||
|
@ -69,6 +74,10 @@ Vertex FLWCreateVertex() {
|
|||
|
||||
ByteBuffer buffer = pair.getSecond();
|
||||
BufferBuilderHelper.fixByteOrder(bufferBuilder, buffer);
|
||||
return new BlockVertexListUnsafe(buffer, drawState.vertexCount());
|
||||
if (bufferBuilder instanceof ShadeSeparatedBufferBuilder separated) {
|
||||
return createReader(buffer, drawState.vertexCount(), separated.getUnshadedStartVertex());
|
||||
} else {
|
||||
return createReader(buffer, drawState.vertexCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ package com.jozufozu.flywheel.core.vertex;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
|
||||
import com.jozufozu.flywheel.fabric.helper.BufferBuilderHelper;
|
||||
import com.jozufozu.flywheel.util.RenderMath;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
|
@ -106,4 +108,20 @@ public class BlockVertexList implements VertexList {
|
|||
return vertexCount;
|
||||
}
|
||||
|
||||
public static class Shaded extends BlockVertexList implements ShadedVertexList {
|
||||
|
||||
private final int unshadedStartVertex;
|
||||
|
||||
public Shaded(ShadeSeparatedBufferBuilder builder) {
|
||||
super(builder);
|
||||
unshadedStartVertex = builder.getUnshadedStartVertex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShaded(int index) {
|
||||
return index < unshadedStartVertex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.ShadedVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.util.RenderMath;
|
||||
|
||||
|
@ -97,4 +98,21 @@ public class BlockVertexListUnsafe implements VertexList {
|
|||
public int getVertexCount() {
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
public static class Shaded extends BlockVertexListUnsafe implements ShadedVertexList {
|
||||
|
||||
private final int unshadedStartVertex;
|
||||
|
||||
public Shaded(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
|
||||
super(buffer, vertexCount);
|
||||
this.unshadedStartVertex = unshadedStartVertex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShaded(int index) {
|
||||
return index < unshadedStartVertex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,115 +22,119 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
|
|||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
|
||||
public enum VirtualEmptyBlockGetter implements BlockAndTintGetter {
|
||||
INSTANCE;
|
||||
|
||||
private final LevelLightEngine lightEngine = new LevelLightEngine(new LightChunkGetter() {
|
||||
@Override
|
||||
public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) {
|
||||
return VirtualEmptyBlockGetter.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockGetter getLevel() {
|
||||
return VirtualEmptyBlockGetter.this;
|
||||
}
|
||||
}, false, false) {
|
||||
private static final LayerLightEventListener SKY_DUMMY_LISTENER = new LayerLightEventListener() {
|
||||
@Override
|
||||
public void checkBlock(BlockPos pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLightWork() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) {
|
||||
return p_164449_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSectionStatus(SectionPos pos, boolean p_75838_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableLightSources(ChunkPos pos, boolean p_164453_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataLayer getDataLayerData(SectionPos pos) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightValue(BlockPos pos) {
|
||||
return 15;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public LayerLightEventListener getLayerListener(LightLayer layer) {
|
||||
if (layer == LightLayer.BLOCK) {
|
||||
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
|
||||
} else {
|
||||
return SKY_DUMMY_LISTENER;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRawBrightness(BlockPos pos, int skyDarken) {
|
||||
return 15 - skyDarken;
|
||||
}
|
||||
};
|
||||
public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
||||
public static final VirtualEmptyBlockGetter INSTANCE = new StaticLightImpl(0, 15);
|
||||
public static final VirtualEmptyBlockGetter FULL_BRIGHT = new StaticLightImpl(15, 15);
|
||||
public static final VirtualEmptyBlockGetter FULL_DARK = new StaticLightImpl(0, 0);
|
||||
|
||||
public static boolean is(BlockAndTintGetter blockGetter) {
|
||||
return blockGetter == INSTANCE;
|
||||
return blockGetter instanceof VirtualEmptyBlockGetter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||
default BlockEntity getBlockEntity(BlockPos pos) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
default BlockState getBlockState(BlockPos pos) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
default FluidState getFluidState(BlockPos pos) {
|
||||
return Fluids.EMPTY.defaultFluidState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
default int getHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBuildHeight() {
|
||||
default int getMinBuildHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getShade(Direction direction, boolean bool) {
|
||||
default float getShade(Direction direction, boolean shaded) {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelLightEngine getLightEngine() {
|
||||
return lightEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockTint(BlockPos pos, ColorResolver resolver) {
|
||||
default int getBlockTint(BlockPos pos, ColorResolver resolver) {
|
||||
Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getOrThrow(Biomes.PLAINS);
|
||||
return resolver.getColor(plainsBiome, pos.getX(), pos.getZ());
|
||||
}
|
||||
|
||||
public static class StaticLightImpl implements VirtualEmptyBlockGetter {
|
||||
private final LevelLightEngine lightEngine;
|
||||
|
||||
public StaticLightImpl(int blockLight, int skyLight) {
|
||||
lightEngine = new LevelLightEngine(new LightChunkGetter() {
|
||||
@Override
|
||||
public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) {
|
||||
return StaticLightImpl.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockGetter getLevel() {
|
||||
return StaticLightImpl.this;
|
||||
}
|
||||
}, false, false) {
|
||||
private final LayerLightEventListener blockListener = createStaticListener(blockLight);
|
||||
private final LayerLightEventListener skyListener = createStaticListener(skyLight);
|
||||
|
||||
@Override
|
||||
public LayerLightEventListener getLayerListener(LightLayer layer) {
|
||||
return layer == LightLayer.BLOCK ? blockListener : skyListener;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static LayerLightEventListener createStaticListener(int light) {
|
||||
return new LayerLightEventListener() {
|
||||
@Override
|
||||
public void checkBlock(BlockPos pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLightWork() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) {
|
||||
return p_164449_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSectionStatus(SectionPos pos, boolean p_75838_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableLightSources(ChunkPos pos, boolean p_164453_) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataLayer getDataLayerData(SectionPos pos) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightValue(BlockPos pos) {
|
||||
return light;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelLightEngine getLightEngine() {
|
||||
return lightEngine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,12 @@ import com.jozufozu.flywheel.Flywheel;
|
|||
|
||||
import io.vram.frex.api.material.MaterialConstants;
|
||||
import io.vram.frex.fabric.compat.FabricMaterial;
|
||||
import io.vram.frex.fabric.compat.FabricQuadView;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.BlendMode;
|
||||
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
|
||||
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.RenderMaterialImpl;
|
||||
import net.fabricmc.fabric.impl.client.indigo.renderer.mesh.QuadViewImpl;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -19,6 +22,7 @@ public class FabricModelUtil {
|
|||
public static final boolean FREX_LOADED = FabricLoader.getInstance().isModLoaded("frex");
|
||||
|
||||
private static final BlendModeGetter BLEND_MODE_GETTER = createBlendModeGetter();
|
||||
private static final ShadedPredicate SHADED_PREDICATE = createShadedPredicate();
|
||||
|
||||
private static BlendModeGetter createBlendModeGetter() {
|
||||
if (FREX_LOADED) {
|
||||
|
@ -50,7 +54,7 @@ public class FabricModelUtil {
|
|||
return BlendMode.DEFAULT;
|
||||
};
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Detected FREX but failed to load wrapper field.", e);
|
||||
Flywheel.LOGGER.error("Detected FREX but failed to load material wrapper field.", e);
|
||||
return material -> BlendMode.DEFAULT;
|
||||
}
|
||||
} else if (INDIUM_LOADED) {
|
||||
|
@ -60,10 +64,38 @@ public class FabricModelUtil {
|
|||
}
|
||||
}
|
||||
|
||||
private static ShadedPredicate createShadedPredicate() {
|
||||
if (FREX_LOADED) {
|
||||
try {
|
||||
Field frexQuadViewField = FabricQuadView.class.getDeclaredField("wrapped");
|
||||
frexQuadViewField.setAccessible(true);
|
||||
return quad -> {
|
||||
try {
|
||||
io.vram.frex.api.mesh.QuadView frexQuadView = (io.vram.frex.api.mesh.QuadView) frexQuadViewField.get(quad);
|
||||
return !frexQuadView.material().disableDiffuse();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return true;
|
||||
};
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Detected FREX but failed to load quad view wrapper field.", e);
|
||||
return quad -> true;
|
||||
}
|
||||
} else if (INDIUM_LOADED) {
|
||||
return quad -> ((link.infra.indium.renderer.mesh.QuadViewImpl) quad).hasShade();
|
||||
} else {
|
||||
return quad -> ((QuadViewImpl) quad).hasShade();
|
||||
}
|
||||
}
|
||||
|
||||
public static BlendMode getBlendMode(RenderMaterial material) {
|
||||
return BLEND_MODE_GETTER.getBlendMode(material);
|
||||
}
|
||||
|
||||
public static boolean isShaded(QuadView quad) {
|
||||
return SHADED_PREDICATE.isShaded(quad);
|
||||
}
|
||||
|
||||
public static boolean doesLayerMatch(BlockState modelState, RenderType layer) {
|
||||
return ItemBlockRenderTypes.getChunkRenderType(modelState) == layer;
|
||||
}
|
||||
|
@ -71,4 +103,8 @@ public class FabricModelUtil {
|
|||
private interface BlendModeGetter {
|
||||
BlendMode getBlendMode(RenderMaterial material);
|
||||
}
|
||||
|
||||
private interface ShadedPredicate {
|
||||
boolean isShaded(QuadView quad);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,16 +20,10 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension {
|
|||
private ByteBuffer buffer;
|
||||
|
||||
@Shadow
|
||||
private boolean building;
|
||||
private int nextElementByte;
|
||||
|
||||
@Shadow
|
||||
public abstract void begin(VertexFormat.Mode p_166780_, VertexFormat p_166781_);
|
||||
|
||||
@Shadow
|
||||
private VertexFormat.Mode mode;
|
||||
|
||||
@Shadow
|
||||
private VertexFormat format;
|
||||
private int vertices;
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
|
@ -39,7 +33,22 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension {
|
|||
private int elementIndex;
|
||||
|
||||
@Shadow
|
||||
private int vertices;
|
||||
private VertexFormat format;
|
||||
|
||||
@Shadow
|
||||
private VertexFormat.Mode mode;
|
||||
|
||||
@Shadow
|
||||
private boolean building;
|
||||
|
||||
@Shadow
|
||||
private void ensureCapacity(int increaseAmount) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int flywheel$getVertices() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flywheel$freeBuffer() {
|
||||
|
@ -61,4 +70,29 @@ public abstract class BufferBuilderMixin implements BufferBuilderExtension {
|
|||
this.currentElement = this.format.getElements().get(0);
|
||||
this.elementIndex = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flywheel$appendBufferUnsafe(ByteBuffer buffer) {
|
||||
if (!building) {
|
||||
throw new IllegalStateException("BufferBuilder not started");
|
||||
}
|
||||
if (elementIndex != 0) {
|
||||
throw new IllegalStateException("Cannot append buffer while building vertex");
|
||||
}
|
||||
|
||||
int numBytes = buffer.remaining();
|
||||
if (numBytes % format.getVertexSize() != 0) {
|
||||
throw new IllegalArgumentException("Cannot append buffer with non-whole number of vertices");
|
||||
}
|
||||
int numVertices = numBytes / format.getVertexSize();
|
||||
|
||||
ensureCapacity(numBytes + format.getVertexSize());
|
||||
int originalPosition = this.buffer.position();
|
||||
this.buffer.position(nextElementByte);
|
||||
MemoryUtil.memCopy(buffer, this.buffer);
|
||||
this.buffer.position(originalPosition);
|
||||
|
||||
nextElementByte += numBytes;
|
||||
vertices += numVertices;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,5 +15,5 @@ public interface DiffuseLightCalculator {
|
|||
return level.effects().constantAmbientLight() ? NETHER : DEFAULT;
|
||||
}
|
||||
|
||||
float getDiffuse(float normalX, float normalY, float normalZ);
|
||||
float getDiffuse(float normalX, float normalY, float normalZ, boolean shaded);
|
||||
}
|
||||
|
|
|
@ -68,11 +68,17 @@ public class RenderMath {
|
|||
return (float) (((((target - current) % 360) + 540) % 360) - 180);
|
||||
}
|
||||
|
||||
public static float diffuseLight(float x, float y, float z) {
|
||||
public static float diffuseLight(float x, float y, float z, boolean shaded) {
|
||||
if (!shaded) {
|
||||
return 1f;
|
||||
}
|
||||
return Math.min(x * x * 0.6f + y * y * ((3f + y) / 4f) + z * z * 0.8f, 1f);
|
||||
}
|
||||
|
||||
public static float diffuseLightNether(float x, float y, float z) {
|
||||
public static float diffuseLightNether(float x, float y, float z, boolean shaded) {
|
||||
if (!shaded) {
|
||||
return 0.9f;
|
||||
}
|
||||
return Math.min(x * x * 0.6f + y * y * 0.9f + z * z * 0.8f, 1f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
/**
|
||||
* This is a silly hack that's needed because flywheel does things too different from vanilla.
|
||||
*
|
||||
* <p>
|
||||
* When a {@link RenderType} is setup, the associated textures are "bound" within RenderSystem, but not actually
|
||||
* bound via opengl. This class provides a helper function to forward the bindings to opengl.
|
||||
* </p>
|
||||
*/
|
||||
public class TextureBinder {
|
||||
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#use "flywheel:context/fog.glsl"
|
||||
#use "flywheel:core/diffuse.glsl"
|
||||
|
||||
uniform float uTime;
|
||||
uniform mat4 uViewProjection;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#use "flywheel:context/fog.glsl"
|
||||
#use "flywheel:core/diffuse.glsl"
|
||||
|
||||
uniform float uTime;
|
||||
uniform mat4 uViewProjection;
|
||||
|
|
Loading…
Reference in a new issue