mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-04 17:24:59 +01:00
Uniformly incomplete
- Initial work on uniform buffer registry - Setup skeleton for ComponentRegistry - InstancingEngine is no longer generic about the program - ProgramCompiler considers ContextShaders as input - Support weak file resolutions - Temporary GLSL version bump to ease UniformProvider growing pains - Centralize component shaders to Components
This commit is contained in:
parent
5e517a1bfe
commit
55de2beabb
57 changed files with 1004 additions and 658 deletions
|
@ -11,24 +11,15 @@ import com.jozufozu.flywheel.backend.model.MeshPool;
|
|||
import com.jozufozu.flywheel.config.BackendTypeArgument;
|
||||
import com.jozufozu.flywheel.config.FlwCommands;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.core.GameStateRegistry;
|
||||
import com.jozufozu.flywheel.core.Models;
|
||||
import com.jozufozu.flywheel.core.PartialModel;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
import com.jozufozu.flywheel.core.StitchedSprite;
|
||||
import com.jozufozu.flywheel.core.*;
|
||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||
import com.jozufozu.flywheel.core.material.MaterialShaders;
|
||||
import com.jozufozu.flywheel.core.shader.NormalDebugStateProvider;
|
||||
import com.jozufozu.flywheel.core.structs.InstanceShaders;
|
||||
import com.jozufozu.flywheel.core.vertex.LayoutShaders;
|
||||
import com.jozufozu.flywheel.event.EntityWorldHandler;
|
||||
import com.jozufozu.flywheel.event.ForgeEvents;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor;
|
||||
import com.jozufozu.flywheel.vanilla.VanillaInstances;
|
||||
import com.jozufozu.flywheel.vanilla.effect.ExampleEffect;
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import net.minecraft.commands.synchronization.ArgumentTypes;
|
||||
|
@ -112,10 +103,7 @@ public class Flywheel {
|
|||
// forgeEventBus.addListener(ExampleEffect::tick);
|
||||
// forgeEventBus.addListener(ExampleEffect::onReload);
|
||||
|
||||
LayoutShaders.init();
|
||||
InstanceShaders.init();
|
||||
Contexts.init();
|
||||
MaterialShaders.init();
|
||||
Components.init();
|
||||
|
||||
GameStateRegistry.register(NormalDebugStateProvider.INSTANCE);
|
||||
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
package com.jozufozu.flywheel.api.material;
|
||||
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
public record Material(RenderType renderType, FileResolution vertexShader, FileResolution fragmentShader) {
|
||||
|
||||
public SourceFile getVertexShader() {
|
||||
return vertexShader.getFile();
|
||||
}
|
||||
|
||||
public SourceFile getFragmentShader() {
|
||||
return fragmentShader.getFile();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package com.jozufozu.flywheel.api.uniform;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
|
||||
public abstract class UniformProvider {
|
||||
|
||||
protected ByteBuffer buffer;
|
||||
protected Notifier notifier;
|
||||
|
||||
public abstract int getSize();
|
||||
|
||||
public void updatePtr(ByteBuffer backing, Notifier notifier) {
|
||||
this.buffer = backing;
|
||||
this.notifier = notifier;
|
||||
}
|
||||
|
||||
public abstract FileResolution getUniformShader();
|
||||
|
||||
public interface Notifier {
|
||||
void signalChanged();
|
||||
}
|
||||
}
|
|
@ -47,6 +47,10 @@ public class Loader implements ResourceManagerReloadListener {
|
|||
throw new ShaderLoadingException("Failed to resolve all source files, see log for details");
|
||||
}
|
||||
|
||||
sources.postResolve();
|
||||
|
||||
FileResolution.checkAll(errorReporter);
|
||||
|
||||
Backend.LOGGER.info("Loaded all shader sources.");
|
||||
|
||||
ClientLevel world = Minecraft.getInstance().level;
|
||||
|
|
|
@ -88,9 +88,9 @@ public abstract class GlProgram extends GlObject {
|
|||
/**
|
||||
* A factory interface to create a {@link GlProgram}.
|
||||
*/
|
||||
public interface Factory<P extends GlProgram> {
|
||||
public interface Factory {
|
||||
|
||||
@NotNull
|
||||
P create(ResourceLocation name, int handle);
|
||||
GlProgram create(ResourceLocation name, int handle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,10 @@ import com.jozufozu.flywheel.backend.instancing.effect.Effect;
|
|||
import com.jozufozu.flywheel.backend.instancing.effect.EffectInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
|
||||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||
import com.jozufozu.flywheel.util.ClientLevelExtension;
|
||||
import com.jozufozu.flywheel.vanilla.effect.ExampleEffect;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -39,7 +38,7 @@ public class InstanceWorld {
|
|||
|
||||
public static InstanceWorld create(LevelAccessor level) {
|
||||
var engine = switch (Backend.getBackendType()) {
|
||||
case INSTANCING -> new InstancingEngine<>(Contexts.WORLD);
|
||||
case INSTANCING -> new InstancingEngine(Components.WORLD);
|
||||
case BATCHING -> new BatchingEngine();
|
||||
case OFF -> throw new IllegalStateException("Cannot create instance world when backend is off.");
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.jozufozu.flywheel.vanilla.effect.ExampleEffect;
|
|||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
@ -131,4 +132,8 @@ public class InstancedRenderDispatcher {
|
|||
debug.add("Disabled");
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec3i getOriginCoordinate(ClientLevel level) {
|
||||
return instanceWorlds.get(level).engine.getOriginCoordinate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
package com.jozufozu.flywheel.backend.instancing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.jozufozu.flywheel.api.InstancedPart;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.GPUInstancer;
|
||||
import com.jozufozu.flywheel.core.model.ModelSupplier;
|
||||
import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.server.level.BlockDestructionProgress;
|
||||
|
||||
public class SadCrumbling {
|
||||
// public void renderCrumbling(LevelRenderer levelRenderer, ClientLevel level, PoseStack stack, Camera camera, Matrix4f projectionMatrix) {
|
||||
// var dataByStage = getDataByStage(levelRenderer, level);
|
||||
// if (dataByStage.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var map = modelsToParts(dataByStage);
|
||||
// var stateSnapshot = GameStateRegistry.takeSnapshot();
|
||||
//
|
||||
//// Vec3 cameraPosition = camera.getPosition();
|
||||
//// var camX = cameraPosition.x - originCoordinate.getX();
|
||||
//// var camY = cameraPosition.y - originCoordinate.getY();
|
||||
//// var camZ = cameraPosition.z - originCoordinate.getZ();
|
||||
////
|
||||
//// // don't want to mutate viewProjection
|
||||
//// var vp = projectionMatrix.copy();
|
||||
//// vp.multiplyWithTranslation((float) -camX, (float) -camY, (float) -camZ);
|
||||
//
|
||||
// GlBuffer instanceBuffer = GlBuffer.requestPersistent(GlBufferType.ARRAY_BUFFER);
|
||||
//
|
||||
// GlVertexArray crumblingVAO = new GlVertexArray();
|
||||
//
|
||||
// crumblingVAO.bind();
|
||||
//
|
||||
// // crumblingVAO.bindAttributes();
|
||||
//
|
||||
// for (var entry : map.entrySet()) {
|
||||
// var model = entry.getKey();
|
||||
// var parts = entry.getValue();
|
||||
//
|
||||
// if (parts.isEmpty()) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// StructType<?> structType = parts.get(0).type;
|
||||
//
|
||||
// for (var meshEntry : model.get()
|
||||
// .entrySet()) {
|
||||
// Material material = meshEntry.getKey();
|
||||
// Mesh mesh = meshEntry.getValue();
|
||||
//
|
||||
// MeshPool.BufferedMesh bufferedMesh = MeshPool.getInstance()
|
||||
// .get(mesh);
|
||||
//
|
||||
// if (bufferedMesh == null || !bufferedMesh.isGpuResident()) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// material.renderType().setupRenderState();
|
||||
//
|
||||
// CoreShaderInfoMap.CoreShaderInfo coreShaderInfo = CoreShaderInfoMap.CoreShaderInfo.get();
|
||||
//
|
||||
//
|
||||
// var program = Compile.PROGRAM.getProgram(new ProgramCompiler.Context(Formats.POS_TEX_NORMAL,
|
||||
// material, structType.getInstanceShader(), Components.CRUMBLING,
|
||||
// coreShaderInfo.getAdjustedAlphaDiscard(), coreShaderInfo.fogType(),
|
||||
// GameStateRegistry.takeSnapshot()));
|
||||
//
|
||||
// program.bind();
|
||||
//
|
||||
// // bufferedMesh.drawInstances();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@NotNull
|
||||
private Map<ModelSupplier, List<InstancedPart>> modelsToParts(Int2ObjectMap<List<BlockEntityInstance<?>>> dataByStage) {
|
||||
var map = new HashMap<ModelSupplier, List<InstancedPart>>();
|
||||
|
||||
for (var entry : dataByStage.int2ObjectEntrySet()) {
|
||||
RenderType currentLayer = ModelBakery.DESTROY_TYPES.get(entry.getIntKey());
|
||||
|
||||
// something about when we call this means that the textures are not ready for use on the first frame they should appear
|
||||
if (currentLayer == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var blockEntityInstance : entry.getValue()) {
|
||||
|
||||
for (var part : blockEntityInstance.getCrumblingParts()) {
|
||||
if (part.getOwner() instanceof GPUInstancer instancer) {
|
||||
|
||||
// queue the instances for copying to the crumbling instance buffer
|
||||
map.computeIfAbsent(instancer.parent.getModel(), k -> new ArrayList<>()).add(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Int2ObjectMap<List<BlockEntityInstance<?>>> getDataByStage(LevelRenderer levelRenderer, ClientLevel level) {
|
||||
var destructionProgress = ((LevelRendererAccessor) levelRenderer).flywheel$getDestructionProgress();
|
||||
if (destructionProgress.isEmpty()) {
|
||||
return Int2ObjectMaps.emptyMap();
|
||||
}
|
||||
|
||||
if (!(InstancedRenderDispatcher.getInstanceWorld(level)
|
||||
.getBlockEntities() instanceof BlockEntityInstanceManager beim)) {
|
||||
return Int2ObjectMaps.emptyMap();
|
||||
}
|
||||
|
||||
var dataByStage = new Int2ObjectArrayMap<List<BlockEntityInstance<?>>>();
|
||||
|
||||
for (var entry : destructionProgress.long2ObjectEntrySet()) {
|
||||
SortedSet<BlockDestructionProgress> progresses = entry.getValue();
|
||||
|
||||
if (progresses == null || progresses.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int progress = progresses.last()
|
||||
.getProgress();
|
||||
|
||||
var data = dataByStage.computeIfAbsent(progress, $ -> new ArrayList<>());
|
||||
|
||||
long pos = entry.getLongKey();
|
||||
|
||||
beim.getCrumblingInstances(pos, data);
|
||||
}
|
||||
|
||||
return dataByStage;
|
||||
}
|
||||
}
|
|
@ -4,67 +4,43 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.jozufozu.flywheel.api.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.Engine;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.model.MeshPool;
|
||||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo;
|
||||
import com.jozufozu.flywheel.core.GameStateRegistry;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.core.compile.ContextShader;
|
||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
||||
import com.jozufozu.flywheel.core.model.Mesh;
|
||||
import com.jozufozu.flywheel.core.model.ModelSupplier;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||
import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
|
||||
import com.jozufozu.flywheel.core.uniform.UniformBuffer;
|
||||
import com.jozufozu.flywheel.util.Textures;
|
||||
import com.jozufozu.flywheel.util.WeakHashSet;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.server.level.BlockDestructionProgress;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||
public class InstancingEngine implements Engine {
|
||||
|
||||
public static int MAX_ORIGIN_DISTANCE = 100;
|
||||
|
||||
protected BlockPos originCoordinate = BlockPos.ZERO;
|
||||
|
||||
protected final ProgramCompiler<P> context;
|
||||
protected final ContextShader context;
|
||||
|
||||
protected final Map<StructType<?>, GPUInstancerFactory<?>> factories = new HashMap<>();
|
||||
|
||||
|
@ -78,7 +54,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
private int vertexCount;
|
||||
private int instanceCount;
|
||||
|
||||
public InstancingEngine(ProgramCompiler<P> context) {
|
||||
public InstancingEngine(ContextShader context) {
|
||||
this.context = context;
|
||||
|
||||
this.instanceManagers = new WeakHashSet<>();
|
||||
|
@ -98,16 +74,8 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
|
||||
@Override
|
||||
public void renderAllRemaining(TaskEngine taskEngine, RenderContext context) {
|
||||
var camX = context.camX() - originCoordinate.getX();
|
||||
var camY = context.camY() - originCoordinate.getY();
|
||||
var camZ = context.camZ() - originCoordinate.getZ();
|
||||
|
||||
// don't want to mutate viewProjection
|
||||
var vp = context.viewProjection().copy();
|
||||
vp.multiplyWithTranslation((float) -camX, (float) -camY, (float) -camZ);
|
||||
|
||||
for (RenderType renderType : renderLists.drainLayers()) {
|
||||
render(renderType, camX, camY, camZ, vp, context.level());
|
||||
render(renderType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,18 +85,10 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
return;
|
||||
}
|
||||
|
||||
var camX = context.camX() - originCoordinate.getX();
|
||||
var camY = context.camY() - originCoordinate.getY();
|
||||
var camZ = context.camZ() - originCoordinate.getZ();
|
||||
|
||||
// don't want to mutate viewProjection
|
||||
var vp = context.viewProjection().copy();
|
||||
vp.multiplyWithTranslation((float) -camX, (float) -camY, (float) -camZ);
|
||||
|
||||
render(type, camX, camY, camZ, vp, context.level());
|
||||
render(type);
|
||||
}
|
||||
|
||||
protected void render(RenderType type, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
protected void render(RenderType type) {
|
||||
vertexCount = 0;
|
||||
instanceCount = 0;
|
||||
|
||||
|
@ -138,16 +98,16 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
return;
|
||||
}
|
||||
|
||||
render(type, multimap, camX, camY, camZ, viewProjection, level);
|
||||
render(type, multimap);
|
||||
}
|
||||
|
||||
protected void render(RenderType type, ListMultimap<ShaderState, DrawCall> multimap, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
protected void render(RenderType type, ListMultimap<ShaderState, DrawCall> multimap) {
|
||||
type.setupRenderState();
|
||||
Textures.bindActiveTextures();
|
||||
CoreShaderInfo coreShaderInfo = CoreShaderInfo.get();
|
||||
StateSnapshot state = GameStateRegistry.takeSnapshot();
|
||||
|
||||
for (var entry : Multimaps.asMap(multimap).entrySet()) {
|
||||
for (var entry : multimap.asMap().entrySet()) {
|
||||
var shader = entry.getKey();
|
||||
var drawCalls = entry.getValue();
|
||||
|
||||
|
@ -157,7 +117,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
continue;
|
||||
}
|
||||
|
||||
setup(shader, coreShaderInfo, camX, camY, camZ, viewProjection, level, state);
|
||||
setup(shader, coreShaderInfo, state);
|
||||
|
||||
for (var drawCall : drawCalls) {
|
||||
drawCall.render();
|
||||
|
@ -168,21 +128,18 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
type.clearRenderState();
|
||||
}
|
||||
|
||||
protected P setup(ShaderState desc, CoreShaderInfo coreShaderInfo, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level, StateSnapshot ctx) {
|
||||
protected void setup(ShaderState desc, CoreShaderInfo coreShaderInfo, StateSnapshot ctx) {
|
||||
|
||||
VertexType vertexType = desc.vertex();
|
||||
FileResolution instanceShader = desc.instance()
|
||||
.getInstanceShader();
|
||||
Material material = desc.material();
|
||||
|
||||
P program = context.getProgram(new ProgramCompiler.Context(vertexType, instanceShader,
|
||||
material.vertexShader(), material.fragmentShader(), coreShaderInfo.getAdjustedAlphaDiscard(),
|
||||
coreShaderInfo.fogType(), ctx));
|
||||
var program = ProgramCompiler.INSTANCE.getProgram(new ProgramCompiler.Context(vertexType, material,
|
||||
instanceShader, context, coreShaderInfo.getAdjustedAlphaDiscard(), coreShaderInfo.fogType(), ctx));
|
||||
|
||||
program.bind();
|
||||
program.uploadUniforms(camX, camY, camZ, viewProjection, level);
|
||||
|
||||
return program;
|
||||
UniformBuffer.getInstance().sync();
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
|
@ -250,131 +207,4 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
|||
info.add("Vertices: " + vertexCount);
|
||||
info.add("Origin: " + originCoordinate.getX() + ", " + originCoordinate.getY() + ", " + originCoordinate.getZ());
|
||||
}
|
||||
|
||||
public void renderCrumbling(LevelRenderer levelRenderer, ClientLevel level, PoseStack stack, Camera camera, Matrix4f projectionMatrix) {
|
||||
var dataByStage = getDataByStage(levelRenderer, level);
|
||||
if (dataByStage.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var map = modelsToParts(dataByStage);
|
||||
var stateSnapshot = GameStateRegistry.takeSnapshot();
|
||||
|
||||
Vec3 cameraPosition = camera.getPosition();
|
||||
var camX = cameraPosition.x - originCoordinate.getX();
|
||||
var camY = cameraPosition.y - originCoordinate.getY();
|
||||
var camZ = cameraPosition.z - originCoordinate.getZ();
|
||||
|
||||
// don't want to mutate viewProjection
|
||||
var vp = projectionMatrix.copy();
|
||||
vp.multiplyWithTranslation((float) -camX, (float) -camY, (float) -camZ);
|
||||
|
||||
GlBuffer instanceBuffer = GlBuffer.requestPersistent(GlBufferType.ARRAY_BUFFER);
|
||||
|
||||
GlVertexArray crumblingVAO = new GlVertexArray();
|
||||
|
||||
crumblingVAO.bind();
|
||||
|
||||
// crumblingVAO.bindAttributes();
|
||||
|
||||
for (var entry : map.entrySet()) {
|
||||
var model = entry.getKey();
|
||||
var parts = entry.getValue();
|
||||
|
||||
if (parts.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StructType<?> structType = parts.get(0).type;
|
||||
|
||||
for (var meshEntry : model.get()
|
||||
.entrySet()) {
|
||||
Material material = meshEntry.getKey();
|
||||
Mesh mesh = meshEntry.getValue();
|
||||
|
||||
MeshPool.BufferedMesh bufferedMesh = MeshPool.getInstance()
|
||||
.get(mesh);
|
||||
|
||||
if (bufferedMesh == null || !bufferedMesh.isGpuResident()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
material.renderType().setupRenderState();
|
||||
|
||||
CoreShaderInfo coreShaderInfo = CoreShaderInfo.get();
|
||||
|
||||
|
||||
CrumblingProgram program = Contexts.CRUMBLING.getProgram(new ProgramCompiler.Context(Formats.POS_TEX_NORMAL,
|
||||
structType.getInstanceShader(), material.vertexShader(), material.fragmentShader(),
|
||||
coreShaderInfo.getAdjustedAlphaDiscard(), coreShaderInfo.fogType(),
|
||||
GameStateRegistry.takeSnapshot()));
|
||||
|
||||
program.bind();
|
||||
program.uploadUniforms(camX, camY, camZ, vp, level);
|
||||
|
||||
// bufferedMesh.drawInstances();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<ModelSupplier, List<InstancedPart>> modelsToParts(Int2ObjectMap<List<BlockEntityInstance<?>>> dataByStage) {
|
||||
var map = new HashMap<ModelSupplier, List<InstancedPart>>();
|
||||
|
||||
for (var entry : dataByStage.int2ObjectEntrySet()) {
|
||||
RenderType currentLayer = ModelBakery.DESTROY_TYPES.get(entry.getIntKey());
|
||||
|
||||
// something about when we call this means that the textures are not ready for use on the first frame they should appear
|
||||
if (currentLayer == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var blockEntityInstance : entry.getValue()) {
|
||||
|
||||
for (var part : blockEntityInstance.getCrumblingParts()) {
|
||||
if (part.getOwner() instanceof GPUInstancer instancer) {
|
||||
|
||||
// queue the instances for copying to the crumbling instance buffer
|
||||
map.computeIfAbsent(instancer.parent.getModel(), k -> new ArrayList<>()).add(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Int2ObjectMap<List<BlockEntityInstance<?>>> getDataByStage(LevelRenderer levelRenderer, ClientLevel level) {
|
||||
var destructionProgress = ((LevelRendererAccessor) levelRenderer).flywheel$getDestructionProgress();
|
||||
if (destructionProgress.isEmpty()) {
|
||||
return Int2ObjectMaps.emptyMap();
|
||||
}
|
||||
|
||||
if (!(InstancedRenderDispatcher.getInstanceWorld(level)
|
||||
.getBlockEntities() instanceof BlockEntityInstanceManager beim)) {
|
||||
return Int2ObjectMaps.emptyMap();
|
||||
}
|
||||
|
||||
var dataByStage = new Int2ObjectArrayMap<List<BlockEntityInstance<?>>>();
|
||||
|
||||
for (var entry : destructionProgress.long2ObjectEntrySet()) {
|
||||
SortedSet<BlockDestructionProgress> progresses = entry.getValue();
|
||||
|
||||
if (progresses == null || progresses.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int progress = progresses.last()
|
||||
.getProgress();
|
||||
|
||||
var data = dataByStage.computeIfAbsent(progress, $ -> new ArrayList<>());
|
||||
|
||||
long pos = entry.getLongKey();
|
||||
|
||||
beim.getCrumblingInstances(pos, data);
|
||||
}
|
||||
|
||||
return dataByStage;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,22 +6,18 @@ 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;
|
||||
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 Material material;
|
||||
private final Lazy<Mesh> supplier;
|
||||
|
||||
public BasicModelSupplier(NonNullSupplier<Mesh> supplier) {
|
||||
this(supplier, DEFAULT_MATERIAL);
|
||||
this(supplier, Materials.DEFAULT);
|
||||
}
|
||||
|
||||
public BasicModelSupplier(NonNullSupplier<Mesh> supplier, Material material) {
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.compile.ContextShader;
|
||||
import com.jozufozu.flywheel.core.vertex.BlockVertex;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class ComponentRegistry {
|
||||
|
||||
private static final Set<ResourceLocation> uniformProviderFiles = new HashSet<>();
|
||||
private static final List<UniformProvider> uniformProviders = new ArrayList<>();
|
||||
|
||||
// TODO: fill out the rest of the registry
|
||||
|
||||
public static Material register(Material material) {
|
||||
return material;
|
||||
}
|
||||
|
||||
public static <T extends StructType<?>> T register(T type) {
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public static <T extends VertexType> T register(T vertexType) {
|
||||
return vertexType;
|
||||
}
|
||||
|
||||
public static ContextShader register(ContextShader contextShader) {
|
||||
return contextShader;
|
||||
}
|
||||
|
||||
public static <T extends UniformProvider> T register(T provider) {
|
||||
|
||||
var file = provider.getUniformShader();
|
||||
|
||||
ResourceLocation location = file.getFileLoc();
|
||||
if (uniformProviderFiles.contains(location)) {
|
||||
throw new IllegalArgumentException("UniformProvider for '" + location + "' already registered");
|
||||
}
|
||||
|
||||
uniformProviderFiles.add(location);
|
||||
uniformProviders.add(provider);
|
||||
return provider;
|
||||
}
|
||||
|
||||
public static Collection<UniformProvider> getAllUniformProviders() {
|
||||
return Collections.unmodifiableCollection(uniformProviders);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
public enum ComponentType {
|
||||
MATERIAL,
|
||||
INSTANCE,
|
||||
LAYOUT,
|
||||
CONTEXT,
|
||||
UNIFORM_PROVIDER
|
||||
}
|
113
src/main/java/com/jozufozu/flywheel/core/Components.java
Normal file
113
src/main/java/com/jozufozu/flywheel/core/Components.java
Normal file
|
@ -0,0 +1,113 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.core.compile.ContextShader;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceChecks;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.uniform.FogProvider;
|
||||
import com.jozufozu.flywheel.core.uniform.ViewProvider;
|
||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class Components {
|
||||
|
||||
|
||||
public static final ViewProvider VIEW_PROVIDER = ComponentRegistry.register(new ViewProvider());
|
||||
public static final FogProvider FOG_PROVIDER = ComponentRegistry.register(new FogProvider());
|
||||
public static final ContextShader WORLD = ComponentRegistry.register(new ContextShader(WorldProgram::new, Files.WORLD_VERTEX, Files.WORLD_FRAGMENT));
|
||||
public static final ContextShader CRUMBLING = ComponentRegistry.register(new ContextShader(CrumblingProgram::new, Files.CRUMBLING_VERTEX, Files.CRUMBLING_FRAGMENT));
|
||||
|
||||
public static void init() {
|
||||
Files.init();
|
||||
Formats.init();
|
||||
StructTypes.init();
|
||||
Materials.init();
|
||||
}
|
||||
|
||||
public static class Files {
|
||||
|
||||
public static final FileResolution VIEW_UNIFORMS = uniform(Flywheel.rl("uniform/view.glsl"));
|
||||
public static final FileResolution FOG_UNIFORMS = uniform(Flywheel.rl("uniform/fog.glsl"));
|
||||
public static final FileResolution BLOCK_LAYOUT = layoutVertex(ResourceUtil.subPath(Names.BLOCK, ".vert"));
|
||||
public static final FileResolution POS_TEX_NORMAL_LAYOUT = layoutVertex(ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert"));
|
||||
public static final FileResolution TRANSFORMED = instanceVertex(ResourceUtil.subPath(Names.TRANSFORMED, ".vert"));
|
||||
public static final FileResolution ORIENTED = instanceVertex(ResourceUtil.subPath(Names.ORIENTED, ".vert"));
|
||||
public static final FileResolution DEFAULT_VERTEX = materialVertex(ResourceUtil.subPath(Names.DEFAULT, ".vert"));
|
||||
public static final FileResolution DEFAULT_FRAGMENT = materialFragment(ResourceUtil.subPath(Names.DEFAULT, ".frag"));
|
||||
public static final FileResolution SHADED_VERTEX = materialVertex(ResourceUtil.subPath(Names.SHADED, ".vert"));
|
||||
public static final FileResolution WORLD_VERTEX = contextVertex(ResourceUtil.subPath(Names.WORLD, ".vert"));
|
||||
public static final FileResolution WORLD_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.WORLD, ".frag"));
|
||||
public static final FileResolution CRUMBLING_VERTEX = contextVertex(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
|
||||
public static final FileResolution CRUMBLING_FRAGMENT = contextFragment(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
|
||||
|
||||
public static FileResolution uniform(ResourceLocation location) {
|
||||
return FileResolution.get(location);
|
||||
}
|
||||
|
||||
public static FileResolution layoutVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.LAYOUT_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution instanceVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.INSTANCE_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution materialVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.MATERIAL_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution materialFragment(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.MATERIAL_FRAGMENT);
|
||||
}
|
||||
|
||||
public static FileResolution contextVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.CONTEXT_VERTEX);
|
||||
}
|
||||
|
||||
public static FileResolution contextFragment(ResourceLocation location) {
|
||||
return FileResolution.get(location)
|
||||
.validateWith(Checks.CONTEXT_FRAGMENT);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// noop, just in case
|
||||
}
|
||||
}
|
||||
|
||||
public static class Checks {
|
||||
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> LAYOUT_VERTEX = SourceChecks.checkFunctionArity("flw_layoutVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> INSTANCE_VERTEX = SourceChecks.checkFunctionArity("flw_instanceVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_VERTEX = SourceChecks.checkFunctionArity("flw_materialVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> MATERIAL_FRAGMENT = SourceChecks.checkFunctionArity("flw_materialFragment", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_VERTEX = SourceChecks.checkFunctionArity("flw_contextVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> CONTEXT_FRAGMENT = SourceChecks.checkFunctionArity("flw_contextFragment", 0);
|
||||
}
|
||||
|
||||
public static class Names {
|
||||
public static final ResourceLocation BLOCK = Flywheel.rl("layout/block");
|
||||
public static final ResourceLocation POS_TEX_NORMAL = Flywheel.rl("layout/pos_tex_normal");
|
||||
|
||||
public static final ResourceLocation TRANSFORMED = Flywheel.rl("instance/transformed");
|
||||
public static final ResourceLocation ORIENTED = Flywheel.rl("instance/oriented");
|
||||
|
||||
public static final ResourceLocation DEFAULT = Flywheel.rl("material/default");
|
||||
public static final ResourceLocation SHADED = Flywheel.rl("material/shaded");
|
||||
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
|
||||
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceChecks;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
|
||||
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class Contexts {
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> VERTEX_CHECK = SourceChecks.checkFunctionArity("flw_contextVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> FRAGMENT_CHECK = SourceChecks.checkFunctionArity("flw_contextFragment", 0);
|
||||
|
||||
public static final ProgramCompiler<WorldProgram> WORLD;
|
||||
public static final ProgramCompiler<CrumblingProgram> CRUMBLING;
|
||||
|
||||
static {
|
||||
var worldVertex = createVertex(ResourceUtil.subPath(Names.WORLD, ".vert"));
|
||||
var worldFragment = createFragment(ResourceUtil.subPath(Names.WORLD, ".frag"));
|
||||
var crumblingVertex = createVertex(ResourceUtil.subPath(Names.CRUMBLING, ".vert"));
|
||||
var crumblingFragment = createFragment(ResourceUtil.subPath(Names.CRUMBLING, ".frag"));
|
||||
|
||||
WORLD = ProgramCompiler.create(WorldProgram::new, worldVertex, worldFragment, GLSLVersion.V330);
|
||||
CRUMBLING = ProgramCompiler.create(CrumblingProgram::new, crumblingVertex, crumblingFragment, GLSLVersion.V330);
|
||||
}
|
||||
|
||||
public static FileResolution createVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location).validateWith(VERTEX_CHECK);
|
||||
}
|
||||
|
||||
public static FileResolution createFragment(ResourceLocation location) {
|
||||
return FileResolution.get(location).validateWith(FRAGMENT_CHECK);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
public static class Names {
|
||||
public static final ResourceLocation WORLD = Flywheel.rl("context/world");
|
||||
public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling");
|
||||
}
|
||||
}
|
19
src/main/java/com/jozufozu/flywheel/core/Materials.java
Normal file
19
src/main/java/com/jozufozu/flywheel/core/Materials.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class Materials {
|
||||
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
|
||||
public static final Material DEFAULT = ComponentRegistry.register(new Material(RenderType.solid(), Components.Files.DEFAULT_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material CHEST = ComponentRegistry.register(new Material(Sheets.chestSheet(), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material SHULKER = ComponentRegistry.register(new Material(RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
public static final Material MINECART = ComponentRegistry.register(new Material(RenderType.entitySolid(MINECART_LOCATION), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
|
||||
public static void init() {
|
||||
// noop
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.jozufozu.flywheel.core.compile;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
|
||||
public record ContextShader(GlProgram.Factory factory, FileResolution vertexShader, FileResolution fragmentShader) {
|
||||
|
||||
public SourceFile getVertexShader() {
|
||||
return vertexShader.getFile();
|
||||
}
|
||||
|
||||
public SourceFile getFragmentShader() {
|
||||
return fragmentShader.getFile();
|
||||
}
|
||||
}
|
|
@ -7,43 +7,38 @@ import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
|||
import com.jozufozu.flywheel.core.CoreShaderInfoMap.CoreShaderInfo.FogType;
|
||||
import com.jozufozu.flywheel.core.shader.ShaderConstants;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
import com.jozufozu.flywheel.core.source.FileIndex;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
|
||||
/**
|
||||
* Handles compilation and deletion of fragment shaders.
|
||||
*/
|
||||
public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShader> {
|
||||
private final FileResolution contextShader;
|
||||
private final GLSLVersion glslVersion;
|
||||
|
||||
public FragmentCompiler(FileResolution contextShader, GLSLVersion glslVersion) {
|
||||
this.contextShader = contextShader;
|
||||
this.glslVersion = glslVersion;
|
||||
public FragmentCompiler() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GlShader _create(Context key) {
|
||||
StringBuilder finalSource = new StringBuilder();
|
||||
|
||||
finalSource.append(CompileUtil.generateHeader(glslVersion, ShaderType.FRAGMENT));
|
||||
finalSource.append(CompileUtil.generateHeader(GLSLVersion.V420, ShaderType.FRAGMENT));
|
||||
|
||||
ShaderConstants shaderConstants = key.getShaderConstants();
|
||||
var shaderConstants = key.getShaderConstants();
|
||||
shaderConstants.writeInto(finalSource);
|
||||
finalSource.append('\n');
|
||||
|
||||
FileIndex index = new FileIndex();
|
||||
var ctx = new CompilationContext();
|
||||
|
||||
// MATERIAL
|
||||
|
||||
SourceFile materialShader = key.materialShader;
|
||||
materialShader.generateFinalSource(index, finalSource);
|
||||
finalSource.append(materialShader.generateFinalSource(ctx));
|
||||
|
||||
// CONTEXT
|
||||
|
||||
SourceFile contextShaderSource = contextShader.getFile();
|
||||
contextShaderSource.generateFinalSource(index, finalSource);
|
||||
SourceFile contextShaderSource = key.contextShader;
|
||||
finalSource.append(contextShaderSource.generateFinalSource(ctx));
|
||||
|
||||
// MAIN
|
||||
|
||||
|
@ -52,7 +47,7 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
|
|||
try {
|
||||
return new GlShader(finalSource.toString(), ShaderType.FRAGMENT, ImmutableList.of(materialShader.name, contextShaderSource.name), shaderConstants);
|
||||
} catch (ShaderCompilationException e) {
|
||||
throw e.withErrorLog(index);
|
||||
throw e.withErrorLog(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +73,7 @@ public class FragmentCompiler extends Memoizer<FragmentCompiler.Context, GlShade
|
|||
* @param fogType Which type of fog should be applied.
|
||||
* @param ctx The shader constants to apply.
|
||||
*/
|
||||
public record Context(SourceFile materialShader, float alphaDiscard, FogType fogType, StateSnapshot ctx) {
|
||||
public record Context(SourceFile materialShader, SourceFile contextShader, float alphaDiscard, FogType fogType, StateSnapshot ctx) {
|
||||
|
||||
public ShaderConstants getShaderConstants() {
|
||||
ShaderConstants shaderConstants = ctx.getShaderConstants();
|
||||
|
|
|
@ -49,7 +49,7 @@ public class ProgramAssembler {
|
|||
return this;
|
||||
}
|
||||
|
||||
public <P extends GlProgram> P build(GlProgram.Factory<P> factory) {
|
||||
public GlProgram build(GlProgram.Factory factory) {
|
||||
return factory.create(name, program);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package com.jozufozu.flywheel.core.compile;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.core.CoreShaderInfoMap;
|
||||
import com.jozufozu.flywheel.core.shader.StateSnapshot;
|
||||
|
@ -22,41 +22,28 @@ import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
|||
* A ProgramCompiler is also responsible for deleting programs and shaders on renderer reload.
|
||||
* </p>
|
||||
*/
|
||||
public class ProgramCompiler<P extends GlProgram> extends Memoizer<ProgramCompiler.Context, P> {
|
||||
public class ProgramCompiler extends Memoizer<ProgramCompiler.Context, GlProgram> {
|
||||
|
||||
private static final List<ProgramCompiler<?>> ALL_COMPILERS = new ArrayList<>();
|
||||
public static final ProgramCompiler INSTANCE = new ProgramCompiler();
|
||||
private static final List<ProgramCompiler> ALL_COMPILERS = new ArrayList<>();
|
||||
|
||||
private final GlProgram.Factory<P> factory;
|
||||
private final VertexCompiler vertexCompiler;
|
||||
private final FragmentCompiler fragmentCompiler;
|
||||
|
||||
public ProgramCompiler(GlProgram.Factory<P> factory, VertexCompiler vertexCompiler, FragmentCompiler fragmentCompiler) {
|
||||
this.factory = factory;
|
||||
this.vertexCompiler = vertexCompiler;
|
||||
this.fragmentCompiler = fragmentCompiler;
|
||||
public ProgramCompiler() {
|
||||
this.vertexCompiler = new VertexCompiler();
|
||||
this.fragmentCompiler = new FragmentCompiler();
|
||||
|
||||
ALL_COMPILERS.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a program compiler using provided templates and headers.
|
||||
* @param factory A factory to add meaning to compiled programs.
|
||||
* @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 <P extends GlProgram> ProgramCompiler<P> create(GlProgram.Factory<P> factory, FileResolution vertexContextShader, FileResolution fragmentContextShader, GLSLVersion glslVersion) {
|
||||
return new ProgramCompiler<>(factory, new VertexCompiler(vertexContextShader, glslVersion), new FragmentCompiler(fragmentContextShader, glslVersion));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or compile a spec to the given vertex type, accounting for all game state conditions specified by the spec.
|
||||
*
|
||||
* @param ctx The context of compilation.
|
||||
* @return A compiled GlProgram.
|
||||
*/
|
||||
public P getProgram(Context ctx) {
|
||||
public GlProgram getProgram(ProgramCompiler.Context ctx) {
|
||||
return super.get(ctx);
|
||||
}
|
||||
|
||||
|
@ -68,17 +55,28 @@ public class ProgramCompiler<P extends GlProgram> extends Memoizer<ProgramCompil
|
|||
}
|
||||
|
||||
@Override
|
||||
protected P _create(Context ctx) {
|
||||
protected GlProgram _create(ProgramCompiler.Context ctx) {
|
||||
// TODO: try-catch here to prevent crashing if shaders failed to compile
|
||||
return new ProgramAssembler(ctx.instanceShader().getFileLoc())
|
||||
.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())))
|
||||
Material material = ctx.material;
|
||||
StateSnapshot snapshot = ctx.ctx();
|
||||
FileResolution instanceShader = ctx.instanceShader();
|
||||
ContextShader contextShader = ctx.contextShader;
|
||||
|
||||
var vertex = new VertexCompiler.Context(ctx.vertexType(), instanceShader.getFile(), material.getVertexShader(),
|
||||
contextShader.getVertexShader(), snapshot);
|
||||
|
||||
var fragment = new FragmentCompiler.Context(material.getFragmentShader(), contextShader.getFragmentShader(),
|
||||
ctx.alphaDiscard(), ctx.fogType(), snapshot);
|
||||
|
||||
return new ProgramAssembler(instanceShader.getFileLoc())
|
||||
.attachShader(vertexCompiler.get(vertex))
|
||||
.attachShader(fragmentCompiler.get(fragment))
|
||||
.link()
|
||||
.build(this.factory);
|
||||
.build(contextShader.factory());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _destroy(P value) {
|
||||
protected void _destroy(GlProgram value) {
|
||||
value.delete();
|
||||
}
|
||||
|
||||
|
@ -89,15 +87,16 @@ public class ProgramCompiler<P extends GlProgram> extends Memoizer<ProgramCompil
|
|||
/**
|
||||
* Represents the entire context of a program's usage.
|
||||
*
|
||||
* @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.
|
||||
* @param vertexType The vertexType the program should be adapted for.
|
||||
* @param material The material shader to use.
|
||||
* @param instanceShader The instance shader to use.
|
||||
* @param contextShader The context 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 record Context(VertexType vertexType, FileResolution instanceShader, FileResolution vertexMaterialShader,
|
||||
FileResolution fragmentMaterialShader, float alphaDiscard, CoreShaderInfoMap.CoreShaderInfo.FogType fogType, StateSnapshot ctx) {
|
||||
public record Context(VertexType vertexType, Material material, FileResolution instanceShader,
|
||||
ContextShader contextShader, float alphaDiscard,
|
||||
CoreShaderInfoMap.CoreShaderInfo.FogType fogType, StateSnapshot ctx) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.jozufozu.flywheel.core.compile;
|
|||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import com.jozufozu.flywheel.core.source.FileIndex;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.ShaderLoadingException;
|
||||
|
||||
public class ShaderCompilationException extends ShaderLoadingException {
|
||||
|
@ -16,11 +16,11 @@ public class ShaderCompilationException extends ShaderLoadingException {
|
|||
this.shaderHandle = shaderHandle;
|
||||
}
|
||||
|
||||
public ShaderLoadingException withErrorLog(FileIndex fileIndex) {
|
||||
public ShaderLoadingException withErrorLog(CompilationContext ctx) {
|
||||
if (this.shaderHandle == -1)
|
||||
return this;
|
||||
|
||||
this.errors = fileIndex.parseErrors(GL20.glGetShaderInfoLog(this.shaderHandle));
|
||||
this.errors = ctx.parseErrors(GL20.glGetShaderInfoLog(this.shaderHandle));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -8,12 +8,9 @@ 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.FileIndex;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.ShaderField;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.parse.ShaderStruct;
|
||||
import com.jozufozu.flywheel.core.source.parse.StructField;
|
||||
import com.jozufozu.flywheel.core.source.span.Span;
|
||||
import com.jozufozu.flywheel.util.Pair;
|
||||
|
||||
|
@ -21,30 +18,26 @@ import com.jozufozu.flywheel.util.Pair;
|
|||
* Handles compilation and deletion of vertex shaders.
|
||||
*/
|
||||
public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
||||
private final FileResolution contextShader;
|
||||
private final GLSLVersion glslVersion;
|
||||
|
||||
public VertexCompiler(FileResolution contextShader, GLSLVersion glslVersion) {
|
||||
this.contextShader = contextShader;
|
||||
this.glslVersion = glslVersion;
|
||||
public VertexCompiler() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GlShader _create(Context key) {
|
||||
StringBuilder finalSource = new StringBuilder();
|
||||
|
||||
finalSource.append(CompileUtil.generateHeader(glslVersion, ShaderType.VERTEX));
|
||||
finalSource.append(CompileUtil.generateHeader(GLSLVersion.V420, ShaderType.VERTEX));
|
||||
|
||||
var shaderConstants = key.ctx.getShaderConstants();
|
||||
shaderConstants.writeInto(finalSource);
|
||||
finalSource.append('\n');
|
||||
|
||||
var index = new FileIndex();
|
||||
var index = new CompilationContext();
|
||||
|
||||
// LAYOUT
|
||||
|
||||
var layoutShader = key.vertexType.getLayoutShader().getFile();
|
||||
layoutShader.generateFinalSource(index, finalSource);
|
||||
finalSource.append(layoutShader.generateFinalSource(index));
|
||||
|
||||
// INSTANCE
|
||||
|
||||
|
@ -62,17 +55,17 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
|||
int newLocation = location + attributeBaseIndex;
|
||||
replacements.add(Pair.of(field.location, Integer.toString(newLocation)));
|
||||
}
|
||||
instanceShader.generateFinalSource(index, finalSource, replacements);
|
||||
finalSource.append(instanceShader.generateFinalSource(index, replacements));
|
||||
|
||||
// MATERIAL
|
||||
|
||||
var materialShader = key.materialShader;
|
||||
materialShader.generateFinalSource(index, finalSource);
|
||||
finalSource.append(materialShader.generateFinalSource(index));
|
||||
|
||||
// CONTEXT
|
||||
|
||||
var contextShaderSource = contextShader.getFile();
|
||||
contextShaderSource.generateFinalSource(index, finalSource);
|
||||
var contextShaderSource = key.contextShader;
|
||||
finalSource.append(contextShaderSource.generateFinalSource(index));
|
||||
|
||||
// MAIN
|
||||
|
||||
|
@ -104,8 +97,9 @@ public class VertexCompiler extends Memoizer<VertexCompiler.Context, GlShader> {
|
|||
* @param vertexType The vertex type to use.
|
||||
* @param instanceShader The instance shader source.
|
||||
* @param materialShader The vertex material shader source.
|
||||
* @param contextShader The context shader source.
|
||||
* @param ctx The shader constants to apply.
|
||||
*/
|
||||
public record Context(VertexType vertexType, SourceFile instanceShader, SourceFile materialShader, StateSnapshot ctx) {
|
||||
public record Context(VertexType vertexType, SourceFile instanceShader, SourceFile materialShader, SourceFile contextShader, StateSnapshot ctx) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
|||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.SerialTaskEngine;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine;
|
||||
import com.jozufozu.flywheel.core.Contexts;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.mixin.LevelRendererAccessor;
|
||||
|
@ -153,15 +153,15 @@ public class CrumblingRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
private static class CrumblingEngine extends InstancingEngine<CrumblingProgram> {
|
||||
private static class CrumblingEngine extends InstancingEngine {
|
||||
private RenderType currentLayer;
|
||||
|
||||
public CrumblingEngine() {
|
||||
super(Contexts.CRUMBLING);
|
||||
super(Components.CRUMBLING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void render(RenderType type, double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
protected void render(RenderType type) {
|
||||
if (!type.affectsCrumbling()) {
|
||||
return;
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public class CrumblingRenderer {
|
|||
return;
|
||||
}
|
||||
|
||||
render(currentLayer, multimap, camX, camY, camZ, viewProjection, level);
|
||||
render(currentLayer, multimap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.material;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceChecks;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
|
||||
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class MaterialShaders {
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> VERTEX_CHECK = SourceChecks.checkFunctionArity("flw_materialVertex", 0);
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> FRAGMENT_CHECK = SourceChecks.checkFunctionArity("flw_materialFragment", 0);
|
||||
|
||||
public static final FileResolution DEFAULT_VERTEX = createVertex(ResourceUtil.subPath(Names.DEFAULT, ".vert"));
|
||||
public static final FileResolution DEFAULT_FRAGMENT = createFragment(ResourceUtil.subPath(Names.DEFAULT, ".frag"));
|
||||
public static final FileResolution SHADED_VERTEX = createVertex(ResourceUtil.subPath(Names.SHADED, ".vert"));
|
||||
|
||||
public static FileResolution createVertex(ResourceLocation location) {
|
||||
return FileResolution.get(location).validateWith(VERTEX_CHECK);
|
||||
}
|
||||
|
||||
public static FileResolution createFragment(ResourceLocation location) {
|
||||
return FileResolution.get(location).validateWith(FRAGMENT_CHECK);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
public static class Names {
|
||||
public static final ResourceLocation DEFAULT = Flywheel.rl("material/default");
|
||||
public static final ResourceLocation SHADED = Flywheel.rl("material/shaded");
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
public class WorldFog {
|
||||
|
||||
private final int uFogRange;
|
||||
private final int uFogColor;
|
||||
private final int uFogShape;
|
||||
|
||||
public WorldFog(GlProgram program) {
|
||||
this.uFogRange = program.getUniformLocation("uFogRange");
|
||||
this.uFogColor = program.getUniformLocation("uFogColor");
|
||||
this.uFogShape = program.getUniformLocation("uFogShape");
|
||||
}
|
||||
|
||||
public void uploadUniforms() {
|
||||
GL20.glUniform2f(uFogRange, RenderSystem.getShaderFogStart(), RenderSystem.getShaderFogEnd());
|
||||
GL20.glUniform4fv(uFogColor, RenderSystem.getShaderFogColor());
|
||||
GL20.glUniform1i(uFogShape, RenderSystem.getShaderFogShape().getIndex());
|
||||
}
|
||||
}
|
|
@ -1,35 +1,18 @@
|
|||
package com.jozufozu.flywheel.core.shader;
|
||||
|
||||
import static org.lwjgl.opengl.GL20.glUniform1f;
|
||||
import static org.lwjgl.opengl.GL20.glUniform1i;
|
||||
import static org.lwjgl.opengl.GL20.glUniform2f;
|
||||
import static org.lwjgl.opengl.GL20.glUniform3f;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class WorldProgram extends GlProgram {
|
||||
protected final int uTime = getUniformLocation("uTime");
|
||||
protected final int uViewProjection = getUniformLocation("uViewProjection");
|
||||
protected final int uCameraPos = getUniformLocation("uCameraPos");
|
||||
protected final int uWindowSize = getUniformLocation("uWindowSize");
|
||||
protected final int uConstantAmbientLight = getUniformLocation("uConstantAmbientLight");
|
||||
private final WorldFog fog;
|
||||
|
||||
// TODO: sampler registry?
|
||||
protected int uBlockAtlas;
|
||||
protected int uLightMap;
|
||||
|
||||
public WorldProgram(ResourceLocation name, int handle) {
|
||||
super(name, handle);
|
||||
|
||||
fog = new WorldFog(this);
|
||||
|
||||
bind();
|
||||
registerSamplers();
|
||||
unbind();
|
||||
|
@ -39,48 +22,4 @@ public class WorldProgram extends GlProgram {
|
|||
uBlockAtlas = setSamplerBinding("uBlockAtlas", 0);
|
||||
uLightMap = setSamplerBinding("uLightMap", 2);
|
||||
}
|
||||
|
||||
// TODO: create uniform registry
|
||||
public void uploadUniforms(double camX, double camY, double camZ, Matrix4f viewProjection, ClientLevel level) {
|
||||
fog.uploadUniforms();
|
||||
uploadTime(AnimationTickHolder.getRenderTime());
|
||||
uploadViewProjection(viewProjection);
|
||||
uploadCameraPos(camX, camY, camZ);
|
||||
uploadWindowSize();
|
||||
uploadConstantAmbientLight(level);
|
||||
}
|
||||
|
||||
protected void uploadTime(float renderTime) {
|
||||
if (uTime < 0) return;
|
||||
|
||||
glUniform1f(uTime, renderTime);
|
||||
}
|
||||
|
||||
protected void uploadViewProjection(Matrix4f viewProjection) {
|
||||
if (uViewProjection < 0) return;
|
||||
|
||||
uploadMatrixUniform(uViewProjection, viewProjection);
|
||||
}
|
||||
|
||||
protected void uploadCameraPos(double camX, double camY, double camZ) {
|
||||
if (uCameraPos < 0) return;
|
||||
|
||||
glUniform3f(uCameraPos, (float) camX, (float) camY, (float) camZ);
|
||||
}
|
||||
|
||||
protected void uploadWindowSize() {
|
||||
if (uWindowSize < 0) return;
|
||||
|
||||
Window window = Minecraft.getInstance().getWindow();
|
||||
|
||||
int height = window.getScreenHeight();
|
||||
int width = window.getScreenWidth();
|
||||
glUniform2f(uWindowSize, width, height);
|
||||
}
|
||||
|
||||
protected void uploadConstantAmbientLight(ClientLevel level) {
|
||||
if (uConstantAmbientLight < 0) return;
|
||||
|
||||
glUniform1i(uConstantAmbientLight, level.effects().constantAmbientLight() ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
import com.jozufozu.flywheel.core.source.error.ErrorBuilder;
|
||||
import com.jozufozu.flywheel.core.source.span.Span;
|
||||
|
||||
public class FileIndex {
|
||||
public class CompilationContext {
|
||||
public final List<SourceFile> files = new ArrayList<>();
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ public class FileIndex {
|
|||
return size;
|
||||
}
|
||||
|
||||
public boolean exists(SourceFile sourceFile) {
|
||||
public boolean contains(SourceFile sourceFile) {
|
||||
return files.contains(sourceFile);
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import net.minecraft.resources.ResourceLocation;
|
|||
public class FileResolution {
|
||||
|
||||
private static final Map<ResourceLocation, FileResolution> ALL = new HashMap<>();
|
||||
private static final Map<ResourceLocation, FileResolution> WEAK = new HashMap<>();
|
||||
private static boolean tooLate = false;
|
||||
|
||||
/**
|
||||
|
@ -56,34 +57,65 @@ public class FileResolution {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Weak resolutions don't persist through resource reloads.<p>
|
||||
* This should be used inside parsing code.
|
||||
*
|
||||
* @param file The location of the file to resolve.
|
||||
* @return A weak resolution for the given file.
|
||||
*/
|
||||
public static FileResolution weak(ResourceLocation file) {
|
||||
FileResolution fileResolution = ALL.get(file);
|
||||
|
||||
if (fileResolution != null) {
|
||||
return fileResolution;
|
||||
}
|
||||
// never too late for weak resolutions.
|
||||
return WEAK.computeIfAbsent(file, FileResolution::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try and resolve all referenced source files, printing errors if any aren't found.
|
||||
*/
|
||||
public static void run(ErrorReporter errorReporter, SourceFinder sources) {
|
||||
for (FileResolution resolution : ALL.values()) {
|
||||
resolution.resolveAndCheck(errorReporter, sources);
|
||||
resolution.resolve(errorReporter, sources);
|
||||
}
|
||||
|
||||
for (FileResolution resolution : WEAK.values()) {
|
||||
resolution.resolve(errorReporter, sources);
|
||||
}
|
||||
|
||||
WEAK.clear();
|
||||
|
||||
tooLate = true;
|
||||
}
|
||||
|
||||
private void resolveAndCheck(ErrorReporter errorReporter, SourceFinder sources) {
|
||||
public static void checkAll(ErrorReporter errorReporter) {
|
||||
for (FileResolution resolution : ALL.values()) {
|
||||
resolution.runChecks(errorReporter);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolve(ErrorReporter errorReporter, SourceFinder sources) {
|
||||
file = sources.findSource(fileLoc);
|
||||
|
||||
if (file == null) {
|
||||
ErrorBuilder builder = errorReporter.error(String.format("could not find source for file %s", fileLoc));
|
||||
for (Span location : neededAt) {
|
||||
builder.pointAtFile(location.getSourceFile())
|
||||
.pointAt(location, 1);
|
||||
}
|
||||
} else {
|
||||
runChecks(errorReporter);
|
||||
reportMissing(errorReporter);
|
||||
}
|
||||
|
||||
// Let the GC do its thing
|
||||
neededAt.clear();
|
||||
}
|
||||
|
||||
private void reportMissing(ErrorReporter errorReporter) {
|
||||
ErrorBuilder builder = errorReporter.error(String.format("could not find source for file %s", fileLoc));
|
||||
for (Span location : neededAt) {
|
||||
builder.pointAtFile(location.getSourceFile())
|
||||
.pointAt(location, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void runChecks(ErrorReporter errorReporter) {
|
||||
for (var check : checks) {
|
||||
check.accept(errorReporter, file);
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -29,14 +30,8 @@ public class ShaderSources implements SourceFinder {
|
|||
public final Index index;
|
||||
|
||||
public ShaderSources(ErrorReporter errorReporter, ResourceManager manager) {
|
||||
Collection<ResourceLocation> allShaders = manager.listResources(SHADER_DIR, s -> {
|
||||
for (String ext : EXTENSIONS) {
|
||||
if (s.endsWith(ext)) return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
for (ResourceLocation location : allShaders) {
|
||||
for (ResourceLocation location : getValidShaderFiles(manager)) {
|
||||
try (Resource resource = manager.getResource(location)) {
|
||||
String source = StringUtil.readToString(resource.getInputStream());
|
||||
|
||||
|
@ -51,9 +46,25 @@ public class ShaderSources implements SourceFinder {
|
|||
index = new Index(shaderSources);
|
||||
}
|
||||
|
||||
public void postResolve() {
|
||||
for (SourceFile file : shaderSources.values()) {
|
||||
file.postResolve();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public SourceFile findSource(ResourceLocation name) {
|
||||
return shaderSources.get(name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<ResourceLocation> getValidShaderFiles(ResourceManager manager) {
|
||||
return manager.listResources(SHADER_DIR, s -> {
|
||||
for (String ext : EXTENSIONS) {
|
||||
if (s.endsWith(ext)) return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ public class SourceFile {
|
|||
public final ImmutableMap<String, ShaderField> fields;
|
||||
private final List<Span> elisions;
|
||||
|
||||
// POST-RESOLUTION
|
||||
private List<Import> flattenedImports;
|
||||
|
||||
public SourceFile(ErrorReporter errorReporter, ShaderSources parent, ResourceLocation name, String source) {
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
|
@ -72,6 +75,37 @@ public class SourceFile {
|
|||
this.fields = parseFields();
|
||||
}
|
||||
|
||||
public void postResolve() {
|
||||
this.flattenImports();
|
||||
}
|
||||
|
||||
private void flattenImports() {
|
||||
// somebody #used us and got resolved before we did
|
||||
if (this.flattenedImports != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.imports.isEmpty()) {
|
||||
this.flattenedImports = Collections.emptyList();
|
||||
return;
|
||||
}
|
||||
|
||||
List<Import> flat = new ArrayList<>(this.imports.size());
|
||||
|
||||
for (Import include : this.imports) {
|
||||
SourceFile file = include.resolution.getFile();
|
||||
|
||||
file.flattenImports();
|
||||
|
||||
flat.addAll(file.flattenedImports);
|
||||
flat.add(include);
|
||||
}
|
||||
|
||||
this.flattenedImports = flat.stream()
|
||||
.distinct()
|
||||
.toList();
|
||||
}
|
||||
|
||||
public Span getLineSpan(int line) {
|
||||
int begin = lines.getLineStart(line);
|
||||
int end = begin + lines.getLine(line).length();
|
||||
|
@ -95,16 +129,23 @@ public class SourceFile {
|
|||
* @param name The name of the struct to find.
|
||||
* @return null if no definition matches the name.
|
||||
*/
|
||||
public Optional<ShaderStruct> findStruct(CharSequence name) {
|
||||
ShaderStruct struct = structs.get(name.toString());
|
||||
public Optional<ShaderStruct> findStruct(String name) {
|
||||
ShaderStruct struct = structs.get(name);
|
||||
|
||||
if (struct != null) return Optional.of(struct);
|
||||
|
||||
for (Import include : imports) {
|
||||
Optional<ShaderStruct> externalStruct = include.getOptional()
|
||||
.flatMap(file -> file.findStruct(name));
|
||||
for (Import include : flattenedImports) {
|
||||
var file = include.getFile();
|
||||
|
||||
if (externalStruct.isPresent()) return externalStruct;
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var external = file.structs.get(name);
|
||||
|
||||
if (external != null) {
|
||||
return Optional.of(external);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
@ -116,16 +157,23 @@ public class SourceFile {
|
|||
* @param name The name of the function to find.
|
||||
* @return Optional#empty() if no definition matches the name.
|
||||
*/
|
||||
public Optional<ShaderFunction> findFunction(CharSequence name) {
|
||||
ShaderFunction local = functions.get(name.toString());
|
||||
public Optional<ShaderFunction> findFunction(String name) {
|
||||
ShaderFunction local = functions.get(name);
|
||||
|
||||
if (local != null) return Optional.of(local);
|
||||
|
||||
for (Import include : imports) {
|
||||
Optional<ShaderFunction> external = include.getOptional()
|
||||
.flatMap(file -> file.findFunction(name));
|
||||
var file = include.getFile();
|
||||
|
||||
if (external.isPresent()) return external;
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var external = file.functions.get(name);
|
||||
|
||||
if (external != null) {
|
||||
return Optional.of(external);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
@ -135,40 +183,46 @@ public class SourceFile {
|
|||
return "#use " + '"' + name + '"';
|
||||
}
|
||||
|
||||
public void generateFinalSource(FileIndex env, StringBuilder source) {
|
||||
generateFinalSource(env, source, Collections.emptyList());
|
||||
public String generateFinalSource(CompilationContext env) {
|
||||
return generateFinalSource(env, Collections.emptyList());
|
||||
}
|
||||
|
||||
public void generateFinalSource(FileIndex env, StringBuilder source, List<Pair<Span, String>> replacements) {
|
||||
for (Import include : imports) {
|
||||
public String generateFinalSource(CompilationContext env, List<Pair<Span, String>> replacements) {
|
||||
var out = new StringBuilder();
|
||||
for (Import include : flattenedImports) {
|
||||
SourceFile file = include.getFile();
|
||||
|
||||
if (file != null && !env.exists(file)) {
|
||||
file.generateFinalSource(env, source, replacements);
|
||||
if (file == null || env.contains(file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out.append(file.generateLineHeader(env))
|
||||
.append(file.replaceAndElide(replacements));
|
||||
}
|
||||
|
||||
source.append("#line ")
|
||||
.append(0)
|
||||
.append(' ')
|
||||
.append(env.getFileID(this))
|
||||
.append(" // ")
|
||||
.append(name)
|
||||
.append('\n');
|
||||
out.append(this.generateLineHeader(env))
|
||||
.append(this.replaceAndElide(replacements));
|
||||
|
||||
var replacementsAndElisions = new ArrayList<>(replacements);
|
||||
for (Span elision : elisions) {
|
||||
replacementsAndElisions.add(Pair.of(elision, ""));
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
source.append(this.replace(replacementsAndElisions));
|
||||
source.append('\n');
|
||||
private String generateLineHeader(CompilationContext env) {
|
||||
return "#line " + 0 + ' ' + env.getFileID(this) + " // " + name + '\n';
|
||||
}
|
||||
|
||||
public String printSource() {
|
||||
return "Source for shader '" + name + "':\n" + lines.printLinesWithNumbers();
|
||||
}
|
||||
|
||||
private CharSequence replaceAndElide(List<Pair<Span, String>> replacements) {
|
||||
var replacementsAndElisions = new ArrayList<>(replacements);
|
||||
for (var include : imports) {
|
||||
replacementsAndElisions.add(Pair.of(include.self, ""));
|
||||
}
|
||||
|
||||
return this.replace(replacementsAndElisions);
|
||||
}
|
||||
|
||||
private CharSequence replace(List<Pair<Span, String>> replacements) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
|
@ -276,7 +330,7 @@ public class SourceFile {
|
|||
Matcher uses = Import.PATTERN.matcher(source);
|
||||
|
||||
Set<String> importedFiles = new HashSet<>();
|
||||
List<Import> imports = new ArrayList<>();
|
||||
var imports = ImmutableList.<Import>builder();
|
||||
|
||||
while (uses.find()) {
|
||||
Span use = Span.fromMatcher(this, uses);
|
||||
|
@ -284,17 +338,14 @@ public class SourceFile {
|
|||
|
||||
String fileName = file.get();
|
||||
if (importedFiles.add(fileName)) {
|
||||
// FIXME: creating imports after the first resource reload crashes the game
|
||||
var checked = Import.create(errorReporter, use, file);
|
||||
if (checked != null) {
|
||||
imports.add(checked);
|
||||
}
|
||||
}
|
||||
|
||||
this.elisions.add(use); // we have to trim that later
|
||||
}
|
||||
|
||||
return ImmutableList.copyOf(imports);
|
||||
return imports.build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.core.source.FileIndex;
|
||||
import com.jozufozu.flywheel.core.source.CompilationContext;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.SourceLines;
|
||||
import com.jozufozu.flywheel.core.source.error.lines.ErrorLine;
|
||||
|
@ -45,7 +45,7 @@ public class ErrorBuilder {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public static ErrorBuilder fromLogLine(FileIndex env, String s) {
|
||||
public static ErrorBuilder fromLogLine(CompilationContext env, String s) {
|
||||
Matcher matcher = ERROR_LINE.matcher(s);
|
||||
|
||||
if (matcher.find()) {
|
||||
|
|
|
@ -17,7 +17,7 @@ public class Import extends AbstractShaderElement {
|
|||
|
||||
public static final Pattern PATTERN = Pattern.compile("^\\s*#\\s*use\\s+\"(.*)\"", Pattern.MULTILINE);
|
||||
|
||||
private final FileResolution resolution;
|
||||
public final FileResolution resolution;
|
||||
|
||||
protected Import(Span self, FileResolution resolution, Span file) {
|
||||
super(self);
|
||||
|
@ -34,11 +34,7 @@ public class Import extends AbstractShaderElement {
|
|||
return null;
|
||||
}
|
||||
|
||||
return new Import(self, FileResolution.get(fileLocation), file);
|
||||
}
|
||||
|
||||
public FileResolution getResolution() {
|
||||
return resolution;
|
||||
return new Import(self, FileResolution.weak(fileLocation), file);
|
||||
}
|
||||
|
||||
public Optional<SourceFile> getOptional() {
|
||||
|
|
|
@ -131,14 +131,14 @@ public abstract class Span implements CharSequence, Comparable<Span> {
|
|||
if (isErr()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return in.findStruct(this);
|
||||
return in.findStruct(this.toString());
|
||||
}
|
||||
|
||||
public Optional<ShaderFunction> findFunction() {
|
||||
if (isErr()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return in.findFunction(this);
|
||||
return in.findFunction(this.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.structs;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceChecks;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
|
||||
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class InstanceShaders {
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> CHECK = SourceChecks.checkFunctionArity("flw_instanceVertex", 0);
|
||||
|
||||
public static final FileResolution TRANSFORMED = create(ResourceUtil.subPath(Names.TRANSFORMED, ".vert"));
|
||||
public static final FileResolution ORIENTED = create(ResourceUtil.subPath(Names.ORIENTED, ".vert"));
|
||||
|
||||
public static FileResolution create(ResourceLocation location) {
|
||||
return FileResolution.get(location).validateWith(CHECK);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
public static class Names {
|
||||
public static final ResourceLocation TRANSFORMED = Flywheel.rl("instance/transformed");
|
||||
public static final ResourceLocation ORIENTED = Flywheel.rl("instance/oriented");
|
||||
}
|
||||
}
|
|
@ -1,12 +1,17 @@
|
|||
package com.jozufozu.flywheel.core.structs;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedType;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedType;
|
||||
|
||||
public class StructTypes {
|
||||
public static final StructType<TransformedPart> TRANSFORMED = new TransformedType();
|
||||
public static final StructType<OrientedPart> ORIENTED = new OrientedType();
|
||||
public static final StructType<TransformedPart> TRANSFORMED = ComponentRegistry.register(new TransformedType());
|
||||
public static final StructType<OrientedPart> ORIENTED = ComponentRegistry.register(new OrientedType());
|
||||
|
||||
public static void init() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.core.model.ModelTransformer;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.structs.InstanceShaders;
|
||||
|
||||
public class TransformedType implements StructType<TransformedPart> {
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class TransformedType implements StructType<TransformedPart> {
|
|||
|
||||
@Override
|
||||
public FileResolution getInstanceShader() {
|
||||
return InstanceShaders.TRANSFORMED;
|
||||
return Components.Files.TRANSFORMED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,11 +4,11 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||
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 StructType<OrientedPart> {
|
||||
|
@ -35,7 +35,7 @@ public class OrientedType implements StructType<OrientedPart> {
|
|||
|
||||
@Override
|
||||
public FileResolution getInstanceShader() {
|
||||
return InstanceShaders.ORIENTED;
|
||||
return Components.Files.ORIENTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package com.jozufozu.flywheel.core.uniform;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
public class FogProvider extends UniformProvider {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 16 + 8 + 4;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (buffer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var color = RenderSystem.getShaderFogColor();
|
||||
|
||||
long ptr = MemoryUtil.memAddress(buffer);
|
||||
|
||||
MemoryUtil.memPutFloat(ptr, color[0]);
|
||||
MemoryUtil.memPutFloat(ptr + 4, color[1]);
|
||||
MemoryUtil.memPutFloat(ptr + 8, color[2]);
|
||||
MemoryUtil.memPutFloat(ptr + 12, color[3]);
|
||||
MemoryUtil.memPutFloat(ptr + 16, RenderSystem.getShaderFogStart());
|
||||
MemoryUtil.memPutFloat(ptr + 20, RenderSystem.getShaderFogEnd());
|
||||
MemoryUtil.memPutInt(ptr + 24, RenderSystem.getShaderFogShape().getIndex());
|
||||
|
||||
notifier.signalChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileResolution getUniformShader() {
|
||||
return Components.Files.FOG_UNIFORMS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package com.jozufozu.flywheel.core.uniform;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLongArray;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||
import com.jozufozu.flywheel.util.RenderMath;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
|
||||
public class UniformBuffer {
|
||||
|
||||
private static final int OFFSET_ALIGNMENT = GL32.glGetInteger(GL32.GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
|
||||
private static final int MAX_SIZE = GL32.glGetInteger(GL32.GL_MAX_UNIFORM_BLOCK_SIZE);
|
||||
private static final int MAX_BINDINGS = GL32.glGetInteger(GL32.GL_MAX_UNIFORM_BUFFER_BINDINGS);
|
||||
private static final boolean PO2_ALIGNMENT = RenderMath.isPowerOf2(OFFSET_ALIGNMENT);
|
||||
|
||||
private static UniformBuffer instance;
|
||||
private final List<Allocated> allocatedProviders;
|
||||
|
||||
public static UniformBuffer getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UniformBuffer();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final MappedGlBuffer buffer;
|
||||
private final ByteBuffer data;
|
||||
|
||||
private final BitSet changedBytes;
|
||||
|
||||
private UniformBuffer() {
|
||||
buffer = new MappedGlBuffer(GlBufferType.UNIFORM_BUFFER);
|
||||
|
||||
Collection<UniformProvider> providers = ComponentRegistry.getAllUniformProviders();
|
||||
|
||||
var builder = ImmutableList.<Allocated>builder();
|
||||
int totalBytes = 0;
|
||||
int index = 0;
|
||||
for (UniformProvider provider : providers) {
|
||||
int size = provider.getSize();
|
||||
|
||||
builder.add(new Allocated(provider, totalBytes, size, index));
|
||||
|
||||
totalBytes = align(totalBytes + size);
|
||||
index++;
|
||||
}
|
||||
|
||||
allocatedProviders = builder.build();
|
||||
|
||||
data = MemoryTracker.create(totalBytes);
|
||||
changedBytes = new BitSet(totalBytes);
|
||||
|
||||
for (Allocated p : allocatedProviders) {
|
||||
p.updatePtr(data);
|
||||
}
|
||||
}
|
||||
|
||||
public void sync() {
|
||||
if (changedBytes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
changedBytes.clear();
|
||||
|
||||
buffer.upload(data);
|
||||
|
||||
int handle = buffer.handle();
|
||||
for (Allocated p : allocatedProviders) {
|
||||
GL32.glBindBufferRange(GL32.GL_UNIFORM_BUFFER, p.index, handle, p.offset, p.size);
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/3407012/rounding-up-to-the-nearest-multiple-of-a-number
|
||||
private static int align(int numToRound) {
|
||||
if (PO2_ALIGNMENT) {
|
||||
return (numToRound + OFFSET_ALIGNMENT - 1) & -OFFSET_ALIGNMENT;
|
||||
} else {
|
||||
return ((numToRound + OFFSET_ALIGNMENT - 1) / OFFSET_ALIGNMENT) * OFFSET_ALIGNMENT;
|
||||
}
|
||||
}
|
||||
|
||||
private class Allocated implements UniformProvider.Notifier {
|
||||
private final UniformProvider provider;
|
||||
private final int offset;
|
||||
private final int size;
|
||||
private final int index;
|
||||
|
||||
private Allocated(UniformProvider provider, int offset, int size, int index) {
|
||||
this.provider = provider;
|
||||
this.offset = offset;
|
||||
this.size = size;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signalChanged() {
|
||||
changedBytes.set(offset, offset + size);
|
||||
}
|
||||
|
||||
private void updatePtr(ByteBuffer bufferBase) {
|
||||
provider.updatePtr(MemoryUtil.memSlice(bufferBase, offset, size), this);
|
||||
}
|
||||
|
||||
public UniformProvider provider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
public int offset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public int index() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.jozufozu.flywheel.core.uniform;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||
import com.jozufozu.flywheel.util.MatrixWrite;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
public class ViewProvider extends UniformProvider {
|
||||
|
||||
public ViewProvider() {
|
||||
MinecraftForge.EVENT_BUS.addListener(this::beginFrame);
|
||||
}
|
||||
|
||||
public void beginFrame(BeginFrameEvent event) {
|
||||
update(RenderContext.CURRENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 4 * 16 + 16 + 4;
|
||||
}
|
||||
|
||||
public void update(RenderContext context) {
|
||||
if (buffer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClientLevel level = context.level();
|
||||
|
||||
int constantAmbientLight = level.effects()
|
||||
.constantAmbientLight() ? 1 : 0;
|
||||
|
||||
Vec3i originCoordinate = InstancedRenderDispatcher.getOriginCoordinate(level);
|
||||
|
||||
var camX = (float) (context.camX() - originCoordinate.getX());
|
||||
var camY = (float) (context.camY() - originCoordinate.getY());
|
||||
var camZ = (float) (context.camZ() - originCoordinate.getZ());
|
||||
|
||||
// don't want to mutate viewProjection
|
||||
var vp = context.viewProjection().copy();
|
||||
vp.multiplyWithTranslation(-camX, -camY, -camZ);
|
||||
|
||||
long ptr = MemoryUtil.memAddress(buffer);
|
||||
|
||||
MatrixWrite.writeUnsafe(vp, ptr);
|
||||
MemoryUtil.memPutFloat(ptr + 64, camX);
|
||||
MemoryUtil.memPutFloat(ptr + 68, camY);
|
||||
MemoryUtil.memPutFloat(ptr + 72, camZ);
|
||||
MemoryUtil.memPutInt(ptr + 76, constantAmbientLight);
|
||||
|
||||
notifier.signalChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileResolution getUniformShader() {
|
||||
return Components.Files.VIEW_UNIFORMS;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.core.model.ShadeSeparatedBufferBuilder;
|
||||
|
@ -40,7 +41,7 @@ public class BlockVertex implements VertexType {
|
|||
|
||||
@Override
|
||||
public FileResolution getLayoutShader() {
|
||||
return LayoutShaders.BLOCK;
|
||||
return Components.Files.BLOCK_LAYOUT;
|
||||
}
|
||||
|
||||
public BlockVertexListUnsafe.Shaded createReader(ByteBuffer buffer, int vertexCount, int unshadedStartVertex) {
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
package com.jozufozu.flywheel.core.vertex;
|
||||
|
||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||
|
||||
public class Formats {
|
||||
public static final BlockVertex BLOCK = new BlockVertex();
|
||||
public static final PosTexNormalVertex POS_TEX_NORMAL = new PosTexNormalVertex();
|
||||
public static final BlockVertex BLOCK = ComponentRegistry.register(new BlockVertex());
|
||||
public static final PosTexNormalVertex POS_TEX_NORMAL = ComponentRegistry.register(new PosTexNormalVertex());
|
||||
|
||||
public static void init() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.vertex;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
import com.jozufozu.flywheel.core.source.SourceChecks;
|
||||
import com.jozufozu.flywheel.core.source.SourceFile;
|
||||
import com.jozufozu.flywheel.core.source.error.ErrorReporter;
|
||||
import com.jozufozu.flywheel.util.ResourceUtil;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class LayoutShaders {
|
||||
public static final BiConsumer<ErrorReporter, SourceFile> CHECK = SourceChecks.checkFunctionArity("flw_layoutVertex", 0);
|
||||
|
||||
public static final FileResolution BLOCK = create(ResourceUtil.subPath(Names.BLOCK, ".vert"));
|
||||
public static final FileResolution POS_TEX_NORMAL = create(ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert"));
|
||||
|
||||
public static FileResolution create(ResourceLocation location) {
|
||||
return FileResolution.get(location).validateWith(CHECK);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
public static class Names {
|
||||
public static final ResourceLocation BLOCK = Flywheel.rl("layout/block");
|
||||
public static final ResourceLocation POS_TEX_NORMAL = Flywheel.rl("layout/pos_tex_normal");
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.jozufozu.flywheel.core.vertex;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
|
@ -30,6 +31,6 @@ public class PosTexNormalVertex implements VertexType {
|
|||
|
||||
@Override
|
||||
public FileResolution getLayoutShader() {
|
||||
return LayoutShaders.POS_TEX_NORMAL;
|
||||
return Components.Files.POS_TEX_NORMAL_LAYOUT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
|
||||
@Mixin(FogRenderer.class)
|
||||
public class FogUpdateMixin {
|
||||
|
||||
@Inject(method = "setupNoFog", at = @At("TAIL"))
|
||||
private static void onNoFog(CallbackInfo ci) {
|
||||
flywheel$updateFog();
|
||||
}
|
||||
|
||||
@Inject(method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZF)V", remap = false, at = @At("TAIL"))
|
||||
private static void onFog(CallbackInfo ci) {
|
||||
flywheel$updateFog();
|
||||
}
|
||||
|
||||
@Inject(method = "levelFogColor", at = @At("TAIL"))
|
||||
private static void onFogColor(CallbackInfo ci) {
|
||||
flywheel$updateFog();
|
||||
}
|
||||
|
||||
private static void flywheel$updateFog() {
|
||||
Components.FOG_PROVIDER.update();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,9 @@ package com.jozufozu.flywheel.util;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.mojang.math.Matrix3f;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
/**
|
||||
* @see com.jozufozu.flywheel.mixin.matrix.Matrix3fMixin
|
||||
* @see com.jozufozu.flywheel.mixin.matrix.Matrix4fMixin
|
||||
|
@ -14,4 +17,12 @@ public interface MatrixWrite {
|
|||
void flywheel$writeUnsafe(long ptr);
|
||||
|
||||
void flywheel$write(ByteBuffer buf);
|
||||
|
||||
static void write(Matrix4f matrix, ByteBuffer buf) {
|
||||
((MatrixWrite) (Object) matrix).flywheel$write(buf);
|
||||
}
|
||||
|
||||
static void writeUnsafe(Matrix4f matrix, long ptr) {
|
||||
((MatrixWrite) (Object) matrix).flywheel$writeUnsafe(ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,26 +50,6 @@ public class RenderMath {
|
|||
return Math.sqrt(lengthSqr(x, y, z));
|
||||
}
|
||||
|
||||
public static float rad(double angle) {
|
||||
if (angle == 0) return 0;
|
||||
return (float) (angle / 180 * Math.PI);
|
||||
}
|
||||
|
||||
public static float deg(double angle) {
|
||||
if (angle == 0) return 0;
|
||||
return (float) (angle * 180 / Math.PI);
|
||||
}
|
||||
|
||||
public static float angleLerp(double pct, double current, double target) {
|
||||
return (float) (current + getShortestAngleDiff(current, target) * pct);
|
||||
}
|
||||
|
||||
public static float getShortestAngleDiff(double current, double target) {
|
||||
current = current % 360;
|
||||
target = target % 360;
|
||||
return (float) (((((target - current) % 360) + 540) % 360) - 180);
|
||||
}
|
||||
|
||||
public static float diffuseLight(float x, float y, float z, boolean shaded) {
|
||||
if (!shaded) {
|
||||
return 1f;
|
||||
|
|
|
@ -11,8 +11,8 @@ 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.Components;
|
||||
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
|
||||
import com.jozufozu.flywheel.core.material.MaterialShaders;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
|
@ -26,7 +26,7 @@ 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, new Material(Sheets.solidBlockSheet(), MaterialShaders.SHADED_VERTEX, MaterialShaders.DEFAULT_FRAGMENT));
|
||||
private static final BasicModelSupplier MODEL = new BasicModelSupplier(BellInstance::createBellModel, new Material(Sheets.solidBlockSheet(), Components.Files.SHADED_VERTEX, Components.Files.DEFAULT_FRAGMENT));
|
||||
|
||||
private final OrientedPart bell;
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ 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.Materials;
|
||||
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
|
||||
import com.jozufozu.flywheel.core.material.MaterialShaders;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
|
||||
|
@ -25,7 +25,6 @@ import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
|
|||
import net.minecraft.Util;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.world.level.block.AbstractChestBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.ChestBlock;
|
||||
|
@ -37,15 +36,14 @@ import net.minecraft.world.level.block.state.properties.ChestType;
|
|||
|
||||
public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends BlockEntityInstance<T> implements DynamicInstance {
|
||||
|
||||
private static final com.jozufozu.flywheel.api.material.Material CHEST_MATERIAL = new com.jozufozu.flywheel.api.material.Material(Sheets.chestSheet(), MaterialShaders.SHADED_VERTEX, MaterialShaders.DEFAULT_FRAGMENT);
|
||||
private static final BiFunction<ChestType, Material, BasicModelSupplier> LID = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createLidModel(type, mat.sprite()), CHEST_MATERIAL));
|
||||
private static final BiFunction<ChestType, Material, BasicModelSupplier> BASE = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createBaseModel(type, mat.sprite()), CHEST_MATERIAL));
|
||||
private static final BiFunction<ChestType, TextureAtlasSprite, BasicModelSupplier> LID = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createLidModel(type, mat), Materials.CHEST));
|
||||
private static final BiFunction<ChestType, TextureAtlasSprite, BasicModelSupplier> BASE = Util.memoize((type, mat) -> new BasicModelSupplier(() -> createBaseModel(type, mat), Materials.CHEST));
|
||||
|
||||
private final OrientedPart body;
|
||||
private final TransformedPart lid;
|
||||
|
||||
private final Float2FloatFunction lidProgress;
|
||||
private final Material renderMaterial;
|
||||
private final TextureAtlasSprite sprite;
|
||||
@NotNull
|
||||
private final ChestType chestType;
|
||||
private final Quaternion baseRotation;
|
||||
|
@ -58,7 +56,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
|
|||
Block block = blockState.getBlock();
|
||||
|
||||
chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE;
|
||||
renderMaterial = Sheets.chooseMaterial(blockEntity, chestType, isChristmas());
|
||||
sprite = Sheets.chooseMaterial(blockEntity, chestType, isChristmas()).sprite();
|
||||
|
||||
body = baseInstance()
|
||||
.setPosition(getInstancePosition());
|
||||
|
@ -126,14 +124,14 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
|
|||
private OrientedPart baseInstance() {
|
||||
|
||||
return instancerManager.factory(StructTypes.ORIENTED)
|
||||
.model(BASE.apply(chestType, renderMaterial))
|
||||
.model(BASE.apply(chestType, sprite))
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
private TransformedPart lidInstance() {
|
||||
|
||||
return instancerManager.factory(StructTypes.TRANSFORMED)
|
||||
.model(LID.apply(chestType, renderMaterial))
|
||||
.model(LID.apply(chestType, sprite))
|
||||
.createInstance();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,12 +5,11 @@ import org.jetbrains.annotations.NotNull;
|
|||
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.Materials;
|
||||
import com.jozufozu.flywheel.core.Models;
|
||||
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
|
||||
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.TransformedPart;
|
||||
|
@ -19,9 +18,7 @@ import com.jozufozu.flywheel.util.transform.TransformStack;
|
|||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Vector3f;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.vehicle.AbstractMinecart;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
|
@ -30,8 +27,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, new Material(RenderType.entitySolid(MINECART_LOCATION), MaterialShaders.SHADED_VERTEX, MaterialShaders.DEFAULT_FRAGMENT));
|
||||
private static final BasicModelSupplier MODEL = new BasicModelSupplier(MinecartInstance::getBodyModel, Materials.MINECART);
|
||||
|
||||
private final PoseStack stack = new PoseStack();
|
||||
|
||||
|
|
|
@ -7,11 +7,10 @@ import java.util.function.Function;
|
|||
import com.jozufozu.flywheel.api.InstancedPart;
|
||||
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.Materials;
|
||||
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
|
||||
import com.jozufozu.flywheel.core.material.MaterialShaders;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
|
@ -21,7 +20,6 @@ import com.mojang.math.Quaternion;
|
|||
import com.mojang.math.Vector3f;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -31,9 +29,8 @@ import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
|
|||
|
||||
public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntity> implements DynamicInstance {
|
||||
|
||||
private static final Material SHULKER_BOX_MATERIAL = new Material(RenderType.entityCutoutNoCull(Sheets.SHULKER_SHEET), MaterialShaders.SHADED_VERTEX, MaterialShaders.DEFAULT_FRAGMENT);
|
||||
private static final Function<TextureAtlasSprite, BasicModelSupplier> BASE = Util.memoize(it -> new BasicModelSupplier(() -> makeBaseModel(it), SHULKER_BOX_MATERIAL));
|
||||
private static final Function<TextureAtlasSprite, BasicModelSupplier> LID = Util.memoize(it -> new BasicModelSupplier(() -> makeLidModel(it), SHULKER_BOX_MATERIAL));
|
||||
private static final Function<TextureAtlasSprite, BasicModelSupplier> BASE = Util.memoize(it -> new BasicModelSupplier(() -> makeBaseModel(it), Materials.SHULKER));
|
||||
private static final Function<TextureAtlasSprite, BasicModelSupplier> LID = Util.memoize(it -> new BasicModelSupplier(() -> makeLidModel(it), Materials.SHULKER));
|
||||
|
||||
private final TextureAtlasSprite texture;
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#use "flywheel:api/vertex.glsl"
|
||||
#use "flywheel:util/fog.glsl"
|
||||
|
||||
uniform mat4 uViewProjection;
|
||||
uniform vec3 uCameraPos;
|
||||
uniform int uFogShape;
|
||||
#use "flywheel:uniform/fog.glsl"
|
||||
#use "flywheel:uniform/view.glsl"
|
||||
|
||||
void flw_contextVertex() {
|
||||
// TODO: remove this
|
||||
|
@ -11,7 +9,7 @@ void flw_contextVertex() {
|
|||
flw_vertexColor = vec4(flw_vertexNormal, 1.0);
|
||||
#endif
|
||||
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, uCameraPos, uFogShape);
|
||||
gl_Position = uViewProjection * flw_vertexPos;
|
||||
flw_distance = fog_distance(flw_vertexPos.xyz, flw_cameraPos.xyz, flw_fogShape);
|
||||
gl_Position = flw_viewProjection * flw_vertexPos;
|
||||
flw_vertexNormal = normalize(flw_vertexNormal);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#use "flywheel:api/fragment.glsl"
|
||||
#use "flywheel:util/fog.glsl"
|
||||
|
||||
uniform vec2 uFogRange;
|
||||
uniform vec4 uFogColor;
|
||||
#use "flywheel:uniform/fog.glsl"
|
||||
|
||||
uniform sampler2D uCrumblingTex;
|
||||
|
||||
|
@ -37,9 +35,9 @@ void flw_contextFragment() {
|
|||
#endif
|
||||
|
||||
#ifdef COLOR_FOG
|
||||
color = linear_fog(color, flw_distance, uFogRange.x, uFogRange.y, uFogColor);
|
||||
color = linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
|
||||
#elif defined(FADE_FOG)
|
||||
color = linear_fog_fade(color, flw_distance, uFogRange.x, uFogRange.y);
|
||||
color = linear_fog_fade(color, flw_distance, flw_fogRange.x, flw_fogRange.y);
|
||||
#endif
|
||||
|
||||
fragColor = color;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#use "flywheel:api/fragment.glsl"
|
||||
#use "flywheel:util/fog.glsl"
|
||||
#use "flywheel:uniform/fog.glsl"
|
||||
|
||||
// optimize discard usage
|
||||
#ifdef ALPHA_DISCARD
|
||||
|
@ -8,9 +9,6 @@ layout (depth_greater) out float gl_FragDepth;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
uniform vec2 uFogRange;
|
||||
uniform vec4 uFogColor;
|
||||
|
||||
uniform sampler2D uBlockAtlas;
|
||||
uniform sampler2D uLightMap;
|
||||
|
||||
|
@ -28,9 +26,9 @@ void flw_contextFragment() {
|
|||
#endif
|
||||
|
||||
#ifdef COLOR_FOG
|
||||
color = linear_fog(color, flw_distance, uFogRange.x, uFogRange.y, uFogColor);
|
||||
color = linear_fog(color, flw_distance, flw_fogRange.x, flw_fogRange.y, flw_fogColor);
|
||||
#elif defined(FADE_FOG)
|
||||
color = linear_fog_fade(color, flw_distance, uFogRange.x, uFogRange.y);
|
||||
color = linear_fog_fade(color, flw_distance, flw_fogRange.x, flw_fogRange.y);
|
||||
#endif
|
||||
|
||||
fragColor = color;
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#use "flywheel:api/vertex.glsl"
|
||||
#use "flywheel:util/diffuse.glsl"
|
||||
|
||||
uniform int uConstantAmbientLight;
|
||||
#use "flywheel:uniform/view.glsl"
|
||||
|
||||
void flw_materialVertex() {
|
||||
flw_vertexNormal = normalize(flw_vertexNormal);
|
||||
|
||||
float diffuseFactor;
|
||||
if (uConstantAmbientLight == 1) {
|
||||
if (flw_constantAmbientLight == 1) {
|
||||
diffuseFactor = diffuseNether(flw_vertexNormal);
|
||||
} else {
|
||||
diffuseFactor = diffuse(flw_vertexNormal);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
layout(std140, binding = 1) uniform flw_fog {
|
||||
vec4 flw_fogColor;
|
||||
vec2 flw_fogRange;
|
||||
int flw_fogShape;
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
layout(std140, binding = 0) uniform flw_view {
|
||||
mat4 flw_viewProjection;
|
||||
vec4 flw_cameraPos;
|
||||
int flw_constantAmbientLight;
|
||||
};
|
|
@ -14,6 +14,7 @@
|
|||
"ClientLevelMixin",
|
||||
"EntityTypeMixin",
|
||||
"FixFabulousDepthMixin",
|
||||
"FogUpdateMixin",
|
||||
"FrustumMixin",
|
||||
"GlStateManagerMixin",
|
||||
"InstanceAddMixin",
|
||||
|
|
Loading…
Reference in a new issue