mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-28 05:44:59 +01:00
Almost sane shaders
- No more ShaderContext. Programs are directly retrieved through ProgramCompilers. - Templates don't need generics - Remove ExtensibleGlProgram
This commit is contained in:
parent
06e1d5a901
commit
bfe123d167
38 changed files with 339 additions and 437 deletions
|
@ -1,9 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
package com.jozufozu.flywheel.backend;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -40,7 +38,6 @@ public class Backend {
|
||||||
public GlCompat compat;
|
public GlCompat compat;
|
||||||
|
|
||||||
public final Loader loader;
|
public final Loader loader;
|
||||||
private final List<ShaderContext<?>> contexts = new ArrayList<>();
|
|
||||||
private final Map<ResourceLocation, StructType<?>> materialRegistry = new HashMap<>();
|
private final Map<ResourceLocation, StructType<?>> materialRegistry = new HashMap<>();
|
||||||
private final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>();
|
private final Map<ResourceLocation, ProgramSpec> programSpecRegistry = new HashMap<>();
|
||||||
|
|
||||||
|
@ -74,14 +71,6 @@ public class Backend {
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a shader context.
|
|
||||||
*/
|
|
||||||
public <C extends ShaderContext<?>> C register(C spec) {
|
|
||||||
contexts.add(spec);
|
|
||||||
return spec;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an instancing material.
|
* Register an instancing material.
|
||||||
*/
|
*/
|
||||||
|
@ -96,6 +85,7 @@ public class Backend {
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public ProgramSpec getSpec(ResourceLocation name) {
|
public ProgramSpec getSpec(ResourceLocation name) {
|
||||||
return programSpecRegistry.get(name);
|
return programSpecRegistry.get(name);
|
||||||
}
|
}
|
||||||
|
@ -118,10 +108,6 @@ public class Backend {
|
||||||
return programSpecRegistry.values();
|
return programSpecRegistry.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ShaderContext<?>> allContexts() {
|
|
||||||
return contexts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isOn() {
|
public static boolean isOn() {
|
||||||
return getInstance().engine != FlwEngine.OFF;
|
return getInstance().engine != FlwEngine.OFF;
|
||||||
}
|
}
|
||||||
|
@ -157,8 +143,6 @@ public class Backend {
|
||||||
void _clearContexts() {
|
void _clearContexts() {
|
||||||
GameStateRegistry.clear();
|
GameStateRegistry.clear();
|
||||||
programSpecRegistry.clear();
|
programSpecRegistry.clear();
|
||||||
contexts.forEach(ShaderContext::delete);
|
|
||||||
contexts.clear();
|
|
||||||
materialRegistry.clear();
|
materialRegistry.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
import com.jozufozu.flywheel.backend.source.Resolver;
|
import com.jozufozu.flywheel.backend.source.Resolver;
|
||||||
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
|
|
||||||
import com.jozufozu.flywheel.backend.source.ShaderSources;
|
import com.jozufozu.flywheel.backend.source.ShaderSources;
|
||||||
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer;
|
||||||
import com.jozufozu.flywheel.core.shader.ProgramSpec;
|
import com.jozufozu.flywheel.core.shader.ProgramSpec;
|
||||||
|
@ -39,7 +38,6 @@ public class Loader implements ResourceManagerReloadListener {
|
||||||
private static final Gson GSON = new GsonBuilder().create();
|
private static final Gson GSON = new GsonBuilder().create();
|
||||||
|
|
||||||
private final Backend backend;
|
private final Backend backend;
|
||||||
private boolean shouldCrash;
|
|
||||||
|
|
||||||
private boolean firstLoad = true;
|
private boolean firstLoad = true;
|
||||||
|
|
||||||
|
@ -56,15 +54,10 @@ public class Loader implements ResourceManagerReloadListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyError() {
|
|
||||||
shouldCrash = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceManagerReload(ResourceManager manager) {
|
public void onResourceManagerReload(ResourceManager manager) {
|
||||||
backend.refresh();
|
backend.refresh();
|
||||||
|
|
||||||
shouldCrash = false;
|
|
||||||
backend._clearContexts();
|
backend._clearContexts();
|
||||||
|
|
||||||
Resolver.INSTANCE.invalidate();
|
Resolver.INSTANCE.invalidate();
|
||||||
|
@ -75,17 +68,9 @@ public class Loader implements ResourceManagerReloadListener {
|
||||||
|
|
||||||
loadProgramSpecs(manager);
|
loadProgramSpecs(manager);
|
||||||
|
|
||||||
Resolver.INSTANCE.resolve(sources);
|
Resolver.INSTANCE.run(sources);
|
||||||
|
|
||||||
for (ShaderContext<?> context : backend.allContexts()) {
|
Backend.LOGGER.info("Loaded all shader sources.");
|
||||||
context.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldCrash) {
|
|
||||||
throw new ShaderLoadingException("Could not load all shaders, see log for details");
|
|
||||||
}
|
|
||||||
|
|
||||||
Backend.LOGGER.info("Loaded all shader programs.");
|
|
||||||
|
|
||||||
ClientLevel world = Minecraft.getInstance().level;
|
ClientLevel world = Minecraft.getInstance().level;
|
||||||
if (Backend.canUseInstancing(world)) {
|
if (Backend.canUseInstancing(world)) {
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
public interface ShaderContext<P extends GlProgram> {
|
|
||||||
|
|
||||||
P getProgram(ResourceLocation loc, VertexType vertexType, RenderLayer layer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load all programs associated with this context. This might be just one, if the context is very specialized.
|
|
||||||
*/
|
|
||||||
void load();
|
|
||||||
|
|
||||||
void delete();
|
|
||||||
}
|
|
|
@ -7,6 +7,8 @@ import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
|
||||||
|
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
@ -87,4 +89,13 @@ public abstract class GlProgram extends GlObject {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "program " + name;
|
return "program " + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory interface to create a {@link GlProgram}.
|
||||||
|
*/
|
||||||
|
public interface Factory<P extends GlProgram> {
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
P create(ResourceLocation name, int handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.lwjgl.opengl.GL20;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||||
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
|
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
|
||||||
import com.jozufozu.flywheel.core.pipeline.ShaderCompiler;
|
import com.jozufozu.flywheel.core.compile.ShaderCompiler;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
|
|
@ -16,4 +16,8 @@ public enum ShaderType {
|
||||||
this.define = define;
|
this.define = define;
|
||||||
this.glEnum = glEnum;
|
this.glEnum = glEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDefineStatement() {
|
||||||
|
return "#define " + define + "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import com.jozufozu.flywheel.backend.model.FallbackAllocator;
|
||||||
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
||||||
import com.jozufozu.flywheel.backend.model.ModelPool;
|
import com.jozufozu.flywheel.backend.model.ModelPool;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
|
import com.jozufozu.flywheel.core.compile.ProgramContext;
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||||
import com.jozufozu.flywheel.util.Textures;
|
import com.jozufozu.flywheel.util.Textures;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
|
@ -78,8 +79,8 @@ public class InstancedMaterialGroup<P extends WorldProgram> implements MaterialG
|
||||||
InstancedMaterial<?> material = entry.getValue();
|
InstancedMaterial<?> material = entry.getValue();
|
||||||
if (material.nothingToRender()) continue;
|
if (material.nothingToRender()) continue;
|
||||||
|
|
||||||
P program = owner.context.getProgram(entry.getKey()
|
P program = owner.context.getProgram(ProgramContext.create(entry.getKey()
|
||||||
.getProgramSpec(), Formats.POS_TEX_NORMAL, layer);
|
.getProgramSpec(), Formats.POS_TEX_NORMAL, layer));
|
||||||
|
|
||||||
program.bind();
|
program.bind();
|
||||||
program.uploadViewProjection(viewProjection);
|
program.uploadViewProjection(viewProjection);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.instancing.Engine;
|
import com.jozufozu.flywheel.backend.instancing.Engine;
|
||||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||||
import com.jozufozu.flywheel.core.WorldContext;
|
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||||
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||||
import com.jozufozu.flywheel.util.WeakHashSet;
|
import com.jozufozu.flywheel.util.WeakHashSet;
|
||||||
|
@ -31,7 +31,7 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||||
|
|
||||||
protected BlockPos originCoordinate = BlockPos.ZERO;
|
protected BlockPos originCoordinate = BlockPos.ZERO;
|
||||||
|
|
||||||
protected final WorldContext<P> context;
|
protected final ProgramCompiler<P> context;
|
||||||
protected final GroupFactory<P> groupFactory;
|
protected final GroupFactory<P> groupFactory;
|
||||||
protected final boolean ignoreOriginCoordinate;
|
protected final boolean ignoreOriginCoordinate;
|
||||||
|
|
||||||
|
@ -39,15 +39,11 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||||
|
|
||||||
private final WeakHashSet<OriginShiftListener> listeners;
|
private final WeakHashSet<OriginShiftListener> listeners;
|
||||||
|
|
||||||
public InstancingEngine(WorldContext<P> context, TaskEngine taskEngine) {
|
public static <P extends WorldProgram> Builder<P> builder(ProgramCompiler<P> context) {
|
||||||
this(context, InstancedMaterialGroup::new, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <P extends WorldProgram> Builder<P> builder(WorldContext<P> context) {
|
|
||||||
return new Builder<>(context);
|
return new Builder<>(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstancingEngine(WorldContext<P> context, GroupFactory<P> groupFactory, boolean ignoreOriginCoordinate) {
|
public InstancingEngine(ProgramCompiler<P> context, GroupFactory<P> groupFactory, boolean ignoreOriginCoordinate) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.ignoreOriginCoordinate = ignoreOriginCoordinate;
|
this.ignoreOriginCoordinate = ignoreOriginCoordinate;
|
||||||
|
|
||||||
|
@ -180,11 +176,11 @@ public class InstancingEngine<P extends WorldProgram> implements Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder<P extends WorldProgram> {
|
public static class Builder<P extends WorldProgram> {
|
||||||
protected final WorldContext<P> context;
|
protected final ProgramCompiler<P> context;
|
||||||
protected GroupFactory<P> groupFactory = InstancedMaterialGroup::new;
|
protected GroupFactory<P> groupFactory = InstancedMaterialGroup::new;
|
||||||
protected boolean ignoreOriginCoordinate;
|
protected boolean ignoreOriginCoordinate;
|
||||||
|
|
||||||
public Builder(WorldContext<P> context) {
|
public Builder(ProgramCompiler<P> context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.source;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.source.error.ErrorBuilder;
|
import com.jozufozu.flywheel.backend.source.error.ErrorBuilder;
|
||||||
|
@ -21,13 +22,13 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
public class FileResolution {
|
public class FileResolution {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spans that have references that resolved to this.
|
* Extra info about where this resolution is required. Includes ProgramSpecs and shader Spans.
|
||||||
*/
|
*/
|
||||||
private final List<Span> foundSpans = new ArrayList<>();
|
private final List<Consumer<ErrorBuilder>> extraCrashInfoProviders = new ArrayList<>();
|
||||||
private final ResourceLocation fileLoc;
|
private final ResourceLocation fileLoc;
|
||||||
private SourceFile file;
|
private SourceFile file;
|
||||||
|
|
||||||
public FileResolution(ResourceLocation fileLoc) {
|
FileResolution(ResourceLocation fileLoc) {
|
||||||
this.fileLoc = fileLoc;
|
this.fileLoc = fileLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +36,10 @@ public class FileResolution {
|
||||||
return fileLoc;
|
return fileLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-null if this file is resolved because there would have been a crash otherwise.
|
||||||
|
* @return The file that this resolution resolves to.
|
||||||
|
*/
|
||||||
public SourceFile getFile() {
|
public SourceFile getFile() {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
@ -48,34 +53,44 @@ public class FileResolution {
|
||||||
* @param span A span where this file is referenced.
|
* @param span A span where this file is referenced.
|
||||||
*/
|
*/
|
||||||
public FileResolution addSpan(Span span) {
|
public FileResolution addSpan(Span span) {
|
||||||
foundSpans.add(span);
|
extraCrashInfoProviders.add(builder -> builder.pointAtFile(span.getSourceFile())
|
||||||
|
.pointAt(span, 1));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addSpec(ResourceLocation name) {
|
||||||
|
extraCrashInfoProviders.add(builder -> builder.extra("needed by spec: " + name + ".json"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if this file actually resolves to something.
|
* Check to see if this file actually resolves to something.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Called after all files are loaded. If we can't find the file here, it doesn't exist.
|
* Called after all files are loaded. If we can't find the file here, it doesn't exist.
|
||||||
* </p>
|
* </p>
|
||||||
|
*
|
||||||
|
* @return True if this file is resolved.
|
||||||
*/
|
*/
|
||||||
void resolve(SourceFinder sources) {
|
boolean resolve(SourceFinder sources) {
|
||||||
file = sources.findSource(fileLoc);
|
file = sources.findSource(fileLoc);
|
||||||
|
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
ErrorBuilder builder = ErrorBuilder.error(String.format("could not find source for file %s", fileLoc));
|
ErrorBuilder builder = ErrorBuilder.error(String.format("could not find source for file %s", fileLoc));
|
||||||
// print the location of all places where this file was referenced
|
for (Consumer<ErrorBuilder> consumer : extraCrashInfoProviders) {
|
||||||
for (Span span : foundSpans) {
|
consumer.accept(builder);
|
||||||
builder.pointAtFile(span.getSourceFile())
|
|
||||||
.pointAt(span, 1);
|
|
||||||
}
|
}
|
||||||
Backend.LOGGER.error(builder.build());
|
Backend.LOGGER.error(builder.build());
|
||||||
throw new ShaderLoadingException();
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let the GC do its thing
|
||||||
|
extraCrashInfoProviders.clear();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalidate() {
|
void invalidate() {
|
||||||
foundSpans.clear();
|
extraCrashInfoProviders.clear();
|
||||||
file = null;
|
file = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,29 +9,51 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
* Manages deferred file resolution.
|
* Manages deferred file resolution.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Interns all referenced files in all sources, duplicating the final lookups and allowing for more dev-friendly
|
* Interns all file names in shader sources and program specs, deduplicating the final lookups and allowing for more
|
||||||
* error reporting.
|
* dev-friendly error reporting.
|
||||||
* </p><p>
|
|
||||||
* See {@link FileResolution} for more information.
|
|
||||||
* </p>
|
* </p>
|
||||||
|
*
|
||||||
|
* @see FileResolution
|
||||||
*/
|
*/
|
||||||
public class Resolver {
|
public class Resolver {
|
||||||
|
|
||||||
public static final Resolver INSTANCE = new Resolver();
|
public static final Resolver INSTANCE = new Resolver();
|
||||||
|
|
||||||
private final Map<ResourceLocation, FileResolution> resolutions = new HashMap<>();
|
private final Map<ResourceLocation, FileResolution> resolutions = new HashMap<>();
|
||||||
|
private boolean hasRun = false;
|
||||||
|
|
||||||
public FileResolution findShader(ResourceLocation fileLoc) {
|
public FileResolution get(ResourceLocation file) {
|
||||||
return resolutions.computeIfAbsent(fileLoc, FileResolution::new);
|
if (!hasRun) {
|
||||||
|
return resolutions.computeIfAbsent(file, FileResolution::new);
|
||||||
|
} else {
|
||||||
|
// Lock the map after resolution has run.
|
||||||
|
FileResolution fileResolution = resolutions.get(file);
|
||||||
|
|
||||||
|
// ...so crash immediately if the file isn't found.
|
||||||
|
if (fileResolution == null) {
|
||||||
|
throw new RuntimeException("could not find source for file: " + file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileResolution;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try and resolve all referenced source files, printing errors if any aren't found.
|
* Try and resolve all referenced source files, printing errors if any aren't found.
|
||||||
*/
|
*/
|
||||||
public void resolve(SourceFinder sources) {
|
public void run(SourceFinder sources) {
|
||||||
|
boolean needsCrash = false;
|
||||||
for (FileResolution resolution : resolutions.values()) {
|
for (FileResolution resolution : resolutions.values()) {
|
||||||
resolution.resolve(sources);
|
if (!resolution.resolve(sources)) {
|
||||||
|
needsCrash = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needsCrash) {
|
||||||
|
throw new ShaderLoadingException("Failed to resolve all source files, see log for details");
|
||||||
|
}
|
||||||
|
|
||||||
|
hasRun = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,5 +65,6 @@ public class Resolver {
|
||||||
*/
|
*/
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
resolutions.values().forEach(FileResolution::invalidate);
|
resolutions.values().forEach(FileResolution::invalidate);
|
||||||
|
hasRun = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import com.jozufozu.flywheel.backend.source.parse.ShaderStruct;
|
||||||
import com.jozufozu.flywheel.backend.source.span.ErrorSpan;
|
import com.jozufozu.flywheel.backend.source.span.ErrorSpan;
|
||||||
import com.jozufozu.flywheel.backend.source.span.Span;
|
import com.jozufozu.flywheel.backend.source.span.Span;
|
||||||
import com.jozufozu.flywheel.backend.source.span.StringSpan;
|
import com.jozufozu.flywheel.backend.source.span.StringSpan;
|
||||||
import com.jozufozu.flywheel.core.pipeline.ShaderCompiler;
|
import com.jozufozu.flywheel.core.compile.FileIndex;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ public class SourceFile {
|
||||||
return "#use " + '"' + name + '"';
|
return "#use " + '"' + name + '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateFinalSource(ShaderCompiler env, StringBuilder source) {
|
public void generateFinalSource(FileIndex env, StringBuilder source) {
|
||||||
for (Import include : imports) {
|
for (Import include : imports) {
|
||||||
SourceFile file = include.getFile();
|
SourceFile file = include.getFile();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import com.jozufozu.flywheel.backend.source.error.lines.SourceLine;
|
||||||
import com.jozufozu.flywheel.backend.source.error.lines.SpanHighlightLine;
|
import com.jozufozu.flywheel.backend.source.error.lines.SpanHighlightLine;
|
||||||
import com.jozufozu.flywheel.backend.source.error.lines.TextLine;
|
import com.jozufozu.flywheel.backend.source.error.lines.TextLine;
|
||||||
import com.jozufozu.flywheel.backend.source.span.Span;
|
import com.jozufozu.flywheel.backend.source.span.Span;
|
||||||
import com.jozufozu.flywheel.core.pipeline.ShaderCompiler;
|
import com.jozufozu.flywheel.core.compile.ShaderCompiler;
|
||||||
import com.jozufozu.flywheel.util.FlwUtil;
|
import com.jozufozu.flywheel.util.FlwUtil;
|
||||||
|
|
||||||
public class ErrorBuilder {
|
public class ErrorBuilder {
|
||||||
|
@ -127,6 +127,7 @@ public class ErrorBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append('\n');
|
||||||
for (ErrorLine line : lines) {
|
for (ErrorLine line : lines) {
|
||||||
int length = line.neededMargin();
|
int length = line.neededMargin();
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ public class Import extends AbstractShaderElement {
|
||||||
super(self);
|
super(self);
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
resolution = resolver.findShader(toRL(file))
|
resolution = resolver.get(toRL(file))
|
||||||
.addSpan(file);
|
.addSpan(file);
|
||||||
|
|
||||||
IMPORTS.add(this);
|
IMPORTS.add(this);
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package com.jozufozu.flywheel.core;
|
package com.jozufozu.flywheel.core;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.GameStateRegistry;
|
import com.jozufozu.flywheel.backend.GameStateRegistry;
|
||||||
import com.jozufozu.flywheel.backend.source.FileResolution;
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
import com.jozufozu.flywheel.backend.source.Resolver;
|
import com.jozufozu.flywheel.backend.source.Resolver;
|
||||||
|
import com.jozufozu.flywheel.core.compile.ProgramCompiler;
|
||||||
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
import com.jozufozu.flywheel.core.crumbling.CrumblingProgram;
|
||||||
import com.jozufozu.flywheel.core.pipeline.PipelineCompiler;
|
|
||||||
import com.jozufozu.flywheel.core.pipeline.WorldCompiler;
|
|
||||||
import com.jozufozu.flywheel.core.shader.NormalDebugStateProvider;
|
import com.jozufozu.flywheel.core.shader.NormalDebugStateProvider;
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||||
import com.jozufozu.flywheel.event.GatherContextEvent;
|
import com.jozufozu.flywheel.event.GatherContextEvent;
|
||||||
|
@ -20,22 +18,17 @@ import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public class Contexts {
|
public class Contexts {
|
||||||
|
|
||||||
public static WorldContext<WorldProgram> WORLD;
|
public static ProgramCompiler<WorldProgram> WORLD;
|
||||||
public static WorldContext<CrumblingProgram> CRUMBLING;
|
public static ProgramCompiler<CrumblingProgram> CRUMBLING;
|
||||||
|
|
||||||
public static void flwInit(GatherContextEvent event) {
|
public static void flwInit(GatherContextEvent event) {
|
||||||
Backend backend = event.getBackend();
|
|
||||||
|
|
||||||
GameStateRegistry.register(NormalDebugStateProvider.INSTANCE);
|
GameStateRegistry.register(NormalDebugStateProvider.INSTANCE);
|
||||||
|
|
||||||
FileResolution crumblingBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.CRUMBLING, ".glsl"));
|
FileResolution worldBuiltins = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.WORLD, ".glsl"));
|
||||||
FileResolution worldBuiltins = Resolver.INSTANCE.findShader(ResourceUtil.subPath(Names.WORLD, ".glsl"));
|
FileResolution crumblingBuiltins = Resolver.INSTANCE.get(ResourceUtil.subPath(Names.CRUMBLING, ".glsl"));
|
||||||
|
|
||||||
PipelineCompiler<CrumblingProgram> crumblingPipeline = new WorldCompiler<>(CrumblingProgram::new, Templates.INSTANCING, crumblingBuiltins);
|
WORLD = Templates.INSTANCING.programCompiler(WorldProgram::new, worldBuiltins);
|
||||||
PipelineCompiler<WorldProgram> worldPipeline = new WorldCompiler<>(WorldProgram::new, Templates.INSTANCING, worldBuiltins);
|
CRUMBLING = Templates.INSTANCING.programCompiler(CrumblingProgram::new, crumblingBuiltins);
|
||||||
|
|
||||||
CRUMBLING = backend.register(WorldContext.builder(backend, Names.CRUMBLING).build(crumblingPipeline));
|
|
||||||
WORLD = backend.register(WorldContext.builder(backend, Names.WORLD).build(worldPipeline));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Names {
|
public static class Names {
|
||||||
|
|
|
@ -28,5 +28,6 @@ public class Materials {
|
||||||
public static class Names {
|
public static class Names {
|
||||||
public static final ResourceLocation MODEL = Flywheel.rl("model");
|
public static final ResourceLocation MODEL = Flywheel.rl("model");
|
||||||
public static final ResourceLocation ORIENTED = Flywheel.rl("oriented");
|
public static final ResourceLocation ORIENTED = Flywheel.rl("oriented");
|
||||||
|
public static final ResourceLocation PASSTHRU = Flywheel.rl("passthru");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package com.jozufozu.flywheel.core;
|
package com.jozufozu.flywheel.core;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
import com.jozufozu.flywheel.core.pipeline.InstancingTemplateData;
|
import com.jozufozu.flywheel.core.compile.InstancingTemplateData;
|
||||||
import com.jozufozu.flywheel.core.pipeline.OneShotTemplateData;
|
import com.jozufozu.flywheel.core.compile.OneShotTemplateData;
|
||||||
import com.jozufozu.flywheel.core.pipeline.Template;
|
import com.jozufozu.flywheel.core.compile.Template;
|
||||||
|
|
||||||
public class Templates {
|
public class Templates {
|
||||||
|
|
||||||
public static final Template<InstancingTemplateData> INSTANCING = new Template<>(GLSLVersion.V330, InstancingTemplateData::new);
|
public static final Template INSTANCING = new Template(GLSLVersion.V330, InstancingTemplateData::new);
|
||||||
public static final Template<OneShotTemplateData> ONE_SHOT = new Template<>(GLSLVersion.V150, OneShotTemplateData::new);
|
public static final Template ONE_SHOT = new Template(GLSLVersion.V150, OneShotTemplateData::new);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.struct.Instanced;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.RenderLayer;
|
|
||||||
import com.jozufozu.flywheel.backend.ShaderContext;
|
|
||||||
import com.jozufozu.flywheel.backend.source.ShaderLoadingException;
|
|
||||||
import com.jozufozu.flywheel.core.pipeline.CachingCompiler;
|
|
||||||
import com.jozufozu.flywheel.core.pipeline.CompilationContext;
|
|
||||||
import com.jozufozu.flywheel.core.pipeline.PipelineCompiler;
|
|
||||||
import com.jozufozu.flywheel.core.shader.ProgramSpec;
|
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
public class WorldContext<P extends WorldProgram> implements ShaderContext<P> {
|
|
||||||
public final Backend backend;
|
|
||||||
protected final Map<ResourceLocation, ProgramSpec> programs = new HashMap<>();
|
|
||||||
protected final ResourceLocation name;
|
|
||||||
protected final Supplier<Stream<ResourceLocation>> specStream;
|
|
||||||
private final CachingCompiler<P> programCache;
|
|
||||||
|
|
||||||
public WorldContext(Backend backend, ResourceLocation name, Supplier<Stream<ResourceLocation>> specStream, PipelineCompiler<P> pipeline) {
|
|
||||||
this.backend = backend;
|
|
||||||
this.name = name;
|
|
||||||
this.specStream = specStream;
|
|
||||||
this.programCache = new CachingCompiler<>(pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load() {
|
|
||||||
|
|
||||||
Backend.LOGGER.info("Loading context '{}'", name);
|
|
||||||
|
|
||||||
specStream.get()
|
|
||||||
.map(backend::getSpec)
|
|
||||||
.forEach(this::loadSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadSpec(ProgramSpec spec) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
programs.put(spec.name, spec);
|
|
||||||
|
|
||||||
Backend.LOGGER.debug("Loaded program {}", spec.name);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Backend.LOGGER.error("Error loading program {}", spec.name);
|
|
||||||
if (!(e instanceof ShaderLoadingException)) {
|
|
||||||
Backend.LOGGER.error("", e);
|
|
||||||
}
|
|
||||||
backend.loader.notifyError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public P getProgram(ResourceLocation loc, VertexType vertexType, RenderLayer layer) {
|
|
||||||
ProgramSpec spec = programs.get(loc);
|
|
||||||
|
|
||||||
if (spec == null) {
|
|
||||||
throw new NullPointerException("Cannot compile shader because '" + loc + "' is not recognized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return programCache.getProgram(CompilationContext.create(vertexType, layer, spec));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete() {
|
|
||||||
programCache.invalidate();
|
|
||||||
programs.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Builder builder(Backend backend, ResourceLocation name) {
|
|
||||||
return new Builder(backend, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
|
||||||
private final Backend backend;
|
|
||||||
private final ResourceLocation name;
|
|
||||||
private Supplier<Stream<ResourceLocation>> specStream;
|
|
||||||
|
|
||||||
public Builder(Backend backend, ResourceLocation name) {
|
|
||||||
this.backend = backend;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setSpecStream(Supplier<Stream<ResourceLocation>> specStream) {
|
|
||||||
this.specStream = specStream;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <P extends WorldProgram> WorldContext<P> build(PipelineCompiler<P> pipeline) {
|
|
||||||
if (specStream == null) {
|
|
||||||
specStream = () -> backend.allMaterials()
|
|
||||||
.stream()
|
|
||||||
.map(t -> t instanceof Instanced<?> i ? i : null)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.map(Instanced::getProgramSpec);
|
|
||||||
}
|
|
||||||
return new WorldContext<>(backend, name, specStream, pipeline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
|
|
||||||
|
public interface FileIndex {
|
||||||
|
/**
|
||||||
|
* Returns an arbitrary file ID for use this compilation context, or generates one if missing.
|
||||||
|
*
|
||||||
|
* @param sourceFile The file to retrieve the ID for.
|
||||||
|
* @return A file ID unique to the given sourceFile.
|
||||||
|
*/
|
||||||
|
int getFileID(SourceFile sourceFile);
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ public class InstancingTemplateData implements TemplateData {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fragmentFooter(StringBuilder template, ShaderCompiler shader) {
|
public void fragmentFooter(StringBuilder template, FileIndex shader) {
|
||||||
Template.prefixFields(template, interpolant, "in", "v2f_");
|
Template.prefixFields(template, interpolant, "in", "v2f_");
|
||||||
|
|
||||||
template.append(String.format("""
|
template.append(String.format("""
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ public class OneShotTemplateData implements TemplateData {
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fragmentFooter(StringBuilder template, ShaderCompiler file) {
|
public void fragmentFooter(StringBuilder template, FileIndex file) {
|
||||||
Template.prefixFields(template, interpolant, "in", "v2f_");
|
Template.prefixFields(template, interpolant, "in", "v2f_");
|
||||||
|
|
||||||
template.append(String.format("""
|
template.append(String.format("""
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
import static org.lwjgl.opengl.GL11.GL_TRUE;
|
||||||
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
|
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
|
||||||
|
@ -11,9 +11,8 @@ import static org.lwjgl.opengl.GL20.glLinkProgram;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||||
import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
|
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
@ -61,7 +60,7 @@ public class ProgramAssembler {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <P extends WorldProgram> P build(ExtensibleGlProgram.Factory<P> factory) {
|
public <P extends GlProgram> P build(GlProgram.Factory<P> factory) {
|
||||||
return factory.create(name, program);
|
return factory.create(name, program);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A caching compiler.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This class is responsible for compiling programs on the fly. An instance of this class will keep a cache of
|
||||||
|
* compiled programs, and will only compile a program if it is not already in the cache.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class ProgramCompiler<P extends GlProgram> {
|
||||||
|
|
||||||
|
protected final Map<ProgramContext, P> cache = new HashMap<>();
|
||||||
|
private final GlProgram.Factory<P> factory;
|
||||||
|
|
||||||
|
private final Template template;
|
||||||
|
private final FileResolution header;
|
||||||
|
|
||||||
|
public ProgramCompiler(GlProgram.Factory<P> factory, Template template, FileResolution header) {
|
||||||
|
this.factory = factory;
|
||||||
|
this.template = template;
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or compile a spec to the given vertex type, accounting for all game state conditions specified by the spec.
|
||||||
|
*
|
||||||
|
* @param ctx The context of compilation.
|
||||||
|
* @return A compiled GlProgram.
|
||||||
|
*/
|
||||||
|
public P getProgram(ProgramContext ctx) {
|
||||||
|
return cache.computeIfAbsent(ctx, this::compile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidate() {
|
||||||
|
cache.values().forEach(P::delete);
|
||||||
|
cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private P compile(ProgramContext ctx) {
|
||||||
|
ShaderCompiler compiler = new ShaderCompiler(ctx, template, header);
|
||||||
|
|
||||||
|
return new ProgramAssembler(compiler.name)
|
||||||
|
.attachShader(compiler.compile(ShaderType.VERTEX))
|
||||||
|
.attachShader(compiler.compile(ShaderType.FRAGMENT))
|
||||||
|
.link()
|
||||||
|
.deleteLinkedShaders()
|
||||||
|
.build(this.factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.RenderLayer;
|
||||||
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
|
import com.jozufozu.flywheel.core.shader.ProgramSpec;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the entire context of a program's usage.
|
||||||
|
*
|
||||||
|
* @param alphaDiscard Alpha threshold below which pixels are discarded.
|
||||||
|
* @param vertexType The vertexType the program should be adapted for.
|
||||||
|
* @param spec The generic program name.
|
||||||
|
* @param ctx An ID representing the state at the time of usage.
|
||||||
|
*/
|
||||||
|
public record ProgramContext(float alphaDiscard, VertexType vertexType, ProgramSpec spec, long ctx) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a compilation context for the given program, vertex type and render layer.
|
||||||
|
*
|
||||||
|
* @param programName The name of the program to use.
|
||||||
|
* @param vertexType The vertex type to use.
|
||||||
|
* @param layer If cutout, the alpha discard threshold is 0.1, otherwise 0.
|
||||||
|
* @return A compilation context.
|
||||||
|
*/
|
||||||
|
public static ProgramContext create(ResourceLocation programName, VertexType vertexType, @Nullable RenderLayer layer) {
|
||||||
|
ProgramSpec spec = Backend.getInstance()
|
||||||
|
.getSpec(programName);
|
||||||
|
|
||||||
|
if (spec == null) {
|
||||||
|
throw new NullPointerException("Cannot compile shader because '" + programName + "' is not recognized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProgramContext(getAlphaDiscard(layer), vertexType, spec, spec.getCurrentStateID());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the alpha discard threshold for the given render layer.
|
||||||
|
*
|
||||||
|
* @param layer The render layer to get the alpha discard threshold for.
|
||||||
|
* @return The alpha discard threshold.
|
||||||
|
*/
|
||||||
|
public static float getAlphaDiscard(@Nullable RenderLayer layer) {
|
||||||
|
return layer == RenderLayer.CUTOUT ? 0.1f : 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceFile getFile() {
|
||||||
|
return spec().getSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ProgramContext that = (ProgramContext) o;
|
||||||
|
// override for instance equality on vertexType
|
||||||
|
return alphaDiscard == that.alphaDiscard && ctx == that.ctx && vertexType == that.vertexType && spec.equals(that.spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(alphaDiscard, vertexType, spec, ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -7,7 +7,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.RenderLayer;
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
import com.jozufozu.flywheel.backend.gl.shader.GlShader;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
import com.jozufozu.flywheel.backend.source.FileResolution;
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
|
@ -15,27 +15,50 @@ import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.backend.source.error.ErrorBuilder;
|
import com.jozufozu.flywheel.backend.source.error.ErrorBuilder;
|
||||||
import com.jozufozu.flywheel.backend.source.error.ErrorReporter;
|
import com.jozufozu.flywheel.backend.source.error.ErrorReporter;
|
||||||
import com.jozufozu.flywheel.backend.source.span.Span;
|
import com.jozufozu.flywheel.backend.source.span.Span;
|
||||||
import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
|
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class ShaderCompiler {
|
/**
|
||||||
|
* Compiles a shader program.
|
||||||
|
*/
|
||||||
|
public class ShaderCompiler implements FileIndex {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the file responsible for this compilation.
|
||||||
|
*/
|
||||||
public final ResourceLocation name;
|
public final ResourceLocation name;
|
||||||
public final Template<?> template;
|
|
||||||
|
/**
|
||||||
|
* The template we'll be using to generate the final source.
|
||||||
|
*/
|
||||||
|
public final Template template;
|
||||||
|
|
||||||
private final FileResolution header;
|
private final FileResolution header;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra {@code #define}s to be added to the shader.
|
||||||
|
*/
|
||||||
private final List<String> defines;
|
private final List<String> defines;
|
||||||
|
|
||||||
private final RenderLayer layer;
|
/**
|
||||||
|
* Alpha threshold below which pixels are discarded.
|
||||||
|
*/
|
||||||
|
private final float alphaDiscard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The vertex type to use.
|
||||||
|
*/
|
||||||
public final VertexType vertexType;
|
public final VertexType vertexType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main file to compile.
|
||||||
|
*/
|
||||||
public final SourceFile mainFile;
|
public final SourceFile mainFile;
|
||||||
|
|
||||||
private final List<SourceFile> files = new ArrayList<>();
|
private final List<SourceFile> files = new ArrayList<>();
|
||||||
|
|
||||||
public ShaderCompiler(CompilationContext context, Template<?> template, FileResolution header) {
|
public ShaderCompiler(ProgramContext context, Template template, FileResolution header) {
|
||||||
this.name = context.spec().name;
|
this.name = context.spec().name;
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.header = header;
|
this.header = header;
|
||||||
|
@ -43,7 +66,7 @@ public class ShaderCompiler {
|
||||||
this.defines = context.spec()
|
this.defines = context.spec()
|
||||||
.getDefines(context.ctx());
|
.getDefines(context.ctx());
|
||||||
this.vertexType = context.vertexType();
|
this.vertexType = context.vertexType();
|
||||||
layer = context.layer();
|
this.alphaDiscard = context.alphaDiscard();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlShader compile(ShaderType type) {
|
public GlShader compile(ShaderType type) {
|
||||||
|
@ -55,11 +78,9 @@ public class ShaderCompiler {
|
||||||
.append('\n')
|
.append('\n')
|
||||||
.append("#extension GL_ARB_explicit_attrib_location : enable\n")
|
.append("#extension GL_ARB_explicit_attrib_location : enable\n")
|
||||||
.append("#extension GL_ARB_conservative_depth : enable\n")
|
.append("#extension GL_ARB_conservative_depth : enable\n")
|
||||||
.append("#define ")
|
.append(type.getDefineStatement()); // special case shader type declaration
|
||||||
.append(type.define) // special case shader type declaration
|
|
||||||
.append('\n');
|
|
||||||
|
|
||||||
if (layer == RenderLayer.CUTOUT) {
|
if (alphaDiscard > 0) {
|
||||||
finalSource.append("#define ALPHA_DISCARD 0.1\n");
|
finalSource.append("#define ALPHA_DISCARD 0.1\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +112,7 @@ public class ShaderCompiler {
|
||||||
return new GlShader(this, type, finalSource.toString());
|
return new GlShader(this, type, finalSource.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public <P extends WorldProgram> P compile(ExtensibleGlProgram.Factory<P> worldShaderPipeline) {
|
public <P extends WorldProgram> P compile(GlProgram.Factory<P> worldShaderPipeline) {
|
||||||
return new ProgramAssembler(this.name)
|
return new ProgramAssembler(this.name)
|
||||||
.attachShader(compile(ShaderType.VERTEX))
|
.attachShader(compile(ShaderType.VERTEX))
|
||||||
.attachShader(compile(ShaderType.FRAGMENT))
|
.attachShader(compile(ShaderType.FRAGMENT))
|
||||||
|
@ -105,6 +126,7 @@ public class ShaderCompiler {
|
||||||
* @param sourceFile The file to retrieve the ID for.
|
* @param sourceFile The file to retrieve the ID for.
|
||||||
* @return A file ID unique to the given sourceFile.
|
* @return A file ID unique to the given sourceFile.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int getFileID(SourceFile sourceFile) {
|
public int getFileID(SourceFile sourceFile) {
|
||||||
int i = files.indexOf(sourceFile);
|
int i = files.indexOf(sourceFile);
|
||||||
if (i != -1) {
|
if (i != -1) {
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -6,6 +6,8 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
import com.jozufozu.flywheel.backend.gl.GLSLVersion;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
|
import com.jozufozu.flywheel.backend.source.FileResolution;
|
||||||
import com.jozufozu.flywheel.backend.source.SourceFile;
|
import com.jozufozu.flywheel.backend.source.SourceFile;
|
||||||
import com.jozufozu.flywheel.backend.source.parse.ShaderStruct;
|
import com.jozufozu.flywheel.backend.source.parse.ShaderStruct;
|
||||||
import com.jozufozu.flywheel.backend.source.parse.StructField;
|
import com.jozufozu.flywheel.backend.source.parse.StructField;
|
||||||
|
@ -17,25 +19,35 @@ import com.jozufozu.flywheel.backend.source.parse.StructField;
|
||||||
* Shader files are written somewhat abstractly. Subclasses of Template handle those abstractions, using SourceFile
|
* Shader files are written somewhat abstractly. Subclasses of Template handle those abstractions, using SourceFile
|
||||||
* metadata to generate shader code that OpenGL can use to call into our shader programs.
|
* metadata to generate shader code that OpenGL can use to call into our shader programs.
|
||||||
* </p>
|
* </p>
|
||||||
* @param <D> Holds metadata, generates errors.
|
|
||||||
*/
|
*/
|
||||||
public class Template<D extends TemplateData> {
|
public class Template {
|
||||||
|
|
||||||
private final Map<SourceFile, D> metadata = new HashMap<>();
|
private final Map<SourceFile, TemplateData> metadata = new HashMap<>();
|
||||||
|
|
||||||
private final Function<SourceFile, D> reader;
|
private final Function<SourceFile, TemplateData> reader;
|
||||||
private final GLSLVersion glslVersion;
|
private final GLSLVersion glslVersion;
|
||||||
|
|
||||||
public Template(GLSLVersion glslVersion, Function<SourceFile, D> reader) {
|
public Template(GLSLVersion glslVersion, Function<SourceFile, TemplateData> reader) {
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
this.glslVersion = glslVersion;
|
this.glslVersion = glslVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public D getMetadata(SourceFile file) {
|
public TemplateData getMetadata(SourceFile file) {
|
||||||
// lazily read files, cache results
|
// lazily read files, cache results
|
||||||
return metadata.computeIfAbsent(file, reader);
|
return metadata.computeIfAbsent(file, reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a program compiler using this template.
|
||||||
|
* @param factory A factory to add meaning to compiled programs.
|
||||||
|
* @param header The header file to use for the program.
|
||||||
|
* @param <P> The type of program to compile.
|
||||||
|
* @return A program compiler.
|
||||||
|
*/
|
||||||
|
public <P extends GlProgram> ProgramCompiler<P> programCompiler(GlProgram.Factory<P> factory, FileResolution header) {
|
||||||
|
return new ProgramCompiler<>(factory, this, header);
|
||||||
|
}
|
||||||
|
|
||||||
public GLSLVersion getVersion() {
|
public GLSLVersion getVersion() {
|
||||||
return glslVersion;
|
return glslVersion;
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
||||||
|
|
||||||
public interface TemplateData {
|
public interface TemplateData {
|
||||||
void vertexFooter(StringBuilder builder, ShaderCompiler file);
|
void vertexFooter(StringBuilder builder, ShaderCompiler file);
|
||||||
void fragmentFooter(StringBuilder builder, ShaderCompiler file);
|
void fragmentFooter(StringBuilder builder, FileIndex file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the necessary glue code here.
|
* Generate the necessary glue code here.
|
|
@ -1,4 +1,4 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
|
@ -1,5 +1,5 @@
|
||||||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
package com.jozufozu.flywheel.core.compile;
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lazily compiles shader programs, caching the results.
|
|
||||||
*
|
|
||||||
* @param <P> The class that the PipelineCompiler outputs.
|
|
||||||
*/
|
|
||||||
public class CachingCompiler<P extends GlProgram> {
|
|
||||||
protected final Map<CompilationContext, P> cache = new HashMap<>();
|
|
||||||
private final PipelineCompiler<P> pipeline;
|
|
||||||
|
|
||||||
public CachingCompiler(PipelineCompiler<P> pipeline) {
|
|
||||||
this.pipeline = pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get or compile a spec to the given vertex type, accounting for all game state conditions specified by the spec.
|
|
||||||
*
|
|
||||||
* @param context The context of compilation.
|
|
||||||
* @return A compiled GlProgram.
|
|
||||||
*/
|
|
||||||
public P getProgram(CompilationContext context) {
|
|
||||||
return cache.computeIfAbsent(context, this.pipeline::compile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
|
||||||
cache.values().forEach(P::delete);
|
|
||||||
cache.clear();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
|
||||||
import com.jozufozu.flywheel.backend.RenderLayer;
|
|
||||||
import com.jozufozu.flywheel.backend.source.SourceFile;
|
|
||||||
import com.jozufozu.flywheel.core.shader.ProgramSpec;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the entire context of a program's usage.
|
|
||||||
*
|
|
||||||
* @param layer
|
|
||||||
* @param vertexType The vertexType the program should be adapted for.
|
|
||||||
* @param spec The generic program name.
|
|
||||||
* @param ctx An ID representing the state at the time of usage.
|
|
||||||
*/
|
|
||||||
public record CompilationContext(RenderLayer layer, VertexType vertexType, ProgramSpec spec, long ctx) {
|
|
||||||
|
|
||||||
public static CompilationContext create(VertexType vertexType, RenderLayer layer, ProgramSpec spec) {
|
|
||||||
return new CompilationContext(layer, vertexType, spec, spec.getCurrentStateID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceFile getFile() {
|
|
||||||
return spec().getSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
CompilationContext that = (CompilationContext) o;
|
|
||||||
// override for instance equality on vertexType
|
|
||||||
return layer == that.layer && ctx == that.ctx && vertexType == that.vertexType && spec.equals(that.spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(layer, vertexType, spec, ctx);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main interface for compiling usable shaders from program specs.
|
|
||||||
* @param <P> the type of the program that this pipeline compiles.
|
|
||||||
*/
|
|
||||||
public interface PipelineCompiler<P extends GlProgram> {
|
|
||||||
|
|
||||||
P compile(CompilationContext vertexType);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core.pipeline;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderType;
|
|
||||||
import com.jozufozu.flywheel.backend.source.FileResolution;
|
|
||||||
import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram;
|
|
||||||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
|
||||||
|
|
||||||
public class WorldCompiler<P extends WorldProgram> implements PipelineCompiler<P> {
|
|
||||||
|
|
||||||
private final ExtensibleGlProgram.Factory<P> factory;
|
|
||||||
|
|
||||||
private final Template<?> template;
|
|
||||||
private final FileResolution header;
|
|
||||||
|
|
||||||
public WorldCompiler(ExtensibleGlProgram.Factory<P> factory, Template<?> template, FileResolution header) {
|
|
||||||
this.factory = factory;
|
|
||||||
this.template = template;
|
|
||||||
this.header = header;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public P compile(CompilationContext usage) {
|
|
||||||
ShaderCompiler compiler = new ShaderCompiler(usage, template, header);
|
|
||||||
|
|
||||||
return new ProgramAssembler(compiler.name)
|
|
||||||
.attachShader(compiler.compile(ShaderType.VERTEX))
|
|
||||||
.attachShader(compiler.compile(ShaderType.FRAGMENT))
|
|
||||||
.link()
|
|
||||||
.deleteLinkedShaders()
|
|
||||||
.build(this.factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
package com.jozufozu.flywheel.core.shader;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.ShaderContext;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ExtensionInstance#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
|
|
||||||
* per-program, this also allows for same extra specialization within a
|
|
||||||
* {@link ShaderContext ShaderContext}.
|
|
||||||
*/
|
|
||||||
public class ExtensibleGlProgram extends GlProgram {
|
|
||||||
|
|
||||||
protected final List<ExtensionInstance> extensions = new ArrayList<>();
|
|
||||||
|
|
||||||
public ExtensibleGlProgram(ResourceLocation name, int handle) {
|
|
||||||
super(name, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bind() {
|
|
||||||
super.bind();
|
|
||||||
|
|
||||||
extensions.forEach(ExtensionInstance::bind);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append("program ")
|
|
||||||
.append(name)
|
|
||||||
.append('[');
|
|
||||||
|
|
||||||
for (ExtensionInstance extension : extensions) {
|
|
||||||
builder.append(extension)
|
|
||||||
.append('+');
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(']');
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory interface to create {@link GlProgram}s parameterized by a list of extensions. This doesn't necessarily
|
|
||||||
* have to return an {@link ExtensibleGlProgram} if implementors want more flexibility for whatever reason.
|
|
||||||
*/
|
|
||||||
public interface Factory<P extends GlProgram> {
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
P create(ResourceLocation name, int handle);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -43,12 +43,13 @@ public class ProgramSpec {
|
||||||
public final ImmutableList<ProgramState> states;
|
public final ImmutableList<ProgramState> states;
|
||||||
|
|
||||||
public ProgramSpec(ResourceLocation source, List<ProgramState> states) {
|
public ProgramSpec(ResourceLocation source, List<ProgramState> states) {
|
||||||
this.source = Resolver.INSTANCE.findShader(source);
|
this.source = Resolver.INSTANCE.get(source);
|
||||||
this.states = ImmutableList.copyOf(states);
|
this.states = ImmutableList.copyOf(states);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(ResourceLocation name) {
|
public void setName(ResourceLocation name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.source.addSpec(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceLocation getSourceLoc() {
|
public ResourceLocation getSourceLoc() {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import static org.lwjgl.opengl.GL20.glUniform1f;
|
||||||
import static org.lwjgl.opengl.GL20.glUniform2f;
|
import static org.lwjgl.opengl.GL20.glUniform2f;
|
||||||
import static org.lwjgl.opengl.GL20.glUniform3f;
|
import static org.lwjgl.opengl.GL20.glUniform3f;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.gl.shader.GlProgram;
|
||||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||||
import com.mojang.blaze3d.platform.Window;
|
import com.mojang.blaze3d.platform.Window;
|
||||||
import com.mojang.math.Matrix4f;
|
import com.mojang.math.Matrix4f;
|
||||||
|
@ -11,11 +12,12 @@ import com.mojang.math.Matrix4f;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
public class WorldProgram extends ExtensibleGlProgram {
|
public class WorldProgram extends GlProgram {
|
||||||
protected final int uTime = getUniformLocation("uTime");
|
protected final int uTime = getUniformLocation("uTime");
|
||||||
protected final int uViewProjection = getUniformLocation("uViewProjection");
|
protected final int uViewProjection = getUniformLocation("uViewProjection");
|
||||||
protected final int uCameraPos = getUniformLocation("uCameraPos");
|
protected final int uCameraPos = getUniformLocation("uCameraPos");
|
||||||
protected final int uWindowSize = getUniformLocation("uWindowSize");
|
protected final int uWindowSize = getUniformLocation("uWindowSize");
|
||||||
|
private final WorldFog fog;
|
||||||
|
|
||||||
protected int uBlockAtlas;
|
protected int uBlockAtlas;
|
||||||
protected int uLightMap;
|
protected int uLightMap;
|
||||||
|
@ -23,7 +25,7 @@ public class WorldProgram extends ExtensibleGlProgram {
|
||||||
public WorldProgram(ResourceLocation name, int handle) {
|
public WorldProgram(ResourceLocation name, int handle) {
|
||||||
super(name, handle);
|
super(name, handle);
|
||||||
|
|
||||||
this.extensions.add(new WorldFog(this));
|
fog = new WorldFog(this);
|
||||||
|
|
||||||
super.bind();
|
super.bind();
|
||||||
registerSamplers();
|
registerSamplers();
|
||||||
|
@ -66,7 +68,7 @@ public class WorldProgram extends ExtensibleGlProgram {
|
||||||
@Override
|
@Override
|
||||||
public void bind() {
|
public void bind() {
|
||||||
super.bind();
|
super.bind();
|
||||||
|
fog.bind();
|
||||||
uploadWindowSize();
|
uploadWindowSize();
|
||||||
uploadTime(AnimationTickHolder.getRenderTime());
|
uploadTime(AnimationTickHolder.getRenderTime());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||||
|
package com.jozufozu.flywheel.core.shader;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"source": "flywheel:passthru.vert",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"when": "flywheel:normal_debug",
|
||||||
|
"define": "DEBUG_NORMAL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#use "flywheel:block.frag"
|
||||||
|
|
||||||
|
#if defined(VERTEX_SHADER)
|
||||||
|
void vertex(inout Vertex v) {
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in a new issue