mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 23:47:09 +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 vertexShader();
|
||||||
|
|
||||||
ResourceLocation cullShader();
|
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;
|
package com.jozufozu.flywheel.api.material;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public interface Material {
|
public interface Material {
|
||||||
RenderType getFallbackRenderType();
|
|
||||||
|
|
||||||
MaterialVertexTransformer getVertexTransformer();
|
|
||||||
|
|
||||||
MaterialShaders shaders();
|
MaterialShaders shaders();
|
||||||
|
|
||||||
FogShader fog();
|
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.api.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
|
import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
|
||||||
import com.jozufozu.flywheel.backend.compile.InstancingPrograms;
|
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.indirect.IndirectEngine;
|
||||||
import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine;
|
import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine;
|
||||||
import com.jozufozu.flywheel.gl.GlCompat;
|
import com.jozufozu.flywheel.gl.GlCompat;
|
||||||
|
@ -16,16 +15,6 @@ import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
public class Backends {
|
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.
|
* Use GPU instancing to render everything.
|
||||||
*/
|
*/
|
||||||
|
@ -33,7 +22,6 @@ public class Backends {
|
||||||
.engineMessage(Component.literal("Using Instancing Engine")
|
.engineMessage(Component.literal("Using Instancing Engine")
|
||||||
.withStyle(ChatFormatting.GREEN))
|
.withStyle(ChatFormatting.GREEN))
|
||||||
.engineFactory(level -> new InstancingEngine(256))
|
.engineFactory(level -> new InstancingEngine(256))
|
||||||
.fallback(() -> Backends.BATCHING)
|
|
||||||
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.supportsInstancing() && InstancingPrograms.allLoaded())
|
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.supportsInstancing() && InstancingPrograms.allLoaded())
|
||||||
.register(Flywheel.rl("instancing"));
|
.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;
|
package com.jozufozu.flywheel.lib.instance;
|
||||||
|
|
||||||
import org.joml.Matrix3f;
|
|
||||||
import org.joml.Matrix4f;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
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.InstanceHandle;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
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.instance.InstanceWriter;
|
||||||
import com.jozufozu.flywheel.api.layout.FloatType;
|
import com.jozufozu.flywheel.api.layout.FloatType;
|
||||||
import com.jozufozu.flywheel.api.layout.IntegerType;
|
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.BufferLayout;
|
||||||
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.lib.layout.LayoutBuilder;
|
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;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
@ -71,42 +64,4 @@ public class OrientedType implements InstanceType<OrientedInstance> {
|
||||||
return CULL_SHADER;
|
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;
|
package com.jozufozu.flywheel.lib.instance;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
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.InstanceHandle;
|
||||||
import com.jozufozu.flywheel.api.instance.InstanceType;
|
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.instance.InstanceWriter;
|
||||||
import com.jozufozu.flywheel.api.layout.IntegerType;
|
import com.jozufozu.flywheel.api.layout.IntegerType;
|
||||||
import com.jozufozu.flywheel.api.layout.Layout;
|
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.BufferLayout;
|
||||||
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
import com.jozufozu.flywheel.lib.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.lib.layout.LayoutBuilder;
|
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;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
@ -67,35 +62,4 @@ public class TransformedType implements InstanceType<TransformedInstance> {
|
||||||
return CULL_SHADER;
|
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;
|
package com.jozufozu.flywheel.lib.material;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.material.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.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.client.renderer.Sheets;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public final class Materials {
|
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");
|
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
|
||||||
|
|
||||||
public static final Material CHUNK_SOLID_SHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_SOLID_SHADED = SimpleMaterial.builder()
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.fallbackRenderType(RenderType.solid())
|
|
||||||
.vertexTransformer(SHADING_TRANSFORMER)
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material CHUNK_SOLID_UNSHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_SOLID_UNSHADED = SimpleMaterial.builder()
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.diffuse(false)
|
.diffuse(false)
|
||||||
.fallbackRenderType(RenderType.solid())
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final Material CHUNK_CUTOUT_MIPPED_SHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_CUTOUT_MIPPED_SHADED = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.HALF)
|
.cutout(CutoutShaders.HALF)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.fallbackRenderType(RenderType.cutoutMipped())
|
|
||||||
.vertexTransformer(SHADING_TRANSFORMER)
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material CHUNK_CUTOUT_MIPPED_UNSHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_CUTOUT_MIPPED_UNSHADED = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.HALF)
|
.cutout(CutoutShaders.HALF)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.diffuse(false)
|
.diffuse(false)
|
||||||
.fallbackRenderType(RenderType.cutoutMipped())
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final Material CHUNK_CUTOUT_SHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_CUTOUT_SHADED = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.ONE_TENTH)
|
.cutout(CutoutShaders.ONE_TENTH)
|
||||||
.mipmap(false)
|
.mipmap(false)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.fallbackRenderType(RenderType.cutout())
|
|
||||||
.vertexTransformer(SHADING_TRANSFORMER)
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material CHUNK_CUTOUT_UNSHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_CUTOUT_UNSHADED = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.ONE_TENTH)
|
.cutout(CutoutShaders.ONE_TENTH)
|
||||||
.mipmap(false)
|
.mipmap(false)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.diffuse(false)
|
.diffuse(false)
|
||||||
.fallbackRenderType(RenderType.cutout())
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final Material CHUNK_TRANSLUCENT_SHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_TRANSLUCENT_SHADED = SimpleMaterial.builder()
|
||||||
.transparency(Transparency.TRANSLUCENT)
|
.transparency(Transparency.TRANSLUCENT)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.fallbackRenderType(RenderType.translucent())
|
|
||||||
.vertexTransformer(SHADING_TRANSFORMER)
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material CHUNK_TRANSLUCENT_UNSHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_TRANSLUCENT_UNSHADED = SimpleMaterial.builder()
|
||||||
.transparency(Transparency.TRANSLUCENT)
|
.transparency(Transparency.TRANSLUCENT)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.diffuse(false)
|
.diffuse(false)
|
||||||
.fallbackRenderType(RenderType.translucent())
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final Material CHUNK_TRIPWIRE_SHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_TRIPWIRE_SHADED = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.ONE_TENTH)
|
.cutout(CutoutShaders.ONE_TENTH)
|
||||||
.transparency(Transparency.TRANSLUCENT)
|
.transparency(Transparency.TRANSLUCENT)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.fallbackRenderType(RenderType.tripwire())
|
|
||||||
.vertexTransformer(SHADING_TRANSFORMER)
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material CHUNK_TRIPWIRE_UNSHADED = SimpleMaterial.builder()
|
public static final Material CHUNK_TRIPWIRE_UNSHADED = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.ONE_TENTH)
|
.cutout(CutoutShaders.ONE_TENTH)
|
||||||
.transparency(Transparency.TRANSLUCENT)
|
.transparency(Transparency.TRANSLUCENT)
|
||||||
.useOverlay(false)
|
.useOverlay(false)
|
||||||
.diffuse(false)
|
.diffuse(false)
|
||||||
.fallbackRenderType(RenderType.tripwire())
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final Material CHEST = SimpleMaterial.builder()
|
public static final Material CHEST = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.ONE_TENTH)
|
.cutout(CutoutShaders.ONE_TENTH)
|
||||||
.texture(Sheets.CHEST_SHEET)
|
.texture(Sheets.CHEST_SHEET)
|
||||||
.mipmap(false)
|
.mipmap(false)
|
||||||
.fallbackRenderType(Sheets.chestSheet())
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material SHULKER = SimpleMaterial.builder()
|
public static final Material SHULKER = SimpleMaterial.builder()
|
||||||
.cutout(CutoutShaders.ONE_TENTH)
|
.cutout(CutoutShaders.ONE_TENTH)
|
||||||
.texture(Sheets.SHULKER_SHEET)
|
.texture(Sheets.SHULKER_SHEET)
|
||||||
.mipmap(false)
|
.mipmap(false)
|
||||||
.backfaceCulling(false)
|
.backfaceCulling(false)
|
||||||
.fallbackRenderType(Sheets.shulkerBoxSheet())
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material BELL = SimpleMaterial.builder()
|
public static final Material BELL = SimpleMaterial.builder()
|
||||||
.mipmap(false)
|
.mipmap(false)
|
||||||
.fallbackRenderType(Sheets.solidBlockSheet())
|
|
||||||
.build();
|
.build();
|
||||||
public static final Material MINECART = SimpleMaterial.builder()
|
public static final Material MINECART = SimpleMaterial.builder()
|
||||||
.texture(MINECART_LOCATION)
|
.texture(MINECART_LOCATION)
|
||||||
.mipmap(false)
|
.mipmap(false)
|
||||||
.fallbackRenderType(RenderType.entitySolid(MINECART_LOCATION))
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private Materials() {
|
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.FogShader;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
import com.jozufozu.flywheel.api.material.MaterialShaders;
|
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.Transparency;
|
||||||
import com.jozufozu.flywheel.api.material.WriteMask;
|
import com.jozufozu.flywheel.api.material.WriteMask;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.inventory.InventoryMenu;
|
import net.minecraft.world.inventory.InventoryMenu;
|
||||||
|
|
||||||
public class SimpleMaterial implements Material {
|
public class SimpleMaterial implements Material {
|
||||||
protected final RenderType fallbackRenderType;
|
|
||||||
protected final MaterialVertexTransformer vertexTransformer;
|
|
||||||
|
|
||||||
protected final MaterialShaders shaders;
|
protected final MaterialShaders shaders;
|
||||||
protected final FogShader fog;
|
protected final FogShader fog;
|
||||||
protected final CutoutShader cutout;
|
protected final CutoutShader cutout;
|
||||||
|
@ -36,8 +31,6 @@ public class SimpleMaterial implements Material {
|
||||||
protected final boolean diffuse;
|
protected final boolean diffuse;
|
||||||
|
|
||||||
protected SimpleMaterial(Builder builder) {
|
protected SimpleMaterial(Builder builder) {
|
||||||
fallbackRenderType = builder.getFallbackRenderType();
|
|
||||||
vertexTransformer = builder.getVertexTransformer();
|
|
||||||
shaders = builder.shaders();
|
shaders = builder.shaders();
|
||||||
fog = builder.fog();
|
fog = builder.fog();
|
||||||
cutout = builder.cutout();
|
cutout = builder.cutout();
|
||||||
|
@ -62,16 +55,6 @@ public class SimpleMaterial implements Material {
|
||||||
return new Builder(material);
|
return new Builder(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RenderType getFallbackRenderType() {
|
|
||||||
return fallbackRenderType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MaterialVertexTransformer getVertexTransformer() {
|
|
||||||
return vertexTransformer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MaterialShaders shaders() {
|
public MaterialShaders shaders() {
|
||||||
return shaders;
|
return shaders;
|
||||||
|
@ -143,9 +126,6 @@ public class SimpleMaterial implements Material {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder implements Material {
|
public static class Builder implements Material {
|
||||||
protected RenderType fallbackRenderType;
|
|
||||||
protected MaterialVertexTransformer vertexTransformer;
|
|
||||||
|
|
||||||
protected MaterialShaders shaders;
|
protected MaterialShaders shaders;
|
||||||
protected FogShader fog;
|
protected FogShader fog;
|
||||||
protected CutoutShader cutout;
|
protected CutoutShader cutout;
|
||||||
|
@ -165,9 +145,6 @@ public class SimpleMaterial implements Material {
|
||||||
protected boolean diffuse;
|
protected boolean diffuse;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
fallbackRenderType = RenderType.solid();
|
|
||||||
vertexTransformer = (vertexList, level) -> {
|
|
||||||
};
|
|
||||||
shaders = StandardMaterialShaders.DEFAULT;
|
shaders = StandardMaterialShaders.DEFAULT;
|
||||||
fog = FogShaders.LINEAR;
|
fog = FogShaders.LINEAR;
|
||||||
cutout = CutoutShaders.OFF;
|
cutout = CutoutShaders.OFF;
|
||||||
|
@ -189,8 +166,6 @@ public class SimpleMaterial implements Material {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder copyFrom(Material material) {
|
public Builder copyFrom(Material material) {
|
||||||
fallbackRenderType = material.getFallbackRenderType();
|
|
||||||
vertexTransformer = material.getVertexTransformer();
|
|
||||||
shaders = material.shaders();
|
shaders = material.shaders();
|
||||||
fog = material.fog();
|
fog = material.fog();
|
||||||
cutout = material.cutout();
|
cutout = material.cutout();
|
||||||
|
@ -208,16 +183,6 @@ public class SimpleMaterial implements Material {
|
||||||
return this;
|
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) {
|
public Builder shaders(MaterialShaders value) {
|
||||||
this.shaders = value;
|
this.shaders = value;
|
||||||
return this;
|
return this;
|
||||||
|
@ -288,16 +253,6 @@ public class SimpleMaterial implements Material {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RenderType getFallbackRenderType() {
|
|
||||||
return fallbackRenderType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MaterialVertexTransformer getVertexTransformer() {
|
|
||||||
return vertexTransformer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MaterialShaders shaders() {
|
public MaterialShaders shaders() {
|
||||||
return shaders;
|
return shaders;
|
||||||
|
|
Loading…
Reference in a new issue