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.StitchedSprite;
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.event.ReloadRenderersEvent;
import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor;
@ -77,6 +78,7 @@ public class Flywheel {
modEventBus.addListener(LayoutShaders::flwInit);
modEventBus.addListener(InstanceShaders::flwInit);
modEventBus.addListener(MaterialShaders::flwInit);
modEventBus.addListener(Contexts::flwInit);
modEventBus.addListener(PartialModel::onModelRegistry);
modEventBus.addListener(PartialModel::onModelBake);

View file

@ -2,7 +2,7 @@ package com.jozufozu.flywheel.api;
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.

View file

@ -4,9 +4,9 @@ import com.jozufozu.flywheel.api.struct.StructType;
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();

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.api;
import com.jozufozu.flywheel.api.struct.StructType;
@Deprecated
public interface MaterialGroup {
/**
* 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.
* @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.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.Instance;
import com.jozufozu.flywheel.api.instance.TickableInstance;
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.LightProvider;
import com.jozufozu.flywheel.light.ListenerStatus;
@ -24,12 +24,12 @@ import net.minecraft.world.level.LightLayer;
*/
public abstract class AbstractInstance implements Instance, LightListener {
protected final MaterialManager materialManager;
public final Level world;
protected final InstancerManager instancerManager;
public final Level level;
public AbstractInstance(MaterialManager materialManager, Level world) {
this.materialManager = materialManager;
this.world = world;
public AbstractInstance(InstancerManager instancerManager, Level level) {
this.instancerManager = instancerManager;
this.level = level;
}
/**
@ -88,11 +88,11 @@ public abstract class AbstractInstance implements Instance, LightListener {
}
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) {
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) {

View file

@ -2,8 +2,8 @@ package com.jozufozu.flywheel.backend.instancing;
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);
}

View file

@ -9,7 +9,7 @@ import java.util.Set;
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.TickableInstance;
import com.jozufozu.flywheel.backend.Backend;
@ -27,7 +27,7 @@ import net.minecraft.core.BlockPos;
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> queuedUpdates;
@ -39,8 +39,8 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
protected DistanceUpdateLimiter frame;
protected DistanceUpdateLimiter tick;
public InstanceManager(MaterialManager materialManager) {
this.materialManager = materialManager;
public InstanceManager(InstancerManager instancerManager) {
this.instancerManager = instancerManager;
this.queuedUpdates = new HashSet<>(64);
this.queuedAdditions = new HashSet<>(64);
this.instances = new HashMap<>();
@ -318,7 +318,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
instances.remove(obj);
dynamicInstances.remove(obj);
tickableInstances.remove(obj);
LightUpdater.get(instance.world)
LightUpdater.get(instance.level)
.removeListener(instance);
}
@ -329,7 +329,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
if (renderer != null) {
renderer.init();
renderer.updateLight();
LightUpdater.get(renderer.world)
LightUpdater.get(renderer.level)
.addListener(renderer);
instances.put(obj, renderer);
@ -356,7 +356,7 @@ public abstract class InstanceManager<T> implements InstancingEngine.OriginShift
public void detachLightListeners() {
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.
* <p>
* The material manager is shared between the different instance managers.
* The instancer manager is shared between the different instance managers.
* </p>
*/
public class InstanceWorld {

View file

@ -6,7 +6,7 @@ import java.util.function.Predicate;
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.BlockEntityInstancingController;
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.
* @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 <T> The type of the block entity.
* @return An instance of the block entity, or {@code null} if the block entity cannot be instanced.
*/
@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));
if (controller == null) {
return null;
}
return controller.createInstance(materialManager, blockEntity);
return controller.createInstance(instancerManager, blockEntity);
}
/**
* 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 <T> The type of the entity.
* @return An instance of the entity, or {@code null} if the entity cannot be instanced.
*/
@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));
if (controller == 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> {
protected BlockEntityType<T> type;
protected BiFunction<MaterialManager, T, BlockEntityInstance<? super T>> instanceFactory;
protected BiFunction<InstancerManager, T, BlockEntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public BlockEntityConfig(BlockEntityType<T> type) {
@ -206,7 +206,7 @@ public class InstancedRenderRegistry {
* @param instanceFactory The instance factory.
* @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;
return this;
}
@ -251,7 +251,7 @@ public class InstancedRenderRegistry {
*/
public static class EntityConfig<T extends Entity> {
protected EntityType<T> type;
protected BiFunction<MaterialManager, T, EntityInstance<? super T>> instanceFactory;
protected BiFunction<InstancerManager, T, EntityInstance<? super T>> instanceFactory;
protected Predicate<T> skipRender;
public EntityConfig(EntityType<T> type) {
@ -263,7 +263,7 @@ public class InstancedRenderRegistry {
* @param instanceFactory The instance factory.
* @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;
return this;
}

View file

@ -17,7 +17,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
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 instanceCount;
@ -27,9 +27,9 @@ public class BatchedMaterialGroup implements MaterialGroup {
@SuppressWarnings("unchecked")
@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) {
return (BatchedMaterial<D>) materials.computeIfAbsent(batched, BatchedMaterial::new);
return (CPUInstancerFactory<D>) materials.computeIfAbsent(batched, CPUInstancerFactory::new);
} else {
throw new ClassCastException("Cannot use type '" + type + "' with CPU instancing.");
}
@ -61,7 +61,7 @@ public class BatchedMaterialGroup implements MaterialGroup {
}
public void clear() {
materials.values().forEach(BatchedMaterial::clear);
materials.values().forEach(CPUInstancerFactory::clear);
}
public void delete() {

View file

@ -21,16 +21,16 @@ import net.minecraft.core.Vec3i;
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();
@SuppressWarnings("unchecked")
@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) {
return (BatchedMaterial<D>) materials.computeIfAbsent(batched, BatchedMaterial::new);
return (CPUInstancerFactory<D>) factories.computeIfAbsent(batched, CPUInstancerFactory::new);
} 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
public void renderAllRemaining(TaskEngine taskEngine, RenderContext context) {
// vertexCount = 0;
// instanceCount = 0;
// 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.Instancer;
import com.jozufozu.flywheel.api.Material;
import com.jozufozu.flywheel.api.InstancerFactory;
import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.core.model.ModelSupplier;
import com.mojang.blaze3d.vertex.PoseStack;
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;
private final Batched<D> type;
public BatchedMaterial(Batched<D> type) {
public CPUInstancerFactory(Batched<D> type) {
this.type = type;
this.models = new HashMap<>();

View file

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

View file

@ -1,6 +1,6 @@
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.instancing.AbstractInstance;
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 BlockEntityInstanceManager(MaterialManager materialManager) {
super(materialManager);
public BlockEntityInstanceManager(InstancerManager instancerManager) {
super(instancerManager);
}
@Override
@ -24,7 +24,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
@Override
protected AbstractInstance createRaw(BlockEntity obj) {
return InstancedRenderRegistry.createInstance(materialManager, obj);
return InstancedRenderRegistry.createInstance(instancerManager, obj);
}
@Override

View file

@ -1,6 +1,6 @@
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;
@ -10,12 +10,12 @@ import net.minecraft.world.level.block.entity.BlockEntity;
*/
public interface BlockEntityInstancingController<T extends BlockEntity> {
/**
* Given a block entity and a material manager, constructs an instance for the block entity.
* @param materialManager The material manager to use.
* Given a block entity and an instancer manager, constructs an instance for the block entity.
* @param instancerManager The instancer manager to use.
* @param blockEntity The block entity to construct an instance for.
* @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.

View file

@ -3,22 +3,22 @@ package com.jozufozu.flywheel.backend.instancing.blockentity;
import java.util.function.BiFunction;
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;
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;
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.skipRender = skipRender;
}
@Override
public BlockEntityInstance<? super T> createInstance(MaterialManager materialManager, T blockEntity) {
return instanceFactory.apply(materialManager, blockEntity);
public BlockEntityInstance<? super T> createInstance(InstancerManager instancerManager, T blockEntity) {
return instanceFactory.apply(instancerManager, blockEntity);
}
@Override

View file

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

View file

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

View file

@ -1,6 +1,6 @@
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;
@ -10,12 +10,12 @@ import net.minecraft.world.entity.Entity;
*/
public interface EntityInstancingController<T extends Entity> {
/**
* Given an entity and a material manager, constructs an instance for the entity.
* @param materialManager The material manager to use.
* Given an entity and an instancer manager, constructs an instance for the entity.
* @param instancerManager The instancer manager to use.
* @param entity The entity to construct an instance for.
* @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.

View file

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

View file

@ -6,10 +6,12 @@ import java.util.List;
import java.util.Map;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.jozufozu.flywheel.api.InstanceData;
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.backend.model.MeshPool;
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.
* @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 Instanced<D> type;
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;
}
@ -56,6 +59,7 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
public void delete() {
models.values().forEach(InstancedModel::delete);
models.clear();
materials.clear();
renderables.clear();
}
@ -71,10 +75,12 @@ public class InstancedMaterial<D extends InstanceData> implements Material<D> {
public void init(MeshPool allocator) {
for (var instanced : uninitialized) {
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();
}

View file

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

View file

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

View file

@ -5,6 +5,8 @@ import java.util.Map;
import org.jetbrains.annotations.NotNull;
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.ModelSupplier;
import com.jozufozu.flywheel.util.Lazy;
@ -13,31 +15,28 @@ import com.jozufozu.flywheel.util.NonNullSupplier;
import net.minecraft.client.renderer.RenderType;
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;
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.renderType = renderType;
this.material = material;
}
public BasicModelSupplier setCutout() {
return setRenderType(RenderType.cutoutMipped());
}
public BasicModelSupplier setRenderType(@NotNull RenderType renderType) {
this.renderType = renderType;
public BasicModelSupplier setMaterial(@NotNull Material material) {
this.material = material;
return this;
}
@Override
public Map<RenderType, Mesh> get() {
return ImmutableMap.of(renderType, supplier.get());
public Map<Material, Mesh> get() {
return ImmutableMap.of(material, supplier.get());
}
public int getVertexCount() {
@ -47,7 +46,7 @@ public class BasicModelSupplier implements ModelSupplier {
@Override
public String toString() {
return "ModelSupplier{" + supplier.map(Mesh::name)
return "BasicModelSupplier{" + supplier.map(Mesh::name)
.orElse("Uninitialized") + '}';
}
}

View file

@ -25,8 +25,8 @@ public class Contexts {
FileResolution crumblingVertex = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
FileResolution crumblingFragment = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
WORLD = ProgramCompiler.create(WorldProgram::new, Templates.INSTANCING, Templates.FRAGMENT, worldVertex, worldFragment);
CRUMBLING = ProgramCompiler.create(CrumblingProgram::new, Templates.INSTANCING, Templates.FRAGMENT, crumblingVertex, crumblingFragment);
WORLD = ProgramCompiler.create(WorldProgram::new, worldVertex, worldFragment);
CRUMBLING = ProgramCompiler.create(CrumblingProgram::new, crumblingVertex, crumblingFragment);
}
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;
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.ShaderType;
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.source.FileIndexImpl;
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> {
private final Template<? extends FragmentData> template;
private final FileResolution contextShader;
public FragmentCompiler(Template<? extends FragmentData> template, FileResolution contextShader) {
this.template = template;
public FragmentCompiler(FileResolution contextShader) {
this.contextShader = contextShader;
}
@ -23,21 +29,77 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
protected GlShader _create(Context key) {
StringBuilder finalSource = new StringBuilder();
finalSource.append(CompileUtil.generateHeader(template.getVersion(), ShaderType.FRAGMENT));
finalSource.append(CompileUtil.generateHeader(GLSLVersion.V150, ShaderType.FRAGMENT));
key.getShaderConstants().writeInto(finalSource);
finalSource.append('\n');
FileIndexImpl index = new FileIndexImpl();
contextShader.getFile().generateFinalSource(index, finalSource);
//
FragmentData appliedTemplate = template.apply(contextShader.getFile());
finalSource.append(appliedTemplate.generateFooter());
SourceFile materialShader = key.materialShader;
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());
}
protected String generateFooter() {
StringBuilder footer = new StringBuilder();
footer.append("""
void main() {
flw_materialFragment();
flw_contextFragment();
}
"""
);
return footer.toString();
}
@Override
protected void _destroy(GlShader value) {
value.delete();
@ -48,9 +110,9 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
*/
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.
@ -62,7 +124,13 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
*/
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.fogType = fogType;
this.ctx = ctx;
@ -84,18 +152,17 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
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
public int hashCode() {
return Objects.hash(alphaDiscard, fogType, ctx);
return Objects.hash(materialShader, alphaDiscard, fogType, ctx);
}
@Override
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.
* @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 fragmentContextShader The context shader to use when compiling fragment shaders.
* @param <P> The type of program to compile.
* @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) {
return new ProgramCompiler<>(factory, new VertexCompiler(vertexTemplate, vertexContextShader), new FragmentCompiler(fragmentTemplate, fragmentContextShader));
public static <P extends GlProgram> ProgramCompiler<P> create(GlProgram.Factory<P> factory, FileResolution vertexContextShader, FileResolution 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
protected P _create(ProgramContext ctx) {
return new ProgramAssembler(ctx.instanceShader.getFileLoc())
.attachShader(vertexCompiler.get(new VertexCompiler.Context(ctx.vertexType, ctx.instanceShader.getFile(), ctx.ctx)))
.attachShader(fragmentCompiler.get(new FragmentCompiler.Context(ctx.alphaDiscard, ctx.fogType, 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.fragmentMaterialShader.getFile(), ctx.alphaDiscard, ctx.fogType, ctx.ctx)))
.link()
.build(this.factory);
}

View file

@ -14,20 +14,26 @@ public final class ProgramContext {
public final VertexType vertexType;
public final FileResolution instanceShader;
public final FileResolution vertexMaterialShader;
public final FileResolution fragmentMaterialShader;
public final float alphaDiscard;
public final FogType fogType;
public final StateSnapshot ctx;
/**
* @param vertexType The vertexType the program should be adapted for.
* @param spec The program to use.
* @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.
* @param vertexType The vertexType the program should be adapted for.
* @param instanceShader The instance shader to use.
* @param vertexMaterialShader The vertex material shader to use.
* @param fragmentMaterialShader The fragment material shader to use.
* @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.instanceShader = instanceShader;
this.vertexMaterialShader = vertexMaterialShader;
this.fragmentMaterialShader = fragmentMaterialShader;
this.alphaDiscard = alphaDiscard;
this.fogType = fogType;
this.ctx = ctx;
@ -38,16 +44,16 @@ public final class ProgramContext {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
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
public int hashCode() {
return Objects.hash(vertexType, instanceShader, alphaDiscard, fogType, ctx);
return Objects.hash(vertexType, instanceShader, vertexMaterialShader, fragmentMaterialShader, alphaDiscard, fogType, ctx);
}
@Override
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;
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.backend.gl.GLSLVersion;
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
import com.jozufozu.flywheel.core.shader.StateSnapshot;
import com.jozufozu.flywheel.core.source.FileIndexImpl;
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.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> {
private final Template<? extends VertexData> template;
private final FileResolution contextShader;
public VertexCompiler(Template<? extends VertexData> template, FileResolution contextShader) {
this.template = template;
public VertexCompiler(FileResolution contextShader) {
this.contextShader = contextShader;
}
@ -23,24 +31,171 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
protected GlShader _create(Context key) {
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);
finalSource.append('\n');
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);
finalSource.append(appliedTemplate.generateFooter(index, key.vertexType));
if (maybeLayoutVertex.isEmpty()) {
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
@ -59,14 +214,20 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
*/
private final SourceFile instanceShader;
/**
* The vertex material shader source.
*/
private final SourceFile materialShader;
/**
* The shader constants to apply.
*/
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.instanceShader = instanceShader;
this.materialShader = materialShader;
this.ctx = ctx;
}
@ -75,12 +236,12 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
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
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;
import com.jozufozu.flywheel.api.MaterialManager;
import com.jozufozu.flywheel.api.InstancerManager;
import com.jozufozu.flywheel.api.instance.DynamicInstance;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
public class CrumblingInstanceManager extends BlockEntityInstanceManager {
public CrumblingInstanceManager(MaterialManager materialManager) {
super(materialManager);
public CrumblingInstanceManager(InstancerManager instancerManager) {
super(instancerManager);
}
@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.instancing.InstanceManager;
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.core.Contexts;
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo;
@ -65,7 +65,7 @@ public class CrumblingRenderer {
State state = STATE.get();
var instanceManager = state.instanceManager;
var engine = state.materialManager;
var engine = state.instancerManager;
TextureManager textureManager = Minecraft.getInstance().getTextureManager();
Camera info = Minecraft.getInstance().gameRenderer.getMainCamera();
@ -140,17 +140,17 @@ public class CrumblingRenderer {
}
private static class State {
private final CrumblingEngine materialManager;
private final CrumblingEngine instancerManager;
private final InstanceManager<BlockEntity> instanceManager;
private State() {
materialManager = new CrumblingEngine();
instanceManager = new CrumblingInstanceManager(materialManager);
materialManager.addListener(instanceManager);
instancerManager = new CrumblingEngine();
instanceManager = new CrumblingInstanceManager(instancerManager);
instancerManager.addListener(instanceManager);
}
private void kill() {
materialManager.delete();
instancerManager.delete();
instanceManager.invalidate();
}
}
@ -190,10 +190,10 @@ public class CrumblingRenderer {
Textures.bindActiveTextures();
CoreShaderInfo coreShaderInfo = getCoreShaderInfo();
for (Map.Entry<Instanced<? extends InstanceData>, InstancedMaterial<?>> entry : materials.entrySet()) {
CrumblingProgram program = setup(entry.getKey(), coreShaderInfo, camX, camY, camZ, viewProjection, level);
for (Map.Entry<Instanced<? extends InstanceData>, GPUInstancerFactory<?>> entry : factories.entrySet()) {
//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);
}

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 net.minecraft.client.renderer.RenderType;
import com.jozufozu.flywheel.api.material.Material;
public interface ModelSupplier {
Map<RenderType, Mesh> get();
Map<Material, Mesh> get();
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.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;

View file

@ -1,4 +1,4 @@
package com.jozufozu.flywheel.core.materials;
package com.jozufozu.flywheel.core.structs;
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.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.mojang.blaze3d.vertex.PoseStack;
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.Instanced;
@ -6,9 +6,9 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout;
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.source.FileResolution;
import com.jozufozu.flywheel.core.structs.InstanceShaders;
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.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.materials.BasicWriterUnsafe;
import com.jozufozu.flywheel.core.structs.BasicWriterUnsafe;
import com.jozufozu.flywheel.util.MatrixWrite;
public class ModelWriterUnsafe extends BasicWriterUnsafe<ModelData> {

View file

@ -1,5 +1,5 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.materials.model;
package com.jozufozu.flywheel.core.structs.model;
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.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.Instanced;
@ -6,9 +6,9 @@ import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout;
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.source.FileResolution;
import com.jozufozu.flywheel.core.structs.InstanceShaders;
import com.mojang.math.Quaternion;
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 com.jozufozu.flywheel.api.struct.StructType;
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 OrientedWriterUnsafe(VecBuffer backingBuffer, StructType<OrientedData> vertexType) {

View file

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

View file

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

View file

@ -2,13 +2,15 @@ package com.jozufozu.flywheel.vanilla;
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.material.Material;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.oriented.OrientedData;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.mojang.math.Quaternion;
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 {
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 float lastRingTime = Float.NaN;
public BellInstance(MaterialManager materialManager, BellBlockEntity blockEntity) {
super(materialManager, blockEntity);
public BellInstance(InstancerManager instancerManager, BellBlockEntity blockEntity) {
super(instancerManager, blockEntity);
bell = createBellInstance()
.setPivot(0.5f, 0.75f, 0.5f)
@ -63,7 +65,7 @@ public class BellInstance extends BlockEntityInstance<BellBlockEntity> implement
}
private OrientedData createBellInstance() {
return materialManager.material(Materials.ORIENTED)
return instancerManager.factory(StructTypes.ORIENTED)
.model(MODEL)
.createInstance();
}

View file

@ -5,14 +5,15 @@ import java.util.function.BiFunction;
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.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.materials.oriented.OrientedData;
import com.jozufozu.flywheel.core.material.MaterialShaders;
import com.jozufozu.flywheel.core.structs.StructTypes;
import com.jozufozu.flywheel.core.structs.model.ModelData;
import com.jozufozu.flywheel.core.structs.oriented.OrientedData;
import com.jozufozu.flywheel.util.AnimationTickHolder;
import com.mojang.math.Quaternion;
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 {
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> BASE = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createBaseModel(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()), new com.jozufozu.flywheel.api.material.Material(Sheets.chestSheet(), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT)));
private final OrientedData body;
private final ModelData lid;
@ -47,8 +48,8 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
private float lastProgress = Float.NaN;
public ChestInstance(MaterialManager materialManager, T blockEntity) {
super(materialManager, blockEntity);
public ChestInstance(InstancerManager instancerManager, T blockEntity) {
super(instancerManager, blockEntity);
Block block = blockState.getBlock();
@ -67,7 +68,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
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));
@ -115,14 +116,14 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
private OrientedData baseInstance() {
return materialManager.material(Materials.ORIENTED)
return instancerManager.factory(StructTypes.ORIENTED)
.model(BASE.apply(chestType, renderMaterial))
.createInstance();
}
private ModelData lidInstance() {
return materialManager.material(Materials.TRANSFORMED)
return instancerManager.factory(StructTypes.MODEL)
.model(LID.apply(chestType, renderMaterial))
.createInstance();
}

View file

@ -2,16 +2,18 @@ package com.jozufozu.flywheel.vanilla;
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.TickableInstance;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.Models;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.material.MaterialShaders;
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.transform.TransformStack;
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 {
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();
@ -37,8 +39,8 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
private ModelData contents;
private BlockState blockstate;
public MinecartInstance(MaterialManager materialManager, T entity) {
super(materialManager, entity);
public MinecartInstance(InstancerManager instancerManager, T entity) {
super(instancerManager, entity);
blockstate = entity.getDisplayBlockState();
contents = getContents();
@ -63,7 +65,7 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
stack.setIdentity();
float pt = AnimationTickHolder.getPartialTicks();
Vec3i originCoordinate = materialManager.getOriginCoordinate();
Vec3i originCoordinate = instancerManager.getOriginCoordinate();
tstack.translate(
Mth.lerp(pt, entity.xOld, entity.getX()) - originCoordinate.getX(),
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)
return null;
return materialManager.material(Materials.TRANSFORMED)
return instancerManager.factory(StructTypes.MODEL)
.model(Models.block(blockstate))
.createInstance();
}
private ModelData getBody() {
return materialManager.material(Materials.TRANSFORMED)
return instancerManager.factory(StructTypes.MODEL)
.model(MODEL)
.createInstance();
}

View file

@ -2,13 +2,15 @@ package com.jozufozu.flywheel.vanilla;
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.material.Material;
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
import com.jozufozu.flywheel.core.BasicModelSupplier;
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
import com.jozufozu.flywheel.core.materials.Materials;
import com.jozufozu.flywheel.core.materials.model.ModelData;
import com.jozufozu.flywheel.core.material.MaterialShaders;
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.transform.TransformStack;
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 {
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> LID = Util.memoize(it -> new BasicModelSupplier(() -> makeLidModel(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), new Material(RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET), () -> MaterialShaders.SHADED_VERTEX, () -> MaterialShaders.DEFAULT_FRAGMENT)));
private final TextureAtlasSprite texture;
@ -37,8 +39,8 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
private float lastProgress = Float.NaN;
public ShulkerBoxInstance(MaterialManager materialManager, ShulkerBoxBlockEntity blockEntity) {
super(materialManager, blockEntity);
public ShulkerBoxInstance(InstancerManager instancerManager, ShulkerBoxBlockEntity blockEntity) {
super(instancerManager, blockEntity);
DyeColor color = blockEntity.getColor();
if (color == null) {
@ -97,13 +99,13 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
}
private ModelData makeBaseInstance() {
return materialManager.material(Materials.TRANSFORMED)
return instancerManager.factory(StructTypes.MODEL)
.model(BASE.apply(texture))
.createInstance();
}
private ModelData makeLidInstance() {
return materialManager.material(Materials.TRANSFORMED)
return instancerManager.factory(StructTypes.MODEL)
.model(LID.apply(texture))
.createInstance();
}

View file

@ -1,21 +1,11 @@
#use "flywheel:api/vertex.glsl"
#use "flywheel:util/diffuse.glsl"
#use "flywheel:util/fog.glsl"
uniform mat4 uViewProjection;
uniform vec3 uCameraPos;
uniform int uConstantAmbientLight;
uniform int uFogShape;
out float _flw_diffuse;
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);
gl_Position = uViewProjection * flw_vertexPos;

View file

@ -8,15 +8,13 @@ uniform vec2 uTextureScale;
uniform sampler2D uBlockAtlas;
uniform sampler2D uCrumbling;
in float _flw_diffuse;
out vec4 fragColor;
void flw_contextFragment() {
vec4 texColor = texture(uBlockAtlas, flw_vertexTexCoord);
vec4 crumblingColor = texture(uCrumbling, flw_vertexTexCoord * uTextureScale);
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
if (color.a < ALPHA_DISCARD) {

View file

@ -14,14 +14,12 @@ uniform vec4 uFogColor;
uniform sampler2D uBlockAtlas;
uniform sampler2D uLightMap;
in float _flw_diffuse;
out vec4 fragColor;
void flw_contextFragment() {
vec4 texColor = texture(uBlockAtlas, flw_vertexTexCoord);
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
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);
}