From 9352ef9ede74d4cf68b448df6449ce9ed00b1c26 Mon Sep 17 00:00:00 2001 From: JozsefA Date: Sat, 22 May 2021 17:45:01 -0700 Subject: [PATCH] Json program specs, new extension/gamestate system. - Program specs are now loaded from json instead of being defined in code and registered manually. - Within the json spec, a program can define a list of states. - A state consists of: - A "when" clause. - A list of strings to be #defined. - A list of extensions to apply at program link time. - Each frame, the first state whose "when" clause returns true will be used. - A when clause consists of: - A state provider defined by a resource location. - A value to match. - When the value returned by the provider matches the value defined in the when clause, the when clause is considered to be 'true'. - There is syntactic sugar for when a provider returns a boolean value. - This system is in its infancy, and there is plenty of room for improvement. --- .../jozufozu/flywheel/backend/Backend.java | 6 +- .../flywheel/backend/ResourceUtil.java | 9 +++ .../flywheel/backend/ShaderContext.java | 22 +++--- .../flywheel/backend/ShaderLoader.java | 43 +++++++++++- .../backend/core/CrumblingProgram.java | 6 +- .../backend/core/FogMultiProgram.java | 59 ---------------- .../flywheel/backend/core/WorldContext.java | 59 ++++++++++------ .../backend/core/WorldTileRenderer.java | 2 +- .../core/shader/ExtensibleGlProgram.java | 23 ++++--- .../flywheel/backend/core/shader/FogMode.java | 27 +------- .../flywheel/backend/core/shader/GlFog.java | 8 +-- .../backend/core/shader/GlFogMode.java | 38 ---------- .../{gl => core}/shader/IMultiProgram.java | 4 +- .../core/shader/IProgramExtension.java | 17 ----- .../backend/core/shader/ProgramExtender.java | 18 ----- .../backend/core/shader/ProgramSpec.java | 22 ------ .../{gl => core}/shader/ShaderCallback.java | 4 +- .../backend/core/shader/SingleProgram.java | 44 ------------ .../shader/StateSensitiveMultiProgram.java | 54 +++++++++++++++ .../backend/core/shader/WorldFog.java | 47 +++++++++++++ .../backend/core/shader/WorldProgram.java | 5 +- .../shader/extension/IExtensionInstance.java | 14 ++++ .../shader/extension/IProgramExtension.java | 26 +++++++ .../extension/UnitExtensionInstance.java | 23 +++++++ .../shader/gamestate/FogStateProvider.java | 22 ++++++ .../shader/gamestate/IGameStateProvider.java | 15 ++++ .../gamestate/NormalDebugStateProvider.java | 26 +++++++ .../gamestate/RainbowDebugStateProvider.java | 27 ++++++++ .../shader/spec/BooleanContextCondition.java | 37 ++++++++++ .../shader/spec/IBooleanStateProvider.java | 13 ++++ .../core/shader/spec/IContextCondition.java | 14 ++++ .../backend/core/shader/spec/ProgramSpec.java | 61 ++++++++++++++++ .../core/shader/spec/ProgramState.java | 67 ++++++++++++++++++ .../core/shader/spec/SpecMetaRegistry.java | 69 +++++++++++++++++++ .../shader/spec/SpecificValueCondition.java | 42 +++++++++++ .../flywheel/backend/gl/shader/GLSLType.java | 45 ------------ .../backend/gl/shader/ShaderSpecLoader.java | 10 --- .../instancing/InstancedTileRenderer.java | 2 +- .../backend/instancing/MaterialSpec.java | 7 +- .../backend/instancing/RenderMaterial.java | 2 +- .../com/jozufozu/flywheel/util/CodecUtil.java | 26 +++++++ .../java/com/jozufozu/flywheel/util/Pair.java | 68 ++++++++++++++++++ .../com/simibubi/create/CreateClient.java | 2 - .../render/ContraptionProgram.java | 6 +- .../render/ContraptionRenderDispatcher.java | 7 +- .../foundation/render/AllMaterialSpecs.java | 2 +- .../foundation/render/AllProgramSpecs.java | 37 +++------- .../render/effects/EffectsContext.java | 15 +++- .../render/effects/SphereFilterProgram.java | 11 ++- .../assets/create/flywheel/programs/belt.json | 33 +++++++++ .../create/flywheel/programs/chromatic.json | 4 ++ .../flywheel/programs/contraption_actor.json | 29 ++++++++ .../programs/contraption_structure.json | 29 ++++++++ .../assets/create/flywheel/programs/flap.json | 29 ++++++++ .../create/flywheel/programs/rotating.json | 33 +++++++++ .../assets/create/flywheel/shaders/belt.vert | 4 +- .../flywheel/shaders/contraption_actor.vert | 2 +- .../shaders/contraption_structure.vert | 2 +- .../assets/create/flywheel/shaders/flap.vert | 2 +- .../create/flywheel/shaders/rotating.vert | 4 +- .../flywheel/flywheel/programs/model.json | 29 ++++++++ .../flywheel/flywheel/programs/oriented.json | 29 ++++++++ .../flywheel/flywheel/shaders/model.vert | 2 +- .../flywheel/flywheel/shaders/oriented.vert | 2 +- 64 files changed, 1053 insertions(+), 393 deletions(-) delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/FogMultiProgram.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFogMode.java rename src/main/java/com/jozufozu/flywheel/backend/{gl => core}/shader/IMultiProgram.java (80%) delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/IProgramExtension.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramExtender.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramSpec.java rename src/main/java/com/jozufozu/flywheel/backend/{gl => core}/shader/ShaderCallback.java (74%) delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/SingleProgram.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/StateSensitiveMultiProgram.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldFog.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IExtensionInstance.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IProgramExtension.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/UnitExtensionInstance.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/FogStateProvider.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/IGameStateProvider.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/NormalDebugStateProvider.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/RainbowDebugStateProvider.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/BooleanContextCondition.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IBooleanStateProvider.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IContextCondition.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramSpec.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramState.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecMetaRegistry.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecificValueCondition.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/gl/shader/GLSLType.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderSpecLoader.java create mode 100644 src/main/java/com/jozufozu/flywheel/util/CodecUtil.java create mode 100644 src/main/java/com/jozufozu/flywheel/util/Pair.java create mode 100644 src/main/resources/assets/create/flywheel/programs/belt.json create mode 100644 src/main/resources/assets/create/flywheel/programs/chromatic.json create mode 100644 src/main/resources/assets/create/flywheel/programs/contraption_actor.json create mode 100644 src/main/resources/assets/create/flywheel/programs/contraption_structure.json create mode 100644 src/main/resources/assets/create/flywheel/programs/flap.json create mode 100644 src/main/resources/assets/create/flywheel/programs/rotating.json create mode 100644 src/main/resources/assets/flywheel/flywheel/programs/model.json create mode 100644 src/main/resources/assets/flywheel/flywheel/programs/oriented.json diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index a704b8273..fc0b3ac8a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -23,8 +23,8 @@ import org.lwjgl.opengl.GLCapabilities; import com.jozufozu.flywheel.backend.core.CrumblingRenderer; import com.jozufozu.flywheel.backend.core.WorldContext; import com.jozufozu.flywheel.backend.core.WorldTileRenderer; -import com.jozufozu.flywheel.backend.core.shader.ProgramSpec; import com.jozufozu.flywheel.backend.core.shader.WorldProgram; +import com.jozufozu.flywheel.backend.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.jozufozu.flywheel.backend.instancing.IFlywheelWorld; @@ -137,6 +137,10 @@ public class Backend { return spec; } + public static ProgramSpec getSpec(ResourceLocation name) { + return programSpecRegistry.get(name); + } + public static boolean isFlywheelWorld(World world) { return world == Minecraft.getInstance().world || (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/ResourceUtil.java b/src/main/java/com/jozufozu/flywheel/backend/ResourceUtil.java index 3a80b026e..a8294d3d1 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ResourceUtil.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ResourceUtil.java @@ -7,4 +7,13 @@ public class ResourceUtil { public static ResourceLocation subPath(ResourceLocation root, String subPath) { return new ResourceLocation(root.getNamespace(), root.getPath() + subPath); } + + public static ResourceLocation removePrefixUnchecked(ResourceLocation full, String root) { + return new ResourceLocation(full.getNamespace(), full.getPath().substring(root.length())); + } + + public static ResourceLocation trim(ResourceLocation loc, String prefix, String suffix) { + String path = loc.getPath(); + return new ResourceLocation(loc.getNamespace(), path.substring(prefix.length(), path.length() - suffix.length())); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java index 89ab4e48f..0a86e017a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java @@ -4,25 +4,23 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import com.jozufozu.flywheel.backend.core.shader.ProgramSpec; +import com.jozufozu.flywheel.backend.core.shader.IMultiProgram; +import com.jozufozu.flywheel.backend.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram; -import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.ShaderTransformer; +import net.minecraft.util.ResourceLocation; + public abstract class ShaderContext

