Shaded shader

- Rename MaterialManager -> InstancerManager and Material ->
InstancerFactory
- Create Material class consisting of RenderType and shader files
- Make ModelSuppliers use Materials as keys instead of RenderTypes
- Move diffuse calculation from context shaders to material/shaded.vert
- Merge used templates directly into compilers and remove template
classes
This commit is contained in:
PepperCode1 2022-05-15 20:09:47 -07:00
parent 15f41e7b9c
commit a7a716b469
66 changed files with 599 additions and 601 deletions

View file

@ -13,7 +13,8 @@ import com.jozufozu.flywheel.core.Models;
import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.core.StitchedSprite; import com.jozufozu.flywheel.core.StitchedSprite;
import com.jozufozu.flywheel.core.compile.ProgramCompiler; import com.jozufozu.flywheel.core.compile.ProgramCompiler;
import com.jozufozu.flywheel.core.materials.InstanceShaders; import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.structs.InstanceShaders;
import com.jozufozu.flywheel.core.vertex.LayoutShaders; import com.jozufozu.flywheel.core.vertex.LayoutShaders;
import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor; import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor;
@ -77,6 +78,7 @@ public class Flywheel {
modEventBus.addListener(LayoutShaders::flwInit); modEventBus.addListener(LayoutShaders::flwInit);
modEventBus.addListener(InstanceShaders::flwInit); modEventBus.addListener(InstanceShaders::flwInit);
modEventBus.addListener(MaterialShaders::flwInit);
modEventBus.addListener(Contexts::flwInit); modEventBus.addListener(Contexts::flwInit);
modEventBus.addListener(PartialModel::onModelRegistry); modEventBus.addListener(PartialModel::onModelRegistry);
modEventBus.addListener(PartialModel::onModelBake); modEventBus.addListener(PartialModel::onModelBake);

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.api;
import com.jozufozu.flywheel.core.model.ModelSupplier; import com.jozufozu.flywheel.core.model.ModelSupplier;
public interface Material<D extends InstanceData> { public interface InstancerFactory<D extends InstanceData> {
/** /**
* Get an instancer for the given model. Calling this method twice with the same key will return the same instancer. * Get an instancer for the given model. Calling this method twice with the same key will return the same instancer.

View file

@ -4,9 +4,9 @@ import com.jozufozu.flywheel.api.struct.StructType;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
public interface MaterialManager { public interface InstancerManager {
<D extends InstanceData> Material<D> material(StructType<D> type); <D extends InstanceData> InstancerFactory<D> factory(StructType<D> type);
Vec3i getOriginCoordinate(); Vec3i getOriginCoordinate();

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.api;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
@Deprecated
public interface MaterialGroup { public interface MaterialGroup {
/** /**
* Get the material as defined by the given {@link StructType type}. * Get the material as defined by the given {@link StructType type}.
@ -10,5 +11,5 @@ public interface MaterialGroup {
* @param <D> The type representing the per instance data. * @param <D> The type representing the per instance data.
* @return A material you can use to render models. * @return A material you can use to render models.
*/ */
<D extends InstanceData> Material<D> material(StructType<D> spec); <D extends InstanceData> InstancerFactory<D> material(StructType<D> spec);
} }

View file

@ -0,0 +1,31 @@
package com.jozufozu.flywheel.api.material;
import java.util.function.Supplier;
import com.jozufozu.flywheel.core.source.FileResolution;
import net.minecraft.client.renderer.RenderType;
public class Material {
protected final RenderType renderType;
protected final Supplier<FileResolution> vertexShader;
protected final Supplier<FileResolution> fragmentShader;
public Material(RenderType renderType, Supplier<FileResolution> vertexShader, Supplier<FileResolution> fragmentShader) {
this.renderType = renderType;
this.vertexShader = vertexShader;
this.fragmentShader = fragmentShader;
}
public RenderType getRenderType() {
return renderType;
}
public FileResolution getVertexShader() {
return vertexShader.get();
}
public FileResolution getFragmentShader() {
return fragmentShader.get();
}
}

View file

@ -3,12 +3,12 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.Arrays; import java.util.Arrays;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.TickableInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
import com.jozufozu.flywheel.core.materials.FlatLit; import com.jozufozu.flywheel.core.structs.FlatLit;
import com.jozufozu.flywheel.light.LightListener; import com.jozufozu.flywheel.light.LightListener;
import com.jozufozu.flywheel.light.LightProvider; import com.jozufozu.flywheel.light.LightProvider;
import com.jozufozu.flywheel.light.ListenerStatus; import com.jozufozu.flywheel.light.ListenerStatus;
@ -24,12 +24,12 @@ import net.minecraft.world.level.LightLayer;
*/ */
public abstract class AbstractInstance implements Instance, LightListener { public abstract class AbstractInstance implements Instance, LightListener {
protected final MaterialManager materialManager; protected final InstancerManager instancerManager;
public final Level world; public final Level level;
public AbstractInstance(MaterialManager materialManager, Level world) { public AbstractInstance(InstancerManager instancerManager, Level level) {
this.materialManager = materialManager; this.instancerManager = instancerManager;
this.world = world; this.level = level;
} }
/** /**
@ -88,11 +88,11 @@ public abstract class AbstractInstance implements Instance, LightListener {
} }
protected void relight(BlockPos pos, FlatLit<?>... models) { protected void relight(BlockPos pos, FlatLit<?>... models) {
relight(world.getBrightness(LightLayer.BLOCK, pos), world.getBrightness(LightLayer.SKY, pos), models); relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), models);
} }
protected <L extends FlatLit<?>> void relight(BlockPos pos, Stream<L> models) { protected <L extends FlatLit<?>> void relight(BlockPos pos, Stream<L> models) {
relight(world.getBrightness(LightLayer.BLOCK, pos), world.getBrightness(LightLayer.SKY, pos), models); relight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos), models);
} }
protected void relight(int block, int sky, FlatLit<?>... models) { protected void relight(int block, int sky, FlatLit<?>... models) {

View file

@ -2,8 +2,8 @@ package com.jozufozu.flywheel.backend.instancing;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
public interface Engine extends RenderDispatcher, MaterialManager { public interface Engine extends RenderDispatcher, InstancerManager {
void addDebugInfo(List<String> info); void addDebugInfo(List<String> info);
} }

View file

@ -9,7 +9,7 @@ import java.util.Set;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
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.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
@ -27,7 +27,7 @@ import net.minecraft.core.BlockPos;
public abstract class InstanceManager<T> implements InstancingEngine.OriginShiftListener { public abstract class InstanceManager<T> implements InstancingEngine.OriginShiftListener {
public final MaterialManager materialManager; public final InstancerManager instancerManager;
private final Set<T> queuedAdditions; private final Set<T> queuedAdditions;
private final Set<T> queuedUpdates; private final Set<T> queuedUpdates;
@ -39,8 +39,8 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
protected DistanceUpdateLimiter frame; protected DistanceUpdateLimiter frame;
protected DistanceUpdateLimiter tick; protected DistanceUpdateLimiter tick;
public InstanceManager(MaterialManager materialManager) { public InstanceManager(InstancerManager instancerManager) {
this.materialManager = materialManager; this.instancerManager = instancerManager;
this.queuedUpdates = new HashSet<>(64); this.queuedUpdates = new HashSet<>(64);
this.queuedAdditions = new HashSet<>(64); this.queuedAdditions = new HashSet<>(64);
this.instances = new HashMap<>(); this.instances = new HashMap<>();
@ -318,7 +318,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
instances.remove(obj); instances.remove(obj);
dynamicInstances.remove(obj); dynamicInstances.remove(obj);
tickableInstances.remove(obj); tickableInstances.remove(obj);
LightUpdater.get(instance.world) LightUpdater.get(instance.level)
.removeListener(instance); .removeListener(instance);
} }
@ -329,7 +329,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
if (renderer != null) { if (renderer != null) {
renderer.init(); renderer.init();
renderer.updateLight(); renderer.updateLight();
LightUpdater.get(renderer.world) LightUpdater.get(renderer.level)
.addListener(renderer); .addListener(renderer);
instances.put(obj, renderer); instances.put(obj, renderer);
@ -356,7 +356,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
public void detachLightListeners() { public void detachLightListeners() {
for (AbstractInstance value : instances.values()) { for (AbstractInstance value : instances.values()) {
LightUpdater.get(value.world).removeListener(value); LightUpdater.get(value.level).removeListener(value);
} }
} }
} }

View file

@ -23,7 +23,7 @@ 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.
* <p> * <p>
* The material manager is shared between the different instance managers. * The instancer manager is shared between the different instance managers.
* </p> * </p>
*/ */
public class InstanceWorld { public class InstanceWorld {

View file

@ -6,7 +6,7 @@ import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstancingController; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstancingController;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityTypeExtension; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityTypeExtension;
@ -48,34 +48,34 @@ public class InstancedRenderRegistry {
/** /**
* Creates an instance for the given block entity, if possible. * Creates an instance for the given block entity, if possible.
* @param materialManager The material manager to use. * @param instancerManager The instancer manager to use.
* @param blockEntity The block entity to create an instance of. * @param blockEntity The block entity to create an instance of.
* @param <T> The type of the block entity. * @param <T> The type of the block entity.
* @return An instance of the block entity, or {@code null} if the block entity cannot be instanced. * @return An instance of the block entity, or {@code null} if the block entity cannot be instanced.
*/ */
@Nullable @Nullable
public static <T extends BlockEntity> BlockEntityInstance<? super T> createInstance(MaterialManager materialManager, T blockEntity) { public static <T extends BlockEntity> BlockEntityInstance<? super T> createInstance(InstancerManager instancerManager, T blockEntity) {
BlockEntityInstancingController<? super T> controller = getController(getType(blockEntity)); BlockEntityInstancingController<? super T> controller = getController(getType(blockEntity));
if (controller == null) { if (controller == null) {
return null; return null;
} }
return controller.createInstance(materialManager, blockEntity); return controller.createInstance(instancerManager, blockEntity);
} }
/** /**
* Creates an instance for the given entity, if possible. * Creates an instance for the given entity, if possible.
* @param materialManager The material manager to use. * @param instancerManager The instancer manager to use.
* @param entity The entity to create an instance of. * @param entity The entity to create an instance of.
* @param <T> The type of the entity. * @param <T> The type of the entity.
* @return An instance of the entity, or {@code null} if the entity cannot be instanced. * @return An instance of the entity, or {@code null} if the entity cannot be instanced.
*/ */
@Nullable @Nullable
public static <T extends Entity> EntityInstance<? super T> createInstance(MaterialManager materialManager, T entity) { public static <T extends Entity> EntityInstance<? super T> createInstance(InstancerManager instancerManager, T entity) {
EntityInstancingController<? super T> controller = getController(getType(entity)); EntityInstancingController<? super T> controller = getController(getType(entity));
if (controller == null) { if (controller == null) {
return null; return null;
} }
return controller.createInstance(materialManager, entity); return controller.createInstance(instancerManager, entity);
} }
/** /**
@ -194,7 +194,7 @@ public class InstancedRenderRegistry {
*/ */
public static class BlockEntityConfig<T extends BlockEntity> { public static class BlockEntityConfig<T extends BlockEntity> {
protected BlockEntityType<T> type; protected BlockEntityType<T> type;
protected BiFunction<MaterialManager, T, BlockEntityInstance<? super T>> instanceFactory; protected BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender; protected Predicate<T> skipRender;
public BlockEntityConfig(BlockEntityType<T> type) { public BlockEntityConfig(BlockEntityType<T> type) {
@ -206,7 +206,7 @@ public class InstancedRenderRegistry {
* @param instanceFactory The instance factory. * @param instanceFactory The instance factory.
* @return {@code this} * @return {@code this}
*/ */
public BlockEntityConfig<T> factory(BiFunction<MaterialManager, T, BlockEntityInstance<? super T>> instanceFactory) { public BlockEntityConfig<T> factory(BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory) {
this.instanceFactory = instanceFactory; this.instanceFactory = instanceFactory;
return this; return this;
} }
@ -251,7 +251,7 @@ public class InstancedRenderRegistry {
*/ */
public static class EntityConfig<T extends Entity> { public static class EntityConfig<T extends Entity> {
protected EntityType<T> type; protected EntityType<T> type;
protected BiFunction<MaterialManager, T, EntityInstance<? super T>> instanceFactory; protected BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender; protected Predicate<T> skipRender;
public EntityConfig(EntityType<T> type) { public EntityConfig(EntityType<T> type) {
@ -263,7 +263,7 @@ public class InstancedRenderRegistry {
* @param instanceFactory The instance factory. * @param instanceFactory The instance factory.
* @return {@code this} * @return {@code this}
*/ */
public EntityConfig<T> factory(BiFunction<MaterialManager, T, EntityInstance<? super T>> instanceFactory) { public EntityConfig<T> factory(BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory) {
this.instanceFactory = instanceFactory; this.instanceFactory = instanceFactory;
return this; return this;
} }

View file

@ -17,7 +17,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
protected final RenderType state; protected final RenderType state;
private final Map<Batched<? extends InstanceData>, BatchedMaterial<?>> materials = new HashMap<>(); private final Map<Batched<? extends InstanceData>, CPUInstancerFactory<?>> materials = new HashMap<>();
private int vertexCount; private int vertexCount;
private int instanceCount; private int instanceCount;
@ -27,9 +27,9 @@ public class BatchedMaterialGroup implements MaterialGroup {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <D extends InstanceData> BatchedMaterial<D> material(StructType<D> type) { public <D extends InstanceData> CPUInstancerFactory<D> material(StructType<D> type) {
if (type instanceof Batched<D> batched) { if (type instanceof Batched<D> batched) {
return (BatchedMaterial<D>) materials.computeIfAbsent(batched, BatchedMaterial::new); return (CPUInstancerFactory<D>) materials.computeIfAbsent(batched, CPUInstancerFactory::new);
} else { } else {
throw new ClassCastException("Cannot use type '" + type + "' with CPU instancing."); throw new ClassCastException("Cannot use type '" + type + "' with CPU instancing.");
} }
@ -61,7 +61,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
} }
public void clear() { public void clear() {
materials.values().forEach(BatchedMaterial::clear); materials.values().forEach(CPUInstancerFactory::clear);
} }
public void delete() { public void delete() {

View file

@ -21,16 +21,16 @@ import net.minecraft.core.Vec3i;
public class BatchingEngine implements Engine { public class BatchingEngine implements Engine {
private final Map<Batched<? extends InstanceData>, BatchedMaterial<?>> materials = new HashMap<>(); private final Map<Batched<? extends InstanceData>, CPUInstancerFactory<?>> factories = new HashMap<>();
private final BatchDrawingTracker batchTracker = new BatchDrawingTracker(); private final BatchDrawingTracker batchTracker = new BatchDrawingTracker();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <D extends InstanceData> BatchedMaterial<D> material(StructType<D> type) { public <D extends InstanceData> CPUInstancerFactory<D> factory(StructType<D> type) {
if (type instanceof Batched<D> batched) { if (type instanceof Batched<D> batched) {
return (BatchedMaterial<D>) materials.computeIfAbsent(batched, BatchedMaterial::new); return (CPUInstancerFactory<D>) factories.computeIfAbsent(batched, CPUInstancerFactory::new);
} else { } else {
throw new ClassCastException("Cannot use type '" + type + "' with batching."); throw new ClassCastException("Cannot use type '" + type + "' with CPU instancing.");
} }
} }
@ -46,7 +46,6 @@ public class BatchingEngine implements Engine {
@Override @Override
public void renderAllRemaining(TaskEngine taskEngine, RenderContext context) { public void renderAllRemaining(TaskEngine taskEngine, RenderContext context) {
// vertexCount = 0; // vertexCount = 0;
// instanceCount = 0; // instanceCount = 0;
// for (BatchedMaterial<?> material : materials.values()) { // for (BatchedMaterial<?> material : materials.values()) {

View file

@ -5,18 +5,18 @@ import java.util.Map;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.InstancerFactory;
import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.core.model.ModelSupplier; import com.jozufozu.flywheel.core.model.ModelSupplier;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
public class BatchedMaterial<D extends InstanceData> implements Material<D> { public class CPUInstancerFactory<D extends InstanceData> implements InstancerFactory<D> {
protected final Map<ModelSupplier, CPUInstancer<D>> models; protected final Map<ModelSupplier, CPUInstancer<D>> models;
private final Batched<D> type; private final Batched<D> type;
public BatchedMaterial(Batched<D> type) { public CPUInstancerFactory(Batched<D> type) {
this.type = type; this.type = type;
this.models = new HashMap<>(); this.models = new HashMap<>();

View file

@ -1,13 +1,13 @@
package com.jozufozu.flywheel.backend.instancing.blockentity; package com.jozufozu.flywheel.backend.instancing.blockentity;
import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.InstancerFactory;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
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.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.core.materials.Materials; import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.core.structs.model.ModelData;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData; import com.jozufozu.flywheel.core.structs.oriented.OrientedData;
import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.util.box.GridAlignedBB;
import com.jozufozu.flywheel.util.box.ImmutableBox; import com.jozufozu.flywheel.util.box.ImmutableBox;
@ -39,12 +39,12 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
protected final BlockPos instancePos; protected final BlockPos instancePos;
protected final BlockState blockState; protected final BlockState blockState;
public BlockEntityInstance(MaterialManager materialManager, T blockEntity) { public BlockEntityInstance(InstancerManager instancerManager, T blockEntity) {
super(materialManager, blockEntity.getLevel()); super(instancerManager, blockEntity.getLevel());
this.blockEntity = blockEntity; this.blockEntity = blockEntity;
this.pos = blockEntity.getBlockPos(); this.pos = blockEntity.getBlockPos();
this.blockState = blockEntity.getBlockState(); this.blockState = blockEntity.getBlockState();
this.instancePos = pos.subtract(materialManager.getOriginCoordinate()); this.instancePos = pos.subtract(instancerManager.getOriginCoordinate());
} }
/** /**
@ -68,7 +68,7 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
* represents should be rendered at to appear in the correct location. * represents should be rendered at to appear in the correct location.
*/ */
public BlockPos getInstancePosition() { public BlockPos getInstancePosition() {
return pos.subtract(materialManager.getOriginCoordinate()); return pos.subtract(instancerManager.getOriginCoordinate());
} }
@Override @Override
@ -76,12 +76,12 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
return pos; return pos;
} }
protected Material<ModelData> getTransformMaterial() { protected InstancerFactory<ModelData> getTransformFactory() {
return materialManager.material(Materials.TRANSFORMED); return instancerManager.factory(StructTypes.MODEL);
} }
protected Material<OrientedData> getOrientedMaterial() { protected InstancerFactory<OrientedData> getOrientedFactory() {
return materialManager.material(Materials.ORIENTED); return instancerManager.factory(StructTypes.ORIENTED);
} }
@Override @Override

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.backend.instancing.blockentity; package com.jozufozu.flywheel.backend.instancing.blockentity;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
@ -13,8 +13,8 @@ import net.minecraft.world.level.block.entity.BlockEntity;
public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> { public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
public BlockEntityInstanceManager(MaterialManager materialManager) { public BlockEntityInstanceManager(InstancerManager instancerManager) {
super(materialManager); super(instancerManager);
} }
@Override @Override
@ -24,7 +24,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
@Override @Override
protected AbstractInstance createRaw(BlockEntity obj) { protected AbstractInstance createRaw(BlockEntity obj) {
return InstancedRenderRegistry.createInstance(materialManager, obj); return InstancedRenderRegistry.createInstance(instancerManager, obj);
} }
@Override @Override

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.backend.instancing.blockentity; package com.jozufozu.flywheel.backend.instancing.blockentity;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
@ -10,12 +10,12 @@ import net.minecraft.world.level.block.entity.BlockEntity;
*/ */
public interface BlockEntityInstancingController<T extends BlockEntity> { public interface BlockEntityInstancingController<T extends BlockEntity> {
/** /**
* Given a block entity and a material manager, constructs an instance for the block entity. * Given a block entity and an instancer manager, constructs an instance for the block entity.
* @param materialManager The material manager to use. * @param instancerManager The instancer manager to use.
* @param blockEntity The block entity to construct an instance for. * @param blockEntity The block entity to construct an instance for.
* @return The instance. * @return The instance.
*/ */
BlockEntityInstance<? super T> createInstance(MaterialManager materialManager, T blockEntity); BlockEntityInstance<? super T> createInstance(InstancerManager instancerManager, T blockEntity);
/** /**
* Checks if the given block entity should not be rendered normally. * Checks if the given block entity should not be rendered normally.

View file

@ -3,22 +3,22 @@ package com.jozufozu.flywheel.backend.instancing.blockentity;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
public class SimpleBlockEntityInstancingController<T extends BlockEntity> implements BlockEntityInstancingController<T> { public class SimpleBlockEntityInstancingController<T extends BlockEntity> implements BlockEntityInstancingController<T> {
protected BiFunction<MaterialManager, T, BlockEntityInstance<? super T>> instanceFactory; protected BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender; protected Predicate<T> skipRender;
public SimpleBlockEntityInstancingController(BiFunction<MaterialManager, T, BlockEntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) { public SimpleBlockEntityInstancingController(BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory; this.instanceFactory = instanceFactory;
this.skipRender = skipRender; this.skipRender = skipRender;
} }
@Override @Override
public BlockEntityInstance<? super T> createInstance(MaterialManager materialManager, T blockEntity) { public BlockEntityInstance<? super T> createInstance(InstancerManager instancerManager, T blockEntity) {
return instanceFactory.apply(materialManager, blockEntity); return instanceFactory.apply(instancerManager, blockEntity);
} }
@Override @Override

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.backend.instancing.entity; package com.jozufozu.flywheel.backend.instancing.entity;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
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.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
@ -39,8 +39,8 @@ public abstract class EntityInstance<E extends Entity> extends AbstractInstance
protected final E entity; protected final E entity;
protected final GridAlignedBB bounds; protected final GridAlignedBB bounds;
public EntityInstance(MaterialManager materialManager, E entity) { public EntityInstance(InstancerManager instancerManager, E entity) {
super(materialManager, entity.level); super(instancerManager, entity.level);
this.entity = entity; this.entity = entity;
bounds = GridAlignedBB.from(entity.getBoundingBox()); bounds = GridAlignedBB.from(entity.getBoundingBox());
} }
@ -72,7 +72,7 @@ public abstract class EntityInstance<E extends Entity> extends AbstractInstance
*/ */
public Vector3f getInstancePosition() { public Vector3f getInstancePosition() {
Vec3 pos = entity.position(); Vec3 pos = entity.position();
Vec3i origin = materialManager.getOriginCoordinate(); Vec3i origin = instancerManager.getOriginCoordinate();
return new Vector3f((float) (pos.x - origin.getX()), (float) (pos.y - origin.getY()), (float) (pos.z - origin.getZ())); return new Vector3f((float) (pos.x - origin.getX()), (float) (pos.y - origin.getY()), (float) (pos.z - origin.getZ()));
} }
@ -85,7 +85,7 @@ public abstract class EntityInstance<E extends Entity> extends AbstractInstance
*/ */
public Vector3f getInstancePosition(float partialTicks) { public Vector3f getInstancePosition(float partialTicks) {
Vec3 pos = entity.position(); Vec3 pos = entity.position();
Vec3i origin = materialManager.getOriginCoordinate(); Vec3i origin = instancerManager.getOriginCoordinate();
return new Vector3f( return new Vector3f(
(float) (Mth.lerp(partialTicks, entity.xOld, pos.x) - origin.getX()), (float) (Mth.lerp(partialTicks, entity.xOld, pos.x) - origin.getX()),
(float) (Mth.lerp(partialTicks, entity.yOld, pos.y) - origin.getY()), (float) (Mth.lerp(partialTicks, entity.yOld, pos.y) - origin.getY()),

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.backend.instancing.entity; package com.jozufozu.flywheel.backend.instancing.entity;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.AbstractInstance; import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
@ -13,8 +13,8 @@ import net.minecraft.world.level.Level;
public class EntityInstanceManager extends InstanceManager<Entity> { public class EntityInstanceManager extends InstanceManager<Entity> {
public EntityInstanceManager(MaterialManager materialManager) { public EntityInstanceManager(InstancerManager instancerManager) {
super(materialManager); super(instancerManager);
} }
@Override @Override
@ -24,7 +24,7 @@ public class EntityInstanceManager extends InstanceManager<Entity> {
@Override @Override
protected AbstractInstance createRaw(Entity obj) { protected AbstractInstance createRaw(Entity obj) {
return InstancedRenderRegistry.createInstance(materialManager, obj); return InstancedRenderRegistry.createInstance(instancerManager, obj);
} }
@Override @Override

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.backend.instancing.entity; package com.jozufozu.flywheel.backend.instancing.entity;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@ -10,12 +10,12 @@ import net.minecraft.world.entity.Entity;
*/ */
public interface EntityInstancingController<T extends Entity> { public interface EntityInstancingController<T extends Entity> {
/** /**
* Given an entity and a material manager, constructs an instance for the entity. * Given an entity and an instancer manager, constructs an instance for the entity.
* @param materialManager The material manager to use. * @param instancerManager The instancer manager to use.
* @param entity The entity to construct an instance for. * @param entity The entity to construct an instance for.
* @return The instance. * @return The instance.
*/ */
EntityInstance<? super T> createInstance(MaterialManager materialManager, T entity); EntityInstance<? super T> createInstance(InstancerManager instancerManager, T entity);
/** /**
* Checks if the given entity should not render normally. * Checks if the given entity should not render normally.

View file

@ -3,22 +3,22 @@ package com.jozufozu.flywheel.backend.instancing.entity;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
public class SimpleEntityInstancingController<T extends Entity> implements EntityInstancingController<T> { public class SimpleEntityInstancingController<T extends Entity> implements EntityInstancingController<T> {
protected BiFunction<MaterialManager, T, EntityInstance<? super T>> instanceFactory; protected BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender; protected Predicate<T> skipRender;
public SimpleEntityInstancingController(BiFunction<MaterialManager, T, EntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) { public SimpleEntityInstancingController(BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory, Predicate<T> skipRender) {
this.instanceFactory = instanceFactory; this.instanceFactory = instanceFactory;
this.skipRender = skipRender; this.skipRender = skipRender;
} }
@Override @Override
public EntityInstance<? super T> createInstance(MaterialManager materialManager, T entity) { public EntityInstance<? super T> createInstance(InstancerManager instancerManager, T entity) {
return instanceFactory.apply(materialManager, entity); return instanceFactory.apply(instancerManager, entity);
} }
@Override @Override

View file

@ -6,10 +6,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Instancer;
import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.InstancerFactory;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.backend.model.MeshPool; import com.jozufozu.flywheel.backend.model.MeshPool;
import com.jozufozu.flywheel.core.model.ModelSupplier; import com.jozufozu.flywheel.core.model.ModelSupplier;
@ -20,16 +22,17 @@ import net.minecraft.client.renderer.RenderType;
* A collection of Instancers that all have the same format. * A collection of Instancers that all have the same format.
* @param <D> * @param <D>
*/ */
public class InstancedMaterial<D extends InstanceData> implements Material<D> { public class GPUInstancerFactory<D extends InstanceData> implements InstancerFactory<D> {
protected final Map<ModelSupplier, InstancedModel<D>> models = new HashMap<>(); protected final Map<ModelSupplier, InstancedModel<D>> models = new HashMap<>();
protected final Instanced<D> type; protected final Instanced<D> type;
protected final List<InstancedModel<D>> uninitialized = new ArrayList<>(); protected final List<InstancedModel<D>> uninitialized = new ArrayList<>();
protected final Multimap<RenderType, Renderable> renderables = ArrayListMultimap.create(); protected final Multimap<RenderType, Material> materials = HashMultimap.create();
protected final Multimap<Material, Renderable> renderables = ArrayListMultimap.create();
public InstancedMaterial(Instanced<D> type) { public GPUInstancerFactory(Instanced<D> type) {
this.type = type; this.type = type;
} }
@ -56,6 +59,7 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
public void delete() { public void delete() {
models.values().forEach(InstancedModel::delete); models.values().forEach(InstancedModel::delete);
models.clear(); models.clear();
materials.clear();
renderables.clear(); renderables.clear();
} }
@ -71,10 +75,12 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
public void init(MeshPool allocator) { public void init(MeshPool allocator) {
for (var instanced : uninitialized) { for (var instanced : uninitialized) {
var map = instanced.init(allocator); var map = instanced.init(allocator);
map.forEach((type, renderable) -> renderables.get(type).add(renderable)); map.forEach((material, renderable) -> {
materials.put(material.getRenderType(), material);
renderables.get(material).add(renderable);
});
} }
uninitialized.clear(); uninitialized.clear();
} }

View file

@ -4,26 +4,25 @@ import java.util.Map;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.backend.gl.GlVertexArray; import com.jozufozu.flywheel.backend.gl.GlVertexArray;
import com.jozufozu.flywheel.backend.model.MeshPool; import com.jozufozu.flywheel.backend.model.MeshPool;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelSupplier; import com.jozufozu.flywheel.core.model.ModelSupplier;
import com.jozufozu.flywheel.util.Pair; import com.jozufozu.flywheel.util.Pair;
import net.minecraft.client.renderer.RenderType;
public class InstancedModel<D extends InstanceData> { public class InstancedModel<D extends InstanceData> {
final GPUInstancer<D> instancer; final GPUInstancer<D> instancer;
final ModelSupplier model; final ModelSupplier model;
private Map<RenderType, Layer> layers; private Map<Material, Layer> layers;
public InstancedModel(GPUInstancer<D> instancer, ModelSupplier model) { public InstancedModel(GPUInstancer<D> instancer, ModelSupplier model) {
this.instancer = instancer; this.instancer = instancer;
this.model = model; this.model = model;
} }
public Map<RenderType, ? extends Renderable> init(MeshPool allocator) { public Map<Material, ? extends Renderable> init(MeshPool allocator) {
instancer.init(); instancer.init();
layers = model.get() layers = model.get()
@ -38,12 +37,12 @@ public class InstancedModel<D extends InstanceData> {
private class Layer implements Renderable { private class Layer implements Renderable {
final RenderType type; final Material material;
MeshPool.BufferedMesh bufferedMesh; MeshPool.BufferedMesh bufferedMesh;
GlVertexArray vao; GlVertexArray vao;
private Layer(MeshPool allocator, RenderType type, Mesh mesh) { private Layer(MeshPool allocator, Material material, Mesh mesh) {
this.type = type; this.material = material;
vao = new GlVertexArray(); vao = new GlVertexArray();
bufferedMesh = allocator.alloc(mesh, vao); bufferedMesh = allocator.alloc(mesh, vao);
instancer.attributeBaseIndex = bufferedMesh.getAttributeCount(); instancer.attributeBaseIndex = bufferedMesh.getAttributeCount();

View file

@ -9,6 +9,7 @@ import java.util.Set;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.backend.instancing.Engine;
@ -44,7 +45,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
protected final ProgramCompiler<P> context; protected final ProgramCompiler<P> context;
private MeshPool allocator; private MeshPool allocator;
protected final Map<Instanced<? extends InstanceData>, InstancedMaterial<?>> materials = new HashMap<>(); protected final Map<Instanced<? extends InstanceData>, GPUInstancerFactory<?>> factories = new HashMap<>();
protected final Set<RenderType> toRender = new HashSet<>(); protected final Set<RenderType> toRender = new HashSet<>();
@ -61,9 +62,9 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@NotNull @NotNull
@Override @Override
public <D extends InstanceData> InstancedMaterial<D> material(StructType<D> type) { public <D extends InstanceData> GPUInstancerFactory<D> factory(StructType<D> type) {
if (type instanceof Instanced<D> instanced) { if (type instanceof Instanced<D> instanced) {
return (InstancedMaterial<D>) materials.computeIfAbsent(instanced, InstancedMaterial::new); return (GPUInstancerFactory<D>) factories.computeIfAbsent(instanced, GPUInstancerFactory::new);
} else { } else {
throw new ClassCastException("Cannot use type '" + type + "' with GPU instancing."); throw new ClassCastException("Cannot use type '" + type + "' with GPU instancing.");
} }
@ -87,7 +88,6 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
@Override @Override
public void renderSpecificType(TaskEngine taskEngine, RenderContext context, RenderType type) { public void renderSpecificType(TaskEngine taskEngine, RenderContext context, RenderType type) {
var camX = context.camX() - originCoordinate.getX(); var camX = context.camX() - originCoordinate.getX();
var camY = context.camY() - originCoordinate.getY(); var camY = context.camY() - originCoordinate.getY();
var camZ = context.camZ() - originCoordinate.getZ(); var camZ = context.camZ() - originCoordinate.getZ();
@ -109,21 +109,23 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
Textures.bindActiveTextures(); Textures.bindActiveTextures();
CoreShaderInfo coreShaderInfo = getCoreShaderInfo(); CoreShaderInfo coreShaderInfo = getCoreShaderInfo();
for (Map.Entry<Instanced<? extends InstanceData>, InstancedMaterial<?>> entry : materials.entrySet()) { for (Map.Entry<Instanced<? extends InstanceData>, GPUInstancerFactory<?>> entry : factories.entrySet()) {
InstancedMaterial<?> material = entry.getValue(); Instanced<? extends InstanceData> instanceType = entry.getKey();
GPUInstancerFactory<?> factory = entry.getValue();
var toRender = material.renderables.get(type); var materials = factory.materials.get(type);
toRender.removeIf(Renderable::shouldRemove); for (Material material : materials) {
var toRender = factory.renderables.get(material);
toRender.removeIf(Renderable::shouldRemove);
if (!toRender.isEmpty()) { if (!toRender.isEmpty()) {
Instanced<? extends InstanceData> instanceType = entry.getKey(); setup(instanceType, material, coreShaderInfo, camX, camY, camZ, viewProjection, level);
setup(instanceType, coreShaderInfo, camX, camY, camZ, viewProjection, level); instanceCount += factory.getInstanceCount();
vertexCount += factory.getVertexCount();
instanceCount += material.getInstanceCount(); toRender.forEach(Renderable::render);
vertexCount += material.getVertexCount(); }
toRender.forEach(Renderable::render);
} }
} }
@ -145,7 +147,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
return coreShaderInfo; return coreShaderInfo;
} }
protected P setup(Instanced<?> instanceType, CoreShaderInfo coreShaderInfo, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) { protected P setup(Instanced<?> instanceType, Material material, CoreShaderInfo coreShaderInfo, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
float alphaDiscard = coreShaderInfo.alphaDiscard(); float alphaDiscard = coreShaderInfo.alphaDiscard();
if (alphaDiscard == 0) { if (alphaDiscard == 0) {
alphaDiscard = 0.0001f; alphaDiscard = 0.0001f;
@ -153,7 +155,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
alphaDiscard = 0; alphaDiscard = 0;
} }
P program = context.getProgram(new ProgramContext(Formats.POS_TEX_NORMAL, instanceType.getInstanceShader(), alphaDiscard, coreShaderInfo.fogType(), GameStateRegistry.takeSnapshot())); P program = context.getProgram(new ProgramContext(Formats.POS_TEX_NORMAL, instanceType.getInstanceShader(), material.getVertexShader(), material.getFragmentShader(), alphaDiscard, coreShaderInfo.fogType(), GameStateRegistry.takeSnapshot()));
program.bind(); program.bind();
program.uploadUniforms(camX, camY, camZ, viewProjection, level); program.uploadUniforms(camX, camY, camZ, viewProjection, level);
@ -162,15 +164,15 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
} }
public void clearAll() { public void clearAll() {
materials.values().forEach(InstancedMaterial::clear); factories.values().forEach(GPUInstancerFactory::clear);
} }
@Override @Override
public void delete() { public void delete() {
materials.values() factories.values()
.forEach(InstancedMaterial::delete); .forEach(GPUInstancerFactory::delete);
materials.clear(); factories.clear();
} }
@Override @Override
@ -193,10 +195,10 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
MeshPool allocator = getModelAllocator(); MeshPool allocator = getModelAllocator();
for (InstancedMaterial<?> material : materials.values()) { for (GPUInstancerFactory<?> factory : factories.values()) {
material.init(allocator); factory.init(allocator);
toRender.addAll(material.renderables.keySet()); toRender.addAll(factory.materials.keySet());
} }
allocator.flush(); allocator.flush();
@ -221,7 +223,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
private void shiftListeners(int cX, int cY, int cZ) { private void shiftListeners(int cX, int cY, int cZ) {
originCoordinate = new BlockPos(cX, cY, cZ); originCoordinate = new BlockPos(cX, cY, cZ);
materials.values().forEach(InstancedMaterial::clear); factories.values().forEach(GPUInstancerFactory::clear);
listeners.forEach(OriginShiftListener::onOriginShift); listeners.forEach(OriginShiftListener::onOriginShift);
} }

View file

@ -5,6 +5,8 @@ import java.util.Map;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelSupplier; import com.jozufozu.flywheel.core.model.ModelSupplier;
import com.jozufozu.flywheel.util.Lazy; import com.jozufozu.flywheel.util.Lazy;
@ -13,31 +15,28 @@ import com.jozufozu.flywheel.util.NonNullSupplier;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
public class BasicModelSupplier implements ModelSupplier { public class BasicModelSupplier implements ModelSupplier {
private static final Material DEFAULT_MATERIAL = new Material(RenderType.solid(), () -> MaterialShaders.DEFAULT_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT);
private RenderType renderType; private Material material;
private final Lazy<Mesh> supplier; private final Lazy<Mesh> supplier;
public BasicModelSupplier(NonNullSupplier<Mesh> supplier) { public BasicModelSupplier(NonNullSupplier<Mesh> supplier) {
this(supplier, RenderType.solid()); this(supplier, DEFAULT_MATERIAL);
} }
public BasicModelSupplier(NonNullSupplier<Mesh> supplier, RenderType renderType) { public BasicModelSupplier(NonNullSupplier<Mesh> supplier, Material material) {
this.supplier = Lazy.of(supplier); this.supplier = Lazy.of(supplier);
this.renderType = renderType; this.material = material;
} }
public BasicModelSupplier setCutout() { public BasicModelSupplier setMaterial(@NotNull Material material) {
return setRenderType(RenderType.cutoutMipped()); this.material = material;
}
public BasicModelSupplier setRenderType(@NotNull RenderType renderType) {
this.renderType = renderType;
return this; return this;
} }
@Override @Override
public Map<RenderType, Mesh> get() { public Map<Material, Mesh> get() {
return ImmutableMap.of(renderType, supplier.get()); return ImmutableMap.of(material, supplier.get());
} }
public int getVertexCount() { public int getVertexCount() {
@ -47,7 +46,7 @@ public class BasicModelSupplier implements ModelSupplier {
@Override @Override
public String toString() { public String toString() {
return "ModelSupplier{" + supplier.map(Mesh::name) return "BasicModelSupplier{" + supplier.map(Mesh::name)
.orElse("Uninitialized") + '}'; .orElse("Uninitialized") + '}';
} }
} }

View file

@ -25,8 +25,8 @@ public class Contexts {
FileResolution crumblingVertex = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".vert")); FileResolution crumblingVertex = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
FileResolution crumblingFragment = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".frag")); FileResolution crumblingFragment = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
WORLD = ProgramCompiler.create(WorldProgram::new, Templates.INSTANCING, Templates.FRAGMENT, worldVertex, worldFragment); WORLD = ProgramCompiler.create(WorldProgram::new, worldVertex, worldFragment);
CRUMBLING = ProgramCompiler.create(CrumblingProgram::new, Templates.INSTANCING, Templates.FRAGMENT, crumblingVertex, crumblingFragment); CRUMBLING = ProgramCompiler.create(CrumblingProgram::new, crumblingVertex, crumblingFragment);
} }
public static class Names { public static class Names {

View file

@ -1,13 +0,0 @@
package com.jozufozu.flywheel.core;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.core.compile.FragmentTemplateData;
import com.jozufozu.flywheel.core.compile.InstancingTemplateData;
import com.jozufozu.flywheel.core.compile.OneShotTemplateData;
import com.jozufozu.flywheel.core.compile.Template;
public class Templates {
public static final Template<InstancingTemplateData> INSTANCING = new Template<>(GLSLVersion.V330, InstancingTemplateData::new);
public static final Template<OneShotTemplateData> ONE_SHOT = new Template<>(GLSLVersion.V150, OneShotTemplateData::new);
public static final Template<FragmentTemplateData> FRAGMENT = new Template<>(GLSLVersion.V150, FragmentTemplateData::new);
}

View file

@ -1,7 +1,10 @@
package com.jozufozu.flywheel.core.compile; package com.jozufozu.flywheel.core.compile;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.backend.gl.shader.GlShader; import com.jozufozu.flywheel.backend.gl.shader.GlShader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType; import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType;
@ -9,13 +12,16 @@ import com.jozufozu.flywheel.core.shader.ShaderConstants;
import com.jozufozu.flywheel.core.shader.StateSnapshot; import com.jozufozu.flywheel.core.shader.StateSnapshot;
import com.jozufozu.flywheel.core.source.FileIndexImpl; import com.jozufozu.flywheel.core.source.FileIndexImpl;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.source.parse.ShaderFunction;
import com.jozufozu.flywheel.core.source.parse.Variable;
public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShader> { public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShader> {
private final Template<? extends FragmentData> template;
private final FileResolution contextShader; private final FileResolution contextShader;
public FragmentCompiler(Template<? extends FragmentData> template, FileResolution contextShader) { public FragmentCompiler(FileResolution contextShader) {
this.template = template;
this.contextShader = contextShader; this.contextShader = contextShader;
} }
@ -23,21 +29,77 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
protected GlShader _create(Context key) { protected GlShader _create(Context key) {
StringBuilder finalSource = new StringBuilder(); StringBuilder finalSource = new StringBuilder();
finalSource.append(CompileUtil.generateHeader(template.getVersion(), ShaderType.FRAGMENT)); finalSource.append(CompileUtil.generateHeader(GLSLVersion.V150, ShaderType.FRAGMENT));
key.getShaderConstants().writeInto(finalSource); key.getShaderConstants().writeInto(finalSource);
finalSource.append('\n'); finalSource.append('\n');
FileIndexImpl index = new FileIndexImpl(); FileIndexImpl index = new FileIndexImpl();
contextShader.getFile().generateFinalSource(index, finalSource); //
FragmentData appliedTemplate = template.apply(contextShader.getFile()); SourceFile materialShader = key.materialShader;
finalSource.append(appliedTemplate.generateFooter());
Optional<ShaderFunction> maybeMaterialFragment = materialShader.findFunction("flw_materialFragment");
if (maybeMaterialFragment.isEmpty()) {
ErrorReporter.generateMissingFunction(materialShader, "flw_materialFragment", "\"flw_materialFragment\" function not defined");
throw new ShaderLoadingException();
}
ShaderFunction materialFragment = maybeMaterialFragment.get();
ImmutableList<Variable> params = materialFragment.getParameters();
if (params.size() != 0) {
ErrorReporter.generateSpanError(materialFragment.getArgs(), "\"flw_materialFragment\" function must not have any arguments");
throw new ShaderLoadingException();
}
materialShader.generateFinalSource(index, finalSource);
//
SourceFile contextShaderSource = contextShader.getFile();
Optional<ShaderFunction> maybeContextFragment = contextShaderSource.findFunction("flw_contextFragment");
if (maybeContextFragment.isEmpty()) {
ErrorReporter.generateMissingFunction(contextShaderSource, "flw_contextFragment", "\"flw_contextFragment\" function not defined");
throw new ShaderLoadingException();
}
ShaderFunction contextFragment = maybeContextFragment.get();
params = contextFragment.getParameters();
if (params.size() != 0) {
ErrorReporter.generateSpanError(contextFragment.getArgs(), "\"flw_contextFragment\" function must not have any arguments");
throw new ShaderLoadingException();
}
contextShaderSource.generateFinalSource(index, finalSource);
//
finalSource.append(generateFooter());
return new GlShader(contextShader.getFile().name, ShaderType.FRAGMENT, finalSource.toString()); return new GlShader(contextShader.getFile().name, ShaderType.FRAGMENT, finalSource.toString());
} }
protected String generateFooter() {
StringBuilder footer = new StringBuilder();
footer.append("""
void main() {
flw_materialFragment();
flw_contextFragment();
}
"""
);
return footer.toString();
}
@Override @Override
protected void _destroy(GlShader value) { protected void _destroy(GlShader value) {
value.delete(); value.delete();
@ -48,9 +110,9 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
*/ */
public static final class Context { public static final class Context {
/** /**
* The shader constants to apply. * The fragment material shader source.
*/ */
private final StateSnapshot ctx; private final SourceFile materialShader;
/** /**
* Alpha threshold below which fragments are discarded. * Alpha threshold below which fragments are discarded.
@ -62,7 +124,13 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
*/ */
private final FogType fogType; private final FogType fogType;
public Context(float alphaDiscard, FogType fogType, StateSnapshot ctx) { /**
* The shader constants to apply.
*/
private final StateSnapshot ctx;
public Context(SourceFile materialShader, float alphaDiscard, FogType fogType, StateSnapshot ctx) {
this.materialShader = materialShader;
this.alphaDiscard = alphaDiscard; this.alphaDiscard = alphaDiscard;
this.fogType = fogType; this.fogType = fogType;
this.ctx = ctx; this.ctx = ctx;
@ -84,18 +152,17 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
if (obj == this) return true; if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false; if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Context) obj; var that = (Context) obj;
return Objects.equals(this.ctx, that.ctx) && Float.floatToIntBits(this.alphaDiscard) == Float.floatToIntBits(that.alphaDiscard) && fogType == that.fogType; return materialShader == that.materialShader && Objects.equals(this.ctx, that.ctx) && Float.floatToIntBits(this.alphaDiscard) == Float.floatToIntBits(that.alphaDiscard) && fogType == that.fogType;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(alphaDiscard, fogType, ctx); return Objects.hash(materialShader, alphaDiscard, fogType, ctx);
} }
@Override @Override
public String toString() { public String toString() {
return "Context[" + "alphaDiscard=" + alphaDiscard + ", " + "fogType=" + fogType + ", " + "ctx=" + ctx + ']'; return "Context[" + "materialShader=" + materialShader + ", " + "alphaDiscard=" + alphaDiscard + ", " + "fogType=" + fogType + ", " + "ctx=" + ctx + ']';
} }
} }
} }

View file

@ -1,8 +0,0 @@
package com.jozufozu.flywheel.core.compile;
public interface FragmentData {
/**
* Generate the necessary glue code here.
*/
String generateFooter();
}

View file

@ -1,48 +0,0 @@
package com.jozufozu.flywheel.core.compile;
import java.util.Optional;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.source.parse.ShaderFunction;
import com.jozufozu.flywheel.core.source.parse.Variable;
public class FragmentTemplateData implements FragmentData {
public final SourceFile file;
public final ShaderFunction contextFragment;
public FragmentTemplateData(SourceFile file) {
this.file = file;
Optional<ShaderFunction> maybeContextFragment = file.findFunction("flw_contextFragment");
if (maybeContextFragment.isEmpty()) {
ErrorReporter.generateMissingFunction(file, "flw_contextFragment", "\"flw_contextFragment\" function not defined");
throw new ShaderLoadingException();
}
contextFragment = maybeContextFragment.get();
ImmutableList<Variable> params = contextFragment.getParameters();
if (params.size() != 0) {
ErrorReporter.generateSpanError(contextFragment.getArgs(), "\"flw_contextFragment\" function must not have any arguments");
throw new ShaderLoadingException();
}
}
@Override
public String generateFooter() {
StringBuilder builder = new StringBuilder();
builder.append("""
void main() {
flw_contextFragment();
}
"""
);
return builder.toString();
}
}

View file

@ -1,109 +0,0 @@
package com.jozufozu.flywheel.core.compile;
import java.util.Optional;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.source.FileIndex;
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.source.parse.ShaderFunction;
import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
import com.jozufozu.flywheel.core.source.parse.StructField;
import com.jozufozu.flywheel.core.source.parse.Variable;
import com.jozufozu.flywheel.core.source.span.Span;
public class InstancingTemplateData implements VertexData {
public final SourceFile file;
public final ShaderFunction instanceVertex;
public final Span instanceName;
public final ShaderStruct instance;
public InstancingTemplateData(SourceFile file) {
this.file = file;
Optional<ShaderFunction> maybeInstanceVertex = file.findFunction("flw_instanceVertex");
if (maybeInstanceVertex.isEmpty()) {
ErrorReporter.generateMissingFunction(file, "flw_instanceVertex", "\"flw_instanceVertex\" function not defined");
throw new ShaderLoadingException();
}
instanceVertex = maybeInstanceVertex.get();
ImmutableList<Variable> params = instanceVertex.getParameters();
if (params.size() != 1) {
ErrorReporter.generateSpanError(instanceVertex.getArgs(), "\"flw_contextFragment\" function must have exactly 1 argument");
throw new ShaderLoadingException();
}
instanceName = params.get(0).type;
Optional<ShaderStruct> maybeInstance = file.findStruct(instanceName);
if (maybeInstance.isEmpty()) {
ErrorReporter.generateMissingStruct(file, instanceName, "struct not defined");
throw new ShaderLoadingException();
}
instance = maybeInstance.get();
}
@Override
public String generateFooter(FileIndex shader, VertexType vertexType) {
ImmutableList<StructField> fields = instance.getFields();
int attributeBinding = vertexType.getLayout()
.getAttributeCount();
StringBuilder template = new StringBuilder();
for (StructField field : fields) {
template.append("layout(location = ")
.append(attributeBinding)
.append(") in")
.append(' ')
.append(field.type)
.append(' ')
.append("_flw_a_i_")
.append(field.name)
.append(";\n");
attributeBinding += CompileUtil.getAttributeCount(field.type);
}
template.append('\n');
template.append(String.format("""
void main() {
flw_layoutVertex();
%s instance;
%s
flw_instanceVertex(instance);
flw_contextVertex();
}
""",
instanceName,
assignFields(instance, "instance.", "_flw_a_i_")
));
return template.toString();
}
public static StringBuilder assignFields(ShaderStruct struct, String prefix1, String prefix2) {
ImmutableList<StructField> fields = struct.getFields();
StringBuilder builder = new StringBuilder();
for (StructField field : fields) {
builder.append(prefix1)
.append(field.name)
.append(" = ")
.append(prefix2)
.append(field.name)
.append(";\n");
}
return builder;
}
}

View file

@ -1,73 +0,0 @@
package com.jozufozu.flywheel.core.compile;
import java.util.Optional;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.source.FileIndex;
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.source.parse.ShaderFunction;
import com.jozufozu.flywheel.core.source.parse.Variable;
public class OneShotTemplateData implements VertexData {
public final SourceFile file;
public final ShaderFunction vertexMain;
public OneShotTemplateData(SourceFile file) {
this.file = file;
Optional<ShaderFunction> maybeVertexMain = file.findFunction("vertex");
if (maybeVertexMain.isEmpty()) {
ErrorReporter.generateFileError(file, "could not find \"vertex\" function");
throw new RuntimeException();
}
vertexMain = maybeVertexMain.get();
ImmutableList<Variable> vertexParameters = vertexMain.getParameters();
if (vertexParameters.size() != 1) {
ErrorReporter.generateSpanError(vertexMain.getArgs(), "a basic model requires vertex function to have one argument");
throw new RuntimeException();
}
Variable vertexParam = vertexMain.getParameters().get(0);
boolean namedVertex = vertexParam.type
.toString()
.equals("Vertex");
if (!(namedVertex && vertexParam.qualifier == Variable.Qualifier.INOUT)) {
ErrorReporter.generateSpanError(vertexParam.qualifierSpan, "first parameter must be inout Vertex");
throw new ShaderLoadingException();
}
}
@Override
public String generateFooter(FileIndex file, VertexType vertexType) {
return """
out vec4 v2f_color;
out vec2 v2f_texCoords;
out vec2 v2f_light;
out float v2f_diffuse;
void main() {
Vertex v = FLWCreateVertex();
vertex(v);
gl_Position = FLWVertex(v);
v.normal = normalize(v.normal);
v2f_color = v.color;
v2f_texCoords = v.texCoords;
v2f_light = v.light;
v2f_diffuse = FLWDiffuse(v.normal);
#if defined(DEBUG_NORMAL)
v2f_color = vec4(v.normal, 1.);
#endif
}
""";
}
}

View file

@ -34,15 +34,13 @@ public class ProgramCompiler<P extends GlProgram> extends Memoizer<ProgramContex
/** /**
* Creates a program compiler using provided templates and headers. * Creates a program compiler using provided templates and headers.
* @param factory A factory to add meaning to compiled programs. * @param factory A factory to add meaning to compiled programs.
* @param vertexTemplate The vertex template to use.
* @param fragmentTemplate The fragment template to use.
* @param vertexContextShader The context shader to use when compiling vertex shaders. * @param vertexContextShader The context shader to use when compiling vertex shaders.
* @param fragmentContextShader The context shader to use when compiling fragment shaders. * @param fragmentContextShader The context shader to use when compiling fragment shaders.
* @param <P> The type of program to compile. * @param <P> The type of program to compile.
* @return A program compiler. * @return A program compiler.
*/ */
public static <V extends VertexData, F extends FragmentData, P extends GlProgram> ProgramCompiler<P> create(GlProgram.Factory<P> factory, Template<V> vertexTemplate, Template<F> fragmentTemplate, FileResolution vertexContextShader, FileResolution fragmentContextShader) { public static <P extends GlProgram> ProgramCompiler<P> create(GlProgram.Factory<P> factory, FileResolution vertexContextShader, FileResolution fragmentContextShader) {
return new ProgramCompiler<>(factory, new VertexCompiler(vertexTemplate, vertexContextShader), new FragmentCompiler(fragmentTemplate, fragmentContextShader)); return new ProgramCompiler<>(factory, new VertexCompiler(vertexContextShader), new FragmentCompiler(fragmentContextShader));
} }
/** /**
@ -65,8 +63,8 @@ public class ProgramCompiler<P extends GlProgram> extends Memoizer<ProgramContex
@Override @Override
protected P _create(ProgramContext ctx) { protected P _create(ProgramContext ctx) {
return new ProgramAssembler(ctx.instanceShader.getFileLoc()) return new ProgramAssembler(ctx.instanceShader.getFileLoc())
.attachShader(vertexCompiler.get(new VertexCompiler.Context(ctx.vertexType, ctx.instanceShader.getFile(), ctx.ctx))) .attachShader(vertexCompiler.get(new VertexCompiler.Context(ctx.vertexType, ctx.instanceShader.getFile(), ctx.vertexMaterialShader.getFile(), ctx.ctx)))
.attachShader(fragmentCompiler.get(new FragmentCompiler.Context(ctx.alphaDiscard, ctx.fogType, ctx.ctx))) .attachShader(fragmentCompiler.get(new FragmentCompiler.Context(ctx.fragmentMaterialShader.getFile(), ctx.alphaDiscard, ctx.fogType, ctx.ctx)))
.link() .link()
.build(this.factory); .build(this.factory);
} }

View file

@ -14,20 +14,26 @@ public final class ProgramContext {
public final VertexType vertexType; public final VertexType vertexType;
public final FileResolution instanceShader; public final FileResolution instanceShader;
public final FileResolution vertexMaterialShader;
public final FileResolution fragmentMaterialShader;
public final float alphaDiscard; public final float alphaDiscard;
public final FogType fogType; public final FogType fogType;
public final StateSnapshot ctx; public final StateSnapshot ctx;
/** /**
* @param vertexType The vertexType the program should be adapted for. * @param vertexType The vertexType the program should be adapted for.
* @param spec The program to use. * @param instanceShader The instance shader to use.
* @param alphaDiscard Alpha threshold below which pixels are discarded. * @param vertexMaterialShader The vertex material shader to use.
* @param fogType Which type of fog should be applied. * @param fragmentMaterialShader The fragment material shader to use.
* @param ctx A snapshot of the game state. * @param alphaDiscard Alpha threshold below which pixels are discarded.
* @param fogType Which type of fog should be applied.
* @param ctx A snapshot of the game state.
*/ */
public ProgramContext(VertexType vertexType, FileResolution instanceShader, float alphaDiscard, FogType fogType, StateSnapshot ctx) { public ProgramContext(VertexType vertexType, FileResolution instanceShader, FileResolution vertexMaterialShader, FileResolution fragmentMaterialShader, float alphaDiscard, FogType fogType, StateSnapshot ctx) {
this.vertexType = vertexType; this.vertexType = vertexType;
this.instanceShader = instanceShader; this.instanceShader = instanceShader;
this.vertexMaterialShader = vertexMaterialShader;
this.fragmentMaterialShader = fragmentMaterialShader;
this.alphaDiscard = alphaDiscard; this.alphaDiscard = alphaDiscard;
this.fogType = fogType; this.fogType = fogType;
this.ctx = ctx; this.ctx = ctx;
@ -38,16 +44,16 @@ public final class ProgramContext {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
var that = (ProgramContext) o; var that = (ProgramContext) o;
return instanceShader == that.instanceShader && vertexType == that.vertexType && ctx.equals(that.ctx) && Float.floatToIntBits(alphaDiscard) == Float.floatToIntBits(that.alphaDiscard) && fogType == that.fogType; return vertexType == that.vertexType && instanceShader == that.instanceShader && vertexMaterialShader == that.vertexMaterialShader && fragmentMaterialShader == that.fragmentMaterialShader && ctx.equals(that.ctx) && Float.floatToIntBits(alphaDiscard) == Float.floatToIntBits(that.alphaDiscard) && fogType == that.fogType;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(vertexType, instanceShader, alphaDiscard, fogType, ctx); return Objects.hash(vertexType, instanceShader, vertexMaterialShader, fragmentMaterialShader, alphaDiscard, fogType, ctx);
} }
@Override @Override
public String toString() { public String toString() {
return "ProgramContext{" + "vertexType=" + vertexType + ", instanceShader=" + instanceShader + ", alphaDiscard=" + alphaDiscard + ", fogType=" + fogType + ", ctx=" + ctx + '}'; return "ProgramContext{" + "vertexType=" + vertexType + ", instanceShader=" + instanceShader + ", vertexMaterialShader=" + vertexMaterialShader + ", fragmentMaterialShader=" + fragmentMaterialShader + ", alphaDiscard=" + alphaDiscard + ", fogType=" + fogType + ", ctx=" + ctx + '}';
} }
} }

View file

@ -1,52 +0,0 @@
package com.jozufozu.flywheel.core.compile;
import java.util.function.Function;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.core.source.SourceFile;
/**
* A class that generates glsl glue code given a SourceFile.
*
* <p>
* Shader files are written somewhat abstractly. Subclasses of Template handle those abstractions, using SourceFile
* metadata to generate shader code that OpenGL can use to call into our shader programs.
* </p>
*/
public class Template<T> extends Memoizer<SourceFile, T> {
private final Function<SourceFile, T> reader;
private final GLSLVersion glslVersion;
public Template(GLSLVersion glslVersion, Function<SourceFile, T> reader) {
this.reader = reader;
this.glslVersion = glslVersion;
}
/**
* Verify that the given SourceFile is valid for this Template and return the metadata.
* @param file The SourceFile to apply this Template to.
* @return The applied template metadata.
*/
public T apply(SourceFile file) {
// lazily read files, cache results
return super.get(file);
}
/**
* @return The GLSL version this template requires.
*/
public GLSLVersion getVersion() {
return glslVersion;
}
@Override
protected T _create(SourceFile key) {
return reader.apply(key);
}
@Override
protected void _destroy(T value) {
// noop
}
}

View file

@ -1,21 +1,29 @@
package com.jozufozu.flywheel.core.compile; package com.jozufozu.flywheel.core.compile;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.backend.gl.shader.GlShader; import com.jozufozu.flywheel.backend.gl.shader.GlShader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.core.shader.StateSnapshot; import com.jozufozu.flywheel.core.shader.StateSnapshot;
import com.jozufozu.flywheel.core.source.FileIndexImpl; import com.jozufozu.flywheel.core.source.FileIndexImpl;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
import com.jozufozu.flywheel.core.source.SourceFile; import com.jozufozu.flywheel.core.source.SourceFile;
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
import com.jozufozu.flywheel.core.source.parse.ShaderFunction;
import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
import com.jozufozu.flywheel.core.source.parse.StructField;
import com.jozufozu.flywheel.core.source.parse.Variable;
import com.jozufozu.flywheel.core.source.span.Span;
public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> { public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
private final Template<? extends VertexData> template;
private final FileResolution contextShader; private final FileResolution contextShader;
public VertexCompiler(Template<? extends VertexData> template, FileResolution contextShader) { public VertexCompiler(FileResolution contextShader) {
this.template = template;
this.contextShader = contextShader; this.contextShader = contextShader;
} }
@ -23,24 +31,171 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
protected GlShader _create(Context key) { protected GlShader _create(Context key) {
StringBuilder finalSource = new StringBuilder(); StringBuilder finalSource = new StringBuilder();
finalSource.append(CompileUtil.generateHeader(template.getVersion(), ShaderType.VERTEX)); finalSource.append(CompileUtil.generateHeader(GLSLVersion.V330, ShaderType.VERTEX));
key.ctx.getShaderConstants().writeInto(finalSource); key.ctx.getShaderConstants().writeInto(finalSource);
finalSource.append('\n'); finalSource.append('\n');
FileIndexImpl index = new FileIndexImpl(); FileIndexImpl index = new FileIndexImpl();
FileResolution layoutShader = key.vertexType.getLayoutShader(); //
layoutShader.getFile().generateFinalSource(index, finalSource);
contextShader.getFile().generateFinalSource(index, finalSource); SourceFile layoutShader = key.vertexType.getLayoutShader().getFile();
key.instanceShader.generateFinalSource(index, finalSource); Optional<ShaderFunction> maybeLayoutVertex = layoutShader.findFunction("flw_layoutVertex");
VertexData appliedTemplate = template.apply(key.instanceShader); if (maybeLayoutVertex.isEmpty()) {
finalSource.append(appliedTemplate.generateFooter(index, key.vertexType)); ErrorReporter.generateMissingFunction(layoutShader, "flw_layoutVertex", "\"flw_layoutVertex\" function not defined");
throw new ShaderLoadingException();
}
return new GlShader(key.instanceShader.name, ShaderType.VERTEX, finalSource.toString()); ShaderFunction layoutVertex = maybeLayoutVertex.get();
ImmutableList<Variable> params = layoutVertex.getParameters();
if (params.size() != 0) {
ErrorReporter.generateSpanError(layoutVertex.getArgs(), "\"flw_layoutVertex\" function must not have any arguments");
throw new ShaderLoadingException();
}
layoutShader.generateFinalSource(index, finalSource);
//
SourceFile instanceShader = key.instanceShader;
Optional<ShaderFunction> maybeInstanceVertex = instanceShader.findFunction("flw_instanceVertex");
if (maybeInstanceVertex.isEmpty()) {
ErrorReporter.generateMissingFunction(instanceShader, "flw_instanceVertex", "\"flw_instanceVertex\" function not defined");
throw new ShaderLoadingException();
}
ShaderFunction instanceVertex = maybeInstanceVertex.get();
params = instanceVertex.getParameters();
if (params.size() != 1) {
ErrorReporter.generateSpanError(instanceVertex.getArgs(), "\"flw_instanceVertex\" function must have exactly 1 argument");
throw new ShaderLoadingException();
}
Span instanceName = params.get(0).type;
Optional<ShaderStruct> maybeInstance = instanceShader.findStruct(instanceName);
if (maybeInstance.isEmpty()) {
ErrorReporter.generateMissingStruct(instanceShader, instanceName, "instance struct not defined");
throw new ShaderLoadingException();
}
ShaderStruct instance = maybeInstance.get();
instanceShader.generateFinalSource(index, finalSource);
//
SourceFile materialShader = key.materialShader;
Optional<ShaderFunction> maybeMaterialVertex = materialShader.findFunction("flw_materialVertex");
if (maybeMaterialVertex.isEmpty()) {
ErrorReporter.generateMissingFunction(materialShader, "flw_materialVertex", "\"flw_materialVertex\" function not defined");
throw new ShaderLoadingException();
}
ShaderFunction materialVertex = maybeMaterialVertex.get();
params = materialVertex.getParameters();
if (params.size() != 0) {
ErrorReporter.generateSpanError(materialVertex.getArgs(), "\"flw_materialVertex\" function must not have any arguments");
throw new ShaderLoadingException();
}
materialShader.generateFinalSource(index, finalSource);
//
SourceFile contextShaderSource = contextShader.getFile();
Optional<ShaderFunction> maybeContextVertex = contextShaderSource.findFunction("flw_contextVertex");
if (maybeContextVertex.isEmpty()) {
ErrorReporter.generateMissingFunction(contextShaderSource, "flw_contextVertex", "\"flw_contextVertex\" function not defined");
throw new ShaderLoadingException();
}
ShaderFunction contextVertex = maybeContextVertex.get();
params = contextVertex.getParameters();
if (params.size() != 0) {
ErrorReporter.generateSpanError(contextVertex.getArgs(), "\"flw_contextVertex\" function must not have any arguments");
throw new ShaderLoadingException();
}
contextShaderSource.generateFinalSource(index, finalSource);
//
finalSource.append(generateFooter(key.vertexType, instance));
return new GlShader(instanceShader.name, ShaderType.VERTEX, finalSource.toString());
}
protected String generateFooter(VertexType vertexType, ShaderStruct instance) {
ImmutableList<StructField> fields = instance.getFields();
int attributeBinding = vertexType.getLayout()
.getAttributeCount();
StringBuilder footer = new StringBuilder();
for (StructField field : fields) {
footer.append("layout(location = ")
.append(attributeBinding)
.append(") in")
.append(' ')
.append(field.type)
.append(' ')
.append("_flw_a_i_")
.append(field.name)
.append(";\n");
attributeBinding += CompileUtil.getAttributeCount(field.type);
}
footer.append('\n');
footer.append(String.format("""
void main() {
flw_layoutVertex();
%s instance;
%s
flw_instanceVertex(instance);
flw_materialVertex();
flw_contextVertex();
}
""",
instance.name,
assignFields(instance, "instance.", "_flw_a_i_")
));
return footer.toString();
}
protected static StringBuilder assignFields(ShaderStruct struct, String prefix1, String prefix2) {
ImmutableList<StructField> fields = struct.getFields();
StringBuilder builder = new StringBuilder();
for (StructField field : fields) {
builder.append(prefix1)
.append(field.name)
.append(" = ")
.append(prefix2)
.append(field.name)
.append(";\n");
}
return builder;
} }
@Override @Override
@ -59,14 +214,20 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
*/ */
private final SourceFile instanceShader; private final SourceFile instanceShader;
/**
* The vertex material shader source.
*/
private final SourceFile materialShader;
/** /**
* The shader constants to apply. * The shader constants to apply.
*/ */
private final StateSnapshot ctx; private final StateSnapshot ctx;
public Context(VertexType vertexType, SourceFile instanceShader, StateSnapshot ctx) { public Context(VertexType vertexType, SourceFile instanceShader, SourceFile materialShader, StateSnapshot ctx) {
this.vertexType = vertexType; this.vertexType = vertexType;
this.instanceShader = instanceShader; this.instanceShader = instanceShader;
this.materialShader = materialShader;
this.ctx = ctx; this.ctx = ctx;
} }
@ -75,12 +236,12 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
var that = (Context) o; var that = (Context) o;
return vertexType == that.vertexType && instanceShader == that.instanceShader && ctx.equals(that.ctx); return vertexType == that.vertexType && instanceShader == that.instanceShader && materialShader == that.materialShader && ctx.equals(that.ctx);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(vertexType, instanceShader, ctx); return Objects.hash(vertexType, instanceShader, materialShader, ctx);
} }
} }
} }

View file

@ -1,12 +0,0 @@
package com.jozufozu.flywheel.core.compile;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.source.FileIndex;
public interface VertexData {
/**
* Generate the necessary glue code here.
* @param file The SourceFile with user written code.
*/
String generateFooter(FileIndex file, VertexType vertexType);
}

View file

@ -1,13 +1,13 @@
package com.jozufozu.flywheel.core.crumbling; package com.jozufozu.flywheel.core.crumbling;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
public class CrumblingInstanceManager extends BlockEntityInstanceManager { public class CrumblingInstanceManager extends BlockEntityInstanceManager {
public CrumblingInstanceManager(MaterialManager materialManager) { public CrumblingInstanceManager(InstancerManager instancerManager) {
super(materialManager); super(instancerManager);
} }
@Override @Override

View file

@ -11,7 +11,7 @@ import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
import com.jozufozu.flywheel.backend.instancing.InstanceManager; import com.jozufozu.flywheel.backend.instancing.InstanceManager;
import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine; import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancedMaterial; import com.jozufozu.flywheel.backend.instancing.instancing.GPUInstancerFactory;
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo; import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo;
@ -65,7 +65,7 @@ public class CrumblingRenderer {
State state = STATE.get(); State state = STATE.get();
var instanceManager = state.instanceManager; var instanceManager = state.instanceManager;
var engine = state.materialManager; var engine = state.instancerManager;
TextureManager textureManager = Minecraft.getInstance().getTextureManager(); TextureManager textureManager = Minecraft.getInstance().getTextureManager();
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera(); Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
@ -140,17 +140,17 @@ public class CrumblingRenderer {
} }
private static class State { private static class State {
private final CrumblingEngine materialManager; private final CrumblingEngine instancerManager;
private final InstanceManager<BlockEntity> instanceManager; private final InstanceManager<BlockEntity> instanceManager;
private State() { private State() {
materialManager = new CrumblingEngine(); instancerManager = new CrumblingEngine();
instanceManager = new CrumblingInstanceManager(materialManager); instanceManager = new CrumblingInstanceManager(instancerManager);
materialManager.addListener(instanceManager); instancerManager.addListener(instanceManager);
} }
private void kill() { private void kill() {
materialManager.delete(); instancerManager.delete();
instanceManager.invalidate(); instanceManager.invalidate();
} }
} }
@ -190,10 +190,10 @@ public class CrumblingRenderer {
Textures.bindActiveTextures(); Textures.bindActiveTextures();
CoreShaderInfo coreShaderInfo = getCoreShaderInfo(); CoreShaderInfo coreShaderInfo = getCoreShaderInfo();
for (Map.Entry<Instanced<? extends InstanceData>, InstancedMaterial<?>> entry : materials.entrySet()) { for (Map.Entry<Instanced<? extends InstanceData>, GPUInstancerFactory<?>> entry : factories.entrySet()) {
CrumblingProgram program = setup(entry.getKey(), coreShaderInfo, camX, camY, camZ, viewProjection, level); //CrumblingProgram program = setup(entry.getKey(), coreShaderInfo, camX, camY, camZ, viewProjection, level);
program.setAtlasSize(width, height); //program.setAtlasSize(width, height);
//entry.getValue().getAllRenderables().forEach(Renderable::draw); //entry.getValue().getAllRenderables().forEach(Renderable::draw);
} }

View file

@ -0,0 +1,26 @@
package com.jozufozu.flywheel.core.material;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.source.Resolver;
import com.jozufozu.flywheel.event.GatherContextEvent;
import com.jozufozu.flywheel.util.ResourceUtil;
import net.minecraft.resources.ResourceLocation;
public class MaterialShaders {
public static FileResolution DEFAULT_VERTEX;
public static FileResolution DEFAULT_FRAGMENT;
public static FileResolution SHADED_VERTEX;
public static void flwInit(GatherContextEvent event) {
DEFAULT_VERTEX = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.DEFAULT, ".vert"));
DEFAULT_FRAGMENT = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.DEFAULT, ".frag"));
SHADED_VERTEX = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.SHADED, ".vert"));
}
public static class Names {
public static final ResourceLocation DEFAULT = Flywheel.rl("material/default");
public static final ResourceLocation SHADED = Flywheel.rl("material/shaded");
}
}

View file

@ -1,12 +0,0 @@
package com.jozufozu.flywheel.core.materials;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.materials.model.ModelType;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
import com.jozufozu.flywheel.core.materials.oriented.OrientedType;
public class Materials {
public static final StructType<ModelData> TRANSFORMED = new ModelType();
public static final StructType<OrientedData> ORIENTED = new OrientedType();
}

View file

@ -2,11 +2,10 @@ package com.jozufozu.flywheel.core.model;
import java.util.Map; import java.util.Map;
import net.minecraft.client.renderer.RenderType; import com.jozufozu.flywheel.api.material.Material;
public interface ModelSupplier { public interface ModelSupplier {
Map<Material, Mesh> get();
Map<RenderType, Mesh> get();
int getVertexCount(); int getVertexCount();
} }

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.materials; package com.jozufozu.flywheel.core.structs;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.util.Color; import com.jozufozu.flywheel.util.Color;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.materials; package com.jozufozu.flywheel.core.structs;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.materials; package com.jozufozu.flywheel.core.structs;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.materials; package com.jozufozu.flywheel.core.structs;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;

View file

@ -0,0 +1,12 @@
package com.jozufozu.flywheel.core.structs;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.structs.model.ModelData;
import com.jozufozu.flywheel.core.structs.model.ModelType;
import com.jozufozu.flywheel.core.structs.oriented.OrientedData;
import com.jozufozu.flywheel.core.structs.oriented.OrientedType;
public class StructTypes {
public static final StructType<ModelData> MODEL = new ModelType();
public static final StructType<OrientedData> ORIENTED = new OrientedType();
}

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.core.materials.model; package com.jozufozu.flywheel.core.structs.model;
import com.jozufozu.flywheel.core.materials.BasicData; import com.jozufozu.flywheel.core.structs.BasicData;
import com.jozufozu.flywheel.util.transform.Transform; import com.jozufozu.flywheel.util.transform.Transform;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f; import com.mojang.math.Matrix3f;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.materials.model; package com.jozufozu.flywheel.core.structs.model;
import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
@ -6,9 +6,9 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems; import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.materials.InstanceShaders;
import com.jozufozu.flywheel.core.model.ModelTransformer; import com.jozufozu.flywheel.core.model.ModelTransformer;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.structs.InstanceShaders;
public class ModelType implements Instanced<ModelData>, Batched<ModelData> { public class ModelType implements Instanced<ModelData>, Batched<ModelData> {

View file

@ -1,8 +1,8 @@
package com.jozufozu.flywheel.core.materials.model; package com.jozufozu.flywheel.core.structs.model;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.materials.BasicWriterUnsafe; import com.jozufozu.flywheel.core.structs.BasicWriterUnsafe;
import com.jozufozu.flywheel.util.MatrixWrite; import com.jozufozu.flywheel.util.MatrixWrite;
public class ModelWriterUnsafe extends BasicWriterUnsafe<ModelData> { public class ModelWriterUnsafe extends BasicWriterUnsafe<ModelData> {

View file

@ -1,5 +1,5 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.materials.model; package com.jozufozu.flywheel.core.structs.model;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.core.materials.oriented; package com.jozufozu.flywheel.core.structs.oriented;
import com.jozufozu.flywheel.core.materials.BasicData; import com.jozufozu.flywheel.core.structs.BasicData;
import com.mojang.math.Quaternion; import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.materials.oriented; package com.jozufozu.flywheel.core.structs.oriented;
import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
@ -6,9 +6,9 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.layout.CommonItems; import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.materials.InstanceShaders;
import com.jozufozu.flywheel.core.model.ModelTransformer; import com.jozufozu.flywheel.core.model.ModelTransformer;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
import com.jozufozu.flywheel.core.structs.InstanceShaders;
import com.mojang.math.Quaternion; import com.mojang.math.Quaternion;
public class OrientedType implements Instanced<OrientedData>, Batched<OrientedData> { public class OrientedType implements Instanced<OrientedData>, Batched<OrientedData> {

View file

@ -1,10 +1,10 @@
package com.jozufozu.flywheel.core.materials.oriented; package com.jozufozu.flywheel.core.structs.oriented;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.materials.BasicWriterUnsafe; import com.jozufozu.flywheel.core.structs.BasicWriterUnsafe;
public class OrientedWriterUnsafe extends BasicWriterUnsafe<OrientedData> { public class OrientedWriterUnsafe extends BasicWriterUnsafe<OrientedData> {
public OrientedWriterUnsafe(VecBuffer backingBuffer, StructType<OrientedData> vertexType) { public OrientedWriterUnsafe(VecBuffer backingBuffer, StructType<OrientedData> vertexType) {

View file

@ -1,5 +1,5 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.materials.oriented; package com.jozufozu.flywheel.core.structs.oriented;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;

View file

@ -1,5 +1,5 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.materials; package com.jozufozu.flywheel.core.structs;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;

View file

@ -2,13 +2,15 @@ package com.jozufozu.flywheel.vanilla;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier; import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart; import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials; import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData; import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.oriented.OrientedData;
import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.mojang.math.Quaternion; import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
@ -20,14 +22,14 @@ import net.minecraft.world.level.block.entity.BellBlockEntity;
public class BellInstance extends BlockEntityInstance<BellBlockEntity> implements DynamicInstance { public class BellInstance extends BlockEntityInstance<BellBlockEntity> implements DynamicInstance {
private static final BasicModelSupplier MODEL = new BasicModelSupplier(BellInstance::createBellModel, Sheets.solidBlockSheet()); private static final BasicModelSupplier MODEL = new BasicModelSupplier(BellInstance::createBellModel, new Material(Sheets.solidBlockSheet(), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT));
private final OrientedData bell; private final OrientedData bell;
private float lastRingTime = Float.NaN; private float lastRingTime = Float.NaN;
public BellInstance(MaterialManager materialManager, BellBlockEntity blockEntity) { public BellInstance(InstancerManager instancerManager, BellBlockEntity blockEntity) {
super(materialManager, blockEntity); super(instancerManager, blockEntity);
bell = createBellInstance() bell = createBellInstance()
.setPivot(0.5f, 0.75f, 0.5f) .setPivot(0.5f, 0.75f, 0.5f)
@ -63,7 +65,7 @@ public class BellInstance extends BlockEntityInstance<BellBlockEntity> implement
} }
private OrientedData createBellInstance() { private OrientedData createBellInstance() {
return materialManager.material(Materials.ORIENTED) return instancerManager.factory(StructTypes.ORIENTED)
.model(MODEL) .model(MODEL)
.createInstance(); .createInstance();
} }

View file

@ -5,14 +5,15 @@ import java.util.function.BiFunction;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier; import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart; import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials; import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData; import com.jozufozu.flywheel.core.structs.model.ModelData;
import com.jozufozu.flywheel.core.structs.oriented.OrientedData;
import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.mojang.math.Quaternion; import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
@ -33,8 +34,8 @@ import net.minecraft.world.level.block.state.properties.ChestType;
public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends BlockEntityInstance<T> implements DynamicInstance { public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends BlockEntityInstance<T> implements DynamicInstance {
private static final BiFunction<ChestType, Material, BasicModelSupplier> LID = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createLidModel(type, mat.sprite()), Sheets.chestSheet())); private static final BiFunction<ChestType, Material, BasicModelSupplier> LID = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createLidModel(type, mat.sprite()), new com.jozufozu.flywheel.api.material.Material(Sheets.chestSheet(), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT)));
private static final BiFunction<ChestType, Material, BasicModelSupplier> BASE = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createBaseModel(type, mat.sprite()), Sheets.chestSheet())); private static final BiFunction<ChestType, Material, BasicModelSupplier> BASE = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createBaseModel(type, mat.sprite()), new com.jozufozu.flywheel.api.material.Material(Sheets.chestSheet(), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT)));
private final OrientedData body; private final OrientedData body;
private final ModelData lid; private final ModelData lid;
@ -47,8 +48,8 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
private float lastProgress = Float.NaN; private float lastProgress = Float.NaN;
public ChestInstance(MaterialManager materialManager, T blockEntity) { public ChestInstance(InstancerManager instancerManager, T blockEntity) {
super(materialManager, blockEntity); super(instancerManager, blockEntity);
Block block = blockState.getBlock(); Block block = blockState.getBlock();
@ -67,7 +68,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
body.setRotation(baseRotation); body.setRotation(baseRotation);
DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> wrapper = chestBlock.combine(blockState, world, getWorldPosition(), true); DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> wrapper = chestBlock.combine(blockState, level, getWorldPosition(), true);
this.lidProgress = wrapper.apply(ChestBlock.opennessCombiner(blockEntity)); this.lidProgress = wrapper.apply(ChestBlock.opennessCombiner(blockEntity));
@ -115,14 +116,14 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
private OrientedData baseInstance() { private OrientedData baseInstance() {
return materialManager.material(Materials.ORIENTED) return instancerManager.factory(StructTypes.ORIENTED)
.model(BASE.apply(chestType, renderMaterial)) .model(BASE.apply(chestType, renderMaterial))
.createInstance(); .createInstance();
} }
private ModelData lidInstance() { private ModelData lidInstance() {
return materialManager.material(Materials.TRANSFORMED) return instancerManager.factory(StructTypes.MODEL)
.model(LID.apply(chestType, renderMaterial)) .model(LID.apply(chestType, renderMaterial))
.createInstance(); .createInstance();
} }

View file

@ -2,16 +2,18 @@ package com.jozufozu.flywheel.vanilla;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
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.material.Material;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier; import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.Models; import com.jozufozu.flywheel.core.Models;
import com.jozufozu.flywheel.core.hardcoded.ModelPart; import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials; import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.ModelData;
import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.transform.TransformStack; import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
@ -29,7 +31,7 @@ import net.minecraft.world.phys.Vec3;
public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance<T> implements DynamicInstance, TickableInstance { public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance<T> implements DynamicInstance, TickableInstance {
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png"); private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
private static final BasicModelSupplier MODEL = new BasicModelSupplier(MinecartInstance::getBodyModel, RenderType.entitySolid(MINECART_LOCATION)); private static final BasicModelSupplier MODEL = new BasicModelSupplier(MinecartInstance::getBodyModel, new Material(RenderType.entitySolid(MINECART_LOCATION), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT));
private final PoseStack stack = new PoseStack(); private final PoseStack stack = new PoseStack();
@ -37,8 +39,8 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
private ModelData contents; private ModelData contents;
private BlockState blockstate; private BlockState blockstate;
public MinecartInstance(MaterialManager materialManager, T entity) { public MinecartInstance(InstancerManager instancerManager, T entity) {
super(materialManager, entity); super(instancerManager, entity);
blockstate = entity.getDisplayBlockState(); blockstate = entity.getDisplayBlockState();
contents = getContents(); contents = getContents();
@ -63,7 +65,7 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
stack.setIdentity(); stack.setIdentity();
float pt = AnimationTickHolder.getPartialTicks(); float pt = AnimationTickHolder.getPartialTicks();
Vec3i originCoordinate = materialManager.getOriginCoordinate(); Vec3i originCoordinate = instancerManager.getOriginCoordinate();
tstack.translate( tstack.translate(
Mth.lerp(pt, entity.xOld, entity.getX()) - originCoordinate.getX(), Mth.lerp(pt, entity.xOld, entity.getX()) - originCoordinate.getX(),
Mth.lerp(pt, entity.yOld, entity.getY()) - originCoordinate.getY(), Mth.lerp(pt, entity.yOld, entity.getY()) - originCoordinate.getY(),
@ -147,13 +149,13 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
if (blockstate.getRenderShape() == RenderShape.INVISIBLE) if (blockstate.getRenderShape() == RenderShape.INVISIBLE)
return null; return null;
return materialManager.material(Materials.TRANSFORMED) return instancerManager.factory(StructTypes.MODEL)
.model(Models.block(blockstate)) .model(Models.block(blockstate))
.createInstance(); .createInstance();
} }
private ModelData getBody() { private ModelData getBody() {
return materialManager.material(Materials.TRANSFORMED) return instancerManager.factory(StructTypes.MODEL)
.model(MODEL) .model(MODEL)
.createInstance(); .createInstance();
} }

View file

@ -2,13 +2,15 @@ package com.jozufozu.flywheel.vanilla;
import java.util.function.Function; import java.util.function.Function;
import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier; import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart; import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials; import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.ModelData;
import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.jozufozu.flywheel.util.transform.TransformStack; import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
@ -26,8 +28,8 @@ import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntity> implements DynamicInstance { public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntity> implements DynamicInstance {
private static final Function<TextureAtlasSprite, BasicModelSupplier> BASE = Util.memoize(it -> new BasicModelSupplier(() -> makeBaseModel(it), RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET))); private static final Function<TextureAtlasSprite, BasicModelSupplier> BASE = Util.memoize(it -> new BasicModelSupplier(() -> makeBaseModel(it), new Material(RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT)));
private static final Function<TextureAtlasSprite, BasicModelSupplier> LID = Util.memoize(it -> new BasicModelSupplier(() -> makeLidModel(it), RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET))); private static final Function<TextureAtlasSprite, BasicModelSupplier> LID = Util.memoize(it -> new BasicModelSupplier(() -> makeLidModel(it), new Material(RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT)));
private final TextureAtlasSprite texture; private final TextureAtlasSprite texture;
@ -37,8 +39,8 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
private float lastProgress = Float.NaN; private float lastProgress = Float.NaN;
public ShulkerBoxInstance(MaterialManager materialManager, ShulkerBoxBlockEntity blockEntity) { public ShulkerBoxInstance(InstancerManager instancerManager, ShulkerBoxBlockEntity blockEntity) {
super(materialManager, blockEntity); super(instancerManager, blockEntity);
DyeColor color = blockEntity.getColor(); DyeColor color = blockEntity.getColor();
if (color == null) { if (color == null) {
@ -97,13 +99,13 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
} }
private ModelData makeBaseInstance() { private ModelData makeBaseInstance() {
return materialManager.material(Materials.TRANSFORMED) return instancerManager.factory(StructTypes.MODEL)
.model(BASE.apply(texture)) .model(BASE.apply(texture))
.createInstance(); .createInstance();
} }
private ModelData makeLidInstance() { private ModelData makeLidInstance() {
return materialManager.material(Materials.TRANSFORMED) return instancerManager.factory(StructTypes.MODEL)
.model(LID.apply(texture)) .model(LID.apply(texture))
.createInstance(); .createInstance();
} }

View file

@ -1,21 +1,11 @@
#use "flywheel:api/vertex.glsl" #use "flywheel:api/vertex.glsl"
#use "flywheel:util/diffuse.glsl"
#use "flywheel:util/fog.glsl" #use "flywheel:util/fog.glsl"
uniform mat4 uViewProjection; uniform mat4 uViewProjection;
uniform vec3 uCameraPos; uniform vec3 uCameraPos;
uniform int uConstantAmbientLight;
uniform int uFogShape; uniform int uFogShape;
out float _flw_diffuse;
void flw_contextVertex() { void flw_contextVertex() {
flw_vertexNormal = normalize(flw_vertexNormal);
if (uConstantAmbientLight == 1) {
_flw_diffuse = diffuseNether(flw_vertexNormal);
} else {
_flw_diffuse = diffuse(flw_vertexNormal);
}
flw_distance = fog_distance(flw_vertexPos.xyz, uCameraPos, uFogShape); flw_distance = fog_distance(flw_vertexPos.xyz, uCameraPos, uFogShape);
gl_Position = uViewProjection * flw_vertexPos; gl_Position = uViewProjection * flw_vertexPos;

View file

@ -8,15 +8,13 @@ uniform vec2 uTextureScale;
uniform sampler2D uBlockAtlas; uniform sampler2D uBlockAtlas;
uniform sampler2D uCrumbling; uniform sampler2D uCrumbling;
in float _flw_diffuse;
out vec4 fragColor; out vec4 fragColor;
void flw_contextFragment() { void flw_contextFragment() {
vec4 texColor = texture(uBlockAtlas, flw_vertexTexCoord); vec4 texColor = texture(uBlockAtlas, flw_vertexTexCoord);
vec4 crumblingColor = texture(uCrumbling, flw_vertexTexCoord * uTextureScale); vec4 crumblingColor = texture(uCrumbling, flw_vertexTexCoord * uTextureScale);
crumblingColor.a *= texColor.a; crumblingColor.a *= texColor.a;
vec4 color = flw_vertexColor * vec4(crumblingColor.rgb * _flw_diffuse, crumblingColor.a); vec4 color = flw_vertexColor * vec4(crumblingColor.rgb, crumblingColor.a);
#ifdef ALPHA_DISCARD #ifdef ALPHA_DISCARD
if (color.a < ALPHA_DISCARD) { if (color.a < ALPHA_DISCARD) {

View file

@ -14,14 +14,12 @@ uniform vec4 uFogColor;
uniform sampler2D uBlockAtlas; uniform sampler2D uBlockAtlas;
uniform sampler2D uLightMap; uniform sampler2D uLightMap;
in float _flw_diffuse;
out vec4 fragColor; out vec4 fragColor;
void flw_contextFragment() { void flw_contextFragment() {
vec4 texColor = texture(uBlockAtlas, flw_vertexTexCoord); vec4 texColor = texture(uBlockAtlas, flw_vertexTexCoord);
vec4 lightColor = texture(uLightMap, flw_vertexLight); vec4 lightColor = texture(uLightMap, flw_vertexLight);
vec4 color = flw_vertexColor * vec4(texColor.rgb * lightColor.rgb * _flw_diffuse, texColor.a); vec4 color = flw_vertexColor * vec4(texColor.rgb * lightColor.rgb, texColor.a);
#ifdef ALPHA_DISCARD #ifdef ALPHA_DISCARD
if (color.a < ALPHA_DISCARD) { if (color.a < ALPHA_DISCARD) {

View file

@ -0,0 +1,4 @@
#use "flywheel:api/fragment.glsl"
void flw_materialFragment() {
}

View file

@ -0,0 +1,4 @@
#use "flywheel:api/vertex.glsl"
void flw_materialVertex() {
}

View file

@ -0,0 +1,16 @@
#use "flywheel:api/vertex.glsl"
#use "flywheel:util/diffuse.glsl"
uniform int uConstantAmbientLight;
void flw_materialVertex() {
flw_vertexNormal = normalize(flw_vertexNormal);
float diffuseFactor;
if (uConstantAmbientLight == 1) {
diffuseFactor = diffuseNether(flw_vertexNormal);
} else {
diffuseFactor = diffuse(flw_vertexNormal);
}
flw_vertexColor = vec4(flw_vertexColor.rgb * diffuseFactor, flw_vertexColor.a);
}