More clean up

This commit is contained in:
PepperCode1 2023-04-07 16:01:03 -07:00
parent 945ed9a1e4
commit 72b5968305
118 changed files with 899 additions and 953 deletions

View file

@ -3,7 +3,9 @@ package com.jozufozu.flywheel;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.slf4j.Logger;
import com.jozufozu.flywheel.backend.Backends;
import com.jozufozu.flywheel.backend.Loader;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer;
import com.jozufozu.flywheel.config.BackendArgument;
import com.jozufozu.flywheel.config.FlwCommands;
@ -14,14 +16,12 @@ import com.jozufozu.flywheel.impl.BackendManagerImpl;
import com.jozufozu.flywheel.impl.IdRegistryImpl;
import com.jozufozu.flywheel.impl.RegistryImpl;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.backend.Backends;
import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.model.PartialModel;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.lib.struct.StructTypes;
import com.jozufozu.flywheel.lib.util.QuadConverter;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
@ -36,7 +36,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.CrashReportCallables;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.IExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
@ -47,7 +46,6 @@ import net.minecraftforge.network.NetworkConstants;
@Mod(Flywheel.ID)
public class Flywheel {
public static final String ID = "flywheel";
public static final Logger LOGGER = LogUtils.getLogger();
private static ArtifactVersion version;
@ -78,11 +76,12 @@ public class Flywheel {
private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener(FlwCommands::registerClientCommands);
forgeEventBus.addListener(BackendManagerImpl::onReloadRenderers);
forgeEventBus.addListener(EventPriority.HIGHEST, QuadConverter::onReloadRenderers);
forgeEventBus.addListener(Models::onReloadRenderers);
forgeEventBus.addListener(DrawBuffer::onReloadRenderers);
forgeEventBus.addListener(InstancedRenderDispatcher::onReloadRenderers);
forgeEventBus.addListener(InstancedRenderDispatcher::onRenderStage);
forgeEventBus.addListener(InstancedRenderDispatcher::onBeginFrame);
forgeEventBus.addListener(InstancedRenderDispatcher::tick);
@ -100,23 +99,23 @@ public class Flywheel {
// forgeEventBus.addListener(ExampleEffect::tick);
// forgeEventBus.addListener(ExampleEffect::onReload);
ShadersModHandler.init();
BackendManagerImpl.init();
Pipelines.init();
Backends.init();
Loader.init();
ShadersModHandler.init();
Formats.init();
StructTypes.init();
Materials.init();
Contexts.init();
Pipelines.init();
MaterialIndices.init();
VanillaInstances.init();
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendNameForCrashReport);
// https://github.com/Jozufozu/Flywheel/issues/69
// Weird issue with accessor loading.
// Only thing I've seen that's close to a fix is to force the class to load before trying to use it.

View file

@ -17,9 +17,8 @@ public final class BackendManager {
return BackendManagerImpl.isOn();
}
// TODO: definitively sort existing calls to this method into API (include behavior in javadoc) or default backend code
public static void refresh() {
BackendManagerImpl.refresh();
public static Backend getOffBackend() {
return BackendManagerImpl.getOffBackend();
}
public static Backend getDefaultBackend() {

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.event;
import org.jetbrains.annotations.NotNull;
import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.util.MatrixUtil;
import com.jozufozu.flywheel.lib.math.MatrixUtil;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.api.instance;
import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.struct.InstancePart;
import net.minecraft.world.level.block.entity.BlockEntity;

View file

@ -2,8 +2,8 @@ package com.jozufozu.flywheel.api.instance;
import org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.InstancePart;
/**
* An interface giving {@link Instance}s a hook to have a function called at

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.api.instance;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.InstancePart;
/**
* An interface giving {@link Instance}s a hook to have a function called at

View file

@ -1,5 +1,7 @@
package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.api.struct.InstancePart;
/**
* An instancer is how you interact with an instanced model.
* <p>

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
public interface InstancerProvider {

View file

@ -1,10 +1,8 @@
package com.jozufozu.flywheel.api.material;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
@ -21,9 +19,5 @@ public interface Material {
RenderType getBatchingRenderType();
VertexTransformer getVertexTransformer();
interface VertexTransformer {
void transform(MutableVertexList vertexList, ClientLevel level);
}
MaterialVertexTransformer getVertexTransformer();
}

View file

@ -0,0 +1,9 @@
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);
}

View file

@ -5,13 +5,11 @@ import org.joml.Vector4fc;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.gl.buffer.ElementBuffer;
import com.jozufozu.flywheel.lib.util.QuadConverter;
/**
* A holder for arbitrary vertex data that can be written to memory or a vertex list.
*/
public interface Mesh {
VertexType getVertexType();
/**
@ -50,18 +48,9 @@ public interface Mesh {
/**
* Create an element buffer object that indexes the vertices of this mesh.
*
* <p>
* Very often models in minecraft are made up of sequential quads, which is a very predictable pattern.
* The default implementation accommodates this, however this can be overridden to change the behavior and
* support more complex models.
* </p>
* @return an element buffer object indexing this model's vertices.
*/
default ElementBuffer createEBO() {
return QuadConverter.getInstance()
.quads2Tris(getVertexCount() / 4);
}
ElementBuffer createEBO();
Vector4fc getBoundingSphere();

View file

@ -1,7 +1,6 @@
package com.jozufozu.flywheel.api.instancer;
package com.jozufozu.flywheel.api.struct;
public interface Handle {
void setChanged();
void setDeleted();

View file

@ -1,6 +1,4 @@
package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.api.struct.StructType;
package com.jozufozu.flywheel.api.struct;
public interface InstancePart {
StructType<?> type();

View file

@ -1,13 +1,9 @@
package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.layout.BufferLayout;
import com.jozufozu.flywheel.api.registry.Registry;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.impl.RegistryImpl;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.resources.ResourceLocation;
/**
@ -33,10 +29,5 @@ public interface StructType<P extends InstancePart> {
ResourceLocation instanceShader();
VertexTransformer<P> getVertexTransformer();
interface VertexTransformer<P extends InstancePart> {
void transform(MutableVertexList vertexList, P struct, ClientLevel level);
}
StructVertexTransformer<P> getVertexTransformer();
}

View file

@ -0,0 +1,9 @@
package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import net.minecraft.client.multiplayer.ClientLevel;
public interface StructVertexTransformer<P extends InstancePart> {
void transform(MutableVertexList vertexList, P struct, ClientLevel level);
}

View file

@ -1,14 +1,11 @@
package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.api.instancer.InstancePart;
/**
* StructWriters can quickly consume many instances of S and write them to some memory address.
* StructWriters can quickly consume many instances and write them to some memory address.
*/
public interface StructWriter<P extends InstancePart> {
/**
* Write the given struct to the given memory address.
*/
void write(final long ptr, final P struct);
}

View file

@ -7,7 +7,6 @@ package com.jozufozu.flywheel.api.vertex;
* VertexList assumes nothing about the layout of the vertices. Implementations should feel free to return constants
* for values that are unused in their layout.
* </p>
* TODO: more flexible elements?
*/
public interface VertexList {
float x(int index);

View file

@ -1,56 +0,0 @@
package com.jozufozu.flywheel.backend;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.FlywheelLevel;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.LevelAccessor;
public class BackendUtil {
private static ParallelTaskExecutor executor;
/**
* Get a thread pool for running Flywheel related work in parallel.
* @return A global Flywheel thread pool.
*/
public static ParallelTaskExecutor getTaskExecutor() {
if (executor == null) {
executor = new ParallelTaskExecutor("Flywheel");
executor.startWorkers();
}
return executor;
}
@Contract("null -> false")
public static boolean canUseInstancing(@Nullable LevelAccessor level) {
return BackendManager.isOn() && isFlywheelLevel(level);
}
/**
* Used to avoid calling Flywheel functions on (fake) levels that don't specifically support it.
*/
public static boolean isFlywheelLevel(@Nullable LevelAccessor level) {
if (level == null) {
return false;
}
if (!level.isClientSide()) {
return false;
}
if (level instanceof FlywheelLevel flywheelLevel && flywheelLevel.supportsFlywheel()) {
return true;
}
return level == Minecraft.getInstance().level;
}
public static boolean isGameActive() {
return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null);
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.lib.backend;
package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.backend.Backend;
@ -6,30 +6,20 @@ 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.versioned.GlCompat;
import com.jozufozu.flywheel.lib.backend.SimpleBackend;
import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextComponent;
public class Backends {
public static final Backend OFF = SimpleBackend.builder()
.engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED))
.engineFactory(level -> {
throw new IllegalStateException("Cannot create engine when backend is off.");
})
.fallback(() -> Backends.OFF)
.supported(() -> true)
.register(Flywheel.rl("off"));
/**
* Use a thread pool to buffer instances in parallel on the CPU.
*/
public static final Backend BATCHING = SimpleBackend.builder()
.engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN))
.engineFactory(level -> new BatchingEngine())
.fallback(() -> Backends.OFF)
.supported(() -> !ShadersModHandler.isShaderPackInUse())
.register(Flywheel.rl("batching"));

View file

@ -1,13 +1,11 @@
package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.error.ErrorReporter;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.impl.BackendManagerImpl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
@ -27,8 +25,6 @@ public class Loader implements ResourceManagerReloadListener {
@Override
public void onResourceManagerReload(ResourceManager manager) {
BackendManager.refresh();
var errorReporter = new ErrorReporter();
ShaderSources sources = new ShaderSources(errorReporter, manager);
@ -38,14 +34,12 @@ public class Loader implements ResourceManagerReloadListener {
FlwCompiler.INSTANCE = new FlwCompiler(sources);
ClientLevel level = Minecraft.getInstance().level;
if (level != null) {
InstancedRenderDispatcher.resetInstanceWorld(level);
}
// TODO: Move this to the impl package
BackendManagerImpl.refresh(Minecraft.getInstance().level);
}
public static void init() {
// Can be null when running datagenerators due to the unfortunate time we call this
// Can be null when running data generators due to the unfortunate time we call this
Minecraft minecraft = Minecraft.getInstance();
if (minecraft == null) {
return;

View file

@ -1,9 +1,10 @@
package com.jozufozu.flywheel.lib.pipeline;
package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent;
import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.lib.pipeline.SimplePipeline;
import net.minecraft.resources.ResourceLocation;
@ -22,7 +23,6 @@ public class Pipelines {
.build();
public static void init() {
// noop
}
public static class Files {

View file

@ -17,6 +17,7 @@ import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlProgram;
@ -27,7 +28,6 @@ import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.util.StringUtil;
public class FlwCompiler {

View file

@ -13,7 +13,6 @@ import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlShader;
import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.util.FlwUtil;
public class ShaderCompiler {
private final Map<ShaderKey, CompilationResult> shaderCache = new HashMap<>();
@ -87,7 +86,7 @@ public class ShaderCompiler {
}
public static class Builder {
private Consumer<FailedCompilation> errorConsumer = FlwUtil::noop;
private Consumer<FailedCompilation> errorConsumer = error -> {};
private CompilationFactory factory = Compilation::new;
private Includer includer = RecursiveIncluder.INSTANCE;

View file

@ -2,14 +2,12 @@ package com.jozufozu.flywheel.backend.engine;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
public abstract class AbstractInstancer<P extends InstancePart> implements Instancer<P> {
public final StructType<P> type;
// Lock for all instance data, only needs to be used in methods that may run on the TaskExecutor.
@ -42,30 +40,33 @@ public abstract class AbstractInstancer<P extends InstancePart> implements Insta
}
}
/**
* Clear all instance data without freeing resources.
*/
public void clear() {
handles.forEach(HandleImpl::clear);
data.clear();
handles.clear();
changed.clear();
deleted.clear();
}
public int getInstanceCount() {
return data.size();
}
public List<P> getRange(int start, int end) {
return data.subList(start, end);
public void notifyDirty(int index) {
if (index < 0 || index >= getInstanceCount()) {
return;
}
synchronized (lock) {
changed.set(index);
}
}
public List<P> getAll() {
return data;
public void notifyRemoval(int index) {
if (index < 0 || index >= getInstanceCount()) {
return;
}
synchronized (lock) {
deleted.set(index);
}
}
protected void removeDeletedInstances() {
if (deleted.isEmpty()) {
return;
}
// Figure out which elements are to be removed.
final int oldSize = this.data.size();
int removeCount = deleted.cardinality();
@ -95,26 +96,19 @@ public abstract class AbstractInstancer<P extends InstancePart> implements Insta
.clear();
}
/**
* Clear all instance data without freeing resources.
*/
public void clear() {
handles.forEach(HandleImpl::clear);
data.clear();
handles.clear();
changed.clear();
deleted.clear();
}
@Override
public String toString() {
return "Instancer[" + getInstanceCount() + ']';
}
public void notifyDirty(int index) {
if (index < 0 || index >= getInstanceCount()) {
return;
}
synchronized (lock) {
changed.set(index);
}
}
public void notifyRemoval(int index) {
if (index < 0 || index >= getInstanceCount()) {
return;
}
synchronized (lock) {
deleted.set(index);
}
return "AbstractInstancer[" + getInstanceCount() + ']';
}
}

View file

@ -1,9 +1,8 @@
package com.jozufozu.flywheel.backend.engine;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.struct.Handle;
public class HandleImpl implements Handle {
private final AbstractInstancer<?> instancer;
private int index;

View file

@ -1,8 +1,8 @@
package com.jozufozu.flywheel.backend.engine;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
public record InstancerKey<P extends InstancePart>(StructType<P> type, Model model, RenderStage stage) {

View file

@ -10,9 +10,9 @@ import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.lib.math.MoreMath;
import com.jozufozu.flywheel.lib.math.RenderMath;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.RenderMath;
public class UniformBuffer {
@ -93,7 +93,7 @@ public class UniformBuffer {
var builder = ImmutableList.<LiveProvider>builder();
int totalBytes = 0;
for (ShaderUniforms provider : providers) {
int size = FlwUtil.align16(provider.byteSize());
int size = MoreMath.align16(provider.byteSize());
builder.add(new LiveProvider(provider, totalBytes, size));

View file

@ -39,6 +39,10 @@ public class BatchedMeshPool {
growthMargin = vertexFormat.getVertexSize() * 32;
}
public VertexFormat getVertexFormat() {
return vertexFormat;
}
/**
* Allocate a mesh in the arena.
*
@ -139,10 +143,6 @@ public class BatchedMeshPool {
pendingUpload.clear();
}
public VertexFormat getVertexFormat() {
return vertexFormat;
}
@Override
public String toString() {
return "BatchedMeshPool{" + "vertexFormat=" + vertexFormat + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}';

View file

@ -5,9 +5,9 @@ import java.util.List;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.util.FlwUtil;

View file

@ -15,10 +15,10 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.engine.InstancerKey;
import com.mojang.blaze3d.vertex.VertexFormat;
@ -83,7 +83,7 @@ public class BatchingTransformManager {
var meshes = model.getMeshes();
for (var entry : meshes.entrySet()) {
var material = entry.getKey();
var renderType = material.getBatchingRenderType();
RenderType renderType = material.getBatchingRenderType();
TransformCall<?> transformCall = new TransformCall<>(instancer, material, alloc(entry.getValue(), renderType.format()));
transformSet.put(renderType, transformCall);
}

View file

@ -1,18 +1,25 @@
package com.jozufozu.flywheel.backend.engine.batching;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import java.util.List;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
public class CPUInstancer<P extends InstancePart> extends AbstractInstancer<P> {
public CPUInstancer(StructType<P> type) {
super(type);
}
void update() {
if (!deleted.isEmpty()) {
removeDeletedInstances();
}
public List<P> getRange(int start, int end) {
return data.subList(start, end);
}
public List<P> getAll() {
return data;
}
public void update() {
removeDeletedInstances();
}
}

View file

@ -32,7 +32,7 @@ public class DrawBuffer {
private boolean prepared;
private int vertexCount;
DrawBuffer(RenderType renderType, VertexFormat format, int stride, VertexListProvider provider) {
public DrawBuffer(RenderType renderType, VertexFormat format, int stride, VertexListProvider provider) {
this.renderType = renderType;
this.format = format;
this.stride = stride;

View file

@ -3,8 +3,6 @@ package com.jozufozu.flywheel.backend.engine.batching;
import java.util.EnumMap;
import java.util.Map;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
import com.jozufozu.flywheel.api.vertex.VertexListProviderRegistry;
@ -20,7 +18,6 @@ public class DrawBufferSet {
private final Map<RenderStage, DrawBuffer> buffers = new EnumMap<>(RenderStage.class);
@ApiStatus.Internal
public DrawBufferSet(RenderType renderType) {
this.renderType = renderType;
format = renderType.format();

View file

@ -2,17 +2,16 @@ package com.jozufozu.flywheel.backend.engine.batching;
import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructVertexTransformer;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import net.minecraft.client.multiplayer.ClientLevel;
@ -37,11 +36,11 @@ public class TransformCall<P extends InstancePart> {
return meshVertexCount * instancer.getInstanceCount();
}
void setup() {
public void setup() {
instancer.update();
}
void submitTasks(TaskExecutor executor, DrawBuffer buffer, int startVertex, PoseStack.Pose matrices, ClientLevel level) {
public void submitTasks(TaskExecutor executor, DrawBuffer buffer, int startVertex, PoseStack.Pose matrices, ClientLevel level) {
int instances = instancer.getInstanceCount();
while (instances > 0) {
@ -57,21 +56,21 @@ public class TransformCall<P extends InstancePart> {
}
}
private void transformRange(ReusableVertexList vertexList, int from, int to, PoseStack.Pose matrices, ClientLevel level) {
public void transformRange(ReusableVertexList vertexList, int from, int to, PoseStack.Pose matrices, ClientLevel level) {
transformList(vertexList, instancer.getRange(from, to), matrices, level);
}
void transformAll(ReusableVertexList vertexList, PoseStack.Pose matrices, ClientLevel level) {
public void transformAll(ReusableVertexList vertexList, PoseStack.Pose matrices, ClientLevel level) {
transformList(vertexList, instancer.getAll(), matrices, level);
}
private void transformList(ReusableVertexList vertexList, List<P> parts, PoseStack.Pose matrices, ClientLevel level) {
public void transformList(ReusableVertexList vertexList, List<P> parts, PoseStack.Pose matrices, ClientLevel level) {
long anchorPtr = vertexList.ptr();
int totalVertexCount = vertexList.vertexCount();
vertexList.vertexCount(meshVertexCount);
StructType.VertexTransformer<P> structVertexTransformer = instancer.type.getVertexTransformer();
StructVertexTransformer<P> structVertexTransformer = instancer.type.getVertexTransformer();
for (P p : parts) {
mesh.copyTo(vertexList.ptr());
@ -88,34 +87,12 @@ public class TransformCall<P extends InstancePart> {
}
private static void applyMatrices(MutableVertexList vertexList, PoseStack.Pose matrices) {
Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f();
Matrix4f modelMatrix = matrices.pose();
Matrix3f normalMatrix = matrices.normal();
for (int i = 0; i < vertexList.vertexCount(); i++) {
pos.set(
vertexList.x(i),
vertexList.y(i),
vertexList.z(i),
1f
);
pos.transform(modelMatrix);
vertexList.x(i, pos.x());
vertexList.y(i, pos.y());
vertexList.z(i, pos.z());
normal.set(
vertexList.normalX(i),
vertexList.normalY(i),
vertexList.normalZ(i)
);
normal.transform(normalMatrix);
normal.normalize();
vertexList.normalX(i, normal.x());
vertexList.normalY(i, normal.y());
vertexList.normalZ(i, normal.z());
VertexTransformations.transformPos(vertexList, i, modelMatrix);
VertexTransformations.transformNormal(vertexList, i, normalMatrix);
}
}
}

View file

@ -8,6 +8,7 @@ import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.layout.LayoutItem;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile;
@ -15,7 +16,6 @@ import com.jozufozu.flywheel.glsl.generate.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import net.minecraft.resources.ResourceLocation;

View file

@ -12,14 +12,14 @@ import static org.lwjgl.opengl.GL45.glVertexArrayElementBuffer;
import static org.lwjgl.opengl.GL45.glVertexArrayVertexBuffer;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.lib.util.QuadConverter;
public class IndirectCullingGroup<P extends InstancePart> {
@ -109,7 +109,7 @@ public class IndirectCullingGroup<P extends InstancePart> {
}
buffers.updateCounts(instanceCountThisFrame, drawSet.size());
meshPool.uploadAll();
meshPool.flush();
uploadInstanceData();
uploadIndirectCommands();
@ -174,7 +174,7 @@ public class IndirectCullingGroup<P extends InstancePart> {
int baseInstance = 0;
for (var batch : drawSet.indirectDraws) {
batch.prepare(baseInstance);
baseInstance += batch.instancer().instanceCount;
baseInstance += batch.instancer().getInstanceCount();
}
return baseInstance;
}

View file

@ -3,32 +3,48 @@ package com.jozufozu.flywheel.backend.engine.indirect;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.lib.material.MaterialIndices;
public final class IndirectDraw<P extends InstancePart> {
public class IndirectDraw<P extends InstancePart> {
private final IndirectInstancer<P> instancer;
private final IndirectMeshPool.BufferedMesh mesh;
private final Material material;
private final RenderStage stage;
int baseInstance = -1;
final int vertexMaterialID;
final int fragmentMaterialID;
private final int vertexMaterialID;
private final int fragmentMaterialID;
boolean needsFullWrite = true;
private int baseInstance = -1;
private boolean needsFullWrite = true;
IndirectDraw(IndirectInstancer<P> instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh mesh) {
public IndirectDraw(IndirectInstancer<P> instancer, Material material, IndirectMeshPool.BufferedMesh mesh, RenderStage stage) {
this.instancer = instancer;
this.material = material;
this.stage = stage;
this.mesh = mesh;
this.stage = stage;
this.vertexMaterialID = MaterialIndices.getVertexShaderIndex(material);
this.fragmentMaterialID = MaterialIndices.getFragmentShaderIndex(material);
}
public IndirectInstancer<P> instancer() {
return instancer;
}
public Material material() {
return material;
}
public IndirectMeshPool.BufferedMesh mesh() {
return mesh;
}
public RenderStage stage() {
return stage;
}
public void prepare(int baseInstance) {
instancer.update();
if (baseInstance == this.baseInstance) {
@ -39,7 +55,7 @@ public final class IndirectDraw<P extends InstancePart> {
needsFullWrite = true;
}
void writeObjects(long objectPtr, long batchIDPtr, int batchID) {
public void writeObjects(long objectPtr, long batchIDPtr, int batchID) {
if (needsFullWrite) {
instancer.writeFull(objectPtr, batchIDPtr, batchID);
} else {
@ -48,7 +64,7 @@ public final class IndirectDraw<P extends InstancePart> {
}
public void writeIndirectCommand(long ptr) {
var boundingSphere = mesh.mesh.getBoundingSphere();
var boundingSphere = mesh.getMesh().getBoundingSphere();
MemoryUtil.memPutInt(ptr, mesh.getIndexCount()); // count
MemoryUtil.memPutInt(ptr + 4, 0); // instanceCount - to be incremented by the compute shader
@ -59,22 +75,5 @@ public final class IndirectDraw<P extends InstancePart> {
boundingSphere.getToAddress(ptr + 20); // boundingSphere
MemoryUtil.memPutInt(ptr + 36, vertexMaterialID); // vertexMaterialID
MemoryUtil.memPutInt(ptr + 40, fragmentMaterialID); // fragmentMaterialID
}
public IndirectInstancer<P> instancer() {
return instancer;
}
public IndirectMeshPool.BufferedMesh mesh() {
return mesh;
}
public Material material() {
return material;
}
public RenderStage stage() {
return stage;
}
}

View file

@ -6,16 +6,15 @@ import java.util.List;
import java.util.Map;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.engine.InstancerKey;
import com.jozufozu.flywheel.util.Pair;
public class IndirectDrawManager {
private final Map<InstancerKey<?>, IndirectInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>();
private final List<IndirectInstancer<?>> initializedInstancers = new ArrayList<>();

View file

@ -11,10 +11,9 @@ import java.util.List;
import java.util.Map;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.util.Textures;
public class IndirectDrawSet<P extends InstancePart> {
@ -31,7 +30,7 @@ public class IndirectDrawSet<P extends InstancePart> {
}
public void add(IndirectInstancer<P> instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh bufferedMesh) {
indirectDraws.add(new IndirectDraw<>(instancer, material, stage, bufferedMesh));
indirectDraws.add(new IndirectDraw<>(instancer, material, bufferedMesh, stage));
determineMultiDraws();
}

View file

@ -7,9 +7,9 @@ import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.gl.GlStateTracker;

View file

@ -2,52 +2,43 @@ package com.jozufozu.flywheel.backend.engine.indirect;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
public class IndirectInstancer<P extends InstancePart> extends AbstractInstancer<P> {
private final long objectStride;
private final StructWriter<P> writer;
int instanceCount = 0;
private final long instanceStride;
public IndirectInstancer(StructType<P> type) {
super(type);
this.objectStride = type.getLayout()
this.instanceStride = type.getLayout()
.getStride();
writer = type.getWriter();
}
public boolean isEmpty() {
return changed.isEmpty() && deleted.isEmpty() && instanceCount == 0;
}
void update() {
if (!deleted.isEmpty()) {
removeDeletedInstances();
}
instanceCount = data.size();
public void update() {
removeDeletedInstances();
}
public void writeSparse(long objectPtr, long batchIDPtr, int batchID) {
final int size = data.size();
int count = data.size();
StructWriter<P> writer = type.getWriter();
for (int i = changed.nextSetBit(0); i >= 0 && i < count; i = changed.nextSetBit(i + 1)) {
// write object
writer.write(objectPtr + instanceStride * i, data.get(i));
for (int i = changed.nextSetBit(0); i >= 0 && i < size; i = changed.nextSetBit(i + 1)) {
writer.write(objectPtr + i * objectStride, data.get(i));
MemoryUtil.memPutInt(batchIDPtr + i * IndirectBuffers.INT_SIZE, batchID);
// write batchID
MemoryUtil.memPutInt(batchIDPtr + IndirectBuffers.INT_SIZE * i, batchID);
}
changed.clear();
}
public void writeFull(long objectPtr, long batchIDPtr, int batchID) {
StructWriter<P> writer = type.getWriter();
for (var object : data) {
// write object
writer.write(objectPtr, object);
objectPtr += objectStride;
objectPtr += instanceStride;
// write batchID
MemoryUtil.memPutInt(batchIDPtr, batchID);

View file

@ -39,6 +39,10 @@ public class IndirectMeshPool {
clientStorage = MemoryBlock.malloc(byteCapacity);
}
public VertexType getVertexType() {
return vertexType;
}
/**
* Allocate a model in the arena.
*
@ -60,24 +64,26 @@ public class IndirectMeshPool {
return meshes.get(mesh);
}
void uploadAll() {
if (!dirty) {
return;
public void flush() {
if (dirty) {
uploadAll();
dirty = false;
}
dirty = false;
}
private void uploadAll() {
final long ptr = clientStorage.ptr();
int byteIndex = 0;
int baseVertex = 0;
for (BufferedMesh model : meshList) {
model.byteIndex = byteIndex;
model.baseVertex = baseVertex;
for (BufferedMesh mesh : meshList) {
mesh.byteIndex = byteIndex;
mesh.baseVertex = baseVertex;
model.buffer(ptr);
mesh.buffer(ptr);
byteIndex += model.size();
baseVertex += model.mesh.getVertexCount();
byteIndex += mesh.size();
baseVertex += mesh.mesh.getVertexCount();
}
nglNamedBufferSubData(vbo, 0, byteIndex, ptr);
@ -90,26 +96,18 @@ public class IndirectMeshPool {
meshList.clear();
}
public VertexType getVertexType() {
return vertexType;
}
public class BufferedMesh {
public final Mesh mesh;
private final Mesh mesh;
private final int vertexCount;
private long byteIndex;
private int baseVertex;
private BufferedMesh(Mesh mesh) {
this.mesh = mesh;
vertexCount = mesh.getVertexCount();
}
private void buffer(long ptr) {
mesh.write(ptr + byteIndex);
}
public Mesh getMesh() {
return mesh;
}
@ -129,5 +127,9 @@ public class IndirectMeshPool {
public VertexType getVertexType() {
return vertexType;
}
private void buffer(long ptr) {
mesh.write(ptr + byteIndex);
}
}
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.util;
package com.jozufozu.flywheel.backend.engine.indirect;
import org.lwjgl.opengl.GL32;

View file

@ -1,86 +1,50 @@
package com.jozufozu.flywheel.backend.engine.instancing;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.gl.GlStateTracker;
import com.jozufozu.flywheel.gl.array.GlVertexArray;
public class DrawCall {
private final GPUInstancer<?> instancer;
private final InstancedMeshPool.BufferedMesh mesh;
final GPUInstancer<?> instancer;
final Material material;
private final int meshAttributes;
InstancedMeshPool.BufferedMesh bufferedMesh;
GlVertexArray vao;
private GlVertexArray vao;
DrawCall(GPUInstancer<?> instancer, Material material, InstancedMeshPool.BufferedMesh mesh) {
public DrawCall(GPUInstancer<?> instancer, InstancedMeshPool.BufferedMesh mesh) {
this.instancer = instancer;
this.material = material;
this.vao = new GlVertexArray();
this.bufferedMesh = mesh;
this.meshAttributes = this.bufferedMesh.getAttributeCount();
this.vao.enableArrays(this.meshAttributes + instancer.instanceFormat.getAttributeCount());
this.mesh = mesh;
meshAttributes = this.mesh.getAttributeCount();
vao = new GlVertexArray();
vao.enableArrays(meshAttributes + this.instancer.getAttributeCount());
}
public Material getMaterial() {
return material;
}
public VertexType getVertexType() {
return bufferedMesh.getVertexType();
public boolean isInvalid() {
return instancer.isInvalid() || vao == null;
}
public void render() {
if (invalid()) {
if (isInvalid()) {
return;
}
try (var ignored = GlStateTracker.getRestoreState()) {
instancer.update();
this.instancer.update();
instancer.bindToVAO(vao, meshAttributes);
bindInstancerToVAO();
if (this.instancer.glInstanceCount > 0) {
bufferedMesh.drawInstances(vao, this.instancer.glInstanceCount);
if (instancer.getInstanceCount() > 0) {
mesh.drawInstances(vao, instancer.getInstanceCount());
}
}
}
public boolean shouldRemove() {
return invalid();
}
/**
* Only {@code true} if the InstancedModel has been destroyed.
*/
private boolean invalid() {
return this.instancer.vbo == null || bufferedMesh == null || vao == null;
}
private void bindInstancerToVAO() {
if (!this.instancer.boundTo.add(vao)) {
return;
}
var instanceFormat = this.instancer.instanceFormat;
vao.bindAttributes(this.instancer.vbo, this.meshAttributes, instanceFormat, 0L);
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
vao.setAttributeDivisor(this.meshAttributes + i, 1);
}
}
public void delete() {
if (invalid()) {
if (vao == null) {
return;
}
vao.delete();
bufferedMesh.delete();
vao = null;
bufferedMesh = null;
}
}

View file

@ -4,8 +4,8 @@ import java.util.HashSet;
import java.util.Set;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.layout.BufferLayout;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
@ -16,17 +16,24 @@ import com.jozufozu.flywheel.gl.buffer.GlBufferUsage;
import com.jozufozu.flywheel.gl.buffer.MappedBuffer;
public class GPUInstancer<P extends InstancePart> extends AbstractInstancer<P> {
private final BufferLayout instanceFormat;
private final int instanceStride;
final BufferLayout instanceFormat;
final Set<GlVertexArray> boundTo = new HashSet<>();
GlBuffer vbo;
int glInstanceCount = 0;
boolean anyToUpdate;
private final Set<GlVertexArray> boundTo = new HashSet<>();
private GlBuffer vbo;
public GPUInstancer(StructType<P> type) {
super(type);
this.instanceFormat = type.getLayout();
instanceFormat = type.getLayout();
instanceStride = instanceFormat.getStride();
}
public int getAttributeCount() {
return instanceFormat.getAttributeCount();
}
public boolean isInvalid() {
return vbo == null;
}
public void init() {
@ -35,63 +42,59 @@ public class GPUInstancer<P extends InstancePart> extends AbstractInstancer<P> {
}
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW);
vbo.setGrowthMargin(instanceFormat.getStride() * 16);
vbo.setGrowthMargin(instanceStride * 16);
}
public boolean isEmpty() {
return deleted.isEmpty() && changed.isEmpty() && glInstanceCount == 0;
public void update() {
removeDeletedInstances();
ensureBufferCapacity();
updateBuffer();
}
void update() {
if (!deleted.isEmpty()) {
removeDeletedInstances();
}
if (checkAndGrowBuffer()) {
// The instance vbo has moved, so we need to re-bind attributes
private void ensureBufferCapacity() {
int count = data.size();
int byteSize = instanceStride * count;
if (vbo.ensureCapacity(byteSize)) {
// The vbo has moved, so we need to re-bind attributes
boundTo.clear();
}
if (!changed.isEmpty()) {
clearAndUpdateBuffer();
}
glInstanceCount = data.size();
}
private void clearAndUpdateBuffer() {
final int size = data.size();
final long clearStart = (long) size * instanceFormat.getStride();
final long clearLength = vbo.getSize() - clearStart;
private void updateBuffer() {
if (changed.isEmpty()) {
return;
}
int count = data.size();
long clearStart = instanceStride * (long) count;
long clearLength = vbo.getSize() - clearStart;
try (MappedBuffer buf = vbo.map()) {
buf.clear(clearStart, clearLength);
if (size > 0) {
final long ptr = buf.getPtr();
final long stride = type.getLayout()
.getStride();
final StructWriter<P> writer = type.getWriter();
long ptr = buf.getPtr();
StructWriter<P> writer = type.getWriter();
for (int i = changed.nextSetBit(0); i >= 0 && i < size; i = changed.nextSetBit(i + 1)) {
writer.write(ptr + i * stride, data.get(i));
}
changed.clear();
for (int i = changed.nextSetBit(0); i >= 0 && i < count; i = changed.nextSetBit(i + 1)) {
writer.write(ptr + instanceStride * i, data.get(i));
}
changed.clear();
} catch (Exception e) {
Flywheel.LOGGER.error("Error updating GPUInstancer:", e);
}
}
/**
* @return {@code true} if the buffer moved.
*/
private boolean checkAndGrowBuffer() {
int size = this.data.size();
int stride = instanceFormat.getStride();
int requiredSize = size * stride;
public void bindToVAO(GlVertexArray vao, int attributeOffset) {
if (!boundTo.add(vao)) {
return;
}
return vbo.ensureCapacity(requiredSize);
vao.bindAttributes(vbo, attributeOffset, instanceFormat, 0L);
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
vao.setAttributeDivisor(attributeOffset + i, 1);
}
}
public void delete() {

View file

@ -39,9 +39,12 @@ public class InstancedMeshPool {
public InstancedMeshPool(VertexType vertexType) {
this.vertexType = vertexType;
int stride = vertexType.getLayout().getStride();
this.vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
vbo.setGrowthMargin(stride * 32);
}
this.vbo.setGrowthMargin(stride * 32);
public VertexType getVertexType() {
return vertexType;
}
/**
@ -161,10 +164,6 @@ public class InstancedMeshPool {
pendingUpload.clear();
}
public VertexType getVertexType() {
return vertexType;
}
@Override
public String toString() {
return "InstancedMeshPool{" + "vertexType=" + vertexType + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}';
@ -210,10 +209,6 @@ public class InstancedMeshPool {
boundTo.clear();
}
public void drawCall(GlVertexArray vao) {
drawInstances(vao, 1);
}
public void drawInstances(GlVertexArray vao, int instanceCount) {
if (isEmpty()) {
return;

View file

@ -14,16 +14,15 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.engine.InstancerKey;
public class InstancingDrawManager {
private final Map<InstancerKey<?>, GPUInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>();
private final List<GPUInstancer<?>> initializedInstancers = new ArrayList<>();
@ -48,9 +47,6 @@ public class InstancingDrawManager {
public void flush() {
for (var instancer : uninitializedInstancers) {
instancer.instancer()
.init();
add(instancer.instancer(), instancer.model(), instancer.stage());
}
uninitializedInstancers.clear();
@ -80,11 +76,13 @@ public class InstancingDrawManager {
}
private void add(GPUInstancer<?> instancer, Model model, RenderStage stage) {
instancer.init();
DrawSet drawSet = drawSets.computeIfAbsent(stage, DrawSet::new);
var meshes = model.getMeshes();
for (var entry : meshes.entrySet()) {
DrawCall drawCall = new DrawCall(instancer, entry.getKey(), alloc(entry.getValue()));
var shaderState = new ShaderState(drawCall.getMaterial(), drawCall.getVertexType(), drawCall.instancer.type);
var mesh = alloc(entry.getValue());
ShaderState shaderState = new ShaderState(entry.getKey(), mesh.getVertexType(), instancer.type);
DrawCall drawCall = new DrawCall(instancer, mesh);
drawSet.put(shaderState, drawCall);
}
initializedInstancers.add(instancer);
@ -96,7 +94,6 @@ public class InstancingDrawManager {
}
public static class DrawSet implements Iterable<Map.Entry<ShaderState, Collection<DrawCall>>> {
public static final DrawSet EMPTY = new DrawSet(ImmutableListMultimap.of());
private final ListMultimap<ShaderState, DrawCall> drawCalls;

View file

@ -8,17 +8,17 @@ import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
import com.jozufozu.flywheel.gl.GlStateTracker;
import com.jozufozu.flywheel.gl.GlTextureUnit;
import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Camera;
@ -47,7 +47,7 @@ public class InstancingEngine implements Engine {
@Override
public void beginFrame(TaskExecutor executor, RenderContext context) {
try (var restoreState = GlStateTracker.getRestoreState()) {
try (var state = GlStateTracker.getRestoreState()) {
drawManager.flush();
}
}
@ -60,7 +60,7 @@ public class InstancingEngine implements Engine {
return;
}
try (var restoreState = GlStateTracker.getRestoreState()) {
try (var state = GlStateTracker.getRestoreState()) {
setup();
render(drawSet);
@ -83,7 +83,7 @@ public class InstancingEngine implements Engine {
var shader = entry.getKey();
var drawCalls = entry.getValue();
drawCalls.removeIf(DrawCall::shouldRemove);
drawCalls.removeIf(DrawCall::isInvalid);
if (drawCalls.isEmpty()) {
continue;
@ -102,9 +102,9 @@ public class InstancingEngine implements Engine {
}
private void setup(ShaderState desc) {
var vertexType = desc.vertex();
var structType = desc.instance();
var material = desc.material();
var vertexType = desc.vertexType();
var structType = desc.instanceType();
var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Pipelines.INSTANCED_ARRAYS);
UniformBuffer.syncAndBind(program);

View file

@ -4,5 +4,5 @@ import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType;
public record ShaderState(Material material, VertexType vertex, StructType<?> instance) {
public record ShaderState(Material material, VertexType vertexType, StructType<?> instanceType) {
}

View file

@ -0,0 +1,18 @@
package com.jozufozu.flywheel.backend.task;
public class FlwTaskExecutor {
private static ParallelTaskExecutor executor;
/**
* Get a thread pool for running Flywheel related work in parallel.
* @return A global Flywheel thread pool.
*/
public static ParallelTaskExecutor get() {
if (executor == null) {
executor = new ParallelTaskExecutor("Flywheel");
executor.startWorkers();
}
return executor;
}
}

View file

@ -146,6 +146,28 @@ public class ParallelTaskExecutor implements TaskExecutor {
}
}
public void discardAndAwait() {
// Discard everyone else's work...
while (taskQueue.pollLast() != null) {
synchronized (tasksCompletedNotifier) {
if (--incompleteTaskCounter == 0) {
tasksCompletedNotifier.notifyAll();
}
}
}
// and wait for any stragglers.
synchronized (tasksCompletedNotifier) {
while (incompleteTaskCounter > 0) {
try {
tasksCompletedNotifier.wait();
} catch (InterruptedException e) {
//
}
}
}
}
@Nullable
private Runnable getNextTask() {
Runnable task = taskQueue.pollFirst();

View file

@ -9,20 +9,19 @@ import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
public class BackendArgument implements ArgumentType<Backend> {
private static final List<String> STRING_IDS = Backend.REGISTRY.getAllIds().stream().map(ResourceLocation::toString).toList();
private static final Dynamic2CommandExceptionType INVALID = new Dynamic2CommandExceptionType((found, constants) -> {
// TODO: don't steal lang
return new TranslatableComponent("commands.forge.arguments.enum.invalid", constants, found);
public static final DynamicCommandExceptionType ERROR_UNKNOWN_BACKEND = new DynamicCommandExceptionType(arg -> {
return new TextComponent("Unknown backend '" + arg + "'");
});
public static final BackendArgument INSTANCE = new BackendArgument();
@ -33,7 +32,7 @@ public class BackendArgument implements ArgumentType<Backend> {
Backend backend = Backend.REGISTRY.get(id);
if (backend == null) {
throw INVALID.createWithContext(reader, id.toString(), STRING_IDS);
throw ERROR_UNKNOWN_BACKEND.createWithContext(reader, id.toString());
}
return backend;

View file

@ -9,7 +9,7 @@ import org.slf4j.Logger;
import com.jozufozu.flywheel.glsl.ShaderLoadingException;
import com.jozufozu.flywheel.glsl.SourceFile;
import com.jozufozu.flywheel.glsl.span.Span;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.lib.math.MoreMath;
import com.jozufozu.flywheel.util.StringUtil;
import com.mojang.logging.LogUtils;
@ -97,14 +97,14 @@ public class ErrorReporter {
int size = lines.size();
int maxWidth = FlwUtil.numDigits(size) + 1;
int maxWidth = MoreMath.numDigits(size) + 1;
StringBuilder builder = new StringBuilder().append('\n');
for (int i = 0; i < size; i++) {
builder.append(i)
.append(StringUtil.repeatChar(' ', maxWidth - FlwUtil.numDigits(i)))
.append(StringUtil.repeatChar(' ', maxWidth - MoreMath.numDigits(i)))
.append("| ")
.append(lines.get(i))
.append('\n');

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.handler;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.util.FlwUtil;
import net.minecraft.world.level.Level;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
@ -14,7 +14,7 @@ public class EntityWorldHandler {
return;
}
if (BackendUtil.canUseInstancing(level)) {
if (FlwUtil.canUseInstancing(level)) {
InstancedRenderDispatcher.getEntities(level)
.queueAdd(event.getEntity());
}
@ -26,7 +26,7 @@ public class EntityWorldHandler {
return;
}
if (BackendUtil.canUseInstancing(level)) {
if (FlwUtil.canUseInstancing(level)) {
InstancedRenderDispatcher.getEntities(level)
.remove(event.getEntity());
}

View file

@ -3,10 +3,10 @@ package com.jozufozu.flywheel.handler;
import java.util.ArrayList;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.light.LightUpdater;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.StringUtil;
import com.jozufozu.flywheel.util.WorldAttached;
@ -33,7 +33,7 @@ public class ForgeEvents {
}
public static void tickLight(TickEvent.ClientTickEvent event) {
if (event.phase == TickEvent.Phase.END && BackendUtil.isGameActive()) {
if (event.phase == TickEvent.Phase.END && FlwUtil.isGameActive()) {
LightUpdater.get(Minecraft.getInstance().level)
.tick();
}

View file

@ -3,14 +3,33 @@ package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.backend.Backends;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.lib.backend.Backends;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.backend.SimpleBackend;
import com.mojang.logging.LogUtils;
import net.minecraft.ChatFormatting;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.fml.CrashReportCallables;
public final class BackendManagerImpl {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Backend OFF_BACKEND = SimpleBackend.builder()
.engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED))
.engineFactory(level -> {
throw new IllegalStateException("Cannot create engine when backend is off.");
})
.supported(() -> true)
.register(Flywheel.rl("off"));
private static final Backend DEFAULT_BACKEND = findDefaultBackend();
private static Backend backend;
@Nullable
@ -19,17 +38,35 @@ public final class BackendManagerImpl {
}
public static boolean isOn() {
return backend != null && backend != Backends.OFF;
return backend != null && backend != OFF_BACKEND;
}
public static void refresh() {
backend = chooseBackend();
public static Backend getOffBackend() {
return OFF_BACKEND;
}
public static Backend getDefaultBackend() {
return DEFAULT_BACKEND;
}
private static Backend findDefaultBackend() {
// TODO: Automatically select the best default config based on the user's driver
// TODO: Figure out how this will work if custom backends are registered and without hardcoding the default backends
return Backends.INDIRECT;
}
public static void onReloadRenderers(ReloadRenderersEvent event) {
refresh(event.getLevel());
}
public static void refresh(@Nullable ClientLevel level) {
backend = chooseBackend();
if (level != null) {
InstancedRenderDispatcher.resetInstanceWorld(level);
}
}
private static Backend chooseBackend() {
var preferred = FlwConfig.get().getBackend();
var actual = preferred.findFallback();
@ -41,21 +78,17 @@ public final class BackendManagerImpl {
return actual;
}
private static Backend findDefaultBackend() {
// TODO: Automatically select the best default config based on the user's driver
// TODO: Figure out how this will work if custom backends are registered
return Backends.INDIRECT;
}
public static String getBackendNameForCrashReport() {
if (backend == null) {
return "Uninitialized";
}
var backendId = Backend.REGISTRY.getId(backend);
if (backendId == null) {
return "Unregistered";
}
return backendId.toString();
public static void init() {
CrashReportCallables.registerCrashCallable("Flywheel Backend", () -> {
if (backend == null) {
return "Uninitialized";
}
var backendId = Backend.REGISTRY.getId(backend);
if (backendId == null) {
return "Unregistered";
}
return backendId.toString();
});
}
private BackendManagerImpl() {

View file

@ -11,8 +11,8 @@ import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instance.effect.Effect;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.task.FlwTaskExecutor;
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.impl.instancing.manager.BlockEntityInstanceManager;
@ -27,9 +27,10 @@ import net.minecraft.world.level.block.entity.BlockEntity;
/**
* A manager class for a single world where instancing is supported.
*/
public class InstanceWorld {
// AutoCloseable is implemented to prevent leaking this object from WorldAttached
public class InstanceWorld implements AutoCloseable {
private final Engine engine;
private final TaskExecutor taskExecutor;
private final ParallelTaskExecutor taskExecutor;
private final InstanceManager<BlockEntity> blockEntities;
private final InstanceManager<Entity> entities;
@ -37,7 +38,7 @@ public class InstanceWorld {
public InstanceWorld(LevelAccessor level) {
engine = BackendManager.getBackend().createEngine(level);
taskExecutor = BackendUtil.getTaskExecutor();
taskExecutor = FlwTaskExecutor.get();
blockEntities = new BlockEntityInstanceManager(engine);
entities = new EntityInstanceManager(engine);
@ -127,9 +128,15 @@ public class InstanceWorld {
* Free all acquired resources and invalidate this instance world.
*/
public void delete() {
taskExecutor.discardAndAwait();
blockEntities.invalidate();
entities.invalidate();
effects.invalidate();
engine.delete();
}
@Override
public void close() {
delete();
}
}

View file

@ -3,14 +3,13 @@ package com.jozufozu.flywheel.impl.instancing;
import java.util.List;
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.api.event.RenderStageEvent;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.effect.Effect;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.extension.ClientLevelExtension;
import com.jozufozu.flywheel.impl.instancing.manager.InstanceManager;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.lib.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.WorldAttached;
import net.minecraft.client.Minecraft;
@ -34,7 +33,7 @@ public class InstancedRenderDispatcher {
return;
}
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
return;
}
@ -49,7 +48,7 @@ public class InstancedRenderDispatcher {
*/
public static void queueUpdate(Entity entity) {
Level level = entity.level;
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
return;
}
@ -63,7 +62,7 @@ public class InstancedRenderDispatcher {
* @param effect The effect whose instance you want to update.
*/
public static void queueUpdate(LevelAccessor level, Effect effect) {
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
return;
}
@ -77,7 +76,7 @@ public class InstancedRenderDispatcher {
* @throws IllegalStateException if the backend is off
*/
private static InstanceWorld getInstanceWorld(LevelAccessor level) {
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
throw new IllegalStateException("Cannot retrieve instance world when backend is off!");
}
return INSTANCE_WORLDS.get(level);
@ -100,7 +99,7 @@ public class InstancedRenderDispatcher {
}
public static void tick(TickEvent.ClientTickEvent event) {
if (!BackendUtil.isGameActive() || event.phase == TickEvent.Phase.START) {
if (!FlwUtil.isGameActive() || event.phase == TickEvent.Phase.START) {
return;
}
@ -117,7 +116,7 @@ public class InstancedRenderDispatcher {
}
Level level = cameraEntity.level;
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
return;
}
@ -129,12 +128,12 @@ public class InstancedRenderDispatcher {
}
public static void onBeginFrame(BeginFrameEvent event) {
if (!BackendUtil.isGameActive()) {
if (!FlwUtil.isGameActive()) {
return;
}
ClientLevel level = event.getContext().level();
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
return;
}
@ -143,26 +142,17 @@ public class InstancedRenderDispatcher {
public static void onRenderStage(RenderStageEvent event) {
ClientLevel level = event.getContext().level();
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
return;
}
INSTANCE_WORLDS.get(level).renderStage(event.getContext(), event.getStage());
}
public static void onReloadRenderers(ReloadRenderersEvent event) {
ClientLevel level = event.getLevel();
if (level == null) {
return;
}
resetInstanceWorld(level);
}
public static void resetInstanceWorld(ClientLevel level) {
INSTANCE_WORLDS.remove(level, InstanceWorld::delete);
if (!BackendUtil.canUseInstancing(level)) {
if (!FlwUtil.canUseInstancing(level)) {
return;
}
@ -175,7 +165,7 @@ public class InstancedRenderDispatcher {
public static void addDebugInfo(List<String> info) {
ClientLevel level = Minecraft.getInstance().level;
if (BackendUtil.canUseInstancing(level)) {
if (FlwUtil.canUseInstancing(level)) {
INSTANCE_WORLDS.get(level).addDebugInfo(info);
} else {
info.add("Disabled");

View file

@ -8,10 +8,10 @@ import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.impl.instancing.InstancingControllerHelper;
import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.impl.instancing.storage.Storage;
import com.jozufozu.flywheel.util.FlwUtil;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
@ -66,7 +66,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
return false;
}
if (BackendUtil.isFlywheelLevel(level)) {
if (FlwUtil.isFlywheelLevel(level)) {
BlockPos pos = blockEntity.getBlockPos();
BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4);

View file

@ -5,10 +5,10 @@ import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.impl.instancing.InstancingControllerHelper;
import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.impl.instancing.storage.Storage;
import com.jozufozu.flywheel.util.FlwUtil;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
@ -53,7 +53,7 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
Level level = entity.level;
return BackendUtil.isFlywheelLevel(level);
return FlwUtil.isFlywheelLevel(level);
}
}
}

View file

@ -64,6 +64,14 @@ public abstract class InstanceManager<T> {
queue.add(Transaction.add(obj));
}
public void remove(T obj) {
getStorage().remove(obj);
}
public void queueRemove(T obj) {
queue.add(Transaction.remove(obj));
}
/**
* Update the instance associated with an object.
*
@ -91,10 +99,6 @@ public abstract class InstanceManager<T> {
queue.add(Transaction.update(obj));
}
public void remove(T obj) {
getStorage().remove(obj);
}
public void recreateAll() {
getStorage().recreateAll();
}

View file

@ -4,7 +4,7 @@ import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.lib.format.AbstractVertexList;
import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.lib.math.RenderMath;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.LightTexture;

View file

@ -7,6 +7,7 @@ import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.backend.Backend;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.pipeline.Pipeline;
@ -66,7 +67,7 @@ public class SimpleBackend implements Backend {
public static class Builder {
private Component engineMessage;
private Function<LevelAccessor, Engine> engineFactory;
private Supplier<Backend> fallback;
private Supplier<Backend> fallback = BackendManager::getOffBackend;
private BooleanSupplier isSupported;
private Pipeline pipelineShader;

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.lib.box;
import static com.jozufozu.flywheel.util.RenderMath.isPowerOf2;
import static com.jozufozu.flywheel.lib.math.RenderMath.isPowerOf2;
import net.minecraft.world.phys.AABB;

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.lib.box;
import java.util.Collection;
import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.lib.math.RenderMath;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -19,7 +19,6 @@ public class MutableBox implements ImmutableBox {
private int maxZ;
public MutableBox() {
}
public MutableBox(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {

View file

@ -1,27 +1,29 @@
package com.jozufozu.flywheel.lib.context;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public class Contexts {
public final class Contexts {
public static final SimpleContext WORLD = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
public static final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
@ApiStatus.Internal
public static void init() {
// noop
}
public static class Files {
public static final class Files {
public static final ResourceLocation WORLD_VERTEX = ResourceUtil.subPath(Names.WORLD, ".vert");
public static final ResourceLocation WORLD_FRAGMENT = ResourceUtil.subPath(Names.WORLD, ".frag");
public static final ResourceLocation CRUMBLING_VERTEX = ResourceUtil.subPath(Names.CRUMBLING, ".vert");
public static final ResourceLocation CRUMBLING_FRAGMENT = ResourceUtil.subPath(Names.CRUMBLING, ".frag");
}
public static class Names {
public static final class Names {
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
}

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.lib.format;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.lib.math.RenderMath;
import net.minecraft.client.renderer.texture.OverlayTexture;

View file

@ -1,25 +1,27 @@
package com.jozufozu.flywheel.lib.format;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public class Formats {
public final class Formats {
public static final BlockVertex BLOCK = VertexType.REGISTRY.registerAndGet(new BlockVertex());
public static final PosTexNormalVertex POS_TEX_NORMAL = VertexType.REGISTRY.registerAndGet(new PosTexNormalVertex());
@ApiStatus.Internal
public static void init() {
// noop
}
public static class Files {
public static final class Files {
public static final ResourceLocation BLOCK_LAYOUT = ResourceUtil.subPath(Names.BLOCK, ".vert");
public static final ResourceLocation POS_TEX_NORMAL_LAYOUT = ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert");
}
public static class Names {
public static final class Names {
public static final ResourceLocation BLOCK = Flywheel.rl("layout/block");
public static final ResourceLocation POS_TEX_NORMAL = Flywheel.rl("layout/pos_tex_normal");
}

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.lib.format;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.lib.math.RenderMath;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture;

View file

@ -5,7 +5,6 @@ import com.jozufozu.flywheel.gl.array.VertexAttributeF;
import com.jozufozu.flywheel.gl.array.VertexAttributeI;
public class CommonItems {
private static final String VEC2_TYPE = "vec2";
private static final String VEC3_TYPE = "vec3";
private static final String VEC4_TYPE = "vec4";
@ -16,6 +15,7 @@ public class CommonItems {
private static final String FLOAT_TYPE = "float";
private static final String UINT_TYPE = "uint";
private static final String LIGHT_COORD_TYPE = "LightCoord";
public static final VecInput LIGHT_COORD = VecInput.builder()
.vertexAttribute(new VertexAttributeI(GlNumericType.USHORT, 2))
.typeName(IVEC2_TYPE)
@ -69,8 +69,4 @@ public class CommonItems {
public static final MatInput MAT3 = new MatInput(3, 3, "mat3", "Mat3F", "unpackMat3F");
public static final MatInput MAT4 = new MatInput(4, 4, "mat4", "Mat4F", "unpackMat4F");
private static class Unpacking {
}
}

View file

@ -5,7 +5,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Stream;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.backend.task.FlwTaskExecutor;
import com.jozufozu.flywheel.lib.box.ImmutableBox;
import com.jozufozu.flywheel.lib.task.WorkGroup;
import com.jozufozu.flywheel.util.FlwUtil;
@ -23,7 +23,6 @@ import net.minecraft.world.level.LightLayer;
* {@link LightUpdated} for LightUpdater to work with them.
*/
public class LightUpdater {
private static final WorldAttached<LightUpdater> LEVELS = new WorldAttached<>(LightUpdater::new);
private final LevelAccessor level;
@ -68,7 +67,7 @@ public class LightUpdater {
}
})
.onComplete(() -> listeners.forEach(this::addListener))
.execute(BackendUtil.getTaskExecutor());
.execute(FlwTaskExecutor.get());
}
/**

View file

@ -21,7 +21,7 @@ import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import net.minecraft.resources.ResourceLocation;
// TODO: add messages to exceptions
public class MaterialIndices {
public final class MaterialIndices {
private static Reference2IntMap<Material> materialIndices;
private static Object2IntMap<ResourceLocation> vertexShaderIndices;
private static Object2IntMap<ResourceLocation> fragmentShaderIndices;

View file

@ -1,11 +1,14 @@
package com.jozufozu.flywheel.lib.material;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.material.MaterialVertexTransformer;
import com.jozufozu.flywheel.gl.GlTextureUnit;
import com.jozufozu.flywheel.lib.material.SimpleMaterial.GlStateShard;
import com.jozufozu.flywheel.lib.math.DiffuseLightCalculator;
import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import com.jozufozu.flywheel.util.DiffuseLightCalculator;
import com.jozufozu.flywheel.util.ResourceUtil;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
@ -18,7 +21,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
public final class Materials {
public static final Material.VertexTransformer SHADING_TRANSFORMER = (vertexList, level) -> {
public static final MaterialVertexTransformer SHADING_TRANSFORMER = (vertexList, level) -> {
if (ShadersModHandler.isShaderPackInUse()) {
return;
}
@ -131,8 +134,8 @@ public final class Materials {
.batchingRenderType(RenderType.entitySolid(MINECART_LOCATION))
.register();
@ApiStatus.Internal
public static void init() {
// noop
}
public static final class Shards {
@ -173,14 +176,14 @@ public final class Materials {
}
}
public static class Files {
public static final class Files {
public static final ResourceLocation DEFAULT_VERTEX = ResourceUtil.subPath(Names.DEFAULT, ".vert");
public static final ResourceLocation SHADED_VERTEX = ResourceUtil.subPath(Names.SHADED, ".vert");
public static final ResourceLocation DEFAULT_FRAGMENT = ResourceUtil.subPath(Names.DEFAULT, ".frag");
public static final ResourceLocation CUTOUT_FRAGMENT = ResourceUtil.subPath(Names.CUTOUT, ".frag");
}
public static class Names {
public static final class Names {
public static final ResourceLocation DEFAULT = Flywheel.rl("material/default");
public static final ResourceLocation CUTOUT = Flywheel.rl("material/cutout");
public static final ResourceLocation SHADED = Flywheel.rl("material/shaded");

View file

@ -1,6 +1,7 @@
package com.jozufozu.flywheel.lib.material;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.material.MaterialVertexTransformer;
import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderType;
@ -12,9 +13,9 @@ public class SimpleMaterial implements Material {
protected final Runnable setup;
protected final Runnable clear;
protected final RenderType batchingRenderType;
protected final VertexTransformer vertexTransformer;
protected final MaterialVertexTransformer vertexTransformer;
public SimpleMaterial(ResourceLocation vertexShader, ResourceLocation fragmentShader, Runnable setup, Runnable clear, RenderType batchingRenderType, VertexTransformer vertexTransformer) {
public SimpleMaterial(ResourceLocation vertexShader, ResourceLocation fragmentShader, Runnable setup, Runnable clear, RenderType batchingRenderType, MaterialVertexTransformer vertexTransformer) {
this.vertexShader = vertexShader;
this.fragmentShader = fragmentShader;
this.setup = setup;
@ -53,7 +54,7 @@ public class SimpleMaterial implements Material {
}
@Override
public VertexTransformer getVertexTransformer() {
public MaterialVertexTransformer getVertexTransformer() {
return vertexTransformer;
}
@ -63,8 +64,7 @@ public class SimpleMaterial implements Material {
protected Runnable setup = () -> {};
protected Runnable clear = () -> {};
protected RenderType batchingRenderType = RenderType.solid();
protected VertexTransformer vertexTransformer = (vertexList, level) -> {
};
protected MaterialVertexTransformer vertexTransformer = (vertexList, level) -> {};
public Builder() {
}
@ -100,7 +100,7 @@ public class SimpleMaterial implements Material {
return this;
}
public Builder vertexTransformer(VertexTransformer vertexTransformer) {
public Builder vertexTransformer(MaterialVertexTransformer vertexTransformer) {
this.vertexTransformer = vertexTransformer;
return this;
}

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.util;
package com.jozufozu.flywheel.lib.math;
import net.minecraft.client.multiplayer.ClientLevel;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.util;
package com.jozufozu.flywheel.lib.math;
import java.nio.ByteBuffer;
@ -9,7 +9,37 @@ import com.jozufozu.flywheel.mixin.matrix.Matrix4fAccessor;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
public class MatrixUtil {
public final class MatrixUtil {
public static float transformPositionX(Matrix4f matrix, float x, float y, float z) {
Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix;
return (m.flywheel$m00() * x) + (m.flywheel$m01() * y) + (m.flywheel$m02() * z) + m.flywheel$m03();
}
public static float transformPositionY(Matrix4f matrix, float x, float y, float z) {
Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix;
return (m.flywheel$m10() * x) + (m.flywheel$m11() * y) + (m.flywheel$m12() * z) + m.flywheel$m13();
}
public static float transformPositionZ(Matrix4f matrix, float x, float y, float z) {
Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix;
return (m.flywheel$m20() * x) + (m.flywheel$m21() * y) + (m.flywheel$m22() * z) + m.flywheel$m23();
}
public static float transformNormalX(Matrix3f matrix, float x, float y, float z) {
Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix;
return (m.flywheel$m00() * x) + (m.flywheel$m01() * y) + (m.flywheel$m02() * z);
}
public static float transformNormalY(Matrix3f matrix, float x, float y, float z) {
Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix;
return (m.flywheel$m10() * x) + (m.flywheel$m11() * y) + (m.flywheel$m12() * z);
}
public static float transformNormalZ(Matrix3f matrix, float x, float y, float z) {
Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix;
return (m.flywheel$m20() * x) + (m.flywheel$m21() * y) + (m.flywheel$m22() * z);
}
public static void write(Matrix4f matrix, ByteBuffer buf) {
Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix;
buf.putFloat(m.flywheel$m00());

View file

@ -0,0 +1,166 @@
package com.jozufozu.flywheel.lib.math;
import org.joml.Math;
import org.joml.Matrix4f;
import org.lwjgl.system.MemoryUtil;
public final class MoreMath {
public static int align16(int numToRound) {
return (numToRound + 16 - 1) & -16;
}
public static int numDigits(int number) {
// cursed but allegedly the fastest algorithm, taken from https://www.baeldung.com/java-number-of-digits-in-int
if (number < 100000) {
if (number < 100) {
if (number < 10) {
return 1;
} else {
return 2;
}
} else {
if (number < 1000) {
return 3;
} else {
if (number < 10000) {
return 4;
} else {
return 5;
}
}
}
} else {
if (number < 10000000) {
if (number < 1000000) {
return 6;
} else {
return 7;
}
} else {
if (number < 100000000) {
return 8;
} else {
if (number < 1000000000) {
return 9;
} else {
return 10;
}
}
}
}
}
/**
* Writes the frustum planes of the given projection matrix to the given buffer.<p>
* Uses a different format that is friendly towards an optimized instruction-parallel
* implementation of sphere-frustum intersection.<p>
* The format is as follows:<p>
* {@code vec4(nxX, pxX, nyX, pyX)}<br>
* {@code vec4(nxY, pxY, nyY, pyY)}<br>
* {@code vec4(nxZ, pxZ, nyZ, pyZ)}<br>
* {@code vec4(nxW, pxW, nyW, pyW)}<br>
* {@code vec2(nzX, pzX)}<br>
* {@code vec2(nzY, pzY)}<br>
* {@code vec2(nzZ, pzZ)}<br>
* {@code vec2(nzW, pzW)}<br>
* <p>
* Writes 96 bytes to the buffer.
*
* @param ptr The buffer to write the planes to.
* @param m The projection matrix to compute the frustum planes for.
*/
public static void writePackedFrustumPlanes(long ptr, Matrix4f m) {
float nxX, nxY, nxZ, nxW;
float pxX, pxY, pxZ, pxW;
float nyX, nyY, nyZ, nyW;
float pyX, pyY, pyZ, pyW;
float nzX, nzY, nzZ, nzW;
float pzX, pzY, pzZ, pzW;
float invl;
nxX = m.m03() + m.m00();
nxY = m.m13() + m.m10();
nxZ = m.m23() + m.m20();
nxW = m.m33() + m.m30();
invl = Math.invsqrt(nxX * nxX + nxY * nxY + nxZ * nxZ);
nxX *= invl;
nxY *= invl;
nxZ *= invl;
nxW *= invl;
pxX = m.m03() - m.m00();
pxY = m.m13() - m.m10();
pxZ = m.m23() - m.m20();
pxW = m.m33() - m.m30();
invl = Math.invsqrt(pxX * pxX + pxY * pxY + pxZ * pxZ);
pxX *= invl;
pxY *= invl;
pxZ *= invl;
pxW *= invl;
nyX = m.m03() + m.m01();
nyY = m.m13() + m.m11();
nyZ = m.m23() + m.m21();
nyW = m.m33() + m.m31();
invl = Math.invsqrt(nyX * nyX + nyY * nyY + nyZ * nyZ);
nyX *= invl;
nyY *= invl;
nyZ *= invl;
nyW *= invl;
pyX = m.m03() - m.m01();
pyY = m.m13() - m.m11();
pyZ = m.m23() - m.m21();
pyW = m.m33() - m.m31();
invl = Math.invsqrt(pyX * pyX + pyY * pyY + pyZ * pyZ);
pyX *= invl;
pyY *= invl;
pyZ *= invl;
pyW *= invl;
nzX = m.m03() + m.m02();
nzY = m.m13() + m.m12();
nzZ = m.m23() + m.m22();
nzW = m.m33() + m.m32();
invl = Math.invsqrt(nzX * nzX + nzY * nzY + nzZ * nzZ);
nzX *= invl;
nzY *= invl;
nzZ *= invl;
nzW *= invl;
pzX = m.m03() - m.m02();
pzY = m.m13() - m.m12();
pzZ = m.m23() - m.m22();
pzW = m.m33() - m.m32();
invl = Math.invsqrt(pzX * pzX + pzY * pzY + pzZ * pzZ);
pzX *= invl;
pzY *= invl;
pzZ *= invl;
pzW *= invl;
MemoryUtil.memPutFloat(ptr, nxX);
MemoryUtil.memPutFloat(ptr + 4, pxX);
MemoryUtil.memPutFloat(ptr + 8, nyX);
MemoryUtil.memPutFloat(ptr + 12, pyX);
MemoryUtil.memPutFloat(ptr + 16, nxY);
MemoryUtil.memPutFloat(ptr + 20, pxY);
MemoryUtil.memPutFloat(ptr + 24, nyY);
MemoryUtil.memPutFloat(ptr + 28, pyY);
MemoryUtil.memPutFloat(ptr + 32, nxZ);
MemoryUtil.memPutFloat(ptr + 36, pxZ);
MemoryUtil.memPutFloat(ptr + 40, nyZ);
MemoryUtil.memPutFloat(ptr + 44, pyZ);
MemoryUtil.memPutFloat(ptr + 48, nxW);
MemoryUtil.memPutFloat(ptr + 52, pxW);
MemoryUtil.memPutFloat(ptr + 56, nyW);
MemoryUtil.memPutFloat(ptr + 60, pyW);
MemoryUtil.memPutFloat(ptr + 64, nzX);
MemoryUtil.memPutFloat(ptr + 68, pzX);
MemoryUtil.memPutFloat(ptr + 72, nzY);
MemoryUtil.memPutFloat(ptr + 76, pzY);
MemoryUtil.memPutFloat(ptr + 80, nzZ);
MemoryUtil.memPutFloat(ptr + 84, pzZ);
MemoryUtil.memPutFloat(ptr + 88, nzW);
MemoryUtil.memPutFloat(ptr + 92, pzW);
}
}

View file

@ -1,9 +1,8 @@
package com.jozufozu.flywheel.util;
package com.jozufozu.flywheel.lib.math;
import net.minecraftforge.client.model.pipeline.LightUtil;
public class RenderMath {
public final class RenderMath {
/**
* Convert a signed byte into a signed, normalized float.
*/

View file

@ -7,7 +7,7 @@ import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.StringUtil;
public class FlwMemoryTracker {
public final class FlwMemoryTracker {
public static final boolean DEBUG_MEMORY_SAFETY = System.getProperty("flw.debugMemorySafety") != null;
static final Cleaner CLEANER = Cleaner.create();

View file

@ -6,21 +6,21 @@ import java.nio.ByteBuffer;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector4f;
import org.lwjgl.system.MemoryUtil;
import org.slf4j.Logger;
import com.dreizak.miniball.highdim.Miniball;
import com.dreizak.miniball.model.PointSet;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexListProviderRegistry;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import com.mojang.logging.LogUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderType;
@ -28,7 +28,9 @@ import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.block.ModelBlockRenderer;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
public class ModelUtil {
public final class ModelUtil {
private static final Logger LOGGER = LogUtils.getLogger();
/**
* An alternative BlockRenderDispatcher that circumvents the Forge rendering pipeline to ensure consistency.
* Meant to be used for virtual rendering.
@ -45,25 +47,24 @@ public class ModelUtil {
}
ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "f_110900_");
} catch (Exception e) {
Flywheel.LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e);
return defaultDispatcher;
}
return dispatcher;
}
public static Pair<VertexType, MemoryBlock> convertBlockBuffer(Pair<DrawState, ByteBuffer> pair) {
public static MemoryBlock convertVanillaBuffer(Pair<DrawState, ByteBuffer> pair, VertexType vertexType) {
DrawState drawState = pair.getFirst();
int vertexCount = drawState.vertexCount();
VertexFormat srcFormat = drawState.format();
VertexType dstVertexType = Formats.BLOCK;
ByteBuffer src = pair.getSecond();
MemoryBlock dst = MemoryBlock.malloc(vertexCount * dstVertexType.getLayout().getStride());
MemoryBlock dst = MemoryBlock.malloc(vertexCount * vertexType.getLayout().getStride());
long srcPtr = MemoryUtil.memAddress(src);
long dstPtr = dst.ptr();
ReusableVertexList srcList = VertexListProviderRegistry.getProvider(srcFormat).createVertexList();
ReusableVertexList dstList = dstVertexType.createVertexList();
ReusableVertexList dstList = vertexType.createVertexList();
srcList.ptr(srcPtr);
dstList.ptr(dstPtr);
srcList.vertexCount(vertexCount);
@ -71,7 +72,7 @@ public class ModelUtil {
srcList.writeAll(dstList);
return Pair.of(dstVertexType, dst);
return dst;
}
@Nullable

View file

@ -15,7 +15,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
public class Models {
public final class Models {
private static final Map<BlockState, Model> BLOCK_STATE = new HashMap<>();
private static final Map<PartialModel, Model> PARTIAL = new HashMap<>();
private static final Map<Pair<PartialModel, Direction>, Model> PARTIAL_DIR = new HashMap<>();

View file

@ -0,0 +1,23 @@
package com.jozufozu.flywheel.lib.model;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.gl.buffer.ElementBuffer;
import com.jozufozu.flywheel.lib.util.QuadConverter;
public interface QuadMesh extends Mesh {
/**
* Create an element buffer object that indexes the vertices of this mesh.
*
* <p>
* Very often models in minecraft are made up of sequential quads, which is a very predictable pattern.
* The default implementation accommodates this, however this can be overridden to change the behavior and
* support more complex models.
* </p>
* @return an element buffer object indexing this model's vertices.
*/
@Override
default ElementBuffer createEBO() {
return QuadConverter.getInstance()
.quads2Tris(getVertexCount() / 4);
}
}

View file

@ -3,13 +3,12 @@ package com.jozufozu.flywheel.lib.model;
import org.joml.Vector4f;
import org.joml.Vector4fc;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
public class SimpleMesh implements Mesh {
public class SimpleMesh implements QuadMesh {
private final VertexType vertexType;
private final int vertexCount;
private final MemoryBlock contents;

View file

@ -5,7 +5,7 @@ import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.jozufozu.flywheel.lib.model.SimpleMesh;
@ -20,7 +20,6 @@ import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.model.BakedModel;
@ -106,8 +105,8 @@ public class BakedModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, shaded);
if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
}
};
ModelBufferingUtil.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer);
@ -121,8 +120,8 @@ public class BakedModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, false);
if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString()));
MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString()));
}
};
ModelBufferingUtil.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer);

View file

@ -5,7 +5,7 @@ import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.jozufozu.flywheel.lib.model.SimpleMesh;
@ -20,7 +20,6 @@ import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.world.level.BlockAndTintGetter;
@ -95,8 +94,8 @@ public class BlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, shaded);
if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
}
};
ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer);
@ -110,8 +109,8 @@ public class BlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, false);
if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString()));
MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "state=" + state.toString() + ",renderType=" + renderType.toString()));
}
};
ModelBufferingUtil.bufferBlock(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer);

View file

@ -8,7 +8,7 @@ import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.jozufozu.flywheel.lib.model.SimpleMesh;
@ -22,7 +22,6 @@ import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos;
@ -102,8 +101,8 @@ public class MultiBlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, shaded);
if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString() + ",shaded=" + shaded));
MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "renderType=" + renderType.toString() + ",shaded=" + shaded));
}
};
ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer);
@ -117,8 +116,8 @@ public class MultiBlockModelBuilder {
buffer.end();
Material material = materialFunc.apply(renderType, false);
if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString()));
MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "renderType=" + renderType.toString()));
}
};
ModelBufferingUtil.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelDataMap, resultConsumer);

View file

@ -5,22 +5,22 @@ import java.util.List;
import org.joml.Vector4f;
import org.joml.Vector4fc;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.format.PosTexNormalVertex;
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.jozufozu.flywheel.lib.model.QuadMesh;
public class ModelPart implements Mesh {
public class ModelPart implements QuadMesh {
private final int vertexCount;
private final MemoryBlock contents;
private final ReusableVertexList vertexList;
private final Vector4f boundingSphere;
private final String name;
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) {
public ModelPart(List<ModelPartBuilder.CuboidBuilder> cuboids, String name) {
this.name = name;
this.vertexCount = countVertices(cuboids);
@ -28,7 +28,7 @@ public class ModelPart implements Mesh {
contents = MemoryBlock.malloc(size());
long ptr = contents.ptr();
VertexWriter writer = new VertexWriterImpl(ptr);
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
for (ModelPartBuilder.CuboidBuilder cuboid : cuboids) {
cuboid.write(writer);
}
@ -39,8 +39,8 @@ public class ModelPart implements Mesh {
boundingSphere = ModelUtil.computeBoundingSphere(vertexList);
}
public static PartBuilder builder(String name, int sizeU, int sizeV) {
return new PartBuilder(name, sizeU, sizeV);
public static ModelPartBuilder builder(String name, int sizeU, int sizeV) {
return new ModelPartBuilder(name, sizeU, sizeV);
}
@Override
@ -78,9 +78,9 @@ public class ModelPart implements Mesh {
return name;
}
private static int countVertices(List<PartBuilder.CuboidBuilder> cuboids) {
private static int countVertices(List<ModelPartBuilder.CuboidBuilder> cuboids) {
int vertices = 0;
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
for (ModelPartBuilder.CuboidBuilder cuboid : cuboids) {
vertices += cuboid.vertices();
}
return vertices;

View file

@ -12,8 +12,7 @@ import com.mojang.math.Vector3f;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
public class PartBuilder {
public class ModelPartBuilder {
private final float sizeU;
private final float sizeV;
@ -22,13 +21,13 @@ public class PartBuilder {
private final List<CuboidBuilder> cuboids = new ArrayList<>();
private final String name;
public PartBuilder(String name, int sizeU, int sizeV) {
public ModelPartBuilder(String name, int sizeU, int sizeV) {
this.name = name;
this.sizeU = (float) sizeU;
this.sizeV = (float) sizeV;
}
public PartBuilder sprite(TextureAtlasSprite sprite) {
public ModelPartBuilder sprite(TextureAtlasSprite sprite) {
this.sprite = sprite;
return this;
}
@ -41,36 +40,35 @@ public class PartBuilder {
return new ModelPart(cuboids, name);
}
private PartBuilder addCuboid(CuboidBuilder builder) {
private ModelPartBuilder addCuboid(CuboidBuilder builder) {
cuboids.add(builder);
return this;
}
public static class CuboidBuilder {
private TextureAtlasSprite sprite;
TextureAtlasSprite sprite;
private Set<Direction> visibleFaces = EnumSet.allOf(Direction.class);
private int textureOffsetU;
private int textureOffsetV;
Set<Direction> visibleFaces = EnumSet.allOf(Direction.class);
int textureOffsetU;
int textureOffsetV;
private float posX1;
private float posY1;
private float posZ1;
private float posX2;
private float posY2;
private float posZ2;
float posX1;
float posY1;
float posZ1;
float posX2;
float posY2;
float posZ2;
private boolean invertYZ;
boolean invertYZ;
private boolean useRotation;
private float rotationX;
private float rotationY;
private float rotationZ;
boolean useRotation;
float rotationX;
float rotationY;
float rotationZ;
private final ModelPartBuilder partBuilder;
final PartBuilder partBuilder;
CuboidBuilder(PartBuilder partBuilder) {
private CuboidBuilder(ModelPartBuilder partBuilder) {
this.partBuilder = partBuilder;
this.sprite = partBuilder.sprite;
}
@ -151,7 +149,7 @@ public class PartBuilder {
return this;
}
public PartBuilder endCuboid() {
public ModelPartBuilder endCuboid() {
return partBuilder.addCuboid(this);
}
@ -254,5 +252,4 @@ public class PartBuilder {
return v / partBuilder.sizeV;
}
}
}

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.lib.modelpart;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.lib.math.RenderMath;
public class VertexWriterImpl implements VertexWriter {
private long ptr;

View file

@ -1,12 +1,11 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.struct.Handle;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType;
public abstract class AbstractInstancePart implements InstancePart {
public final StructType<?> type;
protected final StructType<?> type;
protected final Handle handle;
protected AbstractInstancePart(StructType<?> type, Handle handle) {

View file

@ -1,12 +1,11 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.struct.Handle;
import com.jozufozu.flywheel.api.struct.StructType;
import net.minecraft.client.renderer.LightTexture;
public abstract class ColoredLitPart extends AbstractInstancePart implements FlatLit<ColoredLitPart> {
public byte blockLight;
public byte skyLight;
@ -15,7 +14,7 @@ public abstract class ColoredLitPart extends AbstractInstancePart implements Fla
public byte b = (byte) 0xFF;
public byte a = (byte) 0xFF;
public ColoredLitPart(StructType<?> type, Handle handle) {
public ColoredLitPart(StructType<? extends ColoredLitPart> type, Handle handle) {
super(type, handle);
}
@ -35,7 +34,7 @@ public abstract class ColoredLitPart extends AbstractInstancePart implements Fla
@Override
public int getPackedLight() {
return LightTexture.pack(this.blockLight, this.skyLight);
return LightTexture.pack(blockLight, skyLight);
}
public ColoredLitPart setColor(int color) {

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.struct.InstancePart;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter;

View file

@ -1,13 +1,13 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.struct.Handle;
import com.jozufozu.flywheel.api.struct.StructType;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.core.BlockPos;
public class OrientedPart extends ColoredLitPart {
public float posX;
public float posY;
public float posZ;
@ -19,8 +19,8 @@ public class OrientedPart extends ColoredLitPart {
public float qZ;
public float qW = 1;
public OrientedPart(Handle handle) {
super(StructTypes.ORIENTED, handle);
public OrientedPart(StructType<? extends OrientedPart> type, Handle handle) {
super(type, handle);
}
public OrientedPart setPosition(BlockPos pos) {
@ -87,7 +87,7 @@ public class OrientedPart extends ColoredLitPart {
@Override
public OrientedPart copy(Handle handle) {
var out = new OrientedPart(handle);
var out = StructTypes.ORIENTED.create(handle);
out.posX = this.posX;
out.posY = this.posY;
out.posZ = this.posZ;

View file

@ -1,21 +1,20 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.layout.BufferLayout;
import com.jozufozu.flywheel.api.struct.Handle;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructVertexTransformer;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.lib.layout.CommonItems;
import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.lib.math.RenderMath;
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import net.minecraft.resources.ResourceLocation;
public class OrientedType implements StructType<OrientedPart> {
public static final BufferLayout FORMAT = BufferLayout.builder()
.addItem(CommonItems.LIGHT_COORD, "light")
.addItem(CommonItems.UNORM_4x8, "color")
@ -26,7 +25,7 @@ public class OrientedType implements StructType<OrientedPart> {
@Override
public OrientedPart create(Handle handle) {
return new OrientedPart(handle);
return new OrientedPart(this, handle);
}
@Override
@ -45,11 +44,8 @@ public class OrientedType implements StructType<OrientedPart> {
}
@Override
public VertexTransformer<OrientedPart> getVertexTransformer() {
public StructVertexTransformer<OrientedPart> getVertexTransformer() {
return (vertexList, struct, level) -> {
Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f();
Quaternion q = new Quaternion(struct.qX, struct.qY, struct.qZ, struct.qW);
Matrix4f modelMatrix = new Matrix4f();
@ -67,27 +63,8 @@ public class OrientedType implements StructType<OrientedPart> {
int light = struct.getPackedLight();
for (int i = 0; i < vertexList.vertexCount(); i++) {
pos.set(
vertexList.x(i),
vertexList.y(i),
vertexList.z(i),
1f
);
pos.transform(modelMatrix);
vertexList.x(i, pos.x());
vertexList.y(i, pos.y());
vertexList.z(i, pos.z());
normal.set(
vertexList.normalX(i),
vertexList.normalY(i),
vertexList.normalZ(i)
);
normal.transform(normalMatrix);
normal.normalize();
vertexList.normalX(i, normal.x());
vertexList.normalY(i, normal.y());
vertexList.normalZ(i, normal.z());
VertexTransformations.transformPos(vertexList, i, modelMatrix);
VertexTransformations.transformNormal(vertexList, i, normalMatrix);
vertexList.r(i, r);
vertexList.g(i, g);

View file

@ -1,25 +1,27 @@
package com.jozufozu.flywheel.lib.struct;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public class StructTypes {
public final class StructTypes {
public static final StructType<TransformedPart> TRANSFORMED = StructType.REGISTRY.registerAndGet(new TransformedType());
public static final StructType<OrientedPart> ORIENTED = StructType.REGISTRY.registerAndGet(new OrientedType());
@ApiStatus.Internal
public static void init() {
// noop
}
public static class Files {
public static final class Files {
public static final ResourceLocation TRANSFORMED = ResourceUtil.subPath(Names.TRANSFORMED, ".vert");
public static final ResourceLocation ORIENTED = ResourceUtil.subPath(Names.ORIENTED, ".vert");
}
public static class Names {
public static final class Names {
public static final ResourceLocation TRANSFORMED = Flywheel.rl("instance/transformed");
public static final ResourceLocation ORIENTED = Flywheel.rl("instance/oriented");
}

View file

@ -1,6 +1,7 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.struct.Handle;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.lib.transform.Transform;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f;
@ -16,8 +17,8 @@ public class TransformedPart extends ColoredLitPart implements Transform<Transfo
public final Matrix4f model = new Matrix4f();
public final Matrix3f normal = new Matrix3f();
public TransformedPart(Handle handle) {
super(StructTypes.TRANSFORMED, handle);
public TransformedPart(StructType<? extends TransformedPart> type, Handle handle) {
super(type, handle);
}
public TransformedPart setTransform(PoseStack stack) {
@ -106,7 +107,7 @@ public class TransformedPart extends ColoredLitPart implements Transform<Transfo
@Override
public TransformedPart copy(Handle handle) {
var out = new TransformedPart(handle);
var out = StructTypes.TRANSFORMED.create(handle);
out.model.load(this.model);
out.normal.load(this.normal);
out.r = this.r;

View file

@ -1,18 +1,17 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.api.instancer.Handle;
import com.jozufozu.flywheel.api.layout.BufferLayout;
import com.jozufozu.flywheel.api.struct.Handle;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructVertexTransformer;
import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.lib.layout.CommonItems;
import com.jozufozu.flywheel.util.RenderMath;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import com.jozufozu.flywheel.lib.math.RenderMath;
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
import net.minecraft.resources.ResourceLocation;
public class TransformedType implements StructType<TransformedPart> {
public static final BufferLayout FORMAT = BufferLayout.builder()
.addItem(CommonItems.LIGHT_COORD, "light")
.addItem(CommonItems.UNORM_4x8, "color")
@ -22,7 +21,7 @@ public class TransformedType implements StructType<TransformedPart> {
@Override
public TransformedPart create(Handle handle) {
return new TransformedPart(handle);
return new TransformedPart(this, handle);
}
@Override
@ -41,11 +40,8 @@ public class TransformedType implements StructType<TransformedPart> {
}
@Override
public VertexTransformer<TransformedPart> getVertexTransformer() {
public StructVertexTransformer<TransformedPart> getVertexTransformer() {
return (vertexList, struct, level) -> {
Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f();
float r = RenderMath.uf(struct.r);
float g = RenderMath.uf(struct.g);
float b = RenderMath.uf(struct.b);
@ -53,27 +49,8 @@ public class TransformedType implements StructType<TransformedPart> {
int light = struct.getPackedLight();
for (int i = 0; i < vertexList.vertexCount(); i++) {
pos.set(
vertexList.x(i),
vertexList.y(i),
vertexList.z(i),
1f
);
pos.transform(struct.model);
vertexList.x(i, pos.x());
vertexList.y(i, pos.y());
vertexList.z(i, pos.z());
normal.set(
vertexList.normalX(i),
vertexList.normalY(i),
vertexList.normalZ(i)
);
normal.transform(struct.normal);
normal.normalize();
vertexList.normalX(i, normal.x());
vertexList.normalY(i, normal.y());
vertexList.normalZ(i, normal.z());
VertexTransformations.transformPos(vertexList, i, struct.model);
VertexTransformations.transformNormal(vertexList, i, struct.normal);
vertexList.r(i, r);
vertexList.g(i, g);

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.lib.struct;
import com.jozufozu.flywheel.util.MatrixUtil;
import com.jozufozu.flywheel.lib.math.MatrixUtil;
public class TransformedWriter extends ColoredLitWriter<TransformedPart> {
public static final TransformedWriter INSTANCE = new TransformedWriter();

View file

@ -8,7 +8,7 @@ import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
public class WorkGroup {
public final class WorkGroup {
public static void run(Iterator<Runnable> tasks, Executor executor) {
tasks.forEachRemaining(executor::execute);
}

View file

@ -9,8 +9,8 @@ import com.jozufozu.flywheel.api.event.BeginFrameEvent;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.MatrixUtil;
import com.jozufozu.flywheel.lib.math.MatrixUtil;
import com.jozufozu.flywheel.lib.math.MoreMath;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.core.Vec3i;
@ -134,7 +134,7 @@ public class FlwShaderUniforms implements ShaderUniforms {
var projection = MatrixUtil.toJoml(context.viewProjection());
projection.translate(-camX, -camY, -camZ);
FlwUtil.writePackedFrustumPlanes(ptr + 128, projection);
MoreMath.writePackedFrustumPlanes(ptr + 128, projection);
FRUSTUM_CAPTURE = false;
}

Some files were not shown because too many files have changed in this diff Show more