{ - public final Map> programs = new HashMap<>(); + protected final Map> programs = new HashMap<>(); - protected final ShaderSpecLoader

specLoader; protected ShaderTransformer transformer = new ShaderTransformer(); - public ShaderContext(ShaderSpecLoader

specLoader) { - this.specLoader = specLoader; - } + public ShaderContext() { } // TODO: Untangle the loading functions @@ -31,14 +29,16 @@ public abstract class ShaderContext

{ */ public abstract void load(ShaderLoader loader); + protected abstract IMultiProgram

loadSpecInternal(ShaderLoader loader, ProgramSpec spec); + public void loadProgramFromSpec(ShaderLoader loader, ProgramSpec programSpec) { try { - programs.put(programSpec, specLoader.create(loader, this, programSpec)); + programs.put(programSpec.name, loadSpecInternal(loader, programSpec)); Backend.log.debug("Loaded program {}", programSpec.name); } catch (Exception e) { - Backend.log.error("program '{}': {}", programSpec.name, e.getMessage()); + Backend.log.error("Program '{}': {}", programSpec.name, e); loader.notifyError(); } } @@ -66,7 +66,7 @@ public abstract class ShaderContext

{ } - public P getProgram(ProgramSpec spec) { + public P getProgram(ResourceLocation spec) { return programs.get(spec).get(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java index 2dbf1a100..848b5943c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderLoader.java @@ -27,6 +27,11 @@ import javax.annotation.Nonnull; import org.lwjgl.system.MemoryUtil; import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.jozufozu.flywheel.backend.core.shader.spec.ProgramSpec; +import com.jozufozu.flywheel.backend.core.shader.spec.SpecMetaRegistry; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.shader.GlShader; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; @@ -34,6 +39,9 @@ import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.JsonOps; import net.minecraft.resources.IResource; import net.minecraft.resources.IResourceManager; @@ -43,6 +51,7 @@ import net.minecraftforge.resource.VanillaResourceType; public class ShaderLoader { public static final String SHADER_DIR = "flywheel/shaders/"; + public static final String PROGRAM_DIR = "flywheel/programs/"; public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); // #flwinclude <"valid_namespace:valid/path_to_file.glsl"> @@ -52,6 +61,7 @@ public class ShaderLoader { private final Map shaderSource = new HashMap<>(); private boolean shouldCrash; + private final Gson gson = new GsonBuilder().create(); void onResourceManagerReload(IResourceManager manager, Predicate predicate) { if (predicate.test(VanillaResourceType.SHADERS)) { @@ -63,6 +73,10 @@ public class ShaderLoader { shouldCrash = false; + SpecMetaRegistry.init(); + + loadProgramSpecs(manager); + loadShaderSources(manager); for (ShaderContext context : Backend.contexts) { @@ -70,7 +84,7 @@ public class ShaderLoader { } if (shouldCrash) { - throw new ShaderLoadingException("could not load all shaders, see log for details"); + throw new ShaderLoadingException("Could not load all shaders, see log for details"); } Backend.log.info("Loaded all shader programs."); @@ -81,6 +95,30 @@ public class ShaderLoader { } } + private void loadProgramSpecs(IResourceManager manager) { + Collection programSpecs = manager.getAllResourceLocations(PROGRAM_DIR, s -> s.endsWith(".json")); + + for (ResourceLocation location : programSpecs) { + try { + IResource file = manager.getResource(location); + + String s = readToString(file.getInputStream()); + + ResourceLocation specName = ResourceUtil.trim(location, PROGRAM_DIR, ".json"); + + DataResult> result = ProgramSpec.CODEC.decode(JsonOps.INSTANCE, gson.fromJson(s, JsonElement.class)); + + ProgramSpec spec = result.get().orThrow().getFirst(); + + spec.setName(specName); + + Backend.register(spec); + } catch (Exception e) { + Backend.log.error(e); + } + } + } + public void notifyError() { shouldCrash = true; } @@ -110,8 +148,7 @@ public class ShaderLoader { String file = readToString(resource.getInputStream()); - ResourceLocation name = new ResourceLocation(location.getNamespace(), - location.getPath().substring(SHADER_DIR.length())); + ResourceLocation name = ResourceUtil.removePrefixUnchecked(location, SHADER_DIR); shaderSource.put(name, file); } catch (IOException e) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/CrumblingProgram.java b/src/main/java/com/jozufozu/flywheel/backend/core/CrumblingProgram.java index 2c1606813..1bdf177e9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/core/CrumblingProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/CrumblingProgram.java @@ -4,16 +4,16 @@ import static org.lwjgl.opengl.GL20.glUniform2f; import java.util.List; -import com.jozufozu.flywheel.backend.core.shader.ProgramExtender; import com.jozufozu.flywheel.backend.core.shader.WorldProgram; +import com.jozufozu.flywheel.backend.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.backend.loading.Program; public class CrumblingProgram extends WorldProgram { protected final int uTextureScale; protected int uCrumbling; - public CrumblingProgram(Program program, List fogFactory) { - super(program, fogFactory); + public CrumblingProgram(Program program, List extensions) { + super(program, extensions); uTextureScale = getUniformLocation("uTextureScale"); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/FogMultiProgram.java b/src/main/java/com/jozufozu/flywheel/backend/core/FogMultiProgram.java deleted file mode 100644 index babe5d039..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/core/FogMultiProgram.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.jozufozu.flywheel.backend.core; - -import java.util.Collections; -import java.util.EnumMap; -import java.util.Map; - -import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.ShaderLoader; -import com.jozufozu.flywheel.backend.core.shader.ExtensibleGlProgram; -import com.jozufozu.flywheel.backend.core.shader.GlFog; -import com.jozufozu.flywheel.backend.core.shader.GlFogMode; -import com.jozufozu.flywheel.backend.core.shader.ProgramSpec; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram; -import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader; -import com.jozufozu.flywheel.backend.loading.Program; - -public class FogMultiProgram

implements IMultiProgram

{ - - private final Map programs; - - public FogMultiProgram(Map programs) { - this.programs = programs; - } - - @Override - public P get() { - return programs.get(GlFog.getFogMode()); - } - - @Override - public void delete() { - programs.values().forEach(GlProgram::delete); - } - - public static class SpecLoader

implements ShaderSpecLoader

{ - - private final ExtensibleGlProgram.Factory

factory; - - public SpecLoader(ExtensibleGlProgram.Factory

factory) { - this.factory = factory; - } - - @Override - public IMultiProgram

create(ShaderLoader loader, ShaderContext

ctx, ProgramSpec spec) { - Map programs = new EnumMap<>(GlFogMode.class); - - for (GlFogMode fogMode : GlFogMode.values()) { - Program builder = ctx.loadProgram(loader, spec, fogMode.getDefines()); - - programs.put(fogMode, factory.create(builder, Collections.singletonList(fogMode))); - } - - return new FogMultiProgram<>(programs); - } - - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/backend/core/WorldContext.java index 0bf84e0c9..008e5c7a9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/WorldContext.java @@ -12,10 +12,11 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderLoader; -import com.jozufozu.flywheel.backend.core.shader.ProgramSpec; +import com.jozufozu.flywheel.backend.core.shader.ExtensibleGlProgram; +import com.jozufozu.flywheel.backend.core.shader.IMultiProgram; +import com.jozufozu.flywheel.backend.core.shader.StateSensitiveMultiProgram; import com.jozufozu.flywheel.backend.core.shader.WorldProgram; -import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram; -import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader; +import com.jozufozu.flywheel.backend.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.instancing.MaterialSpec; import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate; @@ -32,45 +33,59 @@ public class WorldContext

extends ShaderContext

{ private static final String declaration = "#flwbuiltins"; private static final Pattern builtinPattern = Pattern.compile(declaration); - public static final WorldContext INSTANCE = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/world"), new FogMultiProgram.SpecLoader<>(WorldProgram::new)); - public static final WorldContext CRUMBLING = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/crumbling"), new FogMultiProgram.SpecLoader<>(CrumblingProgram::new)); + public static final WorldContext INSTANCE = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/world"), WorldProgram::new); + public static final WorldContext CRUMBLING = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/crumbling"), CrumblingProgram::new); - protected ProgramTemplate template; protected final ResourceLocation name; - protected final Supplier> specStream; - protected final TemplateFactory templateFactory; + private final ExtensibleGlProgram.Factory

factory; + protected Supplier> specStream; + protected TemplateFactory templateFactory; private final Map builtins = new EnumMap<>(ShaderType.class); private final Map builtinSources = new EnumMap<>(ShaderType.class); - public WorldContext(ResourceLocation root, ShaderSpecLoader

loader) { - this(root, loader, () -> Backend.allMaterials() - .stream() - .map(MaterialSpec::getProgramSpec), InstancedArraysTemplate::new); - } - - public WorldContext(ResourceLocation root, ShaderSpecLoader

loader, Supplier> specStream, TemplateFactory templateFactory) { - super(loader); + public WorldContext(ResourceLocation root, ExtensibleGlProgram.Factory

factory) { + this.factory = factory; this.name = root; - this.specStream = specStream; - this.templateFactory = templateFactory; builtins.put(ShaderType.FRAGMENT, ResourceUtil.subPath(root, "/builtin.frag")); builtins.put(ShaderType.VERTEX, ResourceUtil.subPath(root, "/builtin.vert")); + + specStream = () -> Backend.allMaterials() + .stream() + .map(MaterialSpec::getProgramSpec); + + templateFactory = InstancedArraysTemplate::new; } + public WorldContext

setSpecStream(Supplier> specStream) { + this.specStream = specStream; + return this; + } + + public WorldContext

setTemplateFactory(TemplateFactory templateFactory) { + this.templateFactory = templateFactory; + return this; + } + + @Override + protected IMultiProgram

loadSpecInternal(ShaderLoader loader, ProgramSpec spec) { + return new StateSensitiveMultiProgram<>(loader, factory, this, spec); + } + + protected ProgramTemplate template; @Override public void load(ShaderLoader loader) { programs.values().forEach(IMultiProgram::delete); programs.clear(); - Backend.log.info("loading context '{}'", name); + Backend.log.info("Loading context '{}'", name); try { builtins.forEach((type, resourceLocation) -> builtinSources.put(type, loader.getShaderSource(resourceLocation))); } catch (ShaderLoadingException e) { loader.notifyError(); - Backend.log.error(String.format("could not find builtin: %s", e.getMessage())); + Backend.log.error(String.format("Could not find builtin: %s", e.getMessage())); return; } @@ -83,7 +98,9 @@ public class WorldContext

extends ShaderContext

{ .pushStage(template) .pushStage(loader::processIncludes); - specStream.get().forEach(spec -> loadProgramFromSpec(loader, spec)); + specStream.get() + .map(Backend::getSpec) + .forEach(spec -> loadProgramFromSpec(loader, spec)); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/WorldTileRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/core/WorldTileRenderer.java index 1e04b9edc..5401bd444 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/core/WorldTileRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/WorldTileRenderer.java @@ -2,8 +2,8 @@ package com.jozufozu.flywheel.backend.core; import java.util.ArrayList; +import com.jozufozu.flywheel.backend.core.shader.ShaderCallback; import com.jozufozu.flywheel.backend.core.shader.WorldProgram; -import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback; import com.jozufozu.flywheel.backend.instancing.InstancedTileRenderer; import net.minecraft.client.renderer.ActiveRenderInfo; diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/ExtensibleGlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/ExtensibleGlProgram.java index 701122ea6..a582595b9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/ExtensibleGlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/ExtensibleGlProgram.java @@ -1,18 +1,20 @@ package com.jozufozu.flywheel.backend.core.shader; +import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import com.jozufozu.flywheel.backend.core.shader.extension.IExtensionInstance; +import com.jozufozu.flywheel.backend.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.loading.Program; /** * A shader program that be arbitrarily "extended". This class can take in any number of program extensions, and - * will initialize them and then call their {@link IProgramExtension#bind() bind} function every subsequent time this + * will initialize them and then call their {@link IExtensionInstance#bind() bind} function every subsequent time this * program is bound. An "extension" is something that interacts with the shader program in a way that is invisible to * the caller using the program. This is used by some programs to implement the different fog modes. Other uses might * include binding extra textures to allow for blocks to have normal maps, for example. As the extensions are @@ -21,15 +23,18 @@ import com.jozufozu.flywheel.backend.loading.Program; */ public class ExtensibleGlProgram extends GlProgram { - protected final List extensions; + protected final List extensions; - public ExtensibleGlProgram(Program program, @Nullable List extensions) { + public ExtensibleGlProgram(Program program, @Nullable List extensions) { super(program); if (extensions != null) { - this.extensions = extensions.stream() - .map(e -> e.create(this)) - .collect(Collectors.toList()); + List list = new ArrayList<>(); + for (IProgramExtension e : extensions) { + IExtensionInstance extension = e.create(this); + list.add(extension); + } + this.extensions = list; } else { this.extensions = Collections.emptyList(); } @@ -39,7 +44,7 @@ public class ExtensibleGlProgram extends GlProgram { public void bind() { super.bind(); - extensions.forEach(IProgramExtension::bind); + extensions.forEach(IExtensionInstance::bind); } @Override @@ -57,7 +62,7 @@ public class ExtensibleGlProgram extends GlProgram { public interface Factory

{ @Nonnull - P create(Program program, @Nullable List extensions); + P create(Program program, @Nullable List extensions); default P create(Program program) { return create(program, null); diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/FogMode.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/FogMode.java index 5e88019d2..b8c80f3f5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/FogMode.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/FogMode.java @@ -3,32 +3,14 @@ package com.jozufozu.flywheel.backend.core.shader; import org.lwjgl.opengl.GL20; import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.backend.core.shader.extension.IExtensionInstance; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import net.minecraft.util.ResourceLocation; public abstract class FogMode { - public static class None implements IProgramExtension { - - public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "fog_none"); - - public None(GlProgram program) { - - } - - @Override - public void bind() { - - } - - @Override - public ResourceLocation name() { - return NAME; - } - } - - public static class Linear implements IProgramExtension { + public static class Linear implements IExtensionInstance { public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "fog_linear"); @@ -52,7 +34,7 @@ public abstract class FogMode { } } - public static class Exp2 implements IProgramExtension { + public static class Exp2 implements IExtensionInstance { public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "fog_exp2"); @@ -75,7 +57,4 @@ public abstract class FogMode { return NAME; } } - - public interface Factory extends IProgramExtension { - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFog.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFog.java index 100c1a71d..dd1111425 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFog.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFog.java @@ -27,9 +27,9 @@ public class GlFog { return GlStateManager.FOG.field_179045_d; } - public static GlFogMode getFogMode() { + public static WorldFog getFogMode() { if (!fogEnabled()) { - return GlFogMode.NONE; + return WorldFog.NONE; } int mode = getFogModeGlEnum(); @@ -37,9 +37,9 @@ public class GlFog { switch (mode) { case GL11.GL_EXP2: case GL11.GL_EXP: - return GlFogMode.EXP2; + return WorldFog.EXP2; case GL11.GL_LINEAR: - return GlFogMode.LINEAR; + return WorldFog.LINEAR; default: throw new UnsupportedOperationException("Unknown fog mode: " + mode); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFogMode.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFogMode.java deleted file mode 100644 index 57f1acea6..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/GlFogMode.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.jozufozu.flywheel.backend.core.shader; - -import java.util.Collections; -import java.util.List; - -import com.google.common.collect.Lists; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -public enum GlFogMode implements ProgramExtender { - NONE(FogMode.None::new), - LINEAR(FogMode.Linear::new, "USE_FOG_LINEAR"), - EXP2(FogMode.Exp2::new, "USE_FOG_EXP2"), - ; - - public static final String USE_FOG = "USE_FOG"; - - private final ProgramExtender fogFactory; - private final List defines; - - GlFogMode(ProgramExtender fogFactory) { - this.fogFactory = fogFactory; - this.defines = Collections.emptyList(); - } - - GlFogMode(ProgramExtender fogFactory, String name) { - this.fogFactory = fogFactory; - this.defines = Lists.newArrayList(USE_FOG, name); - } - - public List getDefines() { - return defines; - } - - @Override - public IProgramExtension create(GlProgram program) { - return fogFactory.create(program); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/IMultiProgram.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/IMultiProgram.java similarity index 80% rename from src/main/java/com/jozufozu/flywheel/backend/gl/shader/IMultiProgram.java rename to src/main/java/com/jozufozu/flywheel/backend/core/shader/IMultiProgram.java index 950bcddc1..f4d7478e4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/IMultiProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/IMultiProgram.java @@ -1,4 +1,6 @@ -package com.jozufozu.flywheel.backend.gl.shader; +package com.jozufozu.flywheel.backend.core.shader; + +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; /** * Encapsulates any number of shader programs for use in similar contexts. diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/IProgramExtension.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/IProgramExtension.java deleted file mode 100644 index 4e825fa5c..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/IProgramExtension.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.jozufozu.flywheel.backend.core.shader; - -import net.minecraft.util.ResourceLocation; - -/** - * A program extension to be passed to - */ -public interface IProgramExtension { - - /** - * Bind the extra program state. It is recommended to grab the state information from global variables, - * or local variables passed through a {@link ProgramExtender} closure. - */ - void bind(); - - ResourceLocation name(); -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramExtender.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramExtender.java deleted file mode 100644 index b187fa7d2..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramExtender.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.jozufozu.flywheel.backend.core.shader; - -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; - -/** - * A factory interface for creating {@link IProgramExtension}s. These are what end up being passed in - * during shader program construction. - */ -public interface ProgramExtender { - - /** - * Construct the extension, binding any necessary information using the provided {@link GlProgram}. - * - * @param program The program being extended. - * @return An extension object, possibly initialized using the program. - */ - IProgramExtension create(GlProgram program); -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramSpec.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramSpec.java deleted file mode 100644 index 6474c008c..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/ProgramSpec.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.jozufozu.flywheel.backend.core.shader; - -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.util.ResourceLocation; - -public class ProgramSpec { - - public final ResourceLocation name; - public final ResourceLocation vert; - public final ResourceLocation frag; - - public final List debugModes = new ArrayList<>(); - - public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag) { - this.name = name; - this.vert = vert; - this.frag = frag; - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderCallback.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/ShaderCallback.java similarity index 74% rename from src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderCallback.java rename to src/main/java/com/jozufozu/flywheel/backend/core/shader/ShaderCallback.java index cdf5cf2ff..2bf2f5440 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderCallback.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/ShaderCallback.java @@ -1,4 +1,6 @@ -package com.jozufozu.flywheel.backend.gl.shader; +package com.jozufozu.flywheel.backend.core.shader; + +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; /** * A Callback for when a shader is called. Used to define shader uniforms. diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/SingleProgram.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/SingleProgram.java deleted file mode 100644 index f4da285f3..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/SingleProgram.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.jozufozu.flywheel.backend.core.shader; - -import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.ShaderLoader; -import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import com.jozufozu.flywheel.backend.gl.shader.IMultiProgram; -import com.jozufozu.flywheel.backend.gl.shader.ShaderSpecLoader; -import com.jozufozu.flywheel.backend.loading.Program; - -public class SingleProgram

implements IMultiProgram

{ - final P program; - - public SingleProgram(P program) { - this.program = program; - } - - @Override - public P get() { - return program; - } - - @Override - public void delete() { - program.delete(); - } - - public static class SpecLoader

implements ShaderSpecLoader

{ - final ProgramFactory

factory; - - public SpecLoader(ProgramFactory

factory) { - this.factory = factory; - } - - @Override - public IMultiProgram

create(ShaderLoader loader, ShaderContext

ctx, ProgramSpec spec) { - return new SingleProgram<>(factory.create(ctx.loadProgram(loader, spec, null))); - } - } - - @FunctionalInterface - public interface ProgramFactory

{ - P create(Program program); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/StateSensitiveMultiProgram.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/StateSensitiveMultiProgram.java new file mode 100644 index 000000000..2dbce5473 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/StateSensitiveMultiProgram.java @@ -0,0 +1,54 @@ +package com.jozufozu.flywheel.backend.core.shader; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.jozufozu.flywheel.backend.ShaderContext; +import com.jozufozu.flywheel.backend.ShaderLoader; +import com.jozufozu.flywheel.backend.core.shader.spec.IContextCondition; +import com.jozufozu.flywheel.backend.core.shader.spec.ProgramSpec; +import com.jozufozu.flywheel.backend.core.shader.spec.ProgramState; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; +import com.jozufozu.flywheel.backend.loading.Program; +import com.jozufozu.flywheel.util.Pair; + +public class StateSensitiveMultiProgram

implements IMultiProgram

{ + + List> variants; + P fallback; + + public StateSensitiveMultiProgram(ShaderLoader loader, ExtensibleGlProgram.Factory

factory, ShaderContext

context, ProgramSpec p) { + variants = new ArrayList<>(p.states.size()); + + for (ProgramState state : p.states) { + + Program variant = context.loadProgram(loader, p, state.getDefines()); + + Pair pair = Pair.of(state.getContext(), factory.create(variant, state.getExtensions())); + + variants.add(pair); + } + + fallback = factory.create(context.loadProgram(loader, p, Collections.emptyList())); + } + + @Override + public P get() { + for (Pair variant : variants) { + if (variant.getFirst().get()) + return variant.getSecond(); + } + + return fallback; + } + + @Override + public void delete() { + for (Pair variant : variants) { + variant.getSecond().delete(); + } + + fallback.delete(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldFog.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldFog.java new file mode 100644 index 000000000..1ae189611 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldFog.java @@ -0,0 +1,47 @@ +package com.jozufozu.flywheel.backend.core.shader; + +import java.util.function.Function; + +import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.backend.core.shader.extension.IExtensionInstance; +import com.jozufozu.flywheel.backend.core.shader.extension.IProgramExtension; +import com.jozufozu.flywheel.backend.core.shader.extension.UnitExtensionInstance; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; + +import net.minecraft.util.ResourceLocation; + +public enum WorldFog implements IProgramExtension { + NONE("none", UnitExtensionInstance::new), + LINEAR("linear", FogMode.Linear::new), + EXP2("exp2", FogMode.Exp2::new), + ; + + private final ResourceLocation id; + private final String name; + private final Function fogFactory; + + WorldFog(String name, Function fogFactory) { + this.id = new ResourceLocation(Flywheel.ID, "fog_" + name); + this.name = name; + this.fogFactory = fogFactory; + } + + public String getName() { + return name; + } + + @Override + public IExtensionInstance create(GlProgram program) { + return fogFactory.apply(program); + } + + @Override + public ResourceLocation getID() { + return id; + } + + @Override + public String toString() { + return name; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldProgram.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldProgram.java index 749be410b..c83c4ba6f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/WorldProgram.java @@ -5,6 +5,7 @@ import static org.lwjgl.opengl.GL20.glUniform3f; import java.util.List; +import com.jozufozu.flywheel.backend.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.backend.loading.Program; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -18,8 +19,8 @@ public class WorldProgram extends ExtensibleGlProgram { protected int uBlockAtlas; protected int uLightMap; - public WorldProgram(Program program, List fogFactory) { - super(program, fogFactory); + public WorldProgram(Program program, List extensions) { + super(program, extensions); uTime = getUniformLocation("uTime"); uViewProjection = getUniformLocation("uViewProjection"); uCameraPos = getUniformLocation("uCameraPos"); diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IExtensionInstance.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IExtensionInstance.java new file mode 100644 index 000000000..586121bce --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IExtensionInstance.java @@ -0,0 +1,14 @@ +package com.jozufozu.flywheel.backend.core.shader.extension; + +import net.minecraft.util.ResourceLocation; + +public interface IExtensionInstance { + + /** + * Bind the extra program state. It is recommended to grab the state information from global variables, + * or local variables passed through a {@link IProgramExtension}. + */ + void bind(); + + ResourceLocation name(); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IProgramExtension.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IProgramExtension.java new file mode 100644 index 000000000..f0ad388b7 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/IProgramExtension.java @@ -0,0 +1,26 @@ +package com.jozufozu.flywheel.backend.core.shader.extension; + +import com.jozufozu.flywheel.backend.core.shader.spec.SpecMetaRegistry; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; +import com.mojang.serialization.Codec; + +import net.minecraft.util.ResourceLocation; + +/** + * A factory interface for creating {@link IExtensionInstance}s. These are what end up being passed in + * during shader program construction. + */ +public interface IProgramExtension { + + Codec CODEC = ResourceLocation.CODEC.xmap(SpecMetaRegistry::getExtension, IProgramExtension::getID); + + /** + * Construct the extension, binding any necessary information using the provided {@link GlProgram}. + * + * @param program The program being extended. + * @return An extension object, possibly initialized using the program. + */ + IExtensionInstance create(GlProgram program); + + ResourceLocation getID(); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/UnitExtensionInstance.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/UnitExtensionInstance.java new file mode 100644 index 000000000..a66e1a30d --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/extension/UnitExtensionInstance.java @@ -0,0 +1,23 @@ +package com.jozufozu.flywheel.backend.core.shader.extension; + +import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; + +import net.minecraft.util.ResourceLocation; + +public class UnitExtensionInstance implements IExtensionInstance { + + public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "unit"); + + public UnitExtensionInstance(GlProgram program) { } + + @Override + public void bind() { + + } + + @Override + public ResourceLocation name() { + return NAME; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/FogStateProvider.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/FogStateProvider.java new file mode 100644 index 000000000..6abddede4 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/FogStateProvider.java @@ -0,0 +1,22 @@ +package com.jozufozu.flywheel.backend.core.shader.gamestate; + +import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.backend.core.shader.GlFog; + +import net.minecraft.util.ResourceLocation; + +public class FogStateProvider implements IGameStateProvider { + + public static final FogStateProvider INSTANCE = new FogStateProvider(); + public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "fog_mode"); + + @Override + public ResourceLocation getID() { + return NAME; + } + + @Override + public Object getValue() { + return GlFog.getFogMode(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/IGameStateProvider.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/IGameStateProvider.java new file mode 100644 index 000000000..82fe2653c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/IGameStateProvider.java @@ -0,0 +1,15 @@ +package com.jozufozu.flywheel.backend.core.shader.gamestate; + +import com.jozufozu.flywheel.backend.core.shader.spec.SpecMetaRegistry; +import com.mojang.serialization.Codec; + +import net.minecraft.util.ResourceLocation; + +public interface IGameStateProvider { + + Codec CODEC = ResourceLocation.CODEC.xmap(SpecMetaRegistry::getStateProvider, IGameStateProvider::getID); + + ResourceLocation getID(); + + Object getValue(); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/NormalDebugStateProvider.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/NormalDebugStateProvider.java new file mode 100644 index 000000000..b87943e22 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/NormalDebugStateProvider.java @@ -0,0 +1,26 @@ +package com.jozufozu.flywheel.backend.core.shader.gamestate; + +import com.jozufozu.flywheel.Flywheel; +import com.jozufozu.flywheel.backend.core.shader.spec.IBooleanStateProvider; + +import net.minecraft.util.ResourceLocation; + +public class NormalDebugStateProvider implements IBooleanStateProvider { + + public static final NormalDebugStateProvider INSTANCE = new NormalDebugStateProvider(); + public static final ResourceLocation NAME = new ResourceLocation(Flywheel.ID, "normal_debug"); + + protected NormalDebugStateProvider() { + + } + + @Override + public boolean isTrue() { + return false; + } + + @Override + public ResourceLocation getID() { + return NAME; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/RainbowDebugStateProvider.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/RainbowDebugStateProvider.java new file mode 100644 index 000000000..a49cf28e8 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/gamestate/RainbowDebugStateProvider.java @@ -0,0 +1,27 @@ +package com.jozufozu.flywheel.backend.core.shader.gamestate; + +import com.jozufozu.flywheel.backend.core.shader.spec.IBooleanStateProvider; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.KineticDebugger; + +import net.minecraft.util.ResourceLocation; + +public class RainbowDebugStateProvider implements IBooleanStateProvider { + + public static final RainbowDebugStateProvider INSTANCE = new RainbowDebugStateProvider(); + public static final ResourceLocation NAME = new ResourceLocation(Create.ID, "rainbow_debug"); + + protected RainbowDebugStateProvider() { + + } + + @Override + public boolean isTrue() { + return KineticDebugger.isActive(); + } + + @Override + public ResourceLocation getID() { + return NAME; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/BooleanContextCondition.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/BooleanContextCondition.java new file mode 100644 index 000000000..ae3dc164c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/BooleanContextCondition.java @@ -0,0 +1,37 @@ +package com.jozufozu.flywheel.backend.core.shader.spec; + +import com.jozufozu.flywheel.backend.core.shader.gamestate.IGameStateProvider; +import com.mojang.serialization.Codec; + +import net.minecraft.util.ResourceLocation; + +public class BooleanContextCondition implements IContextCondition { + + public static final Codec BOOLEAN_SUGAR = IGameStateProvider.CODEC.xmap(gameContext -> { + if (gameContext instanceof IBooleanStateProvider) { + return new BooleanContextCondition(((IBooleanStateProvider) gameContext)); + } + + return null; + }, IContextCondition::contextProvider); + protected final IBooleanStateProvider context; + + public BooleanContextCondition(IBooleanStateProvider context) { + this.context = context; + } + + @Override + public ResourceLocation getID() { + return context.getID(); + } + + @Override + public IGameStateProvider contextProvider() { + return context; + } + + @Override + public boolean get() { + return context.isTrue(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IBooleanStateProvider.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IBooleanStateProvider.java new file mode 100644 index 000000000..3265c11a0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IBooleanStateProvider.java @@ -0,0 +1,13 @@ +package com.jozufozu.flywheel.backend.core.shader.spec; + +import com.jozufozu.flywheel.backend.core.shader.gamestate.IGameStateProvider; + +public interface IBooleanStateProvider extends IGameStateProvider { + + boolean isTrue(); + + @Override + default Boolean getValue() { + return isTrue(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IContextCondition.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IContextCondition.java new file mode 100644 index 000000000..b9499da84 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/IContextCondition.java @@ -0,0 +1,14 @@ +package com.jozufozu.flywheel.backend.core.shader.spec; + +import com.jozufozu.flywheel.backend.core.shader.gamestate.IGameStateProvider; + +import net.minecraft.util.ResourceLocation; + +public interface IContextCondition { + + ResourceLocation getID(); + + IGameStateProvider contextProvider(); + + boolean get(); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramSpec.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramSpec.java new file mode 100644 index 000000000..05c76888f --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramSpec.java @@ -0,0 +1,61 @@ +package com.jozufozu.flywheel.backend.core.shader.spec; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.util.ResourceLocation; + +public class ProgramSpec { + + // TODO: Block model style inheritance? + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + ResourceLocation.CODEC.fieldOf("vert") + .forGetter(ProgramSpec::getVert), + ResourceLocation.CODEC.fieldOf("frag") + .forGetter(ProgramSpec::getFrag), + ProgramState.CODEC.listOf() + .optionalFieldOf("states", Collections.emptyList()) + .forGetter(ProgramSpec::getStates) + ).apply(instance, ProgramSpec::new)); + + public ResourceLocation name; + public final ResourceLocation vert; + public final ResourceLocation frag; + + public final List states; + + public ProgramSpec(ResourceLocation vert, ResourceLocation frag, List states) { + this.vert = vert; + this.frag = frag; + this.states = states; + } + + public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag) { + this.name = name; + this.vert = vert; + this.frag = frag; + this.states = new ArrayList<>(); + } + + public void setName(ResourceLocation name) { + this.name = name; + } + + public ResourceLocation getVert() { + return vert; + } + + public ResourceLocation getFrag() { + return frag; + } + + public List getStates() { + return states; + } + +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramState.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramState.java new file mode 100644 index 000000000..4a39e8b7f --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/ProgramState.java @@ -0,0 +1,67 @@ +package com.jozufozu.flywheel.backend.core.shader.spec; + +import java.util.Collections; +import java.util.List; + +import com.jozufozu.flywheel.backend.core.shader.extension.IProgramExtension; +import com.jozufozu.flywheel.util.CodecUtil; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +public class ProgramState { + + // TODO: Use Codec.dispatch + private static final Codec WHEN = Codec.either( + BooleanContextCondition.BOOLEAN_SUGAR, + SpecificValueCondition.CODEC + ).flatXmap( + either -> either.map(DataResult::success, DataResult::success), + any -> { + if (any instanceof BooleanContextCondition) { + return DataResult.success(Either.left((BooleanContextCondition) any)); + } + + if (any instanceof SpecificValueCondition) { + return DataResult.success(Either.right((SpecificValueCondition) any)); + } + + return DataResult.error("unknown context condition"); + } + ); + + public static final Codec CODEC = RecordCodecBuilder.create(state -> + state.group( + WHEN.fieldOf("when") + .forGetter(ProgramState::getContext), + CodecUtil.oneOrMore(Codec.STRING) + .optionalFieldOf("define", Collections.emptyList()) + .forGetter(ProgramState::getDefines), + CodecUtil.oneOrMore(IProgramExtension.CODEC) + .optionalFieldOf("extend", Collections.emptyList()) + .forGetter(ProgramState::getExtensions) + ).apply(state, ProgramState::new)); + + private final IContextCondition context; + private final List defines; + private final List extensions; + + public ProgramState(IContextCondition context, List defines, List extensions) { + this.context = context; + this.defines = defines; + this.extensions = extensions; + } + + public IContextCondition getContext() { + return context; + } + + public List getDefines() { + return defines; + } + + public List getExtensions() { + return extensions; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecMetaRegistry.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecMetaRegistry.java new file mode 100644 index 000000000..9f26fe448 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecMetaRegistry.java @@ -0,0 +1,69 @@ +package com.jozufozu.flywheel.backend.core.shader.spec; + +import java.util.HashMap; +import java.util.Map; + +import com.jozufozu.flywheel.backend.core.shader.WorldFog; +import com.jozufozu.flywheel.backend.core.shader.extension.IProgramExtension; +import com.jozufozu.flywheel.backend.core.shader.gamestate.FogStateProvider; +import com.jozufozu.flywheel.backend.core.shader.gamestate.IGameStateProvider; +import com.jozufozu.flywheel.backend.core.shader.gamestate.NormalDebugStateProvider; +import com.jozufozu.flywheel.backend.core.shader.gamestate.RainbowDebugStateProvider; + +import net.minecraft.util.ResourceLocation; + +public class SpecMetaRegistry { + + private static final Map registeredExtensions = new HashMap<>(); + private static final Map registeredStateProviders = new HashMap<>(); + + // TODO: proper registration, don't call this from ShaderLoader + private static boolean initialized = false; + public static void init() { + if (initialized) return; + initialized = true; + + register(FogStateProvider.INSTANCE); + register(RainbowDebugStateProvider.INSTANCE); + register(NormalDebugStateProvider.INSTANCE); + + register(WorldFog.LINEAR); + register(WorldFog.EXP2); + } + + public static IGameStateProvider getStateProvider(ResourceLocation location) { + IGameStateProvider out = registeredStateProviders.get(location); + + if (out == null) { + throw new IllegalArgumentException("State provider '" + location + "' does not exist."); + } + + return out; + } + + public static IProgramExtension getExtension(ResourceLocation location) { + IProgramExtension out = registeredExtensions.get(location); + + if (out == null) { + throw new IllegalArgumentException("Extension '" + location + "' does not exist."); + } + + return out; + } + + public static void register(IGameStateProvider context) { + if (registeredStateProviders.containsKey(context.getID())) { + throw new IllegalStateException("Duplicate game state provider: " + context.getID()); + } + + registeredStateProviders.put(context.getID(), context); + } + + public static void register(IProgramExtension extender) { + if (registeredStateProviders.containsKey(extender.getID())) { + throw new IllegalStateException("Duplicate shader extension: " + extender.getID()); + } + + registeredExtensions.put(extender.getID(), extender); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecificValueCondition.java b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecificValueCondition.java new file mode 100644 index 000000000..8b05e3588 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/core/shader/spec/SpecificValueCondition.java @@ -0,0 +1,42 @@ +package com.jozufozu.flywheel.backend.core.shader.spec; + +import com.jozufozu.flywheel.backend.core.shader.gamestate.IGameStateProvider; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.util.ResourceLocation; + +public class SpecificValueCondition implements IContextCondition { + + public static final Codec CODEC = RecordCodecBuilder.create(condition -> condition.group( + IGameStateProvider.CODEC.fieldOf("provider").forGetter(SpecificValueCondition::contextProvider), + Codec.STRING.fieldOf("value").forGetter(SpecificValueCondition::getValue) + ).apply(condition, SpecificValueCondition::new)); + + private final String required; + private final IGameStateProvider context; + + public SpecificValueCondition(IGameStateProvider context, String required) { + this.required = required; + this.context = context; + } + + @Override + public ResourceLocation getID() { + return context.getID(); + } + + public String getValue() { + return required; + } + + @Override + public IGameStateProvider contextProvider() { + return context; + } + + @Override + public boolean get() { + return required.equals(context.getValue().toString()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GLSLType.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GLSLType.java deleted file mode 100644 index 0ef93042d..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GLSLType.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.jozufozu.flywheel.backend.gl.shader; - -import com.jozufozu.flywheel.backend.gl.GlPrimitiveType; - -public class GLSLType { - public static final GLSLType FLOAT = new GLSLType("mat4", GlPrimitiveType.FLOAT, 16); - public static final GLSLType VEC2 = new GLSLType("vec4", GlPrimitiveType.FLOAT, 4); - public static final GLSLType VEC3 = new GLSLType("vec3", GlPrimitiveType.FLOAT, 3); - public static final GLSLType VEC4 = new GLSLType("vec2", GlPrimitiveType.FLOAT, 2); - public static final GLSLType MAT4 = new GLSLType("float", GlPrimitiveType.FLOAT, 1); - - private final String symbol; - private final GlPrimitiveType base; - private final int count; - private final int size; - private final int attributeCount; - - public GLSLType(String symbol, GlPrimitiveType base, int count) { - this.symbol = symbol; - this.base = base; - this.count = count; - this.size = base.getSize() * count; - this.attributeCount = (this.size + 15) / 16; // ceiling division. GLSL vertex attributes can only be 16 bytes wide - } - - public String getSymbol() { - return symbol; - } - - public GlPrimitiveType getBase() { - return base; - } - - public int getCount() { - return count; - } - - public int getSize() { - return size; - } - - public int getAttributeCount() { - return attributeCount; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderSpecLoader.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderSpecLoader.java deleted file mode 100644 index 51ed1d8c1..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/ShaderSpecLoader.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.jozufozu.flywheel.backend.gl.shader; - -import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.ShaderLoader; -import com.jozufozu.flywheel.backend.core.shader.ProgramSpec; - -public interface ShaderSpecLoader

{ - - IMultiProgram

create(ShaderLoader loader, ShaderContext

ctx, ProgramSpec spec); -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedTileRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedTileRenderer.java index 69f81f7a1..8d7c2fe11 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedTileRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedTileRenderer.java @@ -11,8 +11,8 @@ import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.core.WorldContext; import com.jozufozu.flywheel.backend.core.materials.ModelData; import com.jozufozu.flywheel.backend.core.materials.OrientedData; +import com.jozufozu.flywheel.backend.core.shader.ShaderCallback; import com.jozufozu.flywheel.backend.core.shader.WorldProgram; -import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback; import com.simibubi.create.foundation.render.AllMaterialSpecs; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialSpec.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialSpec.java index fc30978b2..7ff1dbcd4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialSpec.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/MaterialSpec.java @@ -1,6 +1,5 @@ package com.jozufozu.flywheel.backend.instancing; -import com.jozufozu.flywheel.backend.core.shader.ProgramSpec; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import net.minecraft.util.ResourceLocation; @@ -9,12 +8,12 @@ public class MaterialSpec { public final ResourceLocation name; - private final ProgramSpec programSpec; + private final ResourceLocation programSpec; private final VertexFormat modelFormat; private final VertexFormat instanceFormat; private final InstanceFactory instanceFactory; - public MaterialSpec(ResourceLocation name, ProgramSpec programSpec, VertexFormat modelFormat, VertexFormat instanceFormat, InstanceFactory instanceFactory) { + public MaterialSpec(ResourceLocation name, ResourceLocation programSpec, VertexFormat modelFormat, VertexFormat instanceFormat, InstanceFactory instanceFactory) { this.name = name; this.programSpec = programSpec; this.modelFormat = modelFormat; @@ -22,7 +21,7 @@ public class MaterialSpec { this.instanceFactory = instanceFactory; } - public ProgramSpec getProgramSpec() { + public ResourceLocation getProgramSpec() { return programSpec; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java index 209516f56..25c85b84b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/RenderMaterial.java @@ -13,9 +13,9 @@ import org.lwjgl.opengl.GL11; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.jozufozu.flywheel.backend.core.PartialModel; +import com.jozufozu.flywheel.backend.core.shader.ShaderCallback; import com.jozufozu.flywheel.backend.core.shader.WorldProgram; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; -import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback; import com.jozufozu.flywheel.util.BufferBuilderReader; import com.jozufozu.flywheel.util.RenderUtil; import com.jozufozu.flywheel.util.VirtualEmptyModelData; diff --git a/src/main/java/com/jozufozu/flywheel/util/CodecUtil.java b/src/main/java/com/jozufozu/flywheel/util/CodecUtil.java new file mode 100644 index 000000000..3b83fac86 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/CodecUtil.java @@ -0,0 +1,26 @@ +package com.jozufozu.flywheel.util; + +import java.util.Collections; +import java.util.List; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; + +public class CodecUtil { + + /** + * Creates a list codec that can be parsed from either a single element or a complete list. + */ + public static Codec> oneOrMore(Codec codec) { + return Codec.either(codec.listOf(), codec) + .xmap( + either -> either.map(l -> l, Collections::singletonList), + list -> { + if (list.size() == 1) { + return Either.right(list.get(0)); + } else { + return Either.left(list); + } + }); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/Pair.java b/src/main/java/com/jozufozu/flywheel/util/Pair.java new file mode 100644 index 000000000..b1e232037 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/Pair.java @@ -0,0 +1,68 @@ +package com.jozufozu.flywheel.util; + +import java.util.Objects; + +public class Pair { + + F first; + S second; + + protected Pair(F first, S second) { + this.first = first; + this.second = second; + } + + public static Pair of(F first, S second) { + return new Pair<>(first, second); + } + + public F getFirst() { + return first; + } + + public S getSecond() { + return second; + } + + public void setFirst(F first) { + this.first = first; + } + + public void setSecond(S second) { + this.second = second; + } + + public Pair copy() { + return Pair.of(first, second); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) + return true; + if (obj instanceof Pair) { + final Pair other = (Pair) obj; + return Objects.equals(first, other.first) && Objects.equals(second, other.second); + } + return false; + } + + @Override + public int hashCode() { + return (nullHash(first) * 31) ^ nullHash(second); + } + + int nullHash(Object o) { + return o == null ? 0 : o.hashCode(); + } + + @Override + public String toString() { + return "(" + first + ", " + second + ")"; + } + + public Pair swap() { + return Pair.of(second, first); + } + +} diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index d9ccf1f64..05401f07f 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -27,7 +27,6 @@ import com.simibubi.create.foundation.item.CustomRenderedItems; import com.simibubi.create.foundation.ponder.content.PonderIndex; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; import com.simibubi.create.foundation.render.AllMaterialSpecs; -import com.simibubi.create.foundation.render.AllProgramSpecs; import com.simibubi.create.foundation.render.CreateFlywheelHandler; import com.simibubi.create.foundation.render.SuperByteBufferCache; import com.simibubi.create.foundation.utility.ghost.GhostBlocks; @@ -87,7 +86,6 @@ public class CreateClient { } public static void clientInit(FMLClientSetupEvent event) { - AllProgramSpecs.init(); AllMaterialSpecs.init(); schematicSender = new ClientSchematicLoader(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java index 203b5c0fa..a343ee9b8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java @@ -4,8 +4,8 @@ import java.util.List; import org.lwjgl.opengl.GL20; -import com.jozufozu.flywheel.backend.core.shader.ProgramExtender; import com.jozufozu.flywheel.backend.core.shader.WorldProgram; +import com.jozufozu.flywheel.backend.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.backend.loading.Program; import net.minecraft.util.math.AxisAlignedBB; @@ -18,8 +18,8 @@ public class ContraptionProgram extends WorldProgram { protected int uLightVolume; - public ContraptionProgram(Program program, List fogFactory) { - super(program, fogFactory); + public ContraptionProgram(Program program, List extensions) { + super(program, extensions); uLightBoxSize = getUniformLocation("uLightBoxSize"); uLightBoxMin = getUniformLocation("uLightBoxMin"); uModel = getUniformLocation("uModel"); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java index 5eb5331f7..5d537347d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java @@ -15,7 +15,6 @@ import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.core.FogMultiProgram; import com.jozufozu.flywheel.backend.core.WorldContext; import com.jozufozu.flywheel.backend.loading.ModelTemplate; import com.mojang.blaze3d.matrix.MatrixStack; @@ -71,8 +70,10 @@ public class ContraptionRenderDispatcher { public static final Compartment> CONTRAPTION = new Compartment<>(); private static final ResourceLocation ctxRoot = new ResourceLocation("create", "context/contraption"); - public static final WorldContext STRUCTURE = new WorldContext<>(ctxRoot, new FogMultiProgram.SpecLoader<>(ContraptionProgram::new), () -> Stream.of(AllProgramSpecs.STRUCTURE), ModelTemplate::new); - public static final WorldContext TILES = new WorldContext<>(ctxRoot, new FogMultiProgram.SpecLoader<>(ContraptionProgram::new)); + public static final WorldContext STRUCTURE = new WorldContext<>(ctxRoot, ContraptionProgram::new) + .setSpecStream(() -> Stream.of(AllProgramSpecs.STRUCTURE)) + .setTemplateFactory(ModelTemplate::new); + public static final WorldContext TILES = new WorldContext<>(ctxRoot, ContraptionProgram::new); public static void tick() { if (Minecraft.getInstance().isGamePaused()) return; diff --git a/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java b/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java index 4a9d1a3da..ce9d21249 100644 --- a/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java +++ b/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java @@ -24,10 +24,10 @@ public class AllMaterialSpecs { .addAttributes(CommonAttributes.VEC3, CommonAttributes.NORMAL, CommonAttributes.UV) .build(); + public static final MaterialSpec ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, UNLIT_MODEL, AllInstanceFormats.ROTATING, RotatingData::new)); public static final MaterialSpec TRANSFORMED = register(new MaterialSpec<>(Locations.MODEL, AllProgramSpecs.MODEL, UNLIT_MODEL, AllInstanceFormats.MODEL, ModelData::new)); public static final MaterialSpec ORIENTED = register(new MaterialSpec<>(Locations.ORIENTED, AllProgramSpecs.ORIENTED, UNLIT_MODEL, AllInstanceFormats.ORIENTED, OrientedData::new)); - public static final MaterialSpec ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, UNLIT_MODEL, AllInstanceFormats.ROTATING, RotatingData::new)); public static final MaterialSpec BELTS = register(new MaterialSpec<>(Locations.BELTS, AllProgramSpecs.BELT, UNLIT_MODEL, AllInstanceFormats.BELT, BeltData::new)); public static final MaterialSpec ACTORS = register(new MaterialSpec<>(Locations.ACTORS, AllProgramSpecs.ACTOR, UNLIT_MODEL, AllInstanceFormats.ACTOR, ActorData::new)); public static final MaterialSpec FLAPS = register(new MaterialSpec<>(Locations.FLAPS, AllProgramSpecs.FLAPS, UNLIT_MODEL, AllInstanceFormats.FLAP, FlapData::new)); diff --git a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java index c6d50eebd..94acc2e71 100644 --- a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java +++ b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java @@ -1,42 +1,21 @@ package com.simibubi.create.foundation.render; -import static com.jozufozu.flywheel.backend.Backend.register; - import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.backend.core.shader.ProgramSpec; import com.simibubi.create.Create; import net.minecraft.util.ResourceLocation; public class AllProgramSpecs { - public static void init() { - // noop, make sure the static field are loaded. - } - public static final ProgramSpec CHROMATIC = register(new ProgramSpec(loc("chromatic"), Locations.EFFECT_VERT, Locations.EFFECT_FRAG)); - public static final ProgramSpec MODEL = register(new ProgramSpec(new ResourceLocation(Flywheel.ID, "model"), Locations.MODEL_VERT, Locations.BLOCK)); - public static final ProgramSpec ORIENTED = register(new ProgramSpec(new ResourceLocation(Flywheel.ID, "oriented"), Locations.ORIENTED, Locations.BLOCK)); - public static final ProgramSpec ROTATING = register(new ProgramSpec(loc("rotating"), Locations.ROTATING, Locations.BLOCK)); - public static final ProgramSpec BELT = register(new ProgramSpec(loc("belt"), Locations.BELT, Locations.BLOCK)); - public static final ProgramSpec FLAPS = register(new ProgramSpec(loc("flap"), Locations.FLAP, Locations.BLOCK)); - public static final ProgramSpec STRUCTURE = register(new ProgramSpec(loc("contraption_structure"), Locations.CONTRAPTION_STRUCTURE, Locations.BLOCK)); - public static final ProgramSpec ACTOR = register(new ProgramSpec(loc("contraption_actor"), Locations.CONTRAPTION_ACTOR, Locations.BLOCK)); + public static final ResourceLocation MODEL = new ResourceLocation(Flywheel.ID, "model");//, Locations.MODEL_VERT, Locations.BLOCK); + public static final ResourceLocation ORIENTED = new ResourceLocation(Flywheel.ID, "oriented");//, Locations.ORIENTED, Locations.BLOCK); - public static class Locations { - public static final ResourceLocation BLOCK = new ResourceLocation(Flywheel.ID, "block.frag"); - - public static final ResourceLocation MODEL_VERT = new ResourceLocation(Flywheel.ID, "model.vert"); - public static final ResourceLocation ORIENTED = new ResourceLocation(Flywheel.ID, "oriented.vert"); - - public static final ResourceLocation ROTATING = loc("rotating.vert"); - public static final ResourceLocation BELT = loc("belt.vert"); - public static final ResourceLocation FLAP = loc("flap.vert"); - public static final ResourceLocation CONTRAPTION_STRUCTURE = loc("contraption_structure.vert"); - public static final ResourceLocation CONTRAPTION_ACTOR = loc("contraption_actor.vert"); - - public static final ResourceLocation EFFECT_VERT = loc("area_effect.vert"); - public static final ResourceLocation EFFECT_FRAG = loc("area_effect.frag"); - } + public static final ResourceLocation ROTATING = loc("rotating"); + public static final ResourceLocation CHROMATIC = loc("chromatic"); + public static final ResourceLocation BELT = loc("belt"); + public static final ResourceLocation FLAPS = loc("flap"); + public static final ResourceLocation STRUCTURE = loc("contraption_structure"); + public static final ResourceLocation ACTOR = loc("contraption_actor"); private static ResourceLocation loc(String name) { return new ResourceLocation(Create.ID, name); diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java index 0f13aa9e8..d0510522f 100644 --- a/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java +++ b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java @@ -1,8 +1,12 @@ package com.simibubi.create.foundation.render.effects; +import java.util.Collections; + +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.ShaderContext; import com.jozufozu.flywheel.backend.ShaderLoader; -import com.jozufozu.flywheel.backend.core.shader.SingleProgram; +import com.jozufozu.flywheel.backend.core.shader.IMultiProgram; +import com.jozufozu.flywheel.backend.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.backend.loading.ShaderTransformer; import com.simibubi.create.foundation.render.AllProgramSpecs; @@ -11,13 +15,18 @@ public class EffectsContext extends ShaderContext { public static final EffectsContext INSTANCE = new EffectsContext(); public EffectsContext() { - super(new SingleProgram.SpecLoader<>(SphereFilterProgram::new)); + super(); + } + + @Override + protected IMultiProgram loadSpecInternal(ShaderLoader loader, ProgramSpec spec) { + return new SphereFilterProgram(loadProgram(loader, spec, Collections.emptyList())); } @Override public void load(ShaderLoader loader) { transformer = new ShaderTransformer() .pushStage(loader::processIncludes); - loadProgramFromSpec(loader, AllProgramSpecs.CHROMATIC); + loadProgramFromSpec(loader, Backend.getSpec(AllProgramSpecs.CHROMATIC)); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/SphereFilterProgram.java b/src/main/java/com/simibubi/create/foundation/render/effects/SphereFilterProgram.java index 80c4b5b67..b11f9c5d4 100644 --- a/src/main/java/com/simibubi/create/foundation/render/effects/SphereFilterProgram.java +++ b/src/main/java/com/simibubi/create/foundation/render/effects/SphereFilterProgram.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL31; +import com.jozufozu.flywheel.backend.core.shader.IMultiProgram; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; @@ -14,7 +15,7 @@ import com.jozufozu.flywheel.backend.loading.Program; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3d; -public class SphereFilterProgram extends GlProgram { +public class SphereFilterProgram extends GlProgram implements IMultiProgram { protected static final int UBO_BINDING = 4; @@ -80,7 +81,7 @@ public class SphereFilterProgram extends GlProgram { } public void uploadFilters(ArrayList filters) { - effectsUBO.bind(GlBufferType.ARRAY_BUFFER); + effectsUBO.bind(); MappedBuffer buffer = effectsUBO.getBuffer(0, BUFFER_SIZE) .putInt(filters.size()) .position(16); @@ -89,7 +90,7 @@ public class SphereFilterProgram extends GlProgram { buffer.flush(); - effectsUBO.unbind(GlBufferType.ARRAY_BUFFER); + effectsUBO.unbind(); } public void bindInverseProjection(Matrix4f mat) { @@ -110,4 +111,8 @@ public class SphereFilterProgram extends GlProgram { GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject); } + @Override + public SphereFilterProgram get() { + return this; + } } diff --git a/src/main/resources/assets/create/flywheel/programs/belt.json b/src/main/resources/assets/create/flywheel/programs/belt.json new file mode 100644 index 000000000..e6b53432e --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/belt.json @@ -0,0 +1,33 @@ +{ + "vert": "create:belt.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": "create:rainbow_debug", + "define": "DEBUG_RAINBOW" + }, + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/chromatic.json b/src/main/resources/assets/create/flywheel/programs/chromatic.json new file mode 100644 index 000000000..f521eefa6 --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/chromatic.json @@ -0,0 +1,4 @@ +{ + "vert": "create:area_effect.vert", + "frag": "create:area_effect.frag" +} diff --git a/src/main/resources/assets/create/flywheel/programs/contraption_actor.json b/src/main/resources/assets/create/flywheel/programs/contraption_actor.json new file mode 100644 index 000000000..e9acf9d1e --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/contraption_actor.json @@ -0,0 +1,29 @@ +{ + "vert": "create:contraption_actor.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/contraption_structure.json b/src/main/resources/assets/create/flywheel/programs/contraption_structure.json new file mode 100644 index 000000000..9440ca25a --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/contraption_structure.json @@ -0,0 +1,29 @@ +{ + "vert": "create:contraption_structure.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/flap.json b/src/main/resources/assets/create/flywheel/programs/flap.json new file mode 100644 index 000000000..f7de4c45e --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/flap.json @@ -0,0 +1,29 @@ +{ + "vert": "create:flap.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/rotating.json b/src/main/resources/assets/create/flywheel/programs/rotating.json new file mode 100644 index 000000000..58d80d445 --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/rotating.json @@ -0,0 +1,33 @@ +{ + "vert": "create:rotating.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": "create:rainbow_debug", + "define": "DEBUG_RAINBOW" + }, + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/shaders/belt.vert b/src/main/resources/assets/create/flywheel/shaders/belt.vert index ce8ec2d5e..be5d51a43 100644 --- a/src/main/resources/assets/create/flywheel/shaders/belt.vert +++ b/src/main/resources/assets/create/flywheel/shaders/belt.vert @@ -39,9 +39,9 @@ BlockFrag FLWMain(Vertex v, Belt instance) { b.texCoords = v.texCoords - instance.sourceTexture + instance.scrollTexture.xy + vec2(0, scroll); b.light = instance.light; - #if defined(RAINBOW_DEBUG) + #if defined(DEBUG_RAINBOW) b.color = instance.color; - #elif defined(NORMAL_DEBUG) + #elif defined(DEBUG_NORMAL) b.color = vec4(norm, 1.); #else b.color = vec4(1.); diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert index b075730b9..25ff4980a 100644 --- a/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert +++ b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert @@ -37,7 +37,7 @@ BlockFrag FLWMain(Vertex v, Actor instance) { b.texCoords = v.texCoords; b.light = instance.light; - #if defined(NORMAL_DEBUG) + #if defined(DEBUG_NORMAL) b.color = vec4(norm, 1.); #else b.color = vec4(1.); diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert b/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert index fb3e66070..a42245c1d 100644 --- a/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert +++ b/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert @@ -27,7 +27,7 @@ BlockFrag FLWMain(Vertex v) { b.texCoords = v.texCoords; b.light = v.modelLight; - #if defined(NORMAL_DEBUG) + #if defined(DEBUG_NORMAL) b.color = vec4(norm, 1.); #else b.color = v.color / diffuse(v.normal); diff --git a/src/main/resources/assets/create/flywheel/shaders/flap.vert b/src/main/resources/assets/create/flywheel/shaders/flap.vert index 047455554..ef39637df 100644 --- a/src/main/resources/assets/create/flywheel/shaders/flap.vert +++ b/src/main/resources/assets/create/flywheel/shaders/flap.vert @@ -57,7 +57,7 @@ BlockFrag FLWMain(Vertex v, Flap flap) { b.diffuse = diffuse(norm); b.texCoords = v.texCoords; b.light = flap.light; - #if defined(NORMAL_DEBUG) + #if defined(DEBUG_NORMAL) b.color = vec4(norm, 1.); #else b.color = vec4(1.); diff --git a/src/main/resources/assets/create/flywheel/shaders/rotating.vert b/src/main/resources/assets/create/flywheel/shaders/rotating.vert index f5fe07bde..5acfdbd3f 100644 --- a/src/main/resources/assets/create/flywheel/shaders/rotating.vert +++ b/src/main/resources/assets/create/flywheel/shaders/rotating.vert @@ -40,9 +40,9 @@ BlockFrag FLWMain(Vertex v, Rotating instance) { b.texCoords = v.texCoords; b.light = instance.light; - #if defined(RAINBOW_DEBUG) + #if defined(DEBUG_RAINBOW) b.color = instance.color; - #elif defined(NORMAL_DEBUG) + #elif defined(DEBUG_NORMAL) b.color = vec4(norm, 1.); #else b.color = vec4(1.); diff --git a/src/main/resources/assets/flywheel/flywheel/programs/model.json b/src/main/resources/assets/flywheel/flywheel/programs/model.json new file mode 100644 index 000000000..b30bb0fe2 --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/programs/model.json @@ -0,0 +1,29 @@ +{ + "vert": "flywheel:model.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/flywheel/flywheel/programs/oriented.json b/src/main/resources/assets/flywheel/flywheel/programs/oriented.json new file mode 100644 index 000000000..0340b5602 --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/programs/oriented.json @@ -0,0 +1,29 @@ +{ + "vert": "flywheel:oriented.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/model.vert b/src/main/resources/assets/flywheel/flywheel/shaders/model.vert index d475c7a3b..310815b56 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/model.vert +++ b/src/main/resources/assets/flywheel/flywheel/shaders/model.vert @@ -26,7 +26,7 @@ BlockFrag FLWMain(Vertex v, Instance i) { b.diffuse = diffuse(norm); b.texCoords = v.texCoords; b.light = i.light; - #if defined(NORMAL_DEBUG) + #if defined(DEBUG_NORMAL) b.color = vec4(norm, 1.); #else b.color = i.color; diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert b/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert index 809e8fa92..5c040349d 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert +++ b/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert @@ -27,7 +27,7 @@ BlockFrag FLWMain(Vertex v, Oriented o) { b.diffuse = diffuse(norm); b.texCoords = v.texCoords; b.light = o.light; - #if defined(NORMAL_DEBUG) + #if defined(DEBUG_NORMAL) b.color = vec4(norm, 1.); #else b.color = o.color;