From 392cfc915633667b354ce9f2c9c3ce0228019359 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sun, 8 Aug 2021 22:33:32 -0700 Subject: [PATCH] Reload - Redo shader loading - Now loads an immutable SourceFile containing some metadata - Replace legacy compilation pipeline with improved new one using new api - Builtins are defined in one file, now "header" - New ErrorReporter/ErrorBuilder methods - Fancier shader loading errors --- .../flywheel/backend/FileResolution.java | 14 +- .../com/jozufozu/flywheel/backend/Index.java | 34 ++++ .../flywheel/backend/ShaderContext.java | 12 -- .../flywheel/backend/ShaderSources.java | 43 +---- .../flywheel/backend/gl/shader/GlProgram.java | 1 - .../flywheel/backend/gl/shader/GlShader.java | 1 - .../instancing/InstancedRenderRegistry.java | 18 +- .../backend/loading/IProcessingStage.java | 7 - .../loading/InstancedArraysTemplate.java | 41 ----- .../flywheel/backend/loading/LayoutTag.java | 19 --- .../backend/loading/ModelTemplate.java | 36 ---- .../backend/loading/ProgramTemplate.java | 30 ---- .../{Program.java => ProtoProgram.java} | 20 +-- .../flywheel/backend/loading/Shader.java | 160 ------------------ .../backend/loading/ShaderTemplate.java | 120 ------------- .../backend/loading/ShaderTransformer.java | 38 ----- .../flywheel/backend/loading/TaggedField.java | 45 ----- .../backend/loading/TaggedStruct.java | 49 ------ .../flywheel/backend/pipeline/ITemplate.java | 41 +++++ .../pipeline/InstanceTemplateData.java | 86 ++++++++++ .../backend/pipeline/InstancingTemplate.java | 76 +++++++++ .../backend/pipeline/LegacyPipeline.java | 137 --------------- .../backend/pipeline/OneShotData.java | 74 ++++++++ .../backend/pipeline/OneShotTemplate.java | 72 ++++++++ .../backend/pipeline/ShaderBuilder.java | 31 ++-- .../flywheel/backend/pipeline/SourceFile.java | 64 ++++++- .../flywheel/backend/pipeline/Template.java | 123 -------------- .../backend/pipeline/WorldShaderPipeline.java | 38 ++--- .../backend/pipeline/error/ErrorBuilder.java | 36 +++- .../backend/pipeline/error/ErrorReporter.java | 35 +++- .../backend/pipeline/parse/Import.java | 9 + .../pipeline/parse/ShaderFunction.java | 18 +- .../backend/pipeline/parse/ShaderStruct.java | 14 +- .../com/jozufozu/flywheel/core/Contexts.java | 22 +-- .../jozufozu/flywheel/core/WorldContext.java | 57 +------ .../com/jozufozu/flywheel/util/FlwUtil.java | 55 ++++++ .../flywheel/flywheel/shaders/block.frag | 12 +- .../builtin.frag => crumbling.glsl} | 24 ++- .../shaders/context/crumbling/builtin.vert | 1 - .../shaders/context/{world => }/fog.glsl | 0 .../{world/builtin.frag => world.glsl} | 26 ++- .../shaders/context/world/builtin.vert | 19 --- .../flywheel/shaders/data/blockfragment.glsl | 7 - .../flywheel/shaders/data/modelvertex.glsl | 1 - .../flywheel/flywheel/shaders/model.glsl | 58 ------- .../flywheel/flywheel/shaders/model.vert | 13 +- .../flywheel/flywheel/shaders/oriented.vert | 18 +- .../flywheel/shaders/smooth_oriented.glsl | 14 +- .../shaders/template/instanced/instanced.frag | 19 --- .../shaders/template/instanced/instanced.vert | 19 --- .../shaders/template/meshlet/meshlet.glsl | 43 ----- .../shaders/template/model/model.frag | 12 -- .../shaders/template/model/model.vert | 15 -- 53 files changed, 766 insertions(+), 1211 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/backend/Index.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/IProcessingStage.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/LayoutTag.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java rename src/main/java/com/jozufozu/flywheel/backend/loading/{Program.java => ProtoProgram.java} (80%) delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTemplate.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTransformer.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/TaggedField.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/loading/TaggedStruct.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/ITemplate.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/InstanceTemplateData.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/InstancingTemplate.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/LegacyPipeline.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotData.java create mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotTemplate.java delete mode 100644 src/main/java/com/jozufozu/flywheel/backend/pipeline/Template.java create mode 100644 src/main/java/com/jozufozu/flywheel/util/FlwUtil.java rename src/main/resources/assets/flywheel/flywheel/shaders/context/{crumbling/builtin.frag => crumbling.glsl} (58%) delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling/builtin.vert rename src/main/resources/assets/flywheel/flywheel/shaders/context/{world => }/fog.glsl (100%) rename src/main/resources/assets/flywheel/flywheel/shaders/context/{world/builtin.frag => world.glsl} (50%) delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/context/world/builtin.vert delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/data/blockfragment.glsl delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/model.glsl delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.frag delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.vert delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/template/meshlet/meshlet.glsl delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.frag delete mode 100644 src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.vert diff --git a/src/main/java/com/jozufozu/flywheel/backend/FileResolution.java b/src/main/java/com/jozufozu/flywheel/backend/FileResolution.java index 4b60c8d80..8561d2136 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/FileResolution.java +++ b/src/main/java/com/jozufozu/flywheel/backend/FileResolution.java @@ -6,7 +6,7 @@ import java.util.List; import javax.annotation.Nullable; import com.jozufozu.flywheel.backend.pipeline.SourceFile; -import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter; +import com.jozufozu.flywheel.backend.pipeline.error.ErrorBuilder; import com.jozufozu.flywheel.backend.pipeline.span.Span; import net.minecraft.util.ResourceLocation; @@ -40,7 +40,17 @@ public class FileResolution { try { file = sources.source(fileLoc); } catch (RuntimeException error) { - ErrorReporter.generateSpanError(foundSpans.get(0), "could not find source"); + ErrorBuilder builder = new ErrorBuilder(); + builder.error(String.format("could not find source for file %s", fileLoc)); + for (Span span : foundSpans) { + builder.in(span.getSourceFile()) + .pointAt(span, 2); + } + Backend.log.error(builder.build()); } } + + void invalidate() { + + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/Index.java b/src/main/java/com/jozufozu/flywheel/backend/Index.java new file mode 100644 index 000000000..640f6a13c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/Index.java @@ -0,0 +1,34 @@ +package com.jozufozu.flywheel.backend; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.Multimap; +import com.google.common.collect.MultimapBuilder; +import com.jozufozu.flywheel.backend.pipeline.SourceFile; +import com.jozufozu.flywheel.backend.pipeline.parse.ShaderStruct; + +import net.minecraft.util.ResourceLocation; + +/** + * Indexes many shader source definitions to allow for error fix suggestions. + */ +public class Index { + + private final Multimap knownNames = MultimapBuilder.hashKeys().hashSetValues().build(); + + public Index(Map sources) { + Collection files = sources.values(); + + for (SourceFile file : files) { + file.getStructs().forEach(knownNames::put); + + } + } + + public Collection getStructDefinitionsMatching(CharSequence name) { + return knownNames.get(name.toString()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java index f1e4ff2c1..6841e8d22 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderContext.java @@ -1,23 +1,11 @@ package com.jozufozu.flywheel.backend; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.function.Supplier; -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; -import com.jozufozu.flywheel.backend.gl.shader.GlShader; -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.pipeline.SourceFile; import com.jozufozu.flywheel.core.shader.IMultiProgram; -import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; -import com.jozufozu.flywheel.core.shader.spec.ProgramState; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java index 2e5f0a3cc..17b974d81 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java @@ -3,9 +3,7 @@ package com.jozufozu.flywheel.backend; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.function.Predicate; @@ -15,16 +13,11 @@ 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.Flywheel; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.backend.loading.Shader; import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; import com.jozufozu.flywheel.backend.pipeline.SourceFile; -import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline; -import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.crumbling.CrumblingRenderer; -import com.jozufozu.flywheel.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.event.GatherContextEvent; import com.jozufozu.flywheel.util.StreamUtil; @@ -49,7 +42,6 @@ public class ShaderSources implements ISelectiveResourceReloadListener { public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); private static final Gson GSON = new GsonBuilder().create(); - private final Map shaderSource = new HashMap<>(); private final Map shaderSources = new HashMap<>(); private final Map resolutions = new HashMap<>(); @@ -57,6 +49,8 @@ public class ShaderSources implements ISelectiveResourceReloadListener { private boolean shouldCrash; private final Backend backend; + public Index index; + public ShaderSources(Backend backend) { this.backend = backend; IResourceManager manager = backend.minecraft.getResourceManager(); @@ -79,43 +73,24 @@ public class ShaderSources implements ISelectiveResourceReloadListener { return resolutions.computeIfAbsent(fileLoc, FileResolution::new); } - @Deprecated - public Shader source(ResourceLocation name, ShaderType type) { - return new Shader(this, type, name, getShaderSource(name)); - } - @Deprecated public void notifyError() { shouldCrash = true; } - @Deprecated - @Nonnull - public String getShaderSource(ResourceLocation loc) { - String source = shaderSource.get(loc); - - if (source == null) { - throw new ShaderLoadingException(String.format("shader '%s' does not exist", loc)); - } - - return source; - } - @Override public void onResourceManagerReload(IResourceManager manager, Predicate predicate) { if (predicate.test(VanillaResourceType.SHADERS)) { backend.refresh(); if (backend.gl20()) { - shaderSource.clear(); - shouldCrash = false; backend.clearContexts(); ModLoader.get() .postEvent(new GatherContextEvent(backend)); - resolutions.clear(); + resolutions.values().forEach(FileResolution::invalidate); loadProgramSpecs(manager); loadShaderSources(manager); @@ -124,12 +99,6 @@ public class ShaderSources implements ISelectiveResourceReloadListener { resolution.resolve(this); } - WorldShaderPipeline pl = new WorldShaderPipeline<>(this, WorldProgram::new); - -// ResourceLocation name = new ResourceLocation(Flywheel.ID, "model.glsl"); -// SourceFile source = source(name); -// pl.compile(name, source, Collections.emptyList()); - for (IShaderContext context : backend.allContexts()) { context.load(); } @@ -140,9 +109,6 @@ public class ShaderSources implements ISelectiveResourceReloadListener { Backend.log.info("Loaded all shader programs."); - // no need to hog all that memory - shaderSource.clear(); - ClientWorld world = Minecraft.getInstance().level; if (Backend.isFlywheelWorld(world)) { // TODO: looks like it might be good to have another event here @@ -169,12 +135,13 @@ public class ShaderSources implements ISelectiveResourceReloadListener { ResourceLocation name = ResourceUtil.removePrefixUnchecked(location, SHADER_DIR); - shaderSource.put(name, source); shaderSources.put(name, new SourceFile(this, name, source)); } catch (IOException e) { } } + + index = new Index(shaderSources); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index 8b7a9f8e6..39981fcb0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -8,7 +8,6 @@ import static org.lwjgl.opengl.GL20.glUseProgram; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlObject; -import com.jozufozu.flywheel.backend.loading.Program; import com.jozufozu.flywheel.util.RenderUtil; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java index 43e7b39e0..2fa733821 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlShader.java @@ -5,7 +5,6 @@ import org.lwjgl.opengl.GL20; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.gl.GlObject; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; -import com.jozufozu.flywheel.backend.loading.Shader; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java index 23d2821e9..399ed3bb8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java @@ -100,7 +100,15 @@ public class InstancedRenderRegistry { return skipRender.getBoolean(o); } - public class TileConfig { + public interface Config, FACTORY> { + + CONFIG factory(FACTORY rendererFactory); + + CONFIG setSkipRender(boolean skipRender); + } + + public class TileConfig implements Config, ITileInstanceFactory> { + private final TileEntityType type; @@ -112,14 +120,14 @@ public class InstancedRenderRegistry { tiles.put(type, rendererFactory); return this; } - public TileConfig setSkipRender(boolean skipRender) { InstancedRenderRegistry.this.skipRender.put(type, skipRender); return this; } - } - public class EntityConfig { + } + public class EntityConfig implements Config, IEntityInstanceFactory> { + private final EntityType type; @@ -131,12 +139,12 @@ public class InstancedRenderRegistry { entities.put(type, rendererFactory); return this; } - public EntityConfig setSkipRender(boolean skipRender) { InstancedRenderRegistry.this.skipRender.put(type, skipRender); return this; } + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/IProcessingStage.java b/src/main/java/com/jozufozu/flywheel/backend/loading/IProcessingStage.java deleted file mode 100644 index 2a60aa8c2..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/IProcessingStage.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -@FunctionalInterface -public interface IProcessingStage { - - void process(Shader shader); -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java deleted file mode 100644 index 5e0e73bf4..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/InstancedArraysTemplate.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.backend.ShaderSources; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; - -import net.minecraft.util.ResourceLocation; - -public class InstancedArraysTemplate extends ProgramTemplate { - - public static final String vertexData = "VertexData"; - public static final String instanceData = "InstanceData"; - public static final String fragment = "Fragment"; - - public static final String vertexPrefix = "a_v_"; - public static final String instancePrefix = "a_i_"; - - public static final String[] requiredVert = new String[]{instanceData, vertexData, fragment}; - - public static final String[] requiredFrag = {fragment}; - - public static final ResourceLocation vert = new ResourceLocation(Flywheel.ID, "template/instanced/instanced.vert"); - public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/instanced/instanced.frag"); - - public InstancedArraysTemplate(ShaderSources loader) { - super(loader); - - templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert))); - templates.put(ShaderType.FRAGMENT, new ShaderTemplate(requiredFrag, loader.getShaderSource(frag))); - } - - @Override - public void attachAttributes(Program builder) { - Shader shader = builder.attached.get(ShaderType.VERTEX); - - shader.getTag(vertexData) - .addPrefixedAttributes(builder, vertexPrefix); - shader.getTag(instanceData) - .addPrefixedAttributes(builder, instancePrefix); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/LayoutTag.java b/src/main/java/com/jozufozu/flywheel/backend/loading/LayoutTag.java deleted file mode 100644 index c7646e658..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/LayoutTag.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.jozufozu.flywheel.backend.gl.GlNumericType; - -public class LayoutTag { - - public static final Pattern pattern = Pattern.compile("Layout\\((\\w+)(?:\\s*,\\s*(\\w*))?\\)"); - - final GlNumericType type; - final boolean normalized; - - public LayoutTag(Matcher matcher) { - type = GlNumericType.byName(matcher.group(1)); - normalized = Boolean.parseBoolean(matcher.group(2)); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java deleted file mode 100644 index f747c452c..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/ModelTemplate.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.backend.ShaderSources; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; - -import net.minecraft.util.ResourceLocation; - -public class ModelTemplate extends ProgramTemplate { - public static final String vertexData = "VertexData"; - public static final String fragment = "Fragment"; - - public static final String vertexPrefix = "a_v_"; - - public static final String[] requiredVert = new String[]{vertexData, fragment}; - - public static final String[] requiredFrag = {fragment}; - - public static final ResourceLocation vert = new ResourceLocation(Flywheel.ID, "template/model/model.vert"); - public static final ResourceLocation frag = new ResourceLocation(Flywheel.ID, "template/model/model.frag"); - - public ModelTemplate(ShaderSources loader) { - super(loader); - - templates.put(ShaderType.VERTEX, new ShaderTemplate(requiredVert, loader.getShaderSource(vert))); - templates.put(ShaderType.FRAGMENT, new ShaderTemplate(requiredFrag, loader.getShaderSource(frag))); - } - - @Override - public void attachAttributes(Program builder) { - Shader shader = builder.attached.get(ShaderType.VERTEX); - - shader.getTag(vertexData) - .addPrefixedAttributes(builder, vertexPrefix); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java deleted file mode 100644 index a04f004fa..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/ProgramTemplate.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import java.util.EnumMap; -import java.util.Map; - -import com.jozufozu.flywheel.backend.ShaderSources; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; - -public abstract class ProgramTemplate implements IProcessingStage { - - protected final ShaderSources loader; - protected Map templates = new EnumMap<>(ShaderType.class); - - public ProgramTemplate(ShaderSources loader) { - this.loader = loader; - } - - @Override - public void process(Shader shader) { - ShaderTemplate template = templates.get(shader.type); - - if (template == null) return; - - shader.setSource(template.apply(shader)); - } - - public void attachAttributes(Program builder) { - - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/Program.java b/src/main/java/com/jozufozu/flywheel/backend/loading/ProtoProgram.java similarity index 80% rename from src/main/java/com/jozufozu/flywheel/backend/loading/Program.java rename to src/main/java/com/jozufozu/flywheel/backend/loading/ProtoProgram.java index d1748467a..374a5a3d7 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/Program.java +++ b/src/main/java/com/jozufozu/flywheel/backend/loading/ProtoProgram.java @@ -23,40 +23,32 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.util.ResourceLocation; -public class Program { +public class ProtoProgram { public final int program; public ResourceLocation name; private int attributeIndex; - public final Map attached; - private final IntList shaders; - public Program() { + public ProtoProgram() { this.program = glCreateProgram(); - attached = new EnumMap<>(ShaderType.class); shaders = new IntArrayList(2); } - public Program attachShader(Shader shader, GlShader glShader) { + public void attachShader(GlShader glShader) { glAttachShader(this.program, glShader.handle()); - - attached.put(shader.type, shader); - - return this; } - public Program addAttribute(String name, int attributeCount) { + public void addAttribute(String name, int attributeCount) { glBindAttribLocation(this.program, attributeIndex, name); attributeIndex += attributeCount; - return this; } /** * Links the attached shaders to this program. */ - public Program link(ResourceLocation name) { + public ProtoProgram link(ResourceLocation name) { this.name = name; glLinkProgram(this.program); @@ -75,7 +67,7 @@ public class Program { return this; } - public Program deleteLinkedShaders() { + public ProtoProgram deleteLinkedShaders() { shaders.forEach((IntConsumer) GL20::glDeleteShader); return this; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java b/src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java deleted file mode 100644 index 33eac3bf6..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/Shader.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import java.io.BufferedReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.jozufozu.flywheel.backend.ShaderSources; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; - -import net.minecraft.util.ResourceLocation; - -public class Shader { - // #flwinclude <"valid_namespace:valid/path_to_file.glsl"> - private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); - - public static final Pattern versionDetector = Pattern.compile("#version[^\\n]*"); - private static final Pattern decorator = Pattern.compile("#\\[([\\w_]*)]"); - - public final ResourceLocation name; - public ShaderType type; - private String source; - private final ShaderSources loader; - - private boolean parsed = false; - final List structs = new ArrayList<>(3); - final Map tag2Struct = new HashMap<>(); - final Map name2Struct = new HashMap<>(); - - public Shader(ShaderSources loader, ShaderType type, ResourceLocation name, String source) { - this.loader = loader; - this.type = type; - this.name = name; - this.source = source; - } - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public TaggedStruct getTag(String tag) { - checkIfParsed(); - return tag2Struct.get(tag); - } - - public TaggedStruct getStruct(String name) { - checkIfParsed(); - return name2Struct.get(name); - } - - private void checkIfParsed() { - if (!parsed) { - throw new IllegalStateException("tagged structs must be explicitly parsed before use"); - } - } - - public void defineAll(Collection defines) { - Matcher matcher = versionDetector.matcher(source); - - if (matcher.find()) { - StringBuffer sourceWithDefines = new StringBuffer(); - String lines = defines.stream() - .map(it -> "#define " + it) - .collect(Collectors.joining("\n")); - - matcher.appendReplacement(sourceWithDefines, matcher.group() + '\n' + lines); - - matcher.appendTail(sourceWithDefines); - - source = sourceWithDefines.toString(); - } - } - - public void parseStructs() { - Matcher structMatcher = TaggedStruct.taggedStruct.matcher(source); - - StringBuffer strippedSrc = new StringBuffer(); - - while (structMatcher.find()) { - TaggedStruct struct = new TaggedStruct(structMatcher); - - structs.add(struct); - - String replacement = decorator.matcher(struct.source) - .replaceFirst(""); - structMatcher.appendReplacement(strippedSrc, replacement); - - tag2Struct.put(struct.tag, struct); - name2Struct.put(struct.name, struct); - } - structMatcher.appendTail(strippedSrc); - - this.source = strippedSrc.toString(); - parsed = true; - } - - public void processIncludes() { - HashSet seen = new HashSet<>(); - seen.add(name); - - source = includeRecursive(source, seen).collect(Collectors.joining("\n")); - } - - private Stream includeRecursive(String source, Set seen) { - return lines(source).flatMap(line -> { - - Matcher matcher = includePattern.matcher(line); - - if (matcher.find()) { - String includeName = matcher.group(1); - - ResourceLocation include = new ResourceLocation(includeName); - - if (seen.add(include)) { - try { - return includeRecursive(loader.getShaderSource(include), seen); - } catch (ShaderLoadingException e) { - throw new ShaderLoadingException("could not resolve import: " + e.getMessage()); - } - } - - } - - return Stream.of(line); - }); - } - - public String printSource() { - StringBuilder builder = new StringBuilder(); - - builder.append("Source for shader '") - .append(name) - .append("':\n"); - int i = 1; - for (String s : source.split("\n")) { - builder.append(String.format("%1$4s: ", i++)) - .append(s) - .append('\n'); - } - - return builder.toString(); - } - - public static Stream lines(String s) { - return new BufferedReader(new StringReader(s)).lines(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTemplate.java deleted file mode 100644 index cb7bdbad0..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTemplate.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ShaderTemplate { - - private static final String delimiter = "#flwbeginbody"; - private static final Pattern headerFinder = Pattern.compile(delimiter); - - private static final Pattern prefixer = Pattern.compile("#FLWPrefixFields\\((\\w+),\\s*(\\w+),\\s*([\\w\\d]+)\\)"); - private static final Pattern assigner = Pattern.compile("#FLWAssignFields\\(([\\w\\d_]+),\\s*([\\w\\d_.]+),\\s*([\\w\\d_.]+)\\)"); - - final String[] requiredStructs; - - final String header; - final String body; - - public ShaderTemplate(String[] requiredStructs, String templateSrc) { - this.requiredStructs = requiredStructs; - Matcher matcher = headerFinder.matcher(templateSrc); - - if (!matcher.find()) { - throw new RuntimeException("Shader template must have a header and footer delimited by '" + delimiter + "'"); - } - - this.header = templateSrc.substring(0, matcher.start()); - this.body = templateSrc.substring(matcher.end()); - - } - - public String apply(Shader shader) { - shader.parseStructs(); - - return header + shader.getSource() + processBody(shader); - } - - public String processBody(Shader shader) { - String s = body; - - List missing = new ArrayList<>(); - - for (String name : requiredStructs) { - TaggedStruct struct = shader.getTag(name); - - if (struct != null) { - s = s.replace(name, struct.name); - } else { - missing.add(name); - } - } - - if (!missing.isEmpty()) { - String err = shader.name + " is missing: " + String.join(", ", missing); - throw new RuntimeException(err); - } - - s = fillPrefixes(shader, s); - s = fillAssigns(shader, s); - - return s; - } - - private String fillPrefixes(Shader shader, String s) { - Matcher prefixMatches = prefixer.matcher(s); - - StringBuffer out = new StringBuffer(); - while (prefixMatches.find()) { - String structName = prefixMatches.group(1); - String modifier = prefixMatches.group(2); - String prefix = prefixMatches.group(3); - - TaggedStruct struct = shader.getStruct(structName); - - StringBuilder builder = new StringBuilder(); - for (TaggedField field : struct.fields) { - builder.append(modifier); - builder.append(' '); - builder.append(field.getType()); - builder.append(' '); - builder.append(prefix); - builder.append(field.getName()); - builder.append(";\n"); - } - - prefixMatches.appendReplacement(out, builder.toString()); - } - prefixMatches.appendTail(out); - return out.toString(); - } - - private String fillAssigns(Shader shader, String s) { - Matcher assignMatches = assigner.matcher(s); - - StringBuffer out = new StringBuffer(); - while (assignMatches.find()) { - String structName = assignMatches.group(1); - String lhs = assignMatches.group(2); - String rhs = assignMatches.group(3); - - TaggedStruct struct = shader.getStruct(structName); - - StringBuilder builder = new StringBuilder(); - for (TaggedField field : struct.fields) { - builder.append(lhs); - builder.append(field.getName()); - builder.append(" = "); - builder.append(rhs); - builder.append(field.getName()); - builder.append(";\n"); - } - - assignMatches.appendReplacement(out, builder.toString()); - } - assignMatches.appendTail(out); - return out.toString(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTransformer.java b/src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTransformer.java deleted file mode 100644 index 4d156f8a7..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/ShaderTransformer.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import java.util.LinkedList; - -public class ShaderTransformer { - - private final LinkedList stages = new LinkedList<>(); - - public ShaderTransformer() { - } - - public ShaderTransformer pushStage(IProcessingStage stage) { - if (stage != null) { - stages.addLast(stage); - } - return this; - } - - public ShaderTransformer popStage() { - stages.removeLast(); - return this; - } - - public ShaderTransformer prependStage(IProcessingStage stage) { - if (stage != null) { - stages.addFirst(stage); - } - return this; - } - - public void transformSource(Shader shader) { - - for (IProcessingStage stage : this.stages) { - stage.process(shader); - } - } - -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/TaggedField.java b/src/main/java/com/jozufozu/flywheel/backend/loading/TaggedField.java deleted file mode 100644 index 754cf8517..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/TaggedField.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class TaggedField { - public static final Pattern fieldPattern = Pattern.compile("(?:#\\[([^\\n]*)]\\s*)?(\\S+)\\s*(\\S+);"); - - public String annotation; - public String name; - public String type; - public LayoutTag layout; - - public TaggedField(Matcher fieldMatcher) { - annotation = fieldMatcher.group(1); - type = fieldMatcher.group(2); - name = fieldMatcher.group(3); - - if (annotation != null) { - Matcher matcher = LayoutTag.pattern.matcher(annotation); - - if (matcher.find()) { - layout = new LayoutTag(matcher); - } - } - } - - public String getAnnotation() { - return annotation; - } - - public String getName() { - return name; - } - - public String getType() { - return type; - } - - - @Override - public String toString() { - return "TaggedField{" + "name='" + name + '\'' + ", type='" + type + '\'' + '}'; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/loading/TaggedStruct.java b/src/main/java/com/jozufozu/flywheel/backend/loading/TaggedStruct.java deleted file mode 100644 index 419736645..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/loading/TaggedStruct.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.jozufozu.flywheel.backend.loading; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class TaggedStruct { - - // https://regexr.com/5t207 - public static final Pattern taggedStruct = Pattern.compile("#\\[(\\w*)]\\s*struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d \\t#\\[\\](),;\\n]*)}\\s*;"); - - public int srcStart, srcEnd; - public String source; - public String tag; - public String name; - public String body; - - List fields = new ArrayList<>(4); - Map fields2Types = new HashMap<>(); - - public TaggedStruct(Matcher foundMatcher) { - this.source = foundMatcher.group(); - - srcStart = foundMatcher.start(); - srcEnd = foundMatcher.end(); - - tag = foundMatcher.group(1); - name = foundMatcher.group(2); - body = foundMatcher.group(3); - - Matcher fielder = TaggedField.fieldPattern.matcher(body); - - while (fielder.find()) { - fields.add(new TaggedField(fielder)); - fields2Types.put(fielder.group(2), fielder.group(1)); - } - } - - public void addPrefixedAttributes(Program builder, String prefix) { - for (TaggedField field : fields) { - int attributeCount = TypeHelper.getAttributeCount(field.type); - - builder.addAttribute(prefix + field.name, attributeCount); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ITemplate.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ITemplate.java new file mode 100644 index 000000000..9547eac6c --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ITemplate.java @@ -0,0 +1,41 @@ +package com.jozufozu.flywheel.backend.pipeline; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.loading.ProtoProgram; +import com.jozufozu.flywheel.backend.pipeline.parse.ShaderStruct; +import com.jozufozu.flywheel.backend.pipeline.parse.StructField; + +public interface ITemplate { + void generateTemplateSource(StringBuilder builder, ShaderType type, SourceFile file); + + void attachAttributes(ProtoProgram program, SourceFile file); + + + static void prefixFields(StringBuilder builder, ShaderStruct struct, String qualifier, String prefix) { + ImmutableList fields = struct.getFields(); + + for (StructField field : fields) { + builder.append(qualifier) + .append(' ') + .append(field.type) + .append(' ') + .append(prefix) + .append(field.name) + .append(";\n"); + } + } + + static void assignFields(StringBuilder builder, ShaderStruct struct, String prefix1, String prefix2) { + ImmutableList fields = struct.getFields(); + + for (StructField field : fields) { + builder.append(prefix1) + .append(field.name) + .append(" = ") + .append(prefix2) + .append(field.name) + .append(";\n"); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstanceTemplateData.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstanceTemplateData.java new file mode 100644 index 000000000..8b503ca01 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstanceTemplateData.java @@ -0,0 +1,86 @@ +package com.jozufozu.flywheel.backend.pipeline; + +import java.util.Optional; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter; +import com.jozufozu.flywheel.backend.pipeline.parse.ShaderFunction; +import com.jozufozu.flywheel.backend.pipeline.parse.ShaderStruct; +import com.jozufozu.flywheel.backend.pipeline.parse.Variable; +import com.jozufozu.flywheel.backend.pipeline.span.Span; + +public class InstanceTemplateData { + + public final SourceFile file; + public final ShaderFunction vertexMain; + public final ShaderFunction fragmentMain; + public final Span interpolantName; + public final Span vertexName; + public final Span instanceName; + public final ShaderStruct interpolant; + public final ShaderStruct vertex; + public final ShaderStruct instance; + + public InstanceTemplateData(SourceFile file) { + this.file = file; + + Optional vertexFunc = file.findFunction("vertex"); + Optional fragmentFunc = file.findFunction("fragment"); + + + if (!fragmentFunc.isPresent()) { + ErrorReporter.generateFileError(file, "could not find \"fragment\" function"); + } + if (!vertexFunc.isPresent()) { + ErrorReporter.generateFileError(file, "could not find \"vertex\" function"); + } + + if (!fragmentFunc.isPresent() || !vertexFunc.isPresent()) { + throw new RuntimeException(); + } + + fragmentMain = fragmentFunc.get(); + vertexMain = vertexFunc.get(); + ImmutableList parameters = fragmentMain.getParameters(); + ImmutableList vertexParams = vertexMain.getParameters(); + + if (parameters.size() != 1) { + ErrorReporter.generateSpanError(fragmentMain.getArgs(), "instancing requires fragment function to have 1 argument"); + } + + if (vertexParams.size() != 2) { + ErrorReporter.generateSpanError(vertexMain.getArgs(), "instancing requires vertex function to have 2 arguments"); + throw new RuntimeException(); + } + + interpolantName = vertexMain.getType(); + vertexName = vertexParams.get(0) + .typeName(); + instanceName = vertexParams.get(1) + .typeName(); + + Optional maybeInterpolant = file.findStruct(interpolantName); + Optional maybeVertex = file.findStruct(vertexName); + Optional maybeInstance = file.findStruct(instanceName); + + if (!maybeVertex.isPresent()) { + ErrorReporter.generateMissingStruct(file, vertexName); + } + + if (!maybeInterpolant.isPresent()) { + ErrorReporter.generateMissingStruct(file, interpolantName); + } + + if (!maybeInstance.isPresent()) { + ErrorReporter.generateMissingStruct(file, instanceName); + } + + if (!maybeVertex.isPresent() || !maybeInterpolant.isPresent() || !maybeInstance.isPresent()) { + throw new RuntimeException(); + } + + interpolant = maybeInterpolant.get(); + vertex = maybeVertex.get(); + instance = maybeInstance.get(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstancingTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstancingTemplate.java new file mode 100644 index 000000000..0a01be533 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/InstancingTemplate.java @@ -0,0 +1,76 @@ +package com.jozufozu.flywheel.backend.pipeline; + +import java.util.HashMap; +import java.util.Map; + +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.loading.ProtoProgram; + +public class InstancingTemplate implements ITemplate { + + public static final InstancingTemplate INSTANCE = new InstancingTemplate(); + + private final Map datas = new HashMap<>(); + + @Override + public void generateTemplateSource(StringBuilder builder, ShaderType type, SourceFile file) { + if (type == ShaderType.VERTEX) { + vertexFooter(builder, file); + } else if (type == ShaderType.FRAGMENT) { + fragmentFooter(builder, file); + } + } + + @Override + public void attachAttributes(ProtoProgram program, SourceFile file) { + InstanceTemplateData data = getData(file); + data.vertex.addPrefixedAttributes(program, "a_v_"); + data.instance.addPrefixedAttributes(program, "a_i_"); + } + + public InstanceTemplateData getData(SourceFile file) { + return datas.computeIfAbsent(file, InstanceTemplateData::new); + } + + public void vertexFooter(StringBuilder template, SourceFile file) { + InstanceTemplateData data = getData(file); + + ITemplate.prefixFields(template, data.vertex, "attribute", "a_v_"); + ITemplate.prefixFields(template, data.instance, "attribute", "a_i_"); + ITemplate.prefixFields(template, data.interpolant, "varying", "v2f_"); + + template.append("void main() {\n"); + template.append(data.vertexName) + .append(" v;\n"); + ITemplate.assignFields(template, data.vertex, "v.", "a_v_"); + + template.append(data.instanceName) + .append(" i;\n"); + ITemplate.assignFields(template, data.instance, "i.", "a_i_"); + + template.append(data.interpolantName) + .append(" o = ") + .append(data.vertexMain.call("v", "i")) + .append(";\n"); + + ITemplate.assignFields(template, data.interpolant, "v2f_", "o."); + + template.append('}'); + } + + public void fragmentFooter(StringBuilder template, SourceFile file) { + InstanceTemplateData data = getData(file); + + ITemplate.prefixFields(template, data.interpolant, "varying", "v2f_"); + + template.append("void main() {\n"); + template.append(data.interpolantName) + .append(" o;\n"); + ITemplate.assignFields(template, data.interpolant, "o.", "v2f_"); + + template.append(data.fragmentMain.call("o")) + .append(";\n"); + + template.append('}'); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/LegacyPipeline.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/LegacyPipeline.java deleted file mode 100644 index c19324483..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/LegacyPipeline.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.jozufozu.flywheel.backend.pipeline; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.ShaderSources; -import com.jozufozu.flywheel.backend.gl.GlObject; -import com.jozufozu.flywheel.backend.gl.shader.GlShader; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; -import com.jozufozu.flywheel.backend.loading.Program; -import com.jozufozu.flywheel.backend.loading.ProgramTemplate; -import com.jozufozu.flywheel.backend.loading.Shader; -import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; -import com.jozufozu.flywheel.backend.loading.ShaderTransformer; -import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; -import com.jozufozu.flywheel.core.shader.GameStateProgram; -import com.jozufozu.flywheel.core.shader.IMultiProgram; -import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; -import com.jozufozu.flywheel.core.shader.spec.ProgramState; - -public class LegacyPipeline

implements IShaderPipeline

{ - - private static final String declaration = "#flwbuiltins"; - private static final Pattern builtinPattern = Pattern.compile(declaration); - - - private final ShaderSources sources; - protected ShaderTransformer transformer; - private final ProgramTemplate template; - private final ExtensibleGlProgram.Factory

factory; - private final Map builtinSources; - - - public LegacyPipeline(ShaderSources sources, ProgramTemplate template, ExtensibleGlProgram.Factory

factory, Map builtinSources) { - this.sources = sources; - this.template = template; - this.factory = factory; - - transformer = new ShaderTransformer().pushStage(this::injectBuiltins) - .pushStage(Shader::processIncludes) - .pushStage(template) - .pushStage(Shader::processIncludes); - this.builtinSources = builtinSources; - } - - @Override - public IMultiProgram

compile(ProgramSpec spec) { - GameStateProgram.Builder

builder = GameStateProgram.builder(compile(spec, null)); - - for (ProgramState state : spec.states) { - - builder.withVariant(state.getContext(), compile(spec, state)); - } - - return builder.build(); - } - - /** - * Ingests the given shaders, compiling them and linking them together after applying the transformer to the source. - * - * @param shaders What are the different shader stages that should be linked together? - * @return A program with all provided shaders attached - */ - protected static Program buildProgram(Shader... shaders) { - List compiled = new ArrayList<>(shaders.length); - try { - Program builder = new Program(); - - for (Shader shader : shaders) { - GlShader sh = new GlShader(shader.name, shader.type, shader.getSource()); - compiled.add(sh); - - builder.attachShader(shader, sh); - } - - return builder; - } finally { - compiled.forEach(GlObject::delete); - } - } - - public Program loadAndLink(ProgramSpec spec, @Nullable ProgramState state) { - Shader vertexFile = sources.source(spec.vert, ShaderType.VERTEX); - Shader fragmentFile = sources.source(spec.frag, ShaderType.FRAGMENT); - - transformer.transformSource(vertexFile); - transformer.transformSource(fragmentFile); - - if (state != null) { - vertexFile.defineAll(state.getDefines()); - fragmentFile.defineAll(state.getDefines()); - } - - Program program = buildProgram(vertexFile, fragmentFile); - template.attachAttributes(program); - - program.link(spec.name).deleteLinkedShaders(); - - String descriptor = program.program + ": " + spec.name; - - if (state != null) - descriptor += "#" + state; - - Backend.log.debug(descriptor); - - return program; - } - - private P compile(ProgramSpec spec, @Nullable ProgramState state) { - if (state != null) { - Program program = loadAndLink(spec, state); - return factory.create(program.name, program.program, state.getExtensions()); - } else { - Program program = loadAndLink(spec, null); - return factory.create(program.name, program.program, null); - } - } - - /** - * Replace #flwbuiltins with whatever expansion this context provides for the given shader. - */ - public void injectBuiltins(Shader shader) { - Matcher matcher = builtinPattern.matcher(shader.getSource()); - - if (matcher.find()) shader.setSource(matcher.replaceFirst(builtinSources.get(shader.type))); - else - throw new ShaderLoadingException(String.format("%s is missing %s, cannot use in World Context", shader.type.name, declaration)); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotData.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotData.java new file mode 100644 index 000000000..99ced1cd8 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotData.java @@ -0,0 +1,74 @@ +package com.jozufozu.flywheel.backend.pipeline; + +import java.util.Optional; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter; +import com.jozufozu.flywheel.backend.pipeline.parse.ShaderFunction; +import com.jozufozu.flywheel.backend.pipeline.parse.ShaderStruct; +import com.jozufozu.flywheel.backend.pipeline.parse.Variable; +import com.jozufozu.flywheel.backend.pipeline.span.Span; + +public class OneShotData { + + public final SourceFile file; + public final ShaderFunction vertexMain; + public final Span interpolantName; + public final Span vertexName; + public final ShaderStruct interpolant; + public final ShaderStruct vertex; + public final ShaderFunction fragmentMain; + + public OneShotData(SourceFile file) { + this.file = file; + + Optional maybeVertexMain = file.findFunction("vertex"); + Optional maybeFragmentMain = file.findFunction("fragment"); + + if (!maybeVertexMain.isPresent()) { + ErrorReporter.generateFileError(file, "could not find \"vertex\" function"); + throw new RuntimeException(); + } + + if (!maybeFragmentMain.isPresent()) { + ErrorReporter.generateFileError(file, "could not find \"fragment\" function"); + throw new RuntimeException(); + } + + vertexMain = maybeVertexMain.get(); + fragmentMain = maybeFragmentMain.get(); + ImmutableList parameters = fragmentMain.getParameters(); + ImmutableList vertexParameters = vertexMain.getParameters(); + + if (vertexParameters.size() != 1) { + ErrorReporter.generateSpanError(vertexMain.getArgs(), "a basic model requires vertex function to have one argument"); + throw new RuntimeException(); + } + + if (parameters.size() != 1) { + ErrorReporter.generateSpanError(fragmentMain.getArgs(), "instancing requires fragment function to have 1 argument"); + throw new RuntimeException(); + } + + + interpolantName = vertexMain.getType(); + vertexName = vertexParameters.get(0) + .typeName(); + + Optional maybeInterpolant = file.findStruct(interpolantName); + Optional maybeVertex = file.findStruct(vertexName); + + if (!maybeVertex.isPresent()) + ErrorReporter.generateMissingStruct(file, vertexName); + + if (!maybeInterpolant.isPresent()) + ErrorReporter.generateMissingStruct(file, interpolantName); + + if (!maybeVertex.isPresent() || !maybeInterpolant.isPresent()) { + throw new RuntimeException(); + } + + interpolant = maybeInterpolant.get(); + vertex = maybeVertex.get(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotTemplate.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotTemplate.java new file mode 100644 index 000000000..805ac34d2 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/OneShotTemplate.java @@ -0,0 +1,72 @@ +package com.jozufozu.flywheel.backend.pipeline; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.loading.ProtoProgram; + +public class OneShotTemplate implements ITemplate { + + public static final OneShotTemplate INSTANCE = new OneShotTemplate(); + + + private final Map datas = new HashMap<>(); + + @Override + public void generateTemplateSource(StringBuilder builder, ShaderType type, SourceFile file) { + if (type == ShaderType.VERTEX) { + vertexFooter(builder, file); + } else if (type == ShaderType.FRAGMENT) { + fragmentFooter(builder, file); + } + } + + @Override + public void attachAttributes(ProtoProgram program, SourceFile file) { + OneShotData data = getData(file); + data.vertex.addPrefixedAttributes(program, "a_v_"); + } + + public OneShotData getData(SourceFile file) { + return datas.computeIfAbsent(file, OneShotData::new); + } + + public void vertexFooter(StringBuilder template, SourceFile file) { + OneShotData data = getData(file); + + ITemplate.prefixFields(template, data.vertex, "attribute", "a_v_"); + ITemplate.prefixFields(template, data.interpolant, "varying", "v2f_"); + + template.append("void main() {\n"); + template.append(data.vertexName) + .append(" v;\n"); + ITemplate.assignFields(template, data.vertex, "v.", "a_v_"); + + template.append(data.interpolantName) + .append(" o = ") + .append(data.vertexMain.call("v")) + .append(";\n"); + + ITemplate.assignFields(template, data.interpolant, "v2f_", "o."); + + template.append('}'); + } + + public void fragmentFooter(StringBuilder template, SourceFile file) { + OneShotData data = getData(file); + + ITemplate.prefixFields(template, data.interpolant, "varying", "v2f_"); + + template.append("void main() {\n"); + template.append(data.interpolant.name) + .append(" o;\n"); + ITemplate.assignFields(template, data.interpolant, "o.", "v2f_"); + + template.append(data.fragmentMain.call("o")) + .append(";\n"); + + template.append('}'); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderBuilder.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderBuilder.java index 35cd5e174..3c4c704cd 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/ShaderBuilder.java @@ -1,8 +1,8 @@ package com.jozufozu.flywheel.backend.pipeline; -import java.util.ArrayList; import java.util.List; +import com.jozufozu.flywheel.backend.FileResolution; import com.jozufozu.flywheel.backend.gl.shader.GlShader; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; @@ -11,18 +11,19 @@ import net.minecraft.util.ResourceLocation; public class ShaderBuilder { public final ResourceLocation name; - public final Template template; + public final ITemplate template; + public final FileResolution header; - private SourceFile mainFile; + public SourceFile mainFile; private GLSLVersion version; private StringBuilder source; private StringBuilder defines; - private CharSequence footer; - public ShaderBuilder(ResourceLocation name, Template template) { + public ShaderBuilder(ResourceLocation name, ITemplate template, FileResolution header) { this.name = name; this.template = template; + this.header = header; } public ShaderBuilder setVersion(GLSLVersion version) { @@ -41,21 +42,13 @@ public class ShaderBuilder { return this; } - public ShaderBuilder setFooter(CharSequence footer) { - this.footer = footer; - return this; - } - public ShaderBuilder setMainSource(SourceFile file) { if (mainFile == file) return this; mainFile = file; source = new StringBuilder(); - for (SourceFile includeFile : Includer.recurseIncludes(file)) { - source.append(includeFile.getElidedSource()); - } - source.append(file.getElidedSource()); + file.generateFinalSource(source); return this; } @@ -70,9 +63,13 @@ public class ShaderBuilder { .append("#define ") .append(type.define) .append('\n') - .append(defines != null ? defines : "") - .append(source) - .append(template.footer(type, mainFile)); + .append(defines != null ? defines : ""); + SourceFile file = header.getFile(); + if (file != null) { + file.generateFinalSource(finalSource); + } + mainFile.generateFinalSource(finalSource); + template.generateTemplateSource(finalSource, type, mainFile); return new GlShader(name, type, finalSource); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/SourceFile.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/SourceFile.java index 618316ffb..6c02398f4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/SourceFile.java @@ -1,14 +1,21 @@ package com.jozufozu.flywheel.backend.pipeline; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.Queue; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.Nullable; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.jozufozu.flywheel.backend.FileResolution; import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.pipeline.parse.Import; import com.jozufozu.flywheel.backend.pipeline.parse.ShaderFunction; @@ -33,7 +40,7 @@ public class SourceFile { public final ResourceLocation name; - private final ShaderSources parent; + public final ShaderSources parent; private final String source; private final CharSequence elided; private final ImmutableList lines; @@ -89,6 +96,61 @@ public class SourceFile { return imports; } + /** + * Search this file and recursively search all imports to find a struct definition matching the given name. + * + * @param name The name of the struct to find. + * @return null if no definition matches the name. + */ + public Optional findStruct(CharSequence name) { + ShaderStruct struct = getStructs().get(name.toString()); + + if (struct != null) return Optional.of(struct); + + for (Import include : getIncludes()) { + Optional externalStruct = include.getOptional() + .flatMap(file -> file.findStruct(name)); + + if (externalStruct.isPresent()) return externalStruct; + } + + return Optional.empty(); + } + + /** + * Search this file and recursively search all imports to find a function definition matching the given name. + * + * @param name The name of the function to find. + * @return Optional#empty() if no definition matches the name. + */ + public Optional findFunction(CharSequence name) { + ShaderFunction local = getFunctions().get(name.toString()); + + if (local != null) return Optional.of(local); + + for (Import include : getIncludes()) { + Optional external = include.getOptional() + .flatMap(file -> file.findFunction(name)); + + if (external.isPresent()) return external; + } + + return Optional.empty(); + } + + public CharSequence importStatement() { + return "#use " + '"' + name + '"'; + } + + public void generateFinalSource(StringBuilder source) { + for (Import include : getIncludes()) { + SourceFile file = include.getFile(); + + if (file != null) file.generateFinalSource(source); + } + source.append(getElidedSource()); + } + public CharPos getCharPos(int charPos) { int lineNo = 0; for (; lineNo < lineStarts.size(); lineNo++) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/Template.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/Template.java deleted file mode 100644 index 176443918..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/Template.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.jozufozu.flywheel.backend.pipeline; - -import com.google.common.collect.ImmutableList; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; -import com.jozufozu.flywheel.backend.pipeline.parse.ShaderFunction; -import com.jozufozu.flywheel.backend.pipeline.parse.ShaderStruct; -import com.jozufozu.flywheel.backend.pipeline.parse.StructField; -import com.jozufozu.flywheel.backend.pipeline.parse.Variable; - -public class Template { - - public CharSequence footer(ShaderType type, SourceFile file) { - switch (type) { - case VERTEX: - return vertexFooter(file); - case FRAGMENT: - return fragmentFooter(file); - } - - return ""; - } - - public CharSequence vertexFooter(SourceFile file) { - ShaderFunction vertexMain = file.getFunctions() - .get("vertex"); - - ImmutableList parameters = vertexMain.getParameters(); - - ShaderStruct interpolant = file.getStructs() - .get(vertexMain.returnType()); - - ShaderStruct vertex = file.getStructs() - .get(parameters.get(0) - .typeName() - .get()); - - ShaderStruct instance = file.getStructs() - .get(parameters.get(1) - .typeName() - .get()); - - StringBuilder template = new StringBuilder(); - - prefixFields(template, vertex, "attribute", "a_v_"); - prefixFields(template, instance, "attribute", "a_i_"); - prefixFields(template, interpolant, "varying", "v2f_"); - - template.append("void main() {\n"); - template.append(vertex.name) - .append(" v;\n"); - assignFields(template, vertex, "v.", "a_v_"); - - template.append(instance.name) - .append(" i;\n"); - assignFields(template, instance, "i.", "a_i_"); - - template.append(interpolant.name) - .append(" o = ") - .append(vertexMain.call("v", "i")) - .append(";\n"); - - assignFields(template, interpolant, "v2f_", "o."); - - template.append('}'); - - return template; - } - - public CharSequence fragmentFooter(SourceFile file) { - ShaderFunction fragmentMain = file.getFunctions() - .get("fragment"); - - ImmutableList parameters = fragmentMain.getParameters(); - - ShaderStruct interpolant = file.getStructs() - .get(parameters.get(0) - .typeName() - .get()); - - StringBuilder template = new StringBuilder(); - - prefixFields(template, interpolant, "varying", "v2f_"); - - template.append("void main() {\n"); - template.append(interpolant.name) - .append(" o;\n"); - assignFields(template, interpolant, "o.", "v2f_"); - - template.append(fragmentMain.call("o")) - .append(";\n"); - - template.append('}'); - - return template; - } - - public static void prefixFields(StringBuilder builder, ShaderStruct struct, String qualifier, String prefix) { - ImmutableList fields = struct.getFields(); - - for (StructField field : fields) { - builder.append(qualifier) - .append(' ') - .append(field.type) - .append(' ') - .append(prefix) - .append(field.name) - .append(";\n"); - } - } - - public static void assignFields(StringBuilder builder, ShaderStruct struct, String prefix1, String prefix2) { - ImmutableList fields = struct.getFields(); - - for (StructField field : fields) { - builder.append(prefix1) - .append(field.name) - .append(" = ") - .append(prefix2) - .append(field.name) - .append(";\n"); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java index 9f98d5c69..436a42f51 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java @@ -12,9 +12,11 @@ import javax.annotation.Nullable; import org.lwjgl.opengl.GL20; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.FileResolution; import com.jozufozu.flywheel.backend.ShaderSources; import com.jozufozu.flywheel.backend.gl.shader.GlShader; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.loading.ProtoProgram; import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; import com.jozufozu.flywheel.core.shader.GameStateProgram; import com.jozufozu.flywheel.core.shader.IMultiProgram; @@ -24,15 +26,20 @@ import com.jozufozu.flywheel.core.shader.spec.ProgramState; import net.minecraft.util.ResourceLocation; -public class WorldShaderPipeline

{ +public class WorldShaderPipeline

implements IShaderPipeline

{ private final ShaderSources sources; private final ExtensibleGlProgram.Factory

factory; - public WorldShaderPipeline(ShaderSources sources, ExtensibleGlProgram.Factory

factory) { + private final ITemplate template; + private final FileResolution header; + + public WorldShaderPipeline(ShaderSources sources, ExtensibleGlProgram.Factory

factory, ITemplate template, FileResolution header) { this.sources = sources; this.factory = factory; + this.template = template; + this.header = header; } public IMultiProgram

compile(ProgramSpec spec) { @@ -43,9 +50,9 @@ public class WorldShaderPipeline

{ } public IMultiProgram

compile(ResourceLocation name, SourceFile file, List variants) { - ShaderBuilder shader = new ShaderBuilder(name, new Template()) + ShaderBuilder shader = new ShaderBuilder(name, template, header) .setMainSource(file) - .setVersion(GLSLVersion.V120); + .setVersion(GLSLVersion.V110); GameStateProgram.Builder

builder = GameStateProgram.builder(compile(shader, name, null)); @@ -65,27 +72,20 @@ public class WorldShaderPipeline

{ GlShader vertex = shader.compile(name, ShaderType.VERTEX); GlShader fragment = shader.compile(name, ShaderType.FRAGMENT); - int program = GL20.glCreateProgram(); + ProtoProgram program = new ProtoProgram(); - GL20.glAttachShader(program, vertex.handle()); - GL20.glAttachShader(program, fragment.handle()); + program.attachShader(vertex); + program.attachShader(fragment); - String log = glGetProgramInfoLog(program); + template.attachAttributes(program, shader.mainFile); - if (!log.isEmpty()) { - Backend.log.debug("Program link log for " + name + ": " + log); - } - - int result = glGetProgrami(program, GL_LINK_STATUS); - - if (result != GL_TRUE) { - throw new RuntimeException("Shader program linking failed, see log for details"); - } + program.link(name); + program.deleteLinkedShaders(); if (variant != null) { - return factory.create(name, program, variant.getExtensions()); + return factory.create(name, program.program, variant.getExtensions()); } else { - return factory.create(name, program, null); + return factory.create(name, program.program, null); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorBuilder.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorBuilder.java index 72115c9c6..4ba70f099 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorBuilder.java @@ -1,19 +1,36 @@ package com.jozufozu.flywheel.backend.pipeline.error; +import java.util.Optional; + +import javax.annotation.Nullable; + import com.jozufozu.flywheel.backend.pipeline.SourceFile; import com.jozufozu.flywheel.backend.pipeline.span.Span; +import com.jozufozu.flywheel.util.FlwUtil; public class ErrorBuilder { private final StringBuilder internal = new StringBuilder(); - public ErrorBuilder header(CharSequence msg) { + public ErrorBuilder error(CharSequence msg) { internal.append("error: ") .append(msg); return endLine(); } - public ErrorBuilder errorIn(SourceFile file) { + public ErrorBuilder note(CharSequence msg) { + internal.append("note: ") + .append(msg); + return endLine(); + } + + public ErrorBuilder hint(CharSequence msg) { + internal.append("hint: ") + .append(msg); + return endLine(); + } + + public ErrorBuilder in(SourceFile file) { internal.append("--> ") .append(file.name); return endLine(); @@ -37,7 +54,18 @@ public class ErrorBuilder { return this; } + public ErrorBuilder hintIncludeFor(Span span) { + if (span == null) return this; + + hint("add " + span.getSourceFile().importStatement()) + .in(span.getSourceFile()) + .pointAt(span, 1); + + return this; + } + public ErrorBuilder pointAt(Span span, int ctxLines) { + SourceFile file = span.getSourceFile(); if (span.lines() == 1) { @@ -47,6 +75,8 @@ public class ErrorBuilder { int firstLine = Math.max(0, spanLine - ctxLines); int lastLine = Math.min(file.getLineCount(), spanLine + ctxLines); + int digits = FlwUtil.numDigits(lastLine); + int firstCol = span.getStart().getCol(); int lastCol = span.getEnd().getCol(); @@ -57,7 +87,7 @@ public class ErrorBuilder { numberedLine(i + 1, line); if (i == spanLine) { - line(" ", generateUnderline(firstCol, lastCol)); + line(FlwUtil.repeatChar(' ', digits), generateUnderline(firstCol, lastCol)); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorReporter.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorReporter.java index d124a009a..03095e40f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorReporter.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/error/ErrorReporter.java @@ -1,7 +1,10 @@ package com.jozufozu.flywheel.backend.pipeline.error; +import java.util.Optional; + import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.pipeline.SourceFile; +import com.jozufozu.flywheel.backend.pipeline.parse.ShaderStruct; import com.jozufozu.flywheel.backend.pipeline.span.Span; public class ErrorReporter { @@ -11,11 +14,37 @@ public class ErrorReporter { ErrorBuilder builder = new ErrorBuilder(); - CharSequence error = builder.header(message) - .errorIn(file) + CharSequence error = builder.error(message) + .in(file) .pointAt(span, 2) .build(); - Backend.log.info(error); + Backend.log.error(error); + } + + public static void generateFileError(SourceFile file, String message) { + + ErrorBuilder builder = new ErrorBuilder(); + + CharSequence error = builder.error(message) + .in(file) + .build(); + + Backend.log.error(error); + } + + public static void generateMissingStruct(SourceFile file, Span vertexName) { + Optional span = file.parent.index.getStructDefinitionsMatching(vertexName) + .stream() + .findFirst() + .map(ShaderStruct::getName); + ErrorBuilder builder = new ErrorBuilder(); + + ErrorBuilder error = builder.error("struct not defined") + .in(file) + .pointAt(vertexName, 2) + .hintIncludeFor(span.orElse(null)); + + Backend.log.error(error.build()); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/Import.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/Import.java index ecfbfc564..9702b7dfb 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/Import.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/Import.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.backend.pipeline.parse; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import javax.annotation.Nullable; @@ -43,6 +44,14 @@ public class Import extends AbstractShaderElement { return new ResourceLocation(""); } + public FileResolution getResolution() { + return resolution; + } + + public Optional getOptional() { + return Optional.ofNullable(resolution.getFile()); + } + @Nullable public SourceFile getFile() { return resolution.getFile(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderFunction.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderFunction.java index 2bfe7648e..c183e25d8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderFunction.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderFunction.java @@ -29,6 +29,22 @@ public class ShaderFunction extends AbstractShaderElement { this.parameters = parseArguments(); } + public Span getType() { + return type; + } + + public Span getName() { + return name; + } + + public Span getArgs() { + return args; + } + + public Span getBody() { + return body; + } + public String call(String... args) { return name + "(" + String.join(", ", args) + ")"; } @@ -37,7 +53,7 @@ public class ShaderFunction extends AbstractShaderElement { return parameters; } - public String returnType() { + public String returnTypeName() { return type.get(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderStruct.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderStruct.java index 74643c005..d28be3a9e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderStruct.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/parse/ShaderStruct.java @@ -1,14 +1,12 @@ package com.jozufozu.flywheel.backend.pipeline.parse; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.jozufozu.flywheel.backend.loading.Program; +import com.jozufozu.flywheel.backend.loading.ProtoProgram; import com.jozufozu.flywheel.backend.loading.TypeHelper; -import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter; import com.jozufozu.flywheel.backend.pipeline.span.Span; public class ShaderStruct extends AbstractShaderElement { @@ -30,6 +28,14 @@ public class ShaderStruct extends AbstractShaderElement { this.fields2Types = createTypeLookup(); } + public Span getName() { + return name; + } + + public Span getBody() { + return body; + } + public ImmutableList getFields() { return fields; } @@ -59,7 +65,7 @@ public class ShaderStruct extends AbstractShaderElement { return fields.build(); } - public void addPrefixedAttributes(Program builder, String prefix) { + public void addPrefixedAttributes(ProtoProgram builder, String prefix) { for (StructField field : fields) { int attributeCount = TypeHelper.getAttributeCount(field.type); diff --git a/src/main/java/com/jozufozu/flywheel/core/Contexts.java b/src/main/java/com/jozufozu/flywheel/core/Contexts.java index 8767824d9..a9ce0b778 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Contexts.java +++ b/src/main/java/com/jozufozu/flywheel/core/Contexts.java @@ -1,15 +1,16 @@ package com.jozufozu.flywheel.core; -import java.util.List; - import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.FileResolution; +import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.SpecMetaRegistry; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.pipeline.IShaderPipeline; +import com.jozufozu.flywheel.backend.pipeline.InstancingTemplate; +import com.jozufozu.flywheel.backend.pipeline.WorldShaderPipeline; import com.jozufozu.flywheel.core.crumbling.CrumblingProgram; import com.jozufozu.flywheel.core.shader.WorldFog; import com.jozufozu.flywheel.core.shader.WorldProgram; -import com.jozufozu.flywheel.core.shader.extension.IProgramExtension; import com.jozufozu.flywheel.core.shader.gamestate.FogStateProvider; import com.jozufozu.flywheel.core.shader.gamestate.NormalDebugStateProvider; import com.jozufozu.flywheel.event.GatherContextEvent; @@ -33,13 +34,14 @@ public class Contexts { SpecMetaRegistry.register(WorldFog.LINEAR); SpecMetaRegistry.register(WorldFog.EXP2); - CRUMBLING = backend.register(new WorldContext<>(backend, CrumblingProgram::new).withName(Names.CRUMBLING) - .withBuiltin(ShaderType.FRAGMENT, Names.CRUMBLING, "/builtin.frag") - .withBuiltin(ShaderType.VERTEX, Names.CRUMBLING, "/builtin.vert")); + FileResolution crumblingBuiltins = backend.sources.resolveFile(ResourceUtil.subPath(Names.CRUMBLING, ".glsl")); + FileResolution worldBuiltins = backend.sources.resolveFile(ResourceUtil.subPath(Names.WORLD, ".glsl")); - WORLD = backend.register(new WorldContext<>(backend, WorldProgram::new).withName(Names.WORLD) - .withBuiltin(ShaderType.FRAGMENT, Names.WORLD, "/builtin.frag") - .withBuiltin(ShaderType.VERTEX, Names.WORLD, "/builtin.vert")); + IShaderPipeline crumblingPipeline = new WorldShaderPipeline<>(backend.sources, CrumblingProgram::new, InstancingTemplate.INSTANCE, crumblingBuiltins); + IShaderPipeline worldPipeline = new WorldShaderPipeline<>(backend.sources, WorldProgram::new, InstancingTemplate.INSTANCE, worldBuiltins); + + CRUMBLING = backend.register(new WorldContext<>(backend, crumblingPipeline).withName(Names.CRUMBLING)); + WORLD = backend.register(new WorldContext<>(backend, worldPipeline).withName(Names.WORLD)); } public static class Names { diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java index 382efc173..390bbd71b 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java @@ -1,22 +1,12 @@ package com.jozufozu.flywheel.core; -import java.util.EnumMap; -import java.util.Map; import java.util.function.Supplier; import java.util.stream.Stream; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.ShaderContext; -import com.jozufozu.flywheel.backend.ShaderSources; -import com.jozufozu.flywheel.backend.gl.shader.ShaderType; -import com.jozufozu.flywheel.backend.loading.InstancedArraysTemplate; -import com.jozufozu.flywheel.backend.loading.ProgramTemplate; -import com.jozufozu.flywheel.backend.loading.ShaderLoadingException; import com.jozufozu.flywheel.backend.material.MaterialSpec; import com.jozufozu.flywheel.backend.pipeline.IShaderPipeline; -import com.jozufozu.flywheel.backend.pipeline.LegacyPipeline; -import com.jozufozu.flywheel.core.shader.ExtensibleGlProgram; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; @@ -25,24 +15,16 @@ import net.minecraft.util.ResourceLocation; public class WorldContext

extends ShaderContext

{ protected ResourceLocation name; protected Supplier> specStream; - protected TemplateFactory templateFactory; - private final Map builtins = new EnumMap<>(ShaderType.class); - private final Map builtinSources = new EnumMap<>(ShaderType.class); + public final IShaderPipeline

pipeline; - private final ExtensibleGlProgram.Factory

factory; - - public IShaderPipeline

pipeline; - - public WorldContext(Backend backend, ExtensibleGlProgram.Factory

factory) { + public WorldContext(Backend backend, IShaderPipeline

factory) { super(backend); - this.factory = factory; + this.pipeline = factory; specStream = () -> backend.allMaterials() .stream() .map(MaterialSpec::getProgramName); - - templateFactory = InstancedArraysTemplate::new; } public WorldContext

withName(ResourceLocation name) { @@ -50,42 +32,16 @@ public class WorldContext

extends ShaderContext

{ return this; } - public WorldContext

withBuiltin(ShaderType shaderType, ResourceLocation folder, String file) { - return withBuiltin(shaderType, ResourceUtil.subPath(folder, file)); - } - - public WorldContext

withBuiltin(ShaderType shaderType, ResourceLocation file) { - builtins.put(shaderType, file); - return this; - } - public WorldContext

withSpecStream(Supplier> specStream) { this.specStream = specStream; return this; } - public WorldContext

withTemplateFactory(TemplateFactory templateFactory) { - this.templateFactory = templateFactory; - return this; - } - @Override public void load() { Backend.log.info("Loading context '{}'", name); - try { - builtins.forEach((type, resourceLocation) -> builtinSources.put(type, backend.sources.getShaderSource(resourceLocation))); - } catch (ShaderLoadingException e) { - backend.sources.notifyError(); - - Backend.log.error(String.format("Could not find builtin: %s", e.getMessage())); - - return; - } - - pipeline = new LegacyPipeline<>(backend.sources, templateFactory.create(backend.sources), factory, builtinSources); - specStream.get() .map(backend::getSpec) .forEach(this::loadSpec); @@ -98,12 +54,9 @@ public class WorldContext

extends ShaderContext

{ Backend.log.debug("Loaded program {}", spec.name); } catch (Exception e) { - Backend.log.error("Program '{}': {}", spec.name, e); + Backend.log.error("Error loading program {}", spec.name); + Backend.log.error("", e); backend.sources.notifyError(); } } - - public interface TemplateFactory { - ProgramTemplate create(ShaderSources loader); - } } diff --git a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java new file mode 100644 index 000000000..bcb2177d6 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java @@ -0,0 +1,55 @@ +package com.jozufozu.flywheel.util; + +import java.util.Arrays; + +public class FlwUtil { + + public static String repeatChar(char c, int n) { + char[] arr = new char[n]; + + Arrays.fill(arr, c); + + return new String(arr); + } + + public static int numDigits(int number) { + // cursed but allegedly the fastest algorithm, taken from https://www.baeldung.com/java-number-of-digits-in-int + if (number < 100000) { + if (number < 100) { + if (number < 10) { + return 1; + } else { + return 2; + } + } else { + if (number < 1000) { + return 3; + } else { + if (number < 10000) { + return 4; + } else { + return 5; + } + } + } + } else { + if (number < 10000000) { + if (number < 1000000) { + return 6; + } else { + return 7; + } + } else { + if (number < 100000000) { + return 8; + } else { + if (number < 1000000000) { + return 9; + } else { + return 10; + } + } + } + } + } +} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/block.frag b/src/main/resources/assets/flywheel/flywheel/shaders/block.frag index 1eae7e5cc..5e1402b05 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/block.frag +++ b/src/main/resources/assets/flywheel/flywheel/shaders/block.frag @@ -1,8 +1,13 @@ -#flwbuiltins -#flwinclude <"flywheel:data/blockfragment.glsl"> +struct BlockFrag { + vec2 texCoords; + vec4 color; + float diffuse; + vec2 light; +}; -void FLWMain(BlockFrag r) { +#if defined(FRAGMENT_SHADER) +void fragment(BlockFrag r) { vec4 tex = FLWBlockTexture(r.texCoords); vec4 color = vec4(tex.rgb * FLWLight(r.light).rgb * r.diffuse, tex.a) * r.color; @@ -15,3 +20,4 @@ void FLWMain(BlockFrag r) { // flw_Tint = r.color; FLWFinalizeColor(color); } +#endif diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling/builtin.frag b/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.glsl similarity index 58% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling/builtin.frag rename to src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.glsl index 3f68e588c..9d7de9986 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling/builtin.frag +++ b/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling.glsl @@ -1,10 +1,31 @@ -#flwinclude <"flywheel:context/world/fog.glsl"> +#use "flywheel:context/fog.glsl" + +uniform float uTime; +uniform mat4 uViewProjection; +uniform vec3 uCameraPos; uniform vec2 uTextureScale; uniform sampler2D uBlockAtlas; uniform sampler2D uLightMap; uniform sampler2D uCrumbling; +uniform vec2 uWindowSize; + +void FLWFinalizeNormal(inout vec3 normal) { + // noop +} + +#if defined(VERTEX_SHADER) +void FLWFinalizeWorldPos(inout vec4 worldPos) { + #if defined(USE_FOG) + FragDistance = length(worldPos.xyz - uCameraPos); + #endif + + gl_Position = uViewProjection * worldPos; +} + +#elif defined(FRAGMENT_SHADER) + vec4 FLWBlockTexture(vec2 texCoords) { vec4 cr = texture2D(uCrumbling, texCoords * uTextureScale); float diffuseAlpha = texture2D(uBlockAtlas, texCoords).a; @@ -27,3 +48,4 @@ void FLWFinalizeColor(vec4 color) { vec4 FLWLight(vec2 lightCoords) { return vec4(1.); } +#endif diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling/builtin.vert b/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling/builtin.vert deleted file mode 100644 index 730ca3556..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/context/crumbling/builtin.vert +++ /dev/null @@ -1 +0,0 @@ -#flwinclude <"flywheel:context/world/builtin.vert"> diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/world/fog.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/context/fog.glsl similarity index 100% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/world/fog.glsl rename to src/main/resources/assets/flywheel/flywheel/shaders/context/fog.glsl diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/world/builtin.frag b/src/main/resources/assets/flywheel/flywheel/shaders/context/world.glsl similarity index 50% rename from src/main/resources/assets/flywheel/flywheel/shaders/context/world/builtin.frag rename to src/main/resources/assets/flywheel/flywheel/shaders/context/world.glsl index 831d5a1de..e21ee6a9a 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/context/world/builtin.frag +++ b/src/main/resources/assets/flywheel/flywheel/shaders/context/world.glsl @@ -1,10 +1,31 @@ -#flwinclude <"flywheel:context/world/fog.glsl"> -#flwinclude <"flywheel:core/lightutil.glsl"> +#use "flywheel:context/fog.glsl" +uniform float uTime; +uniform mat4 uViewProjection; +uniform vec3 uCameraPos; + +uniform vec2 uTextureScale; uniform sampler2D uBlockAtlas; uniform sampler2D uLightMap; + uniform vec2 uWindowSize; +void FLWFinalizeNormal(inout vec3 normal) { + // noop +} + +#if defined(VERTEX_SHADER) +void FLWFinalizeWorldPos(inout vec4 worldPos) { + #if defined(USE_FOG) + FragDistance = length(worldPos.xyz - uCameraPos); + #endif + + gl_Position = uViewProjection * worldPos; +} + +#elif defined(FRAGMENT_SHADER) +#use "flywheel:core/lightutil.glsl" + vec4 FLWBlockTexture(vec2 texCoords) { return texture2D(uBlockAtlas, texCoords); } @@ -24,3 +45,4 @@ void FLWFinalizeColor(vec4 color) { vec4 FLWLight(vec2 lightCoords) { return texture2D(uLightMap, shiftLight(lightCoords)); } +#endif diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/context/world/builtin.vert b/src/main/resources/assets/flywheel/flywheel/shaders/context/world/builtin.vert deleted file mode 100644 index 251267397..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/context/world/builtin.vert +++ /dev/null @@ -1,19 +0,0 @@ -uniform float uTime; -uniform mat4 uViewProjection; -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -void FLWFinalizeWorldPos(inout vec4 worldPos) { - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz - uCameraPos); - #endif - - gl_Position = uViewProjection * worldPos; -} - -void FLWFinalizeNormal(inout vec3 normal) { - // noop -} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/data/blockfragment.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/data/blockfragment.glsl deleted file mode 100644 index e5d09eb16..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/data/blockfragment.glsl +++ /dev/null @@ -1,7 +0,0 @@ -#[Fragment] -struct BlockFrag { - vec2 texCoords; - vec4 color; - float diffuse; - vec2 light; -}; diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/data/modelvertex.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/data/modelvertex.glsl index 5e34d2883..ae77b9b68 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/data/modelvertex.glsl +++ b/src/main/resources/assets/flywheel/flywheel/shaders/data/modelvertex.glsl @@ -1,4 +1,3 @@ -#[VertexData] struct Vertex { vec3 pos; vec3 normal; diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/model.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/model.glsl deleted file mode 100644 index b5ec6955c..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/model.glsl +++ /dev/null @@ -1,58 +0,0 @@ -#use "flywheel:core/diffuse.glsl" - -struct Instance { - vec2 light; - vec4 color; - mat4 transform; - mat3 normalMat; -}; - -struct Vertex { - vec3 pos; - vec3 normal; - vec2 texCoords; -}; - -struct BlockFrag { - vec2 texCoords; - vec4 color; - float diffuse; - vec2 light; -}; - -BlockFrag vertex(Vertex v, Instance i) { - vec4 worldPos = i.transform * vec4(v.pos, 1.); - - vec3 norm = i.normalMat * v.normal; - - FLWFinalizeWorldPos(worldPos); - FLWFinalizeNormal(norm); - - norm = normalize(norm); - - BlockFrag b; - b.diffuse = diffuse(norm); - b.texCoords = v.texCoords; - b.light = i.light; - #if defined(DEBUG_NORMAL) - b.color = vec4(norm, 1.); - #else - b.color = i.color; - #endif - return b; -} - -void fragment(BlockFrag r) { - vec4 tex = FLWBlockTexture(r.texCoords); - - vec4 color = vec4(tex.rgb * FLWLight(r.light).rgb * r.diffuse, tex.a) * r.color; - - // flw_WorldPos = ; - // flw_Normal = ; - // flw_Albedo = tex.rgb; - // flw_Alpha = tex.a; - // flw_LightMap = r.light; - // flw_Tint = r.color; - FLWFinalizeColor(color); -} - diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/model.vert b/src/main/resources/assets/flywheel/flywheel/shaders/model.vert index efdfbf804..cbd40f7d6 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/model.vert +++ b/src/main/resources/assets/flywheel/flywheel/shaders/model.vert @@ -1,10 +1,9 @@ -#flwbuiltins -#flwinclude <"flywheel:core/diffuse.glsl"> +#use "flywheel:core/diffuse.glsl" -#flwinclude <"flywheel:data/modelvertex.glsl"> -#flwinclude <"flywheel:data/blockfragment.glsl"> +#use "flywheel:data/modelvertex.glsl" + +#use "flywheel:block.frag" -#[InstanceData] struct Instance { vec2 light; vec4 color; @@ -12,7 +11,8 @@ struct Instance { mat3 normalMat; }; -BlockFrag FLWMain(Vertex v, Instance i) { +#if defined(VERTEX_SHADER) +BlockFrag vertex(Vertex v, Instance i) { vec4 worldPos = i.transform * vec4(v.pos, 1.); vec3 norm = i.normalMat * v.normal; @@ -33,3 +33,4 @@ BlockFrag FLWMain(Vertex v, Instance i) { #endif return b; } +#endif diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert b/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert index 5c040349d..2cf8f2322 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert +++ b/src/main/resources/assets/flywheel/flywheel/shaders/oriented.vert @@ -1,9 +1,10 @@ -#flwbuiltins -#flwinclude <"flywheel:core/matutils.glsl"> -#flwinclude <"flywheel:core/quaternion.glsl"> -#flwinclude <"flywheel:core/diffuse.glsl"> +#use "flywheel:core/matutils.glsl" +#use "flywheel:core/quaternion.glsl" +#use "flywheel:core/diffuse.glsl" + +#use "flywheel:data/modelvertex.glsl" +#use "flywheel:block.frag" -#[InstanceData] struct Oriented { vec2 light; vec4 color; @@ -12,10 +13,8 @@ struct Oriented { vec4 rotation; }; -#flwinclude <"flywheel:data/modelvertex.glsl"> -#flwinclude <"flywheel:data/blockfragment.glsl"> - -BlockFrag FLWMain(Vertex v, Oriented o) { +#if defined(VERTEX_SHADER) +BlockFrag vertex(Vertex v, Oriented o) { vec4 worldPos = vec4(rotateVertexByQuat(v.pos - o.pivot, o.rotation) + o.pivot + o.pos, 1.); vec3 norm = rotateVertexByQuat(v.normal, o.rotation); @@ -34,3 +33,4 @@ BlockFrag FLWMain(Vertex v, Oriented o) { #endif return b; } +#endif diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/smooth_oriented.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/smooth_oriented.glsl index 4b6aac8ce..c657678aa 100644 --- a/src/main/resources/assets/flywheel/flywheel/shaders/smooth_oriented.glsl +++ b/src/main/resources/assets/flywheel/flywheel/shaders/smooth_oriented.glsl @@ -1,9 +1,7 @@ -#flwbuiltins -#flwinclude <"flywheel:core/matutils.glsl"> -#flwinclude <"flywheel:core/quaternion.glsl"> -#flwinclude <"flywheel:core/diffuse.glsl"> +#use "flywheel:core/matutils.glsl" +#use "flywheel:core/quaternion.glsl" +#use "flywheel:core/diffuse.glsl" -#[InstanceData] struct Oriented { // each vec 4 is 2 light coords packed // x z @@ -21,10 +19,10 @@ struct Oriented { vec4 rotation; }; -#flwinclude <"flywheel:data/modelvertex.glsl"> -#flwinclude <"flywheel:data/blockfragment.glsl"> +#use "flywheel:data/modelvertex.glsl" +#use "flywheel:block.frag" -BlockFrag FLWMain(Vertex v, Oriented o) { +BlockFrag vertex(Vertex v, Oriented o) { vec4 worldPos = vec4(rotateVertexByQuat(v.pos - o.pivot, o.rotation) + o.pivot + o.pos, 1.); vec3 norm = rotateVertexByQuat(v.normal, o.rotation); diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.frag b/src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.frag deleted file mode 100644 index 2f1bd8e03..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.frag +++ /dev/null @@ -1,19 +0,0 @@ -#version 110 - -#flwbeginbody - -#FLWPrefixFields(Fragment, varying, v2f_) - -//vec3 flw_WorldPos; -//vec3 flw_Normal; -//vec3 flw_Albedo; -//float flw_Alpha; -//vec2 flw_LightMap; -//vec4 flw_Tint; - -void main() { - Fragment f; - #FLWAssignFields(Fragment, f., v2f_) - - FLWMain(f); -} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.vert b/src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.vert deleted file mode 100644 index 83cc28e2b..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/template/instanced/instanced.vert +++ /dev/null @@ -1,19 +0,0 @@ -#version 110 - -#flwbeginbody -#FLWPrefixFields(VertexData, attribute, a_v_) -#FLWPrefixFields(InstanceData, attribute, a_i_) - -#FLWPrefixFields(Fragment, varying, v2f_) - -void main() { - VertexData v; - #FLWAssignFields(VertexData, v., a_v_) - - InstanceData i; - #FLWAssignFields(InstanceData, i., a_i_) - - Fragment o = FLWMain(v, i); - - #FLWAssignFields(Fragment, v2f_, o.) -} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/template/meshlet/meshlet.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/template/meshlet/meshlet.glsl deleted file mode 100644 index c1c3f8328..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/template/meshlet/meshlet.glsl +++ /dev/null @@ -1,43 +0,0 @@ -#version 450 -#extension GL_NV_mesh_shader : require - -layout(local_size_x=32) in; - -layout(max_vertices=64, max_primitives=32) out; - -layout (std430, binding = 1) buffer _vertices { - FLWVertexData vertices[]; -} vb; - -struct s_meshlet { - uint vertices[64]; - uint indices[96]; - uint vertex_count; - uint index_count; -}; - -layout (std430, binding = 2) buffer _meshlets { - s_meshlet meshlets[]; -} mbuf; - -layout (location = 0) out PerVertexData { - vec4 color; -} v_out[];// [max_vertices] - -void main() { - uint mi = gl_WorkGroupID.x; - uint thread_id = gl_LocalInvocationID.x; - - uint primIdx = thread_id * 3; - uint vertStartIdx = thread_id * 2; - - gl_MeshVerticesNV[vertStartIdx + 0].gl_Position; - gl_MeshVerticesNV[vertStartIdx + 1].gl_Position; - - gl_PrimitiveIndicesNV[primIdx + 0] = mbuf.meshlets[mi].indices[primIdx + 0]; - gl_PrimitiveIndicesNV[primIdx + 1] = mbuf.meshlets[mi].indices[primIdx + 1]; - gl_PrimitiveIndicesNV[primIdx + 2] = mbuf.meshlets[mi].indices[primIdx + 2]; - - gl_PrimitiveCountNV = mbuf.meshlets[mi].vertex_count / 2; - -} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.frag b/src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.frag deleted file mode 100644 index fb9620d7d..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.frag +++ /dev/null @@ -1,12 +0,0 @@ -#version 110 - -#flwbeginbody - -#FLWPrefixFields(Fragment, varying, v2f_) - -void main() { - Fragment f; - #FLWAssignFields(Fragment, f., v2f_) - - FLWMain(f); -} diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.vert b/src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.vert deleted file mode 100644 index 1a235e153..000000000 --- a/src/main/resources/assets/flywheel/flywheel/shaders/template/model/model.vert +++ /dev/null @@ -1,15 +0,0 @@ -#version 110 - -#flwbeginbody -#FLWPrefixFields(VertexData, attribute, a_v_) - -#FLWPrefixFields(Fragment, varying, v2f_) - -void main() { - VertexData v; - #FLWAssignFields(VertexData, v., a_v_) - - Fragment o = FLWMain(v); - - #FLWAssignFields(Fragment, v2f_, o.) -}