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.apache.maven.artifact.versioning.ArtifactVersion;
import org.slf4j.Logger; import org.slf4j.Logger;
import com.jozufozu.flywheel.backend.Backends;
import com.jozufozu.flywheel.backend.Loader; import com.jozufozu.flywheel.backend.Loader;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer; import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer;
import com.jozufozu.flywheel.config.BackendArgument; import com.jozufozu.flywheel.config.BackendArgument;
import com.jozufozu.flywheel.config.FlwCommands; 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.IdRegistryImpl;
import com.jozufozu.flywheel.impl.RegistryImpl; import com.jozufozu.flywheel.impl.RegistryImpl;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; 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.context.Contexts;
import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.material.MaterialIndices; import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.material.Materials;
import com.jozufozu.flywheel.lib.model.Models; import com.jozufozu.flywheel.lib.model.Models;
import com.jozufozu.flywheel.lib.model.PartialModel; 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.struct.StructTypes;
import com.jozufozu.flywheel.lib.util.QuadConverter; import com.jozufozu.flywheel.lib.util.QuadConverter;
import com.jozufozu.flywheel.lib.util.ShadersModHandler; 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.common.MinecraftForge;
import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.CrashReportCallables;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.IExtensionPoint; import net.minecraftforge.fml.IExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
@ -47,7 +46,6 @@ import net.minecraftforge.network.NetworkConstants;
@Mod(Flywheel.ID) @Mod(Flywheel.ID)
public class Flywheel { public class Flywheel {
public static final String ID = "flywheel"; public static final String ID = "flywheel";
public static final Logger LOGGER = LogUtils.getLogger(); public static final Logger LOGGER = LogUtils.getLogger();
private static ArtifactVersion version; private static ArtifactVersion version;
@ -78,11 +76,12 @@ public class Flywheel {
private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) { private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) {
forgeEventBus.addListener(FlwCommands::registerClientCommands); forgeEventBus.addListener(FlwCommands::registerClientCommands);
forgeEventBus.addListener(BackendManagerImpl::onReloadRenderers);
forgeEventBus.addListener(EventPriority.HIGHEST, QuadConverter::onReloadRenderers); forgeEventBus.addListener(EventPriority.HIGHEST, QuadConverter::onReloadRenderers);
forgeEventBus.addListener(Models::onReloadRenderers); forgeEventBus.addListener(Models::onReloadRenderers);
forgeEventBus.addListener(DrawBuffer::onReloadRenderers); forgeEventBus.addListener(DrawBuffer::onReloadRenderers);
forgeEventBus.addListener(InstancedRenderDispatcher::onReloadRenderers);
forgeEventBus.addListener(InstancedRenderDispatcher::onRenderStage); forgeEventBus.addListener(InstancedRenderDispatcher::onRenderStage);
forgeEventBus.addListener(InstancedRenderDispatcher::onBeginFrame); forgeEventBus.addListener(InstancedRenderDispatcher::onBeginFrame);
forgeEventBus.addListener(InstancedRenderDispatcher::tick); forgeEventBus.addListener(InstancedRenderDispatcher::tick);
@ -100,23 +99,23 @@ public class Flywheel {
// forgeEventBus.addListener(ExampleEffect::tick); // forgeEventBus.addListener(ExampleEffect::tick);
// forgeEventBus.addListener(ExampleEffect::onReload); // forgeEventBus.addListener(ExampleEffect::onReload);
ShadersModHandler.init(); BackendManagerImpl.init();
Pipelines.init();
Backends.init(); Backends.init();
Loader.init(); Loader.init();
ShadersModHandler.init();
Formats.init(); Formats.init();
StructTypes.init(); StructTypes.init();
Materials.init(); Materials.init();
Contexts.init(); Contexts.init();
Pipelines.init();
MaterialIndices.init(); MaterialIndices.init();
VanillaInstances.init(); VanillaInstances.init();
CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendNameForCrashReport);
// https://github.com/Jozufozu/Flywheel/issues/69 // https://github.com/Jozufozu/Flywheel/issues/69
// Weird issue with accessor loading. // 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. // 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(); return BackendManagerImpl.isOn();
} }
// TODO: definitively sort existing calls to this method into API (include behavior in javadoc) or default backend code public static Backend getOffBackend() {
public static void refresh() { return BackendManagerImpl.getOffBackend();
BackendManagerImpl.refresh();
} }
public static Backend getDefaultBackend() { public static Backend getDefaultBackend() {

View file

@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.event;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.joml.FrustumIntersection; 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.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f; import com.mojang.math.Matrix4f;

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.api.instance;
import java.util.List; 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; 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 org.joml.FrustumIntersection;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.instancer.Instancer; 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 * 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; 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.instancer.Instancer;
import com.jozufozu.flywheel.api.struct.InstancePart;
/** /**
* An interface giving {@link Instance}s a hook to have a function called at * 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; package com.jozufozu.flywheel.api.instancer;
import com.jozufozu.flywheel.api.struct.InstancePart;
/** /**
* An instancer is how you interact with an instanced model. * An instancer is how you interact with an instanced model.
* <p> * <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.event.RenderStage;
import com.jozufozu.flywheel.api.model.Model; 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.struct.StructType;
public interface InstancerProvider { public interface InstancerProvider {

View file

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

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.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.gl.buffer.ElementBuffer; 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. * A holder for arbitrary vertex data that can be written to memory or a vertex list.
*/ */
public interface Mesh { public interface Mesh {
VertexType getVertexType(); VertexType getVertexType();
/** /**
@ -50,18 +48,9 @@ public interface Mesh {
/** /**
* Create an element buffer object that indexes the vertices of this 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. * @return an element buffer object indexing this model's vertices.
*/ */
default ElementBuffer createEBO() { ElementBuffer createEBO();
return QuadConverter.getInstance()
.quads2Tris(getVertexCount() / 4);
}
Vector4fc getBoundingSphere(); Vector4fc getBoundingSphere();

View file

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

View file

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

View file

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

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; 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> { public interface StructWriter<P extends InstancePart> {
/** /**
* Write the given struct to the given memory address. * Write the given struct to the given memory address.
*/ */
void write(final long ptr, final P struct); 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 * VertexList assumes nothing about the layout of the vertices. Implementations should feel free to return constants
* for values that are unused in their layout. * for values that are unused in their layout.
* </p> * </p>
* TODO: more flexible elements?
*/ */
public interface VertexList { public interface VertexList {
float x(int index); 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.Flywheel;
import com.jozufozu.flywheel.api.backend.Backend; 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.indirect.IndirectEngine;
import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine; import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine;
import com.jozufozu.flywheel.gl.versioned.GlCompat; 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.context.Contexts;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.lib.util.ShadersModHandler; import com.jozufozu.flywheel.lib.util.ShadersModHandler;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
public class Backends { 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. * Use a thread pool to buffer instances in parallel on the CPU.
*/ */
public static final Backend BATCHING = SimpleBackend.builder() public static final Backend BATCHING = SimpleBackend.builder()
.engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN))
.engineFactory(level -> new BatchingEngine()) .engineFactory(level -> new BatchingEngine())
.fallback(() -> Backends.OFF)
.supported(() -> !ShadersModHandler.isShaderPackInUse()) .supported(() -> !ShadersModHandler.isShaderPackInUse())
.register(Flywheel.rl("batching")); .register(Flywheel.rl("batching"));

View file

@ -1,13 +1,11 @@
package com.jozufozu.flywheel.backend; package com.jozufozu.flywheel.backend;
import com.jozufozu.flywheel.api.backend.BackendManager;
import com.jozufozu.flywheel.backend.compile.FlwCompiler; import com.jozufozu.flywheel.backend.compile.FlwCompiler;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.error.ErrorReporter; 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.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.server.packs.resources.ReloadableResourceManager; import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener; import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
@ -27,8 +25,6 @@ public class Loader implements ResourceManagerReloadListener {
@Override @Override
public void onResourceManagerReload(ResourceManager manager) { public void onResourceManagerReload(ResourceManager manager) {
BackendManager.refresh();
var errorReporter = new ErrorReporter(); var errorReporter = new ErrorReporter();
ShaderSources sources = new ShaderSources(errorReporter, manager); ShaderSources sources = new ShaderSources(errorReporter, manager);
@ -38,14 +34,12 @@ public class Loader implements ResourceManagerReloadListener {
FlwCompiler.INSTANCE = new FlwCompiler(sources); FlwCompiler.INSTANCE = new FlwCompiler(sources);
ClientLevel level = Minecraft.getInstance().level; // TODO: Move this to the impl package
if (level != null) { BackendManagerImpl.refresh(Minecraft.getInstance().level);
InstancedRenderDispatcher.resetInstanceWorld(level);
}
} }
public static void init() { 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(); Minecraft minecraft = Minecraft.getInstance();
if (minecraft == null) { if (minecraft == null) {
return; 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.Flywheel;
import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent; import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent;
import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent; import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.lib.pipeline.SimplePipeline;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -22,7 +23,6 @@ public class Pipelines {
.build(); .build();
public static void init() { public static void init() {
// noop
} }
public static class Files { 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.struct.StructType;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.api.vertex.VertexType; 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.backend.engine.indirect.IndirectComponent;
import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.GLSLVersion;
import com.jozufozu.flywheel.gl.shader.GlProgram; 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.FnSignature;
import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.material.MaterialIndices; import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.StringUtil;
public class FlwCompiler { 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.GlShader;
import com.jozufozu.flywheel.gl.shader.ShaderType; import com.jozufozu.flywheel.gl.shader.ShaderType;
import com.jozufozu.flywheel.glsl.SourceComponent; import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.util.FlwUtil;
public class ShaderCompiler { public class ShaderCompiler {
private final Map<ShaderKey, CompilationResult> shaderCache = new HashMap<>(); private final Map<ShaderKey, CompilationResult> shaderCache = new HashMap<>();
@ -87,7 +86,7 @@ public class ShaderCompiler {
} }
public static class Builder { public static class Builder {
private Consumer<FailedCompilation> errorConsumer = FlwUtil::noop; private Consumer<FailedCompilation> errorConsumer = error -> {};
private CompilationFactory factory = Compilation::new; private CompilationFactory factory = Compilation::new;
private Includer includer = RecursiveIncluder.INSTANCE; private Includer includer = RecursiveIncluder.INSTANCE;

View file

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

View file

@ -1,9 +1,8 @@
package com.jozufozu.flywheel.backend.engine; 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 { public class HandleImpl implements Handle {
private final AbstractInstancer<?> instancer; private final AbstractInstancer<?> instancer;
private int index; private int index;

View file

@ -1,8 +1,8 @@
package com.jozufozu.flywheel.backend.engine; package com.jozufozu.flywheel.backend.engine;
import com.jozufozu.flywheel.api.event.RenderStage; 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.model.Model;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
public record InstancerKey<P extends InstancePart>(StructType<P> type, Model model, RenderStage stage) { 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.GlBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.gl.shader.GlProgram; 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.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.RenderMath;
public class UniformBuffer { public class UniformBuffer {
@ -93,7 +93,7 @@ public class UniformBuffer {
var builder = ImmutableList.<LiveProvider>builder(); var builder = ImmutableList.<LiveProvider>builder();
int totalBytes = 0; int totalBytes = 0;
for (ShaderUniforms provider : providers) { for (ShaderUniforms provider : providers) {
int size = FlwUtil.align16(provider.byteSize()); int size = MoreMath.align16(provider.byteSize());
builder.add(new LiveProvider(provider, totalBytes, size)); builder.add(new LiveProvider(provider, totalBytes, size));

View file

@ -39,6 +39,10 @@ public class BatchedMeshPool {
growthMargin = vertexFormat.getVertexSize() * 32; growthMargin = vertexFormat.getVertexSize() * 32;
} }
public VertexFormat getVertexFormat() {
return vertexFormat;
}
/** /**
* Allocate a mesh in the arena. * Allocate a mesh in the arena.
* *
@ -139,10 +143,6 @@ public class BatchedMeshPool {
pendingUpload.clear(); pendingUpload.clear();
} }
public VertexFormat getVertexFormat() {
return vertexFormat;
}
@Override @Override
public String toString() { public String toString() {
return "BatchedMeshPool{" + "vertexFormat=" + vertexFormat + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}'; 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.backend.Engine;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage; 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.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model; 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.struct.StructType;
import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.util.FlwUtil; 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.ImmutableListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.jozufozu.flywheel.api.event.RenderStage; 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.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.model.Model; 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.struct.StructType;
import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.backend.engine.InstancerKey;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
@ -83,7 +83,7 @@ public class BatchingTransformManager {
var meshes = model.getMeshes(); var meshes = model.getMeshes();
for (var entry : meshes.entrySet()) { for (var entry : meshes.entrySet()) {
var material = entry.getKey(); var material = entry.getKey();
var renderType = material.getBatchingRenderType(); RenderType renderType = material.getBatchingRenderType();
TransformCall<?> transformCall = new TransformCall<>(instancer, material, alloc(entry.getValue(), renderType.format())); TransformCall<?> transformCall = new TransformCall<>(instancer, material, alloc(entry.getValue(), renderType.format()));
transformSet.put(renderType, transformCall); transformSet.put(renderType, transformCall);
} }

View file

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

View file

@ -32,7 +32,7 @@ public class DrawBuffer {
private boolean prepared; private boolean prepared;
private int vertexCount; 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.renderType = renderType;
this.format = format; this.format = format;
this.stride = stride; this.stride = stride;

View file

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

View file

@ -2,17 +2,16 @@ package com.jozufozu.flywheel.backend.engine.batching;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.instancer.InstancePart;
import com.jozufozu.flywheel.api.material.Material; 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.task.TaskExecutor;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f; import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f; import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import com.mojang.math.Vector4f;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@ -37,11 +36,11 @@ public class TransformCall<P extends InstancePart> {
return meshVertexCount * instancer.getInstanceCount(); return meshVertexCount * instancer.getInstanceCount();
} }
void setup() { public void setup() {
instancer.update(); 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(); int instances = instancer.getInstanceCount();
while (instances > 0) { 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); 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); 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(); long anchorPtr = vertexList.ptr();
int totalVertexCount = vertexList.vertexCount(); int totalVertexCount = vertexList.vertexCount();
vertexList.vertexCount(meshVertexCount); vertexList.vertexCount(meshVertexCount);
StructType.VertexTransformer<P> structVertexTransformer = instancer.type.getVertexTransformer(); StructVertexTransformer<P> structVertexTransformer = instancer.type.getVertexTransformer();
for (P p : parts) { for (P p : parts) {
mesh.copyTo(vertexList.ptr()); mesh.copyTo(vertexList.ptr());
@ -88,34 +87,12 @@ public class TransformCall<P extends InstancePart> {
} }
private static void applyMatrices(MutableVertexList vertexList, PoseStack.Pose matrices) { private static void applyMatrices(MutableVertexList vertexList, PoseStack.Pose matrices) {
Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f();
Matrix4f modelMatrix = matrices.pose(); Matrix4f modelMatrix = matrices.pose();
Matrix3f normalMatrix = matrices.normal(); Matrix3f normalMatrix = matrices.normal();
for (int i = 0; i < vertexList.vertexCount(); i++) { for (int i = 0; i < vertexList.vertexCount(); i++) {
pos.set( VertexTransformations.transformPos(vertexList, i, modelMatrix);
vertexList.x(i), VertexTransformations.transformNormal(vertexList, i, normalMatrix);
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());
} }
} }
} }

View file

@ -8,6 +8,7 @@ import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.layout.LayoutItem; import com.jozufozu.flywheel.api.layout.LayoutItem;
import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.pipeline.Pipeline;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.Pipelines;
import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.ShaderSources;
import com.jozufozu.flywheel.glsl.SourceComponent; import com.jozufozu.flywheel.glsl.SourceComponent;
import com.jozufozu.flywheel.glsl.SourceFile; 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.GlslBlock;
import com.jozufozu.flywheel.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.glsl.generate.GlslBuilder;
import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.glsl.generate.GlslExpr;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import net.minecraft.resources.ResourceLocation; 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 static org.lwjgl.opengl.GL45.glVertexArrayVertexBuffer;
import com.jozufozu.flywheel.api.event.RenderStage; 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.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType; 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.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.backend.engine.UniformBuffer;
import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.jozufozu.flywheel.lib.util.QuadConverter; import com.jozufozu.flywheel.lib.util.QuadConverter;
public class IndirectCullingGroup<P extends InstancePart> { public class IndirectCullingGroup<P extends InstancePart> {
@ -109,7 +109,7 @@ public class IndirectCullingGroup<P extends InstancePart> {
} }
buffers.updateCounts(instanceCountThisFrame, drawSet.size()); buffers.updateCounts(instanceCountThisFrame, drawSet.size());
meshPool.uploadAll(); meshPool.flush();
uploadInstanceData(); uploadInstanceData();
uploadIndirectCommands(); uploadIndirectCommands();
@ -174,7 +174,7 @@ public class IndirectCullingGroup<P extends InstancePart> {
int baseInstance = 0; int baseInstance = 0;
for (var batch : drawSet.indirectDraws) { for (var batch : drawSet.indirectDraws) {
batch.prepare(baseInstance); batch.prepare(baseInstance);
baseInstance += batch.instancer().instanceCount; baseInstance += batch.instancer().getInstanceCount();
} }
return baseInstance; return baseInstance;
} }

View file

@ -3,32 +3,48 @@ package com.jozufozu.flywheel.backend.engine.indirect;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.event.RenderStage; 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.material.Material;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.lib.material.MaterialIndices; 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 IndirectInstancer<P> instancer;
private final IndirectMeshPool.BufferedMesh mesh; private final IndirectMeshPool.BufferedMesh mesh;
private final Material material; private final Material material;
private final RenderStage stage; private final RenderStage stage;
int baseInstance = -1;
final int vertexMaterialID; private final int vertexMaterialID;
final int fragmentMaterialID; 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.instancer = instancer;
this.material = material; this.material = material;
this.stage = stage;
this.mesh = mesh; this.mesh = mesh;
this.stage = stage;
this.vertexMaterialID = MaterialIndices.getVertexShaderIndex(material); this.vertexMaterialID = MaterialIndices.getVertexShaderIndex(material);
this.fragmentMaterialID = MaterialIndices.getFragmentShaderIndex(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) { public void prepare(int baseInstance) {
instancer.update(); instancer.update();
if (baseInstance == this.baseInstance) { if (baseInstance == this.baseInstance) {
@ -39,7 +55,7 @@ public final class IndirectDraw<P extends InstancePart> {
needsFullWrite = true; needsFullWrite = true;
} }
void writeObjects(long objectPtr, long batchIDPtr, int batchID) { public void writeObjects(long objectPtr, long batchIDPtr, int batchID) {
if (needsFullWrite) { if (needsFullWrite) {
instancer.writeFull(objectPtr, batchIDPtr, batchID); instancer.writeFull(objectPtr, batchIDPtr, batchID);
} else { } else {
@ -48,7 +64,7 @@ public final class IndirectDraw<P extends InstancePart> {
} }
public void writeIndirectCommand(long ptr) { public void writeIndirectCommand(long ptr) {
var boundingSphere = mesh.mesh.getBoundingSphere(); var boundingSphere = mesh.getMesh().getBoundingSphere();
MemoryUtil.memPutInt(ptr, mesh.getIndexCount()); // count MemoryUtil.memPutInt(ptr, mesh.getIndexCount()); // count
MemoryUtil.memPutInt(ptr + 4, 0); // instanceCount - to be incremented by the compute shader 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 boundingSphere.getToAddress(ptr + 20); // boundingSphere
MemoryUtil.memPutInt(ptr + 36, vertexMaterialID); // vertexMaterialID MemoryUtil.memPutInt(ptr + 36, vertexMaterialID); // vertexMaterialID
MemoryUtil.memPutInt(ptr + 40, fragmentMaterialID); // fragmentMaterialID 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 java.util.Map;
import com.jozufozu.flywheel.api.event.RenderStage; 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.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model; 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.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.backend.engine.InstancerKey;
import com.jozufozu.flywheel.util.Pair; import com.jozufozu.flywheel.util.Pair;
public class IndirectDrawManager { public class IndirectDrawManager {
private final Map<InstancerKey<?>, IndirectInstancer<?>> instancers = new HashMap<>(); private final Map<InstancerKey<?>, IndirectInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>(); private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>();
private final List<IndirectInstancer<?>> initializedInstancers = new ArrayList<>(); private final List<IndirectInstancer<?>> initializedInstancers = new ArrayList<>();

View file

@ -11,10 +11,9 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.jozufozu.flywheel.api.event.RenderStage; 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.material.Material;
import com.jozufozu.flywheel.api.struct.InstancePart;
import com.jozufozu.flywheel.lib.material.MaterialIndices; import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.util.Textures;
public class IndirectDrawSet<P extends InstancePart> { 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) { 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(); determineMultiDraws();
} }

View file

@ -7,9 +7,9 @@ import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.backend.Engine;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage; 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.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model; 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.struct.StructType;
import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.gl.GlStateTracker; 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 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.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.engine.AbstractInstancer; import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
public class IndirectInstancer<P extends InstancePart> extends AbstractInstancer<P> { public class IndirectInstancer<P extends InstancePart> extends AbstractInstancer<P> {
private final long instanceStride;
private final long objectStride;
private final StructWriter<P> writer;
int instanceCount = 0;
public IndirectInstancer(StructType<P> type) { public IndirectInstancer(StructType<P> type) {
super(type); super(type);
this.objectStride = type.getLayout() this.instanceStride = type.getLayout()
.getStride(); .getStride();
writer = type.getWriter();
} }
public boolean isEmpty() { public void update() {
return changed.isEmpty() && deleted.isEmpty() && instanceCount == 0; removeDeletedInstances();
}
void update() {
if (!deleted.isEmpty()) {
removeDeletedInstances();
}
instanceCount = data.size();
} }
public void writeSparse(long objectPtr, long batchIDPtr, int batchID) { 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)) { // write batchID
writer.write(objectPtr + i * objectStride, data.get(i)); MemoryUtil.memPutInt(batchIDPtr + IndirectBuffers.INT_SIZE * i, batchID);
MemoryUtil.memPutInt(batchIDPtr + i * IndirectBuffers.INT_SIZE, batchID);
} }
changed.clear(); changed.clear();
} }
public void writeFull(long objectPtr, long batchIDPtr, int batchID) { public void writeFull(long objectPtr, long batchIDPtr, int batchID) {
StructWriter<P> writer = type.getWriter();
for (var object : data) { for (var object : data) {
// write object // write object
writer.write(objectPtr, object); writer.write(objectPtr, object);
objectPtr += objectStride; objectPtr += instanceStride;
// write batchID // write batchID
MemoryUtil.memPutInt(batchIDPtr, batchID); MemoryUtil.memPutInt(batchIDPtr, batchID);

View file

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

View file

@ -1,86 +1,50 @@
package com.jozufozu.flywheel.backend.engine.instancing; 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.GlStateTracker;
import com.jozufozu.flywheel.gl.array.GlVertexArray; import com.jozufozu.flywheel.gl.array.GlVertexArray;
public class DrawCall { public class DrawCall {
private final GPUInstancer<?> instancer;
private final InstancedMeshPool.BufferedMesh mesh;
final GPUInstancer<?> instancer;
final Material material;
private final int meshAttributes; private final int meshAttributes;
InstancedMeshPool.BufferedMesh bufferedMesh; private GlVertexArray vao;
GlVertexArray vao;
DrawCall(GPUInstancer<?> instancer, Material material, InstancedMeshPool.BufferedMesh mesh) { public DrawCall(GPUInstancer<?> instancer, InstancedMeshPool.BufferedMesh mesh) {
this.instancer = instancer; this.instancer = instancer;
this.material = material; this.mesh = mesh;
this.vao = new GlVertexArray();
this.bufferedMesh = mesh; meshAttributes = this.mesh.getAttributeCount();
this.meshAttributes = this.bufferedMesh.getAttributeCount(); vao = new GlVertexArray();
this.vao.enableArrays(this.meshAttributes + instancer.instanceFormat.getAttributeCount()); vao.enableArrays(meshAttributes + this.instancer.getAttributeCount());
} }
public Material getMaterial() { public boolean isInvalid() {
return material; return instancer.isInvalid() || vao == null;
}
public VertexType getVertexType() {
return bufferedMesh.getVertexType();
} }
public void render() { public void render() {
if (invalid()) { if (isInvalid()) {
return; return;
} }
try (var ignored = GlStateTracker.getRestoreState()) { try (var ignored = GlStateTracker.getRestoreState()) {
instancer.update();
this.instancer.update(); instancer.bindToVAO(vao, meshAttributes);
bindInstancerToVAO(); if (instancer.getInstanceCount() > 0) {
mesh.drawInstances(vao, instancer.getInstanceCount());
if (this.instancer.glInstanceCount > 0) {
bufferedMesh.drawInstances(vao, this.instancer.glInstanceCount);
} }
} }
} }
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() { public void delete() {
if (invalid()) { if (vao == null) {
return; return;
} }
vao.delete(); vao.delete();
bufferedMesh.delete();
vao = null; vao = null;
bufferedMesh = null;
} }
} }

View file

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

View file

@ -39,9 +39,12 @@ public class InstancedMeshPool {
public InstancedMeshPool(VertexType vertexType) { public InstancedMeshPool(VertexType vertexType) {
this.vertexType = vertexType; this.vertexType = vertexType;
int stride = vertexType.getLayout().getStride(); 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(); pendingUpload.clear();
} }
public VertexType getVertexType() {
return vertexType;
}
@Override @Override
public String toString() { public String toString() {
return "InstancedMeshPool{" + "vertexType=" + vertexType + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}'; return "InstancedMeshPool{" + "vertexType=" + vertexType + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}';
@ -210,10 +209,6 @@ public class InstancedMeshPool {
boundTo.clear(); boundTo.clear();
} }
public void drawCall(GlVertexArray vao) {
drawInstances(vao, 1);
}
public void drawInstances(GlVertexArray vao, int instanceCount) { public void drawInstances(GlVertexArray vao, int instanceCount) {
if (isEmpty()) { if (isEmpty()) {
return; return;

View file

@ -14,16 +14,15 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.jozufozu.flywheel.api.event.RenderStage; 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.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.model.Model; 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.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.backend.engine.InstancerKey;
public class InstancingDrawManager { public class InstancingDrawManager {
private final Map<InstancerKey<?>, GPUInstancer<?>> instancers = new HashMap<>(); private final Map<InstancerKey<?>, GPUInstancer<?>> instancers = new HashMap<>();
private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>(); private final List<UninitializedInstancer> uninitializedInstancers = new ArrayList<>();
private final List<GPUInstancer<?>> initializedInstancers = new ArrayList<>(); private final List<GPUInstancer<?>> initializedInstancers = new ArrayList<>();
@ -48,9 +47,6 @@ public class InstancingDrawManager {
public void flush() { public void flush() {
for (var instancer : uninitializedInstancers) { for (var instancer : uninitializedInstancers) {
instancer.instancer()
.init();
add(instancer.instancer(), instancer.model(), instancer.stage()); add(instancer.instancer(), instancer.model(), instancer.stage());
} }
uninitializedInstancers.clear(); uninitializedInstancers.clear();
@ -80,11 +76,13 @@ public class InstancingDrawManager {
} }
private void add(GPUInstancer<?> instancer, Model model, RenderStage stage) { private void add(GPUInstancer<?> instancer, Model model, RenderStage stage) {
instancer.init();
DrawSet drawSet = drawSets.computeIfAbsent(stage, DrawSet::new); DrawSet drawSet = drawSets.computeIfAbsent(stage, DrawSet::new);
var meshes = model.getMeshes(); var meshes = model.getMeshes();
for (var entry : meshes.entrySet()) { for (var entry : meshes.entrySet()) {
DrawCall drawCall = new DrawCall(instancer, entry.getKey(), alloc(entry.getValue())); var mesh = alloc(entry.getValue());
var shaderState = new ShaderState(drawCall.getMaterial(), drawCall.getVertexType(), drawCall.instancer.type); ShaderState shaderState = new ShaderState(entry.getKey(), mesh.getVertexType(), instancer.type);
DrawCall drawCall = new DrawCall(instancer, mesh);
drawSet.put(shaderState, drawCall); drawSet.put(shaderState, drawCall);
} }
initializedInstancers.add(instancer); initializedInstancers.add(instancer);
@ -96,7 +94,6 @@ public class InstancingDrawManager {
} }
public static class DrawSet implements Iterable<Map.Entry<ShaderState, Collection<DrawCall>>> { public static class DrawSet implements Iterable<Map.Entry<ShaderState, Collection<DrawCall>>> {
public static final DrawSet EMPTY = new DrawSet(ImmutableListMultimap.of()); public static final DrawSet EMPTY = new DrawSet(ImmutableListMultimap.of());
private final ListMultimap<ShaderState, DrawCall> drawCalls; 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.context.Context;
import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage; 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.instancer.Instancer;
import com.jozufozu.flywheel.api.model.Model; 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.struct.StructType;
import com.jozufozu.flywheel.api.task.TaskExecutor; 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.compile.FlwCompiler;
import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.backend.engine.UniformBuffer;
import com.jozufozu.flywheel.gl.GlStateTracker; import com.jozufozu.flywheel.gl.GlStateTracker;
import com.jozufozu.flywheel.gl.GlTextureUnit; import com.jozufozu.flywheel.gl.GlTextureUnit;
import com.jozufozu.flywheel.lib.material.MaterialIndices; import com.jozufozu.flywheel.lib.material.MaterialIndices;
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
@ -47,7 +47,7 @@ public class InstancingEngine implements Engine {
@Override @Override
public void beginFrame(TaskExecutor executor, RenderContext context) { public void beginFrame(TaskExecutor executor, RenderContext context) {
try (var restoreState = GlStateTracker.getRestoreState()) { try (var state = GlStateTracker.getRestoreState()) {
drawManager.flush(); drawManager.flush();
} }
} }
@ -60,7 +60,7 @@ public class InstancingEngine implements Engine {
return; return;
} }
try (var restoreState = GlStateTracker.getRestoreState()) { try (var state = GlStateTracker.getRestoreState()) {
setup(); setup();
render(drawSet); render(drawSet);
@ -83,7 +83,7 @@ public class InstancingEngine implements Engine {
var shader = entry.getKey(); var shader = entry.getKey();
var drawCalls = entry.getValue(); var drawCalls = entry.getValue();
drawCalls.removeIf(DrawCall::shouldRemove); drawCalls.removeIf(DrawCall::isInvalid);
if (drawCalls.isEmpty()) { if (drawCalls.isEmpty()) {
continue; continue;
@ -102,9 +102,9 @@ public class InstancingEngine implements Engine {
} }
private void setup(ShaderState desc) { private void setup(ShaderState desc) {
var vertexType = desc.vertex();
var structType = desc.instance();
var material = desc.material(); var material = desc.material();
var vertexType = desc.vertexType();
var structType = desc.instanceType();
var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Pipelines.INSTANCED_ARRAYS); var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Pipelines.INSTANCED_ARRAYS);
UniformBuffer.syncAndBind(program); 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.struct.StructType;
import com.jozufozu.flywheel.api.vertex.VertexType; 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 @Nullable
private Runnable getNextTask() { private Runnable getNextTask() {
Runnable task = taskQueue.pollFirst(); 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.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException; 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.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
public class BackendArgument implements ArgumentType<Backend> { public class BackendArgument implements ArgumentType<Backend> {
private static final List<String> STRING_IDS = Backend.REGISTRY.getAllIds().stream().map(ResourceLocation::toString).toList(); private static final List<String> STRING_IDS = Backend.REGISTRY.getAllIds().stream().map(ResourceLocation::toString).toList();
private static final Dynamic2CommandExceptionType INVALID = new Dynamic2CommandExceptionType((found, constants) -> { public static final DynamicCommandExceptionType ERROR_UNKNOWN_BACKEND = new DynamicCommandExceptionType(arg -> {
// TODO: don't steal lang return new TextComponent("Unknown backend '" + arg + "'");
return new TranslatableComponent("commands.forge.arguments.enum.invalid", constants, found);
}); });
public static final BackendArgument INSTANCE = new BackendArgument(); public static final BackendArgument INSTANCE = new BackendArgument();
@ -33,7 +32,7 @@ public class BackendArgument implements ArgumentType<Backend> {
Backend backend = Backend.REGISTRY.get(id); Backend backend = Backend.REGISTRY.get(id);
if (backend == null) { if (backend == null) {
throw INVALID.createWithContext(reader, id.toString(), STRING_IDS); throw ERROR_UNKNOWN_BACKEND.createWithContext(reader, id.toString());
} }
return backend; return backend;

View file

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

View file

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

View file

@ -3,10 +3,10 @@ package com.jozufozu.flywheel.handler;
import java.util.ArrayList; import java.util.ArrayList;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.lib.light.LightUpdater; import com.jozufozu.flywheel.lib.light.LightUpdater;
import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker; import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker;
import com.jozufozu.flywheel.util.FlwUtil;
import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.StringUtil;
import com.jozufozu.flywheel.util.WorldAttached; import com.jozufozu.flywheel.util.WorldAttached;
@ -33,7 +33,7 @@ public class ForgeEvents {
} }
public static void tickLight(TickEvent.ClientTickEvent event) { 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) LightUpdater.get(Minecraft.getInstance().level)
.tick(); .tick();
} }

View file

@ -3,14 +3,33 @@ package com.jozufozu.flywheel.impl;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.backend.Backend; 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.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 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 { public final class BackendManagerImpl {
private static final Logger LOGGER = LogUtils.getLogger(); 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 final Backend DEFAULT_BACKEND = findDefaultBackend();
private static Backend backend; private static Backend backend;
@Nullable @Nullable
@ -19,17 +38,35 @@ public final class BackendManagerImpl {
} }
public static boolean isOn() { public static boolean isOn() {
return backend != null && backend != Backends.OFF; return backend != null && backend != OFF_BACKEND;
} }
public static void refresh() { public static Backend getOffBackend() {
backend = chooseBackend(); return OFF_BACKEND;
} }
public static Backend getDefaultBackend() { public static Backend getDefaultBackend() {
return DEFAULT_BACKEND; 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() { private static Backend chooseBackend() {
var preferred = FlwConfig.get().getBackend(); var preferred = FlwConfig.get().getBackend();
var actual = preferred.findFallback(); var actual = preferred.findFallback();
@ -41,21 +78,17 @@ public final class BackendManagerImpl {
return actual; return actual;
} }
private static Backend findDefaultBackend() { public static void init() {
// TODO: Automatically select the best default config based on the user's driver CrashReportCallables.registerCrashCallable("Flywheel Backend", () -> {
// TODO: Figure out how this will work if custom backends are registered if (backend == null) {
return Backends.INDIRECT; return "Uninitialized";
} }
var backendId = Backend.REGISTRY.getId(backend);
public static String getBackendNameForCrashReport() { if (backendId == null) {
if (backend == null) { return "Unregistered";
return "Uninitialized"; }
} return backendId.toString();
var backendId = Backend.REGISTRY.getId(backend); });
if (backendId == null) {
return "Unregistered";
}
return backendId.toString();
} }
private BackendManagerImpl() { 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.DynamicInstance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.api.instance.effect.Effect; import com.jozufozu.flywheel.api.instance.effect.Effect;
import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.backend.task.FlwTaskExecutor;
import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwCommands;
import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.config.FlwConfig;
import com.jozufozu.flywheel.impl.instancing.manager.BlockEntityInstanceManager; 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. * 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 Engine engine;
private final TaskExecutor taskExecutor; private final ParallelTaskExecutor taskExecutor;
private final InstanceManager<BlockEntity> blockEntities; private final InstanceManager<BlockEntity> blockEntities;
private final InstanceManager<Entity> entities; private final InstanceManager<Entity> entities;
@ -37,7 +38,7 @@ public class InstanceWorld {
public InstanceWorld(LevelAccessor level) { public InstanceWorld(LevelAccessor level) {
engine = BackendManager.getBackend().createEngine(level); engine = BackendManager.getBackend().createEngine(level);
taskExecutor = BackendUtil.getTaskExecutor(); taskExecutor = FlwTaskExecutor.get();
blockEntities = new BlockEntityInstanceManager(engine); blockEntities = new BlockEntityInstanceManager(engine);
entities = new EntityInstanceManager(engine); entities = new EntityInstanceManager(engine);
@ -127,9 +128,15 @@ public class InstanceWorld {
* Free all acquired resources and invalidate this instance world. * Free all acquired resources and invalidate this instance world.
*/ */
public void delete() { public void delete() {
taskExecutor.discardAndAwait();
blockEntities.invalidate(); blockEntities.invalidate();
entities.invalidate(); entities.invalidate();
effects.invalidate(); effects.invalidate();
engine.delete(); engine.delete();
} }
@Override
public void close() {
delete();
}
} }

View file

@ -3,14 +3,13 @@ package com.jozufozu.flywheel.impl.instancing;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.event.BeginFrameEvent; 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.event.RenderStageEvent;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.effect.Effect; import com.jozufozu.flywheel.api.instance.effect.Effect;
import com.jozufozu.flywheel.backend.BackendUtil;
import com.jozufozu.flywheel.extension.ClientLevelExtension; import com.jozufozu.flywheel.extension.ClientLevelExtension;
import com.jozufozu.flywheel.impl.instancing.manager.InstanceManager; 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 com.jozufozu.flywheel.util.WorldAttached;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -34,7 +33,7 @@ public class InstancedRenderDispatcher {
return; return;
} }
if (!BackendUtil.canUseInstancing(level)) { if (!FlwUtil.canUseInstancing(level)) {
return; return;
} }
@ -49,7 +48,7 @@ public class InstancedRenderDispatcher {
*/ */
public static void queueUpdate(Entity entity) { public static void queueUpdate(Entity entity) {
Level level = entity.level; Level level = entity.level;
if (!BackendUtil.canUseInstancing(level)) { if (!FlwUtil.canUseInstancing(level)) {
return; return;
} }
@ -63,7 +62,7 @@ public class InstancedRenderDispatcher {
* @param effect The effect whose instance you want to update. * @param effect The effect whose instance you want to update.
*/ */
public static void queueUpdate(LevelAccessor level, Effect effect) { public static void queueUpdate(LevelAccessor level, Effect effect) {
if (!BackendUtil.canUseInstancing(level)) { if (!FlwUtil.canUseInstancing(level)) {
return; return;
} }
@ -77,7 +76,7 @@ public class InstancedRenderDispatcher {
* @throws IllegalStateException if the backend is off * @throws IllegalStateException if the backend is off
*/ */
private static InstanceWorld getInstanceWorld(LevelAccessor level) { 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!"); throw new IllegalStateException("Cannot retrieve instance world when backend is off!");
} }
return INSTANCE_WORLDS.get(level); return INSTANCE_WORLDS.get(level);
@ -100,7 +99,7 @@ public class InstancedRenderDispatcher {
} }
public static void tick(TickEvent.ClientTickEvent event) { public static void tick(TickEvent.ClientTickEvent event) {
if (!BackendUtil.isGameActive() || event.phase == TickEvent.Phase.START) { if (!FlwUtil.isGameActive() || event.phase == TickEvent.Phase.START) {
return; return;
} }
@ -117,7 +116,7 @@ public class InstancedRenderDispatcher {
} }
Level level = cameraEntity.level; Level level = cameraEntity.level;
if (!BackendUtil.canUseInstancing(level)) { if (!FlwUtil.canUseInstancing(level)) {
return; return;
} }
@ -129,12 +128,12 @@ public class InstancedRenderDispatcher {
} }
public static void onBeginFrame(BeginFrameEvent event) { public static void onBeginFrame(BeginFrameEvent event) {
if (!BackendUtil.isGameActive()) { if (!FlwUtil.isGameActive()) {
return; return;
} }
ClientLevel level = event.getContext().level(); ClientLevel level = event.getContext().level();
if (!BackendUtil.canUseInstancing(level)) { if (!FlwUtil.canUseInstancing(level)) {
return; return;
} }
@ -143,26 +142,17 @@ public class InstancedRenderDispatcher {
public static void onRenderStage(RenderStageEvent event) { public static void onRenderStage(RenderStageEvent event) {
ClientLevel level = event.getContext().level(); ClientLevel level = event.getContext().level();
if (!BackendUtil.canUseInstancing(level)) { if (!FlwUtil.canUseInstancing(level)) {
return; return;
} }
INSTANCE_WORLDS.get(level).renderStage(event.getContext(), event.getStage()); 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) { public static void resetInstanceWorld(ClientLevel level) {
INSTANCE_WORLDS.remove(level, InstanceWorld::delete); INSTANCE_WORLDS.remove(level, InstanceWorld::delete);
if (!BackendUtil.canUseInstancing(level)) { if (!FlwUtil.canUseInstancing(level)) {
return; return;
} }
@ -175,7 +165,7 @@ public class InstancedRenderDispatcher {
public static void addDebugInfo(List<String> info) { public static void addDebugInfo(List<String> info) {
ClientLevel level = Minecraft.getInstance().level; ClientLevel level = Minecraft.getInstance().level;
if (BackendUtil.canUseInstancing(level)) { if (FlwUtil.canUseInstancing(level)) {
INSTANCE_WORLDS.get(level).addDebugInfo(info); INSTANCE_WORLDS.get(level).addDebugInfo(info);
} else { } else {
info.add("Disabled"); 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.BlockEntityInstance;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext; 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.InstancingControllerHelper;
import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage; import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.impl.instancing.storage.Storage; 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.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
@ -66,7 +66,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
return false; return false;
} }
if (BackendUtil.isFlywheelLevel(level)) { if (FlwUtil.isFlywheelLevel(level)) {
BlockPos pos = blockEntity.getBlockPos(); BlockPos pos = blockEntity.getBlockPos();
BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); 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.backend.Engine;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.controller.InstanceContext; 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.InstancingControllerHelper;
import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage; import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage;
import com.jozufozu.flywheel.impl.instancing.storage.Storage; import com.jozufozu.flywheel.impl.instancing.storage.Storage;
import com.jozufozu.flywheel.util.FlwUtil;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@ -53,7 +53,7 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
Level level = entity.level; 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)); 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. * Update the instance associated with an object.
* *
@ -91,10 +99,6 @@ public abstract class InstanceManager<T> {
queue.add(Transaction.update(obj)); queue.add(Transaction.update(obj));
} }
public void remove(T obj) {
getStorage().remove(obj);
}
public void recreateAll() { public void recreateAll() {
getStorage().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.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.lib.format.AbstractVertexList; 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 com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.LightTexture;

View file

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

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.lib.box; 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; import net.minecraft.world.phys.AABB;

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.lib.box;
import java.util.Collection; 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.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -19,7 +19,6 @@ public class MutableBox implements ImmutableBox {
private int maxZ; private int maxZ;
public MutableBox() { public MutableBox() {
} }
public MutableBox(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { 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; package com.jozufozu.flywheel.lib.context;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.context.Context;
import com.jozufozu.flywheel.util.ResourceUtil; import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation; 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 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)); public static final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT));
@ApiStatus.Internal
public static void init() { 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_VERTEX = ResourceUtil.subPath(Names.WORLD, ".vert");
public static final ResourceLocation WORLD_FRAGMENT = ResourceUtil.subPath(Names.WORLD, ".frag"); 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_VERTEX = ResourceUtil.subPath(Names.CRUMBLING, ".vert");
public static final ResourceLocation CRUMBLING_FRAGMENT = ResourceUtil.subPath(Names.CRUMBLING, ".frag"); 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 WORLD = Flywheel.rl("context/world");
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling"); 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 org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; 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; import net.minecraft.client.renderer.texture.OverlayTexture;

View file

@ -1,25 +1,27 @@
package com.jozufozu.flywheel.lib.format; package com.jozufozu.flywheel.lib.format;
import org.jetbrains.annotations.ApiStatus;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.util.ResourceUtil; import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation; 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 BlockVertex BLOCK = VertexType.REGISTRY.registerAndGet(new BlockVertex());
public static final PosTexNormalVertex POS_TEX_NORMAL = VertexType.REGISTRY.registerAndGet(new PosTexNormalVertex()); public static final PosTexNormalVertex POS_TEX_NORMAL = VertexType.REGISTRY.registerAndGet(new PosTexNormalVertex());
@ApiStatus.Internal
public static void init() { 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 BLOCK_LAYOUT = ResourceUtil.subPath(Names.BLOCK, ".vert");
public static final ResourceLocation POS_TEX_NORMAL_LAYOUT = ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".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 BLOCK = Flywheel.rl("layout/block");
public static final ResourceLocation POS_TEX_NORMAL = Flywheel.rl("layout/pos_tex_normal"); 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 org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; 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.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture; 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; import com.jozufozu.flywheel.gl.array.VertexAttributeI;
public class CommonItems { public class CommonItems {
private static final String VEC2_TYPE = "vec2"; private static final String VEC2_TYPE = "vec2";
private static final String VEC3_TYPE = "vec3"; private static final String VEC3_TYPE = "vec3";
private static final String VEC4_TYPE = "vec4"; 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 FLOAT_TYPE = "float";
private static final String UINT_TYPE = "uint"; private static final String UINT_TYPE = "uint";
private static final String LIGHT_COORD_TYPE = "LightCoord"; private static final String LIGHT_COORD_TYPE = "LightCoord";
public static final VecInput LIGHT_COORD = VecInput.builder() public static final VecInput LIGHT_COORD = VecInput.builder()
.vertexAttribute(new VertexAttributeI(GlNumericType.USHORT, 2)) .vertexAttribute(new VertexAttributeI(GlNumericType.USHORT, 2))
.typeName(IVEC2_TYPE) .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 MAT3 = new MatInput(3, 3, "mat3", "Mat3F", "unpackMat3F");
public static final MatInput MAT4 = new MatInput(4, 4, "mat4", "Mat4F", "unpackMat4F"); 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.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Stream; 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.box.ImmutableBox;
import com.jozufozu.flywheel.lib.task.WorkGroup; import com.jozufozu.flywheel.lib.task.WorkGroup;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.FlwUtil;
@ -23,7 +23,6 @@ import net.minecraft.world.level.LightLayer;
* {@link LightUpdated} for LightUpdater to work with them. * {@link LightUpdated} for LightUpdater to work with them.
*/ */
public class LightUpdater { public class LightUpdater {
private static final WorldAttached<LightUpdater> LEVELS = new WorldAttached<>(LightUpdater::new); private static final WorldAttached<LightUpdater> LEVELS = new WorldAttached<>(LightUpdater::new);
private final LevelAccessor level; private final LevelAccessor level;
@ -68,7 +67,7 @@ public class LightUpdater {
} }
}) })
.onComplete(() -> listeners.forEach(this::addListener)) .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; import net.minecraft.resources.ResourceLocation;
// TODO: add messages to exceptions // TODO: add messages to exceptions
public class MaterialIndices { public final class MaterialIndices {
private static Reference2IntMap<Material> materialIndices; private static Reference2IntMap<Material> materialIndices;
private static Object2IntMap<ResourceLocation> vertexShaderIndices; private static Object2IntMap<ResourceLocation> vertexShaderIndices;
private static Object2IntMap<ResourceLocation> fragmentShaderIndices; private static Object2IntMap<ResourceLocation> fragmentShaderIndices;

View file

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

View file

@ -1,6 +1,7 @@
package com.jozufozu.flywheel.lib.material; package com.jozufozu.flywheel.lib.material;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.material.MaterialVertexTransformer;
import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
@ -12,9 +13,9 @@ public class SimpleMaterial implements Material {
protected final Runnable setup; protected final Runnable setup;
protected final Runnable clear; protected final Runnable clear;
protected final RenderType batchingRenderType; 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.vertexShader = vertexShader;
this.fragmentShader = fragmentShader; this.fragmentShader = fragmentShader;
this.setup = setup; this.setup = setup;
@ -53,7 +54,7 @@ public class SimpleMaterial implements Material {
} }
@Override @Override
public VertexTransformer getVertexTransformer() { public MaterialVertexTransformer getVertexTransformer() {
return vertexTransformer; return vertexTransformer;
} }
@ -63,8 +64,7 @@ public class SimpleMaterial implements Material {
protected Runnable setup = () -> {}; protected Runnable setup = () -> {};
protected Runnable clear = () -> {}; protected Runnable clear = () -> {};
protected RenderType batchingRenderType = RenderType.solid(); protected RenderType batchingRenderType = RenderType.solid();
protected VertexTransformer vertexTransformer = (vertexList, level) -> { protected MaterialVertexTransformer vertexTransformer = (vertexList, level) -> {};
};
public Builder() { public Builder() {
} }
@ -100,7 +100,7 @@ public class SimpleMaterial implements Material {
return this; return this;
} }
public Builder vertexTransformer(VertexTransformer vertexTransformer) { public Builder vertexTransformer(MaterialVertexTransformer vertexTransformer) {
this.vertexTransformer = vertexTransformer; this.vertexTransformer = vertexTransformer;
return this; 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; 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; import java.nio.ByteBuffer;
@ -9,7 +9,37 @@ import com.jozufozu.flywheel.mixin.matrix.Matrix4fAccessor;
import com.mojang.math.Matrix3f; import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f; 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) { public static void write(Matrix4f matrix, ByteBuffer buf) {
Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix;
buf.putFloat(m.flywheel$m00()); 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; import net.minecraftforge.client.model.pipeline.LightUtil;
public class RenderMath { public final class RenderMath {
/** /**
* Convert a signed byte into a signed, normalized float. * 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; 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; public static final boolean DEBUG_MEMORY_SAFETY = System.getProperty("flw.debugMemorySafety") != null;
static final Cleaner CLEANER = Cleaner.create(); static final Cleaner CLEANER = Cleaner.create();

View file

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

View file

@ -15,7 +15,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState; 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<BlockState, Model> BLOCK_STATE = new HashMap<>();
private static final Map<PartialModel, Model> PARTIAL = new HashMap<>(); private static final Map<PartialModel, Model> PARTIAL = new HashMap<>();
private static final Map<Pair<PartialModel, Direction>, Model> PARTIAL_DIR = 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.Vector4f;
import org.joml.Vector4fc; import org.joml.Vector4fc;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.memory.MemoryBlock;
public class SimpleMesh implements Mesh { public class SimpleMesh implements QuadMesh {
private final VertexType vertexType; private final VertexType vertexType;
private final int vertexCount; private final int vertexCount;
private final MemoryBlock contents; private final MemoryBlock contents;

View file

@ -5,7 +5,7 @@ import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.model.Mesh; 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.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil; import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.jozufozu.flywheel.lib.model.SimpleMesh; 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.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BakedModel;
@ -106,8 +105,8 @@ public class BakedModelBuilder {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, shaded); Material material = materialFunc.apply(renderType, shaded);
if (material != null) { if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); 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); 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(); buffer.end();
Material material = materialFunc.apply(renderType, false); Material material = materialFunc.apply(renderType, false);
if (material != null) { if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString())); 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); 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.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.model.Mesh; 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.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil; import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.jozufozu.flywheel.lib.model.SimpleMesh; 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.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockAndTintGetter;
@ -95,8 +94,8 @@ public class BlockModelBuilder {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, shaded); Material material = materialFunc.apply(renderType, shaded);
if (material != null) { if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); 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); ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer);
@ -110,8 +109,8 @@ public class BlockModelBuilder {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, false); Material material = materialFunc.apply(renderType, false);
if (material != null) { if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString())); 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); 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.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.model.Mesh; 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.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil; import com.jozufozu.flywheel.lib.model.ModelUtil;
import com.jozufozu.flywheel.lib.model.SimpleMesh; 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.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -102,8 +101,8 @@ public class MultiBlockModelBuilder {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, shaded); Material material = materialFunc.apply(renderType, shaded);
if (material != null) { if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString() + ",shaded=" + shaded)); 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); ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer);
@ -117,8 +116,8 @@ public class MultiBlockModelBuilder {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, false); Material material = materialFunc.apply(renderType, false);
if (material != null) { if (material != null) {
Pair<VertexType, MemoryBlock> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK);
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString())); 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); 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.Vector4f;
import org.joml.Vector4fc; import org.joml.Vector4fc;
import com.jozufozu.flywheel.api.model.Mesh;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.format.Formats;
import com.jozufozu.flywheel.lib.format.PosTexNormalVertex; import com.jozufozu.flywheel.lib.format.PosTexNormalVertex;
import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.memory.MemoryBlock;
import com.jozufozu.flywheel.lib.model.ModelUtil; 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 int vertexCount;
private final MemoryBlock contents; private final MemoryBlock contents;
private final ReusableVertexList vertexList; private final ReusableVertexList vertexList;
private final Vector4f boundingSphere; private final Vector4f boundingSphere;
private final String name; private final String name;
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) { public ModelPart(List<ModelPartBuilder.CuboidBuilder> cuboids, String name) {
this.name = name; this.name = name;
this.vertexCount = countVertices(cuboids); this.vertexCount = countVertices(cuboids);
@ -28,7 +28,7 @@ public class ModelPart implements Mesh {
contents = MemoryBlock.malloc(size()); contents = MemoryBlock.malloc(size());
long ptr = contents.ptr(); long ptr = contents.ptr();
VertexWriter writer = new VertexWriterImpl(ptr); VertexWriter writer = new VertexWriterImpl(ptr);
for (PartBuilder.CuboidBuilder cuboid : cuboids) { for (ModelPartBuilder.CuboidBuilder cuboid : cuboids) {
cuboid.write(writer); cuboid.write(writer);
} }
@ -39,8 +39,8 @@ public class ModelPart implements Mesh {
boundingSphere = ModelUtil.computeBoundingSphere(vertexList); boundingSphere = ModelUtil.computeBoundingSphere(vertexList);
} }
public static PartBuilder builder(String name, int sizeU, int sizeV) { public static ModelPartBuilder builder(String name, int sizeU, int sizeV) {
return new PartBuilder(name, sizeU, sizeV); return new ModelPartBuilder(name, sizeU, sizeV);
} }
@Override @Override
@ -78,9 +78,9 @@ public class ModelPart implements Mesh {
return name; return name;
} }
private static int countVertices(List<PartBuilder.CuboidBuilder> cuboids) { private static int countVertices(List<ModelPartBuilder.CuboidBuilder> cuboids) {
int vertices = 0; int vertices = 0;
for (PartBuilder.CuboidBuilder cuboid : cuboids) { for (ModelPartBuilder.CuboidBuilder cuboid : cuboids) {
vertices += cuboid.vertices(); vertices += cuboid.vertices();
} }
return vertices; return vertices;

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.lib.struct; 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.core.BlockPos;
import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockAndTintGetter;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.lib.struct; 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 class TransformedWriter extends ColoredLitWriter<TransformedPart> {
public static final TransformedWriter INSTANCE = new TransformedWriter(); public static final TransformedWriter INSTANCE = new TransformedWriter();

View file

@ -8,7 +8,7 @@ import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class WorkGroup { public final class WorkGroup {
public static void run(Iterator<Runnable> tasks, Executor executor) { public static void run(Iterator<Runnable> tasks, Executor executor) {
tasks.forEachRemaining(executor::execute); 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.event.RenderContext;
import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.api.uniform.ShaderUniforms;
import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.lib.math.MatrixUtil;
import com.jozufozu.flywheel.util.MatrixUtil; import com.jozufozu.flywheel.lib.math.MoreMath;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
@ -134,7 +134,7 @@ public class FlwShaderUniforms implements ShaderUniforms {
var projection = MatrixUtil.toJoml(context.viewProjection()); var projection = MatrixUtil.toJoml(context.viewProjection());
projection.translate(-camX, -camY, -camZ); projection.translate(-camX, -camY, -camZ);
FlwUtil.writePackedFrustumPlanes(ptr + 128, projection); MoreMath.writePackedFrustumPlanes(ptr + 128, projection);
FRUSTUM_CAPTURE = false; FRUSTUM_CAPTURE = false;
} }

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