mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-28 16:06:28 +01:00
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.
This commit is contained in:
parent
d58897d59a
commit
9352ef9ede
64 changed files with 1053 additions and 393 deletions
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<P extends GlProgram> {
|
||||
|
||||
public final Map<ProgramSpec, IMultiProgram<P>> programs = new HashMap<>();
|
||||
protected final Map<ResourceLocation, IMultiProgram<P>> programs = new HashMap<>();
|
||||
|
||||
protected final ShaderSpecLoader<P> specLoader;
|
||||
protected ShaderTransformer transformer = new ShaderTransformer();
|
||||
|
||||
public ShaderContext(ShaderSpecLoader<P> specLoader) {
|
||||
this.specLoader = specLoader;
|
||||
}
|
||||
public ShaderContext() { }
|
||||
|
||||
// TODO: Untangle the loading functions
|
||||
|
||||
|
@ -31,14 +29,16 @@ public abstract class ShaderContext<P extends GlProgram> {
|
|||
*/
|
||||
public abstract void load(ShaderLoader loader);
|
||||
|
||||
protected abstract IMultiProgram<P> 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<P extends GlProgram> {
|
|||
|
||||
}
|
||||
|
||||
public P getProgram(ProgramSpec spec) {
|
||||
public P getProgram(ResourceLocation spec) {
|
||||
return programs.get(spec).get();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String> 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<ResourceLocation, String> shaderSource = new HashMap<>();
|
||||
|
||||
private boolean shouldCrash;
|
||||
private final Gson gson = new GsonBuilder().create();
|
||||
|
||||
void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> 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<ResourceLocation> 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<Pair<ProgramSpec, JsonElement>> 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) {
|
||||
|
|
|
@ -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<ProgramExtender> fogFactory) {
|
||||
super(program, fogFactory);
|
||||
public CrumblingProgram(Program program, List<IProgramExtension> extensions) {
|
||||
super(program, extensions);
|
||||
|
||||
uTextureScale = getUniformLocation("uTextureScale");
|
||||
}
|
||||
|
|
|
@ -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<P extends GlProgram> implements IMultiProgram<P> {
|
||||
|
||||
private final Map<GlFogMode, P> programs;
|
||||
|
||||
public FogMultiProgram(Map<GlFogMode, P> 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<P extends GlProgram> implements ShaderSpecLoader<P> {
|
||||
|
||||
private final ExtensibleGlProgram.Factory<P> factory;
|
||||
|
||||
public SpecLoader(ExtensibleGlProgram.Factory<P> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMultiProgram<P> create(ShaderLoader loader, ShaderContext<P> ctx, ProgramSpec spec) {
|
||||
Map<GlFogMode, P> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<P extends WorldProgram> extends ShaderContext<P> {
|
|||
private static final String declaration = "#flwbuiltins";
|
||||
private static final Pattern builtinPattern = Pattern.compile(declaration);
|
||||
|
||||
public static final WorldContext<WorldProgram> INSTANCE = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/world"), new FogMultiProgram.SpecLoader<>(WorldProgram::new));
|
||||
public static final WorldContext<CrumblingProgram> CRUMBLING = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/crumbling"), new FogMultiProgram.SpecLoader<>(CrumblingProgram::new));
|
||||
public static final WorldContext<WorldProgram> INSTANCE = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/world"), WorldProgram::new);
|
||||
public static final WorldContext<CrumblingProgram> CRUMBLING = new WorldContext<>(new ResourceLocation(Flywheel.ID, "context/crumbling"), CrumblingProgram::new);
|
||||
|
||||
protected ProgramTemplate template;
|
||||
protected final ResourceLocation name;
|
||||
protected final Supplier<Stream<ProgramSpec>> specStream;
|
||||
protected final TemplateFactory templateFactory;
|
||||
private final ExtensibleGlProgram.Factory<P> factory;
|
||||
protected Supplier<Stream<ResourceLocation>> specStream;
|
||||
protected TemplateFactory templateFactory;
|
||||
|
||||
private final Map<ShaderType, ResourceLocation> builtins = new EnumMap<>(ShaderType.class);
|
||||
private final Map<ShaderType, String> builtinSources = new EnumMap<>(ShaderType.class);
|
||||
|
||||
public WorldContext(ResourceLocation root, ShaderSpecLoader<P> loader) {
|
||||
this(root, loader, () -> Backend.allMaterials()
|
||||
.stream()
|
||||
.map(MaterialSpec::getProgramSpec), InstancedArraysTemplate::new);
|
||||
}
|
||||
|
||||
public WorldContext(ResourceLocation root, ShaderSpecLoader<P> loader, Supplier<Stream<ProgramSpec>> specStream, TemplateFactory templateFactory) {
|
||||
super(loader);
|
||||
public WorldContext(ResourceLocation root, ExtensibleGlProgram.Factory<P> 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<P> setSpecStream(Supplier<Stream<ResourceLocation>> specStream) {
|
||||
this.specStream = specStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WorldContext<P> setTemplateFactory(TemplateFactory templateFactory) {
|
||||
this.templateFactory = templateFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IMultiProgram<P> 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<P extends WorldProgram> extends ShaderContext<P> {
|
|||
.pushStage(template)
|
||||
.pushStage(loader::processIncludes);
|
||||
|
||||
specStream.get().forEach(spec -> loadProgramFromSpec(loader, spec));
|
||||
specStream.get()
|
||||
.map(Backend::getSpec)
|
||||
.forEach(spec -> loadProgramFromSpec(loader, spec));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<IProgramExtension> extensions;
|
||||
protected final List<IExtensionInstance> extensions;
|
||||
|
||||
public ExtensibleGlProgram(Program program, @Nullable List<ProgramExtender> extensions) {
|
||||
public ExtensibleGlProgram(Program program, @Nullable List<IProgramExtension> extensions) {
|
||||
super(program);
|
||||
|
||||
if (extensions != null) {
|
||||
this.extensions = extensions.stream()
|
||||
.map(e -> e.create(this))
|
||||
.collect(Collectors.toList());
|
||||
List<IExtensionInstance> 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<P extends GlProgram> {
|
||||
|
||||
@Nonnull
|
||||
P create(Program program, @Nullable List<ProgramExtender> extensions);
|
||||
P create(Program program, @Nullable List<IProgramExtension> extensions);
|
||||
|
||||
default P create(Program program) {
|
||||
return create(program, null);
|
||||
|
|
|
@ -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 {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<String> 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<String> getDefines() {
|
||||
return defines;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IProgramExtension create(GlProgram program) {
|
||||
return fogFactory.create(program);
|
||||
}
|
||||
}
|
|
@ -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.
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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<ResourceLocation> debugModes = new ArrayList<>();
|
||||
|
||||
public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag) {
|
||||
this.name = name;
|
||||
this.vert = vert;
|
||||
this.frag = frag;
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
|
@ -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<P extends GlProgram> implements IMultiProgram<P> {
|
||||
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<P extends GlProgram> implements ShaderSpecLoader<P> {
|
||||
final ProgramFactory<P> factory;
|
||||
|
||||
public SpecLoader(ProgramFactory<P> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMultiProgram<P> create(ShaderLoader loader, ShaderContext<P> ctx, ProgramSpec spec) {
|
||||
return new SingleProgram<>(factory.create(ctx.loadProgram(loader, spec, null)));
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ProgramFactory<P extends GlProgram> {
|
||||
P create(Program program);
|
||||
}
|
||||
}
|
|
@ -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<P extends GlProgram> implements IMultiProgram<P> {
|
||||
|
||||
List<Pair<IContextCondition, P>> variants;
|
||||
P fallback;
|
||||
|
||||
public StateSensitiveMultiProgram(ShaderLoader loader, ExtensibleGlProgram.Factory<P> factory, ShaderContext<P> context, ProgramSpec p) {
|
||||
variants = new ArrayList<>(p.states.size());
|
||||
|
||||
for (ProgramState state : p.states) {
|
||||
|
||||
Program variant = context.loadProgram(loader, p, state.getDefines());
|
||||
|
||||
Pair<IContextCondition, P> 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<IContextCondition, P> variant : variants) {
|
||||
if (variant.getFirst().get())
|
||||
return variant.getSecond();
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
for (Pair<IContextCondition, P> variant : variants) {
|
||||
variant.getSecond().delete();
|
||||
}
|
||||
|
||||
fallback.delete();
|
||||
}
|
||||
}
|
|
@ -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<GlProgram, IExtensionInstance> fogFactory;
|
||||
|
||||
WorldFog(String name, Function<GlProgram, IExtensionInstance> 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;
|
||||
}
|
||||
}
|
|
@ -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<ProgramExtender> fogFactory) {
|
||||
super(program, fogFactory);
|
||||
public WorldProgram(Program program, List<IProgramExtension> extensions) {
|
||||
super(program, extensions);
|
||||
uTime = getUniformLocation("uTime");
|
||||
uViewProjection = getUniformLocation("uViewProjection");
|
||||
uCameraPos = getUniformLocation("uCameraPos");
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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<IProgramExtension> 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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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<IGameStateProvider> CODEC = ResourceLocation.CODEC.xmap(SpecMetaRegistry::getStateProvider, IGameStateProvider::getID);
|
||||
|
||||
ResourceLocation getID();
|
||||
|
||||
Object getValue();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<BooleanContextCondition> 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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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<ProgramSpec> 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<ProgramState> states;
|
||||
|
||||
public ProgramSpec(ResourceLocation vert, ResourceLocation frag, List<ProgramState> 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<ProgramState> getStates() {
|
||||
return states;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<IContextCondition> 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<ProgramState> 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<String> defines;
|
||||
private final List<IProgramExtension> extensions;
|
||||
|
||||
public ProgramState(IContextCondition context, List<String> defines, List<IProgramExtension> extensions) {
|
||||
this.context = context;
|
||||
this.defines = defines;
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
||||
public IContextCondition getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public List<String> getDefines() {
|
||||
return defines;
|
||||
}
|
||||
|
||||
public List<IProgramExtension> getExtensions() {
|
||||
return extensions;
|
||||
}
|
||||
}
|
|
@ -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<ResourceLocation, IProgramExtension> registeredExtensions = new HashMap<>();
|
||||
private static final Map<ResourceLocation, IGameStateProvider> 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);
|
||||
}
|
||||
}
|
|
@ -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<SpecificValueCondition> 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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<P extends GlProgram> {
|
||||
|
||||
IMultiProgram<P> create(ShaderLoader loader, ShaderContext<P> ctx, ProgramSpec spec);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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<D extends InstanceData> {
|
|||
|
||||
public final ResourceLocation name;
|
||||
|
||||
private final ProgramSpec programSpec;
|
||||
private final ResourceLocation programSpec;
|
||||
private final VertexFormat modelFormat;
|
||||
private final VertexFormat instanceFormat;
|
||||
private final InstanceFactory<D> instanceFactory;
|
||||
|
||||
public MaterialSpec(ResourceLocation name, ProgramSpec programSpec, VertexFormat modelFormat, VertexFormat instanceFormat, InstanceFactory<D> instanceFactory) {
|
||||
public MaterialSpec(ResourceLocation name, ResourceLocation programSpec, VertexFormat modelFormat, VertexFormat instanceFormat, InstanceFactory<D> instanceFactory) {
|
||||
this.name = name;
|
||||
this.programSpec = programSpec;
|
||||
this.modelFormat = modelFormat;
|
||||
|
@ -22,7 +21,7 @@ public class MaterialSpec<D extends InstanceData> {
|
|||
this.instanceFactory = instanceFactory;
|
||||
}
|
||||
|
||||
public ProgramSpec getProgramSpec() {
|
||||
public ResourceLocation getProgramSpec() {
|
||||
return programSpec;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
26
src/main/java/com/jozufozu/flywheel/util/CodecUtil.java
Normal file
26
src/main/java/com/jozufozu/flywheel/util/CodecUtil.java
Normal file
|
@ -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 <T> Codec<List<T>> oneOrMore(Codec<T> 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
68
src/main/java/com/jozufozu/flywheel/util/Pair.java
Normal file
68
src/main/java/com/jozufozu/flywheel/util/Pair.java
Normal file
|
@ -0,0 +1,68 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Pair<F, S> {
|
||||
|
||||
F first;
|
||||
S second;
|
||||
|
||||
protected Pair(F first, S second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public static <F, S> Pair<F, S> 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<F, S> 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<S, F> swap() {
|
||||
return Pair.of(second, first);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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<ProgramExtender> fogFactory) {
|
||||
super(program, fogFactory);
|
||||
public ContraptionProgram(Program program, List<IProgramExtension> extensions) {
|
||||
super(program, extensions);
|
||||
uLightBoxSize = getUniformLocation("uLightBoxSize");
|
||||
uLightBoxMin = getUniformLocation("uLightBoxMin");
|
||||
uModel = getUniformLocation("uModel");
|
||||
|
|
|
@ -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<Pair<Contraption, Integer>> CONTRAPTION = new Compartment<>();
|
||||
|
||||
private static final ResourceLocation ctxRoot = new ResourceLocation("create", "context/contraption");
|
||||
public static final WorldContext<ContraptionProgram> STRUCTURE = new WorldContext<>(ctxRoot, new FogMultiProgram.SpecLoader<>(ContraptionProgram::new), () -> Stream.of(AllProgramSpecs.STRUCTURE), ModelTemplate::new);
|
||||
public static final WorldContext<ContraptionProgram> TILES = new WorldContext<>(ctxRoot, new FogMultiProgram.SpecLoader<>(ContraptionProgram::new));
|
||||
public static final WorldContext<ContraptionProgram> STRUCTURE = new WorldContext<>(ctxRoot, ContraptionProgram::new)
|
||||
.setSpecStream(() -> Stream.of(AllProgramSpecs.STRUCTURE))
|
||||
.setTemplateFactory(ModelTemplate::new);
|
||||
public static final WorldContext<ContraptionProgram> TILES = new WorldContext<>(ctxRoot, ContraptionProgram::new);
|
||||
|
||||
public static void tick() {
|
||||
if (Minecraft.getInstance().isGamePaused()) return;
|
||||
|
|
|
@ -24,10 +24,10 @@ public class AllMaterialSpecs {
|
|||
.addAttributes(CommonAttributes.VEC3, CommonAttributes.NORMAL, CommonAttributes.UV)
|
||||
.build();
|
||||
|
||||
public static final MaterialSpec<RotatingData> ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, UNLIT_MODEL, AllInstanceFormats.ROTATING, RotatingData::new));
|
||||
public static final MaterialSpec<ModelData> TRANSFORMED = register(new MaterialSpec<>(Locations.MODEL, AllProgramSpecs.MODEL, UNLIT_MODEL, AllInstanceFormats.MODEL, ModelData::new));
|
||||
public static final MaterialSpec<OrientedData> ORIENTED = register(new MaterialSpec<>(Locations.ORIENTED, AllProgramSpecs.ORIENTED, UNLIT_MODEL, AllInstanceFormats.ORIENTED, OrientedData::new));
|
||||
|
||||
public static final MaterialSpec<RotatingData> ROTATING = register(new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, UNLIT_MODEL, AllInstanceFormats.ROTATING, RotatingData::new));
|
||||
public static final MaterialSpec<BeltData> BELTS = register(new MaterialSpec<>(Locations.BELTS, AllProgramSpecs.BELT, UNLIT_MODEL, AllInstanceFormats.BELT, BeltData::new));
|
||||
public static final MaterialSpec<ActorData> ACTORS = register(new MaterialSpec<>(Locations.ACTORS, AllProgramSpecs.ACTOR, UNLIT_MODEL, AllInstanceFormats.ACTOR, ActorData::new));
|
||||
public static final MaterialSpec<FlapData> FLAPS = register(new MaterialSpec<>(Locations.FLAPS, AllProgramSpecs.FLAPS, UNLIT_MODEL, AllInstanceFormats.FLAP, FlapData::new));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<SphereFilterProgram> {
|
|||
public static final EffectsContext INSTANCE = new EffectsContext();
|
||||
|
||||
public EffectsContext() {
|
||||
super(new SingleProgram.SpecLoader<>(SphereFilterProgram::new));
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IMultiProgram<SphereFilterProgram> 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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<SphereFilterProgram> {
|
||||
|
||||
protected static final int UBO_BINDING = 4;
|
||||
|
||||
|
@ -80,7 +81,7 @@ public class SphereFilterProgram extends GlProgram {
|
|||
}
|
||||
|
||||
public void uploadFilters(ArrayList<FilterSphere> 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;
|
||||
}
|
||||
}
|
||||
|
|
33
src/main/resources/assets/create/flywheel/programs/belt.json
Normal file
33
src/main/resources/assets/create/flywheel/programs/belt.json
Normal file
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"vert": "create:area_effect.vert",
|
||||
"frag": "create:area_effect.frag"
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
29
src/main/resources/assets/create/flywheel/programs/flap.json
Normal file
29
src/main/resources/assets/create/flywheel/programs/flap.json
Normal file
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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.);
|
||||
|
|
|
@ -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.);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.);
|
||||
|
|
|
@ -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.);
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue