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;