mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
Gone, reduced to batches
- Remove BatchingEngine. - Remove InstanceVertexTransformer and BoundingSphereTransformer. - Remove fallback RenderType and MaterialVertexTransformer.
This commit is contained in:
parent
b7a1eba59a
commit
2dbdf83ec2
20 changed files with 0 additions and 1093 deletions
|
@ -1,13 +0,0 @@
|
|||
package com.jozufozu.flywheel.api.instance;
|
||||
|
||||
import org.joml.Vector4f;
|
||||
|
||||
public interface InstanceBoundingSphereTransformer<I extends Instance> {
|
||||
/**
|
||||
* Transform the bounding sphere of a mesh to match the location of the instance.
|
||||
*
|
||||
* @param boundingSphere The bounding sphere of the mesh formatted as < x, y, z, radius >
|
||||
* @param instance The instance to transform the bounding sphere for.
|
||||
*/
|
||||
void transform(Vector4f boundingSphere, I instance);
|
||||
}
|
|
@ -35,8 +35,4 @@ public interface InstanceType<I extends Instance> {
|
|||
ResourceLocation vertexShader();
|
||||
|
||||
ResourceLocation cullShader();
|
||||
|
||||
InstanceVertexTransformer<I> getVertexTransformer();
|
||||
|
||||
InstanceBoundingSphereTransformer<I> getBoundingSphereTransformer();
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package com.jozufozu.flywheel.api.instance;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||
|
||||
public interface InstanceVertexTransformer<I extends Instance> {
|
||||
void transform(MutableVertexList vertexList, I instance);
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
package com.jozufozu.flywheel.api.material;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public interface Material {
|
||||
RenderType getFallbackRenderType();
|
||||
|
||||
MaterialVertexTransformer getVertexTransformer();
|
||||
|
||||
MaterialShaders shaders();
|
||||
|
||||
FogShader fog();
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package com.jozufozu.flywheel.api.material;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
||||
public interface MaterialVertexTransformer {
|
||||
void transform(MutableVertexList vertexList, ClientLevel level);
|
||||
}
|
|
@ -5,7 +5,6 @@ import com.jozufozu.flywheel.Flywheel;
|
|||
import com.jozufozu.flywheel.api.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
|
||||
import com.jozufozu.flywheel.backend.compile.InstancingPrograms;
|
||||
import com.jozufozu.flywheel.backend.engine.batching.BatchingEngine;
|
||||
import com.jozufozu.flywheel.backend.engine.indirect.IndirectEngine;
|
||||
import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine;
|
||||
import com.jozufozu.flywheel.gl.GlCompat;
|
||||
|
@ -16,16 +15,6 @@ import net.minecraft.ChatFormatting;
|
|||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class Backends {
|
||||
/**
|
||||
* Use a thread pool to buffer instances in parallel on the CPU.
|
||||
*/
|
||||
public static final Backend BATCHING = SimpleBackend.builder()
|
||||
.engineMessage(Component.literal("Using Batching Engine")
|
||||
.withStyle(ChatFormatting.GREEN))
|
||||
.engineFactory(level -> new BatchingEngine(256))
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse())
|
||||
.register(Flywheel.rl("batching"));
|
||||
|
||||
/**
|
||||
* Use GPU instancing to render everything.
|
||||
*/
|
||||
|
@ -33,7 +22,6 @@ public class Backends {
|
|||
.engineMessage(Component.literal("Using Instancing Engine")
|
||||
.withStyle(ChatFormatting.GREEN))
|
||||
.engineFactory(level -> new InstancingEngine(256))
|
||||
.fallback(() -> Backends.BATCHING)
|
||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.supportsInstancing() && InstancingPrograms.allLoaded())
|
||||
.register(Flywheel.rl("instancing"));
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.FrustumIntersection;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.RenderContext;
|
||||
import com.jozufozu.flywheel.lib.math.MatrixMath;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public record BatchContext(FrustumIntersection frustum, ClientLevel level, PoseStack.Pose matrices) {
|
||||
@NotNull
|
||||
static BatchContext create(RenderContext context, BlockPos origin) {
|
||||
Vec3 cameraPos = context.camera()
|
||||
.getPosition();
|
||||
var stack = MatrixMath.copyPoseStack(context.stack());
|
||||
stack.translate(origin.getX() - cameraPos.x, origin.getY() - cameraPos.y, origin.getZ() - cameraPos.z);
|
||||
|
||||
Matrix4f viewProjection = new Matrix4f(context.viewProjection());
|
||||
viewProjection.translate((float) (origin.getX() - cameraPos.x), (float) (origin.getY() - cameraPos.y), (float) (origin.getZ() - cameraPos.z));
|
||||
|
||||
return new BatchContext(new FrustumIntersection(viewProjection), context.level(), stack.last());
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.jozufozu.flywheel.api.backend.Engine;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexView;
|
||||
import com.jozufozu.flywheel.backend.engine.InstanceHandleImpl;
|
||||
import com.jozufozu.flywheel.extension.RenderTypeExtension;
|
||||
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
|
||||
public class BatchedCrumbling {
|
||||
public static void render(List<Engine.CrumblingBlock> crumblingBlocks, BatchContext batchContext, BatchedDrawTracker drawTracker) {
|
||||
var instancesPerType = doCrumblingSort(crumblingBlocks);
|
||||
|
||||
for (var entry : instancesPerType.entrySet()) {
|
||||
// TODO: separate concept of renderstage from drawbuffer
|
||||
var drawBuffer = RenderTypeExtension.getDrawBufferSet(entry.getKey())
|
||||
.getBuffer(RenderStage.AFTER_BLOCK_ENTITIES);
|
||||
|
||||
var bucket = entry.getValue();
|
||||
|
||||
drawBuffer.prepare(bucket.vertexCount);
|
||||
|
||||
VertexView vertexView = drawBuffer.slice(0, 0);
|
||||
long basePtr = vertexView.ptr();
|
||||
|
||||
int totalVertices = 0;
|
||||
|
||||
for (var pair : bucket.instances) {
|
||||
var instance = pair.first();
|
||||
var instancer = pair.second();
|
||||
|
||||
totalVertices += bufferOne(instancer, totalVertices, vertexView, drawBuffer, instance);
|
||||
}
|
||||
|
||||
vertexView.ptr(basePtr);
|
||||
vertexView.vertexCount(totalVertices);
|
||||
|
||||
// apply these in bulk
|
||||
BatchingTransforms.applyDecalUVs(vertexView);
|
||||
BatchingTransforms.applyMatrices(vertexView, batchContext.matrices());
|
||||
|
||||
drawTracker._draw(drawBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<RenderType, CrumblingBucket> doCrumblingSort(List<Engine.CrumblingBlock> crumblingBlocks) {
|
||||
Map<RenderType, CrumblingBucket> out = new HashMap<>();
|
||||
|
||||
for (Engine.CrumblingBlock crumblingBlock : crumblingBlocks) {
|
||||
var crumblingType = ModelBakery.DESTROY_TYPES.get(crumblingBlock.progress());
|
||||
|
||||
for (Instance instance : crumblingBlock.instances()) {
|
||||
if (!(instance.handle() instanceof InstanceHandleImpl impl)) {
|
||||
continue;
|
||||
}
|
||||
if (!(impl.instancer instanceof BatchedInstancer<?> instancer)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var bucket = out.computeIfAbsent(crumblingType, $ -> new CrumblingBucket());
|
||||
bucket.instances.add(Pair.of(instance, instancer));
|
||||
|
||||
for (TransformCall<?> transformCall : instancer.getTransformCalls()) {
|
||||
var mesh = transformCall.mesh;
|
||||
bucket.vertexCount += mesh.vertexCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static <I extends Instance> int bufferOne(BatchedInstancer<I> batchedInstancer, int baseVertex, VertexView vertexView, DrawBuffer drawBuffer, Instance instance) {
|
||||
int totalVertices = 0;
|
||||
|
||||
for (TransformCall<I> transformCall : batchedInstancer.getTransformCalls()) {
|
||||
Mesh mesh = transformCall.mesh.mesh;
|
||||
|
||||
vertexView.ptr(drawBuffer.ptrForVertex(baseVertex + totalVertices));
|
||||
vertexView.vertexCount(mesh.vertexCount());
|
||||
|
||||
mesh.write(vertexView);
|
||||
batchedInstancer.type.getVertexTransformer()
|
||||
.transform(vertexView, (I) instance);
|
||||
|
||||
totalVertices += mesh.vertexCount();
|
||||
}
|
||||
|
||||
return totalVertices;
|
||||
}
|
||||
|
||||
private static class CrumblingBucket {
|
||||
private int vertexCount;
|
||||
private final List<Pair<Instance, BatchedInstancer<?>>> instances = new ArrayList<>();
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerKey;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerStorage;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
class BatchedDrawManager extends InstancerStorage<BatchedInstancer<?>> {
|
||||
public final BatchedDrawTracker drawTracker = new BatchedDrawTracker();
|
||||
private final Map<RenderStage, BatchedStagePlan> stagePlans = new EnumMap<>(RenderStage.class);
|
||||
private final Map<VertexFormat, BatchedMeshPool> meshPools = new HashMap<>();
|
||||
|
||||
public Collection<BatchedStagePlan> getStagePlans() {
|
||||
return stagePlans.values();
|
||||
}
|
||||
|
||||
public void renderStage(TaskExecutor executor, RenderStage stage) {
|
||||
var stagePlan = stagePlans.get(stage);
|
||||
|
||||
if (stagePlan == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
executor.syncUntil(stagePlan.flag::isRaised);
|
||||
stagePlan.flag.lower();
|
||||
|
||||
drawTracker.draw(stage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <I extends Instance> BatchedInstancer<?> create(InstanceType<I> type) {
|
||||
return new BatchedInstancer<>(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
protected <I extends Instance> void add(InstancerKey<I> key, BatchedInstancer<?> instancer, Model model, RenderStage stage) {
|
||||
var stagePlan = stagePlans.computeIfAbsent(stage, renderStage -> new BatchedStagePlan(renderStage, drawTracker));
|
||||
var meshes = model.meshes();
|
||||
for (var entry : meshes.entrySet()) {
|
||||
var material = entry.getKey();
|
||||
RenderType renderType = material.getFallbackRenderType();
|
||||
var mesh = alloc(entry.getValue(), renderType.format());
|
||||
var transformCall = new TransformCall<>(instancer, material, mesh);
|
||||
stagePlan.put(renderType, transformCall);
|
||||
instancer.addTransformCall((TransformCall) transformCall);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
super.flush();
|
||||
|
||||
for (var pool : meshPools.values()) {
|
||||
pool.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
super.delete();
|
||||
|
||||
meshPools.values()
|
||||
.forEach(BatchedMeshPool::delete);
|
||||
meshPools.clear();
|
||||
}
|
||||
|
||||
private BatchedMeshPool.BufferedMesh alloc(Mesh mesh, VertexFormat format) {
|
||||
return meshPools.computeIfAbsent(format, BatchedMeshPool::new)
|
||||
.alloc(mesh);
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.extension.BufferBuilderExtension;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
|
||||
public class BatchedDrawTracker {
|
||||
private final Map<RenderStage, Set<DrawBuffer>> activeBuffers = new EnumMap<>(RenderStage.class);
|
||||
{
|
||||
for (RenderStage stage : RenderStage.values()) {
|
||||
activeBuffers.put(stage, new HashSet<>());
|
||||
}
|
||||
}
|
||||
|
||||
private final BufferBuilder scratch;
|
||||
|
||||
public BatchedDrawTracker() {
|
||||
scratch = new BufferBuilder(8);
|
||||
|
||||
((BufferBuilderExtension) scratch).flywheel$freeBuffer();
|
||||
}
|
||||
|
||||
public void markActive(RenderStage stage, DrawBuffer buffer) {
|
||||
synchronized (activeBuffers) {
|
||||
activeBuffers.get(stage)
|
||||
.add(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove?
|
||||
public void markInactive(RenderStage stage, DrawBuffer buffer) {
|
||||
synchronized (activeBuffers) {
|
||||
activeBuffers.get(stage)
|
||||
.remove(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasStage(RenderStage stage) {
|
||||
synchronized (activeBuffers) {
|
||||
return !activeBuffers.get(stage)
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw and reset all DrawBuffers for the given RenderStage.
|
||||
*
|
||||
* @param stage The RenderStage to draw.
|
||||
*/
|
||||
public void draw(RenderStage stage) {
|
||||
// This may appear jank, but flag synchronization in BatchingEngine guarantees that
|
||||
// the mapped-to Set will not be modified here. We don't have the same guarantee for
|
||||
// activeBuffers itself, so we need to synchronize to fetch the Set.
|
||||
|
||||
Set<DrawBuffer> buffers;
|
||||
synchronized (activeBuffers) {
|
||||
buffers = activeBuffers.get(stage);
|
||||
}
|
||||
|
||||
for (DrawBuffer buffer : buffers) {
|
||||
_draw(buffer);
|
||||
}
|
||||
buffers.clear();
|
||||
}
|
||||
|
||||
public void _draw(DrawBuffer buffer) {
|
||||
if (buffer.hasVertices()) {
|
||||
BufferBuilderExtension scratch = (BufferBuilderExtension) this.scratch;
|
||||
buffer.inject(scratch);
|
||||
buffer.getRenderType()
|
||||
.end(this.scratch, RenderSystem.getVertexSorting());
|
||||
}
|
||||
buffer.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all active DrawBuffers.
|
||||
*/
|
||||
public void reset() {
|
||||
for (Set<DrawBuffer> buffers : activeBuffers.values()) {
|
||||
for (DrawBuffer buffer : buffers) {
|
||||
buffer.reset();
|
||||
}
|
||||
buffers.clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
||||
|
||||
public class BatchedInstancer<I extends Instance> extends AbstractInstancer<I> {
|
||||
private final List<TransformCall<I>> transformCalls = new ArrayList<>();
|
||||
|
||||
public BatchedInstancer(InstanceType<I> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
public List<I> getRange(int start, int end) {
|
||||
return instances.subList(start, end);
|
||||
}
|
||||
|
||||
public List<I> getAll() {
|
||||
return instances;
|
||||
}
|
||||
|
||||
public I get(int index) {
|
||||
return instances.get(index);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
removeDeletedInstances();
|
||||
}
|
||||
|
||||
public void addTransformCall(TransformCall<I> transformCall) {
|
||||
transformCalls.add(transformCall);
|
||||
}
|
||||
|
||||
public List<TransformCall<I>> getTransformCalls() {
|
||||
return transformCalls;
|
||||
}
|
||||
}
|
|
@ -1,221 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector4fc;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexView;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexViewProviderRegistry;
|
||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
public class BatchedMeshPool {
|
||||
private final VertexFormat vertexFormat;
|
||||
private final VertexView vertexView;
|
||||
private final int growthMargin;
|
||||
|
||||
private final Map<Mesh, BufferedMesh> meshes = new HashMap<>();
|
||||
private final List<BufferedMesh> allBuffered = new ArrayList<>();
|
||||
private final List<BufferedMesh> pendingBuffer = new ArrayList<>();
|
||||
|
||||
private MemoryBlock data;
|
||||
private long byteSize;
|
||||
|
||||
private boolean dirty;
|
||||
private boolean anyToRemove;
|
||||
|
||||
/**
|
||||
* Create a new mesh pool.
|
||||
*/
|
||||
public BatchedMeshPool(VertexFormat vertexFormat) {
|
||||
this.vertexFormat = vertexFormat;
|
||||
vertexView = VertexViewProviderRegistry.getProvider(vertexFormat).createVertexView();
|
||||
growthMargin = vertexFormat.getVertexSize() * 128;
|
||||
}
|
||||
|
||||
public VertexFormat getVertexFormat() {
|
||||
return vertexFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a mesh in the arena.
|
||||
*
|
||||
* @param mesh The mesh to allocate.
|
||||
* @return A handle to the allocated mesh.
|
||||
*/
|
||||
public BufferedMesh alloc(Mesh mesh) {
|
||||
return meshes.computeIfAbsent(mesh, m -> {
|
||||
BufferedMesh bufferedMesh = new BufferedMesh(m, byteSize);
|
||||
byteSize += bufferedMesh.size();
|
||||
allBuffered.add(bufferedMesh);
|
||||
pendingBuffer.add(bufferedMesh);
|
||||
|
||||
dirty = true;
|
||||
return bufferedMesh;
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BufferedMesh get(Mesh mesh) {
|
||||
return meshes.get(mesh);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
if (dirty) {
|
||||
if (anyToRemove) {
|
||||
processDeletions();
|
||||
}
|
||||
|
||||
realloc();
|
||||
bufferPending();
|
||||
|
||||
dirty = false;
|
||||
pendingBuffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void processDeletions() {
|
||||
// remove deleted meshes
|
||||
allBuffered.removeIf(bufferedMesh -> {
|
||||
boolean deleted = bufferedMesh.isDeleted();
|
||||
if (deleted) {
|
||||
meshes.remove(bufferedMesh.mesh);
|
||||
}
|
||||
return deleted;
|
||||
});
|
||||
|
||||
// re-evaluate first vertex for each mesh
|
||||
int byteIndex = 0;
|
||||
for (BufferedMesh mesh : allBuffered) {
|
||||
if (mesh.byteIndex != byteIndex) {
|
||||
pendingBuffer.add(mesh);
|
||||
}
|
||||
|
||||
mesh.byteIndex = byteIndex;
|
||||
|
||||
byteIndex += mesh.size();
|
||||
}
|
||||
|
||||
this.byteSize = byteIndex;
|
||||
this.anyToRemove = false;
|
||||
}
|
||||
|
||||
private void realloc() {
|
||||
if (byteSize < 0) {
|
||||
throw new IllegalArgumentException("Size " + byteSize + " < 0");
|
||||
}
|
||||
|
||||
if (byteSize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
data = MemoryBlock.malloc(byteSize);
|
||||
} else if (byteSize > data.size()) {
|
||||
data = data.realloc(byteSize + growthMargin);
|
||||
}
|
||||
}
|
||||
|
||||
private void bufferPending() {
|
||||
try {
|
||||
for (BufferedMesh mesh : pendingBuffer) {
|
||||
mesh.write(vertexView);
|
||||
}
|
||||
|
||||
pendingBuffer.clear();
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Error uploading pooled meshes:", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
if (data != null) {
|
||||
data.free();
|
||||
}
|
||||
meshes.clear();
|
||||
allBuffered.clear();
|
||||
pendingBuffer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BatchedMeshPool{" + "vertexFormat=" + vertexFormat + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}';
|
||||
}
|
||||
|
||||
public class BufferedMesh {
|
||||
public final Mesh mesh;
|
||||
private final int vertexCount;
|
||||
private final int byteSize;
|
||||
private final Vector4fc boundingSphere;
|
||||
|
||||
private long byteIndex;
|
||||
private boolean deleted;
|
||||
|
||||
private BufferedMesh(Mesh mesh, long byteIndex) {
|
||||
this.mesh = mesh;
|
||||
vertexCount = mesh.vertexCount();
|
||||
byteSize = vertexCount * vertexFormat.getVertexSize();
|
||||
boundingSphere = mesh.boundingSphere();
|
||||
this.byteIndex = byteIndex;
|
||||
}
|
||||
|
||||
public VertexFormat vertexFormat() {
|
||||
return vertexFormat;
|
||||
}
|
||||
|
||||
public int vertexCount() {
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return byteSize;
|
||||
}
|
||||
|
||||
public Vector4fc boundingSphere() {
|
||||
return boundingSphere;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return mesh.isEmpty() || isDeleted();
|
||||
}
|
||||
|
||||
private long ptr() {
|
||||
return BatchedMeshPool.this.data.ptr() + byteIndex;
|
||||
}
|
||||
|
||||
private void write(VertexView vertexView) {
|
||||
if (isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
vertexView.ptr(ptr());
|
||||
vertexView.vertexCount(vertexCount);
|
||||
mesh.write(vertexView);
|
||||
}
|
||||
|
||||
public void copyTo(long ptr) {
|
||||
if (isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MemoryUtil.memCopy(ptr(), ptr, byteSize);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
deleted = true;
|
||||
BatchedMeshPool.this.dirty = true;
|
||||
BatchedMeshPool.this.anyToRemove = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.lib.task.Flag;
|
||||
import com.jozufozu.flywheel.lib.task.SimplyComposedPlan;
|
||||
import com.jozufozu.flywheel.lib.task.StageFlag;
|
||||
import com.jozufozu.flywheel.lib.task.Synchronizer;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
/**
|
||||
* All the rendering that happens within a render stage.
|
||||
*/
|
||||
public class BatchedStagePlan implements SimplyComposedPlan<BatchContext> {
|
||||
/**
|
||||
* This flag will be raised when this stage completes execution.
|
||||
*/
|
||||
public final Flag flag;
|
||||
|
||||
private final RenderStage stage;
|
||||
private final BatchedDrawTracker tracker;
|
||||
private final Map<RenderType, BufferPlan> bufferPlans = new HashMap<>();
|
||||
|
||||
public BatchedStagePlan(RenderStage stage, BatchedDrawTracker tracker) {
|
||||
this.flag = new StageFlag(stage);
|
||||
this.stage = stage;
|
||||
this.tracker = tracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TaskExecutor taskExecutor, BatchContext context, Runnable onCompletion) {
|
||||
if (isEmpty()) {
|
||||
flag.raise();
|
||||
onCompletion.run();
|
||||
return;
|
||||
}
|
||||
|
||||
taskExecutor.execute(() -> {
|
||||
var sync = new Synchronizer(bufferPlans.size(), () -> {
|
||||
flag.raise();
|
||||
onCompletion.run();
|
||||
});
|
||||
|
||||
for (var plan : bufferPlans.values()) {
|
||||
plan.execute(taskExecutor, context, sync);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void put(RenderType renderType, TransformCall<?> transformCall) {
|
||||
bufferPlans.computeIfAbsent(renderType, type -> new BufferPlan(DrawBuffer.get(type, stage)))
|
||||
.add(transformCall);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return bufferPlans.isEmpty();
|
||||
}
|
||||
|
||||
private class BufferPlan implements SimplyComposedPlan<BatchContext> {
|
||||
private final DrawBuffer buffer;
|
||||
private final List<TransformCall<?>> transformCalls = new ArrayList<>();
|
||||
|
||||
public BufferPlan(DrawBuffer drawBuffer) {
|
||||
buffer = drawBuffer;
|
||||
}
|
||||
|
||||
public void add(TransformCall<?> transformCall) {
|
||||
transformCalls.add(transformCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TaskExecutor taskExecutor, BatchContext ctx, Runnable onCompletion) {
|
||||
var vertexCount = setupAndCountVertices();
|
||||
|
||||
if (vertexCount <= 0) {
|
||||
onCompletion.run();
|
||||
return;
|
||||
}
|
||||
|
||||
tracker.markActive(stage, buffer);
|
||||
buffer.prepare(vertexCount);
|
||||
|
||||
var vertexCounter = new AtomicInteger(0);
|
||||
var planContext = new TransformCall.PlanContext(ctx.frustum(), vertexCounter, buffer, ctx.level(), ctx.matrices());
|
||||
|
||||
var synchronizer = new Synchronizer(transformCalls.size(), () -> {
|
||||
buffer.verticesToDraw(vertexCounter.get());
|
||||
onCompletion.run();
|
||||
});
|
||||
|
||||
for (var transformCall : transformCalls) {
|
||||
transformCall.plan()
|
||||
.execute(taskExecutor, planContext, synchronizer);
|
||||
}
|
||||
}
|
||||
|
||||
private int setupAndCountVertices() {
|
||||
int vertices = 0;
|
||||
for (var transformCall : transformCalls) {
|
||||
transformCall.setup();
|
||||
vertices += transformCall.getTotalVertexCount();
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.RenderContext;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.task.Plan;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerStorage;
|
||||
import com.jozufozu.flywheel.lib.task.DynamicNestedPlan;
|
||||
import com.jozufozu.flywheel.lib.task.Flag;
|
||||
import com.jozufozu.flywheel.lib.task.MapContextPlan;
|
||||
import com.jozufozu.flywheel.lib.task.NamedFlag;
|
||||
import com.jozufozu.flywheel.lib.task.SimplePlan;
|
||||
|
||||
public class BatchingEngine extends AbstractEngine {
|
||||
private final BatchedDrawManager drawManager = new BatchedDrawManager();
|
||||
|
||||
private final Flag flushFlag = new NamedFlag("flushed");
|
||||
|
||||
public BatchingEngine(int maxOriginDistance) {
|
||||
super(maxOriginDistance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plan<RenderContext> createFramePlan() {
|
||||
return SimplePlan.<RenderContext>of(() -> {
|
||||
drawManager.flush();
|
||||
flushFlag.raise();
|
||||
}).then(MapContextPlan.map((RenderContext ctx) -> BatchContext.create(ctx, renderOrigin))
|
||||
.to(DynamicNestedPlan.of(drawManager::getStagePlans)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderStage(TaskExecutor executor, RenderContext context, RenderStage stage) {
|
||||
executor.syncUntil(flushFlag::isRaised);
|
||||
if (stage.isLast()) {
|
||||
flushFlag.lower();
|
||||
}
|
||||
|
||||
drawManager.renderStage(executor, stage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
|
||||
executor.syncUntil(flushFlag::isRaised);
|
||||
|
||||
var batchContext = BatchContext.create(context, this.renderOrigin);
|
||||
BatchedCrumbling.render(crumblingBlocks, batchContext, this.drawManager.drawTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstancerStorage<? extends AbstractInstancer<?>> getStorage() {
|
||||
return drawManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
drawManager.delete();
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
|
||||
public class BatchingTransforms {
|
||||
public static void applyMatrices(MutableVertexList vertexList, PoseStack.Pose matrices) {
|
||||
Matrix4f modelMatrix = matrices.pose();
|
||||
Matrix3f normalMatrix = matrices.normal();
|
||||
|
||||
for (int i = 0; i < vertexList.vertexCount(); i++) {
|
||||
VertexTransformations.transformPos(vertexList, i, modelMatrix);
|
||||
VertexTransformations.transformNormal(vertexList, i, normalMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the same operation as {@link SheetedDecalTextureGenerator} in-place.
|
||||
* <br>
|
||||
* Call this in world space.
|
||||
*
|
||||
* @param vertexList The vertex list to apply the transformations to.
|
||||
*/
|
||||
public static void applyDecalUVs(MutableVertexList vertexList) {
|
||||
Vector3f normal = new Vector3f();
|
||||
Vector4f pos = new Vector4f();
|
||||
|
||||
for (int i = 0; i < vertexList.vertexCount(); i++) {
|
||||
vertexList.getPos(i, pos);
|
||||
vertexList.getNormal(i, normal);
|
||||
|
||||
Direction direction = Direction.getNearest(normal.x(), normal.y(), normal.z());
|
||||
pos.rotateY((float)Math.PI);
|
||||
pos.rotateX((-(float)Math.PI / 2F));
|
||||
pos.rotate(direction.getRotation());
|
||||
float u = -pos.x();
|
||||
float v = -pos.y();
|
||||
|
||||
vertexList.u(i, u);
|
||||
vertexList.v(i, v);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector4fc;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceBoundingSphereTransformer;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceVertexTransformer;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.material.MaterialVertexTransformer;
|
||||
import com.jozufozu.flywheel.api.task.Plan;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexView;
|
||||
import com.jozufozu.flywheel.lib.task.ForEachSlicePlan;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
||||
public class TransformCall<I extends Instance> {
|
||||
public final BatchedInstancer<I> instancer;
|
||||
public final Material material;
|
||||
public final BatchedMeshPool.BufferedMesh mesh;
|
||||
|
||||
private final int meshVertexCount;
|
||||
private final Plan<PlanContext> drawPlan;
|
||||
|
||||
public TransformCall(BatchedInstancer<I> instancer, Material material, BatchedMeshPool.BufferedMesh mesh) {
|
||||
this.instancer = instancer;
|
||||
this.material = material;
|
||||
this.mesh = mesh;
|
||||
|
||||
InstanceVertexTransformer<I> instanceVertexTransformer = instancer.type.getVertexTransformer();
|
||||
InstanceBoundingSphereTransformer<I> boundingSphereTransformer = instancer.type.getBoundingSphereTransformer();
|
||||
MaterialVertexTransformer materialVertexTransformer = material.getVertexTransformer();
|
||||
|
||||
meshVertexCount = mesh.vertexCount();
|
||||
Vector4fc meshBoundingSphere = mesh.boundingSphere();
|
||||
|
||||
drawPlan = ForEachSlicePlan.of(instancer::getAll, (subList, ctx) -> {
|
||||
VertexView vertexView = ctx.buffer.slice(0, meshVertexCount);
|
||||
Vector4f boundingSphere = new Vector4f();
|
||||
|
||||
for (I instance : subList) {
|
||||
boundingSphere.set(meshBoundingSphere);
|
||||
boundingSphereTransformer.transform(boundingSphere, instance);
|
||||
|
||||
if (!ctx.frustum.testSphere(boundingSphere.x, boundingSphere.y, boundingSphere.z, boundingSphere.w)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int baseVertex = ctx.vertexCounter.getAndAdd(meshVertexCount);
|
||||
vertexView.ptr(ctx.buffer.ptrForVertex(baseVertex));
|
||||
|
||||
mesh.copyTo(vertexView.ptr());
|
||||
instanceVertexTransformer.transform(vertexView, instance);
|
||||
materialVertexTransformer.transform(vertexView, ctx.level);
|
||||
BatchingTransforms.applyMatrices(vertexView, ctx.matrices);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setup() {
|
||||
instancer.update();
|
||||
}
|
||||
|
||||
public int getTotalVertexCount() {
|
||||
return meshVertexCount * instancer.getInstanceCount();
|
||||
}
|
||||
|
||||
public Plan<PlanContext> plan() {
|
||||
return drawPlan;
|
||||
}
|
||||
|
||||
public record PlanContext(FrustumIntersection frustum, AtomicInteger vertexCounter, DrawBuffer buffer, ClientLevel level, PoseStack.Pose matrices) {
|
||||
}
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
package com.jozufozu.flywheel.lib.instance;
|
||||
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceBoundingSphereTransformer;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceVertexTransformer;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceWriter;
|
||||
import com.jozufozu.flywheel.api.layout.FloatType;
|
||||
import com.jozufozu.flywheel.api.layout.IntegerType;
|
||||
|
@ -16,8 +11,6 @@ import com.jozufozu.flywheel.api.layout.VectorSize;
|
|||
import com.jozufozu.flywheel.lib.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.lib.layout.LayoutBuilder;
|
||||
import com.jozufozu.flywheel.lib.math.RenderMath;
|
||||
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
|
@ -71,42 +64,4 @@ public class OrientedType implements InstanceType<OrientedInstance> {
|
|||
return CULL_SHADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceVertexTransformer<OrientedInstance> getVertexTransformer() {
|
||||
return (vertexList, instance) -> {
|
||||
Matrix4f modelMatrix = new Matrix4f();
|
||||
modelMatrix.translate(instance.posX + instance.pivotX, instance.posY + instance.pivotY, instance.posZ + instance.pivotZ);
|
||||
modelMatrix.rotate(instance.rotation);
|
||||
modelMatrix.translate(-instance.pivotX, -instance.pivotY, -instance.pivotZ);
|
||||
|
||||
Matrix3f normalMatrix = new Matrix3f();
|
||||
normalMatrix.set(instance.rotation);
|
||||
|
||||
float r = RenderMath.uf(instance.r);
|
||||
float g = RenderMath.uf(instance.g);
|
||||
float b = RenderMath.uf(instance.b);
|
||||
float a = RenderMath.uf(instance.a);
|
||||
int light = instance.getPackedLight();
|
||||
|
||||
for (int i = 0; i < vertexList.vertexCount(); i++) {
|
||||
VertexTransformations.transformPos(vertexList, i, modelMatrix);
|
||||
VertexTransformations.transformNormal(vertexList, i, normalMatrix);
|
||||
|
||||
vertexList.r(i, r);
|
||||
vertexList.g(i, g);
|
||||
vertexList.b(i, b);
|
||||
vertexList.a(i, a);
|
||||
vertexList.light(i, light);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceBoundingSphereTransformer<OrientedInstance> getBoundingSphereTransformer() {
|
||||
return (boundingSphere, instance) -> {
|
||||
boundingSphere.sub(instance.pivotX, instance.pivotY, instance.pivotZ, 0);
|
||||
boundingSphere.rotate(instance.rotation);
|
||||
boundingSphere.add(instance.posX + instance.pivotX, instance.posY + instance.pivotY, instance.posZ + instance.pivotZ, 0);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package com.jozufozu.flywheel.lib.instance;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceBoundingSphereTransformer;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceHandle;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceVertexTransformer;
|
||||
import com.jozufozu.flywheel.api.instance.InstanceWriter;
|
||||
import com.jozufozu.flywheel.api.layout.IntegerType;
|
||||
import com.jozufozu.flywheel.api.layout.Layout;
|
||||
|
@ -13,9 +11,6 @@ import com.jozufozu.flywheel.api.layout.VectorSize;
|
|||
import com.jozufozu.flywheel.lib.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.lib.layout.LayoutBuilder;
|
||||
import com.jozufozu.flywheel.lib.math.MatrixMath;
|
||||
import com.jozufozu.flywheel.lib.math.RenderMath;
|
||||
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
|
@ -67,35 +62,4 @@ public class TransformedType implements InstanceType<TransformedInstance> {
|
|||
return CULL_SHADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceVertexTransformer<TransformedInstance> getVertexTransformer() {
|
||||
return (vertexList, instance) -> {
|
||||
float r = RenderMath.uf(instance.r);
|
||||
float g = RenderMath.uf(instance.g);
|
||||
float b = RenderMath.uf(instance.b);
|
||||
float a = RenderMath.uf(instance.a);
|
||||
int light = instance.getPackedLight();
|
||||
|
||||
for (int i = 0; i < vertexList.vertexCount(); i++) {
|
||||
VertexTransformations.transformPos(vertexList, i, instance.model);
|
||||
VertexTransformations.transformNormal(vertexList, i, instance.normal);
|
||||
|
||||
vertexList.r(i, r);
|
||||
vertexList.g(i, g);
|
||||
vertexList.b(i, b);
|
||||
vertexList.a(i, a);
|
||||
vertexList.light(i, light);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceBoundingSphereTransformer<TransformedInstance> getBoundingSphereTransformer() {
|
||||
return (boundingSphere, instance) -> {
|
||||
var radius = boundingSphere.w;
|
||||
boundingSphere.w = 1;
|
||||
boundingSphere.mul(instance.model);
|
||||
boundingSphere.w = radius * MatrixMath.extractScale(instance.model);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,120 +1,83 @@
|
|||
package com.jozufozu.flywheel.lib.material;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.material.MaterialVertexTransformer;
|
||||
import com.jozufozu.flywheel.api.material.Transparency;
|
||||
import com.jozufozu.flywheel.lib.math.DiffuseLightCalculator;
|
||||
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public final class Materials {
|
||||
public static final MaterialVertexTransformer SHADING_TRANSFORMER = (vertexList, level) -> {
|
||||
if (ShadersModHandler.isShaderPackInUse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DiffuseLightCalculator diffuseCalc = DiffuseLightCalculator.forLevel(level);
|
||||
for (int i = 0; i < vertexList.vertexCount(); i++) {
|
||||
float diffuse = diffuseCalc.getDiffuse(vertexList.normalX(i), vertexList.normalY(i), vertexList.normalZ(i), true);
|
||||
vertexList.r(i, vertexList.r(i) * diffuse);
|
||||
vertexList.g(i, vertexList.g(i) * diffuse);
|
||||
vertexList.b(i, vertexList.b(i) * diffuse);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
|
||||
|
||||
public static final Material CHUNK_SOLID_SHADED = SimpleMaterial.builder()
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.solid())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_SOLID_UNSHADED = SimpleMaterial.builder()
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
.fallbackRenderType(RenderType.solid())
|
||||
.build();
|
||||
|
||||
public static final Material CHUNK_CUTOUT_MIPPED_SHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.HALF)
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.cutoutMipped())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_CUTOUT_MIPPED_UNSHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.HALF)
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
.fallbackRenderType(RenderType.cutoutMipped())
|
||||
.build();
|
||||
|
||||
public static final Material CHUNK_CUTOUT_SHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.mipmap(false)
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.cutout())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_CUTOUT_UNSHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.mipmap(false)
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
.fallbackRenderType(RenderType.cutout())
|
||||
.build();
|
||||
|
||||
public static final Material CHUNK_TRANSLUCENT_SHADED = SimpleMaterial.builder()
|
||||
.transparency(Transparency.TRANSLUCENT)
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.translucent())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_TRANSLUCENT_UNSHADED = SimpleMaterial.builder()
|
||||
.transparency(Transparency.TRANSLUCENT)
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
.fallbackRenderType(RenderType.translucent())
|
||||
.build();
|
||||
|
||||
public static final Material CHUNK_TRIPWIRE_SHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.transparency(Transparency.TRANSLUCENT)
|
||||
.useOverlay(false)
|
||||
.fallbackRenderType(RenderType.tripwire())
|
||||
.vertexTransformer(SHADING_TRANSFORMER)
|
||||
.build();
|
||||
public static final Material CHUNK_TRIPWIRE_UNSHADED = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.transparency(Transparency.TRANSLUCENT)
|
||||
.useOverlay(false)
|
||||
.diffuse(false)
|
||||
.fallbackRenderType(RenderType.tripwire())
|
||||
.build();
|
||||
|
||||
public static final Material CHEST = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.texture(Sheets.CHEST_SHEET)
|
||||
.mipmap(false)
|
||||
.fallbackRenderType(Sheets.chestSheet())
|
||||
.build();
|
||||
public static final Material SHULKER = SimpleMaterial.builder()
|
||||
.cutout(CutoutShaders.ONE_TENTH)
|
||||
.texture(Sheets.SHULKER_SHEET)
|
||||
.mipmap(false)
|
||||
.backfaceCulling(false)
|
||||
.fallbackRenderType(Sheets.shulkerBoxSheet())
|
||||
.build();
|
||||
public static final Material BELL = SimpleMaterial.builder()
|
||||
.mipmap(false)
|
||||
.fallbackRenderType(Sheets.solidBlockSheet())
|
||||
.build();
|
||||
public static final Material MINECART = SimpleMaterial.builder()
|
||||
.texture(MINECART_LOCATION)
|
||||
.mipmap(false)
|
||||
.fallbackRenderType(RenderType.entitySolid(MINECART_LOCATION))
|
||||
.build();
|
||||
|
||||
private Materials() {
|
||||
|
|
|
@ -5,18 +5,13 @@ import com.jozufozu.flywheel.api.material.DepthTest;
|
|||
import com.jozufozu.flywheel.api.material.FogShader;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.material.MaterialShaders;
|
||||
import com.jozufozu.flywheel.api.material.MaterialVertexTransformer;
|
||||
import com.jozufozu.flywheel.api.material.Transparency;
|
||||
import com.jozufozu.flywheel.api.material.WriteMask;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
|
||||
public class SimpleMaterial implements Material {
|
||||
protected final RenderType fallbackRenderType;
|
||||
protected final MaterialVertexTransformer vertexTransformer;
|
||||
|
||||
protected final MaterialShaders shaders;
|
||||
protected final FogShader fog;
|
||||
protected final CutoutShader cutout;
|
||||
|
@ -36,8 +31,6 @@ public class SimpleMaterial implements Material {
|
|||
protected final boolean diffuse;
|
||||
|
||||
protected SimpleMaterial(Builder builder) {
|
||||
fallbackRenderType = builder.getFallbackRenderType();
|
||||
vertexTransformer = builder.getVertexTransformer();
|
||||
shaders = builder.shaders();
|
||||
fog = builder.fog();
|
||||
cutout = builder.cutout();
|
||||
|
@ -62,16 +55,6 @@ public class SimpleMaterial implements Material {
|
|||
return new Builder(material);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderType getFallbackRenderType() {
|
||||
return fallbackRenderType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialVertexTransformer getVertexTransformer() {
|
||||
return vertexTransformer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialShaders shaders() {
|
||||
return shaders;
|
||||
|
@ -143,9 +126,6 @@ public class SimpleMaterial implements Material {
|
|||
}
|
||||
|
||||
public static class Builder implements Material {
|
||||
protected RenderType fallbackRenderType;
|
||||
protected MaterialVertexTransformer vertexTransformer;
|
||||
|
||||
protected MaterialShaders shaders;
|
||||
protected FogShader fog;
|
||||
protected CutoutShader cutout;
|
||||
|
@ -165,9 +145,6 @@ public class SimpleMaterial implements Material {
|
|||
protected boolean diffuse;
|
||||
|
||||
public Builder() {
|
||||
fallbackRenderType = RenderType.solid();
|
||||
vertexTransformer = (vertexList, level) -> {
|
||||
};
|
||||
shaders = StandardMaterialShaders.DEFAULT;
|
||||
fog = FogShaders.LINEAR;
|
||||
cutout = CutoutShaders.OFF;
|
||||
|
@ -189,8 +166,6 @@ public class SimpleMaterial implements Material {
|
|||
}
|
||||
|
||||
public Builder copyFrom(Material material) {
|
||||
fallbackRenderType = material.getFallbackRenderType();
|
||||
vertexTransformer = material.getVertexTransformer();
|
||||
shaders = material.shaders();
|
||||
fog = material.fog();
|
||||
cutout = material.cutout();
|
||||
|
@ -208,16 +183,6 @@ public class SimpleMaterial implements Material {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder fallbackRenderType(RenderType type) {
|
||||
this.fallbackRenderType = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder vertexTransformer(MaterialVertexTransformer vertexTransformer) {
|
||||
this.vertexTransformer = vertexTransformer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder shaders(MaterialShaders value) {
|
||||
this.shaders = value;
|
||||
return this;
|
||||
|
@ -288,16 +253,6 @@ public class SimpleMaterial implements Material {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderType getFallbackRenderType() {
|
||||
return fallbackRenderType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialVertexTransformer getVertexTransformer() {
|
||||
return vertexTransformer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MaterialShaders shaders() {
|
||||
return shaders;
|
||||
|
|
Loading…
Reference in a new issue