diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java index c4485ebe5..c4a42a7cd 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java +++ b/src/main/java/com/jozufozu/flywheel/backend/ShaderSources.java @@ -11,6 +11,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.function.Predicate; @@ -25,11 +26,14 @@ 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.shader.spec.ProgramSpec; import com.jozufozu.flywheel.event.GatherContextEvent; import com.mojang.blaze3d.systems.RenderSystem; @@ -86,6 +90,11 @@ public class ShaderSources implements ISelectiveResourceReloadListener { loadProgramSpecs(manager); loadShaderSources(manager); + WorldShaderPipeline pl = new WorldShaderPipeline<>(this); + + SourceFile source = source(new ResourceLocation(Flywheel.ID, "model.glsl")); + pl.compile(source, Collections.emptyList()); + for (IShaderContext context : backend.allContexts()) { context.load(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/pipeline/PipelineProgramBuilder.java b/src/main/java/com/jozufozu/flywheel/backend/pipeline/PipelineProgramBuilder.java index 1842801ed..041e532ed 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/PipelineProgramBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/PipelineProgramBuilder.java @@ -21,4 +21,14 @@ public class PipelineProgramBuilder { sources.addAll(files); return this; } + + public CharSequence build() { + StringBuilder builder = new StringBuilder(); + + for (SourceFile source : sources) { + builder.append(source.getElidedSource()); + } + + return builder; + } } 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 57be021c3..08e815487 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/SourceFile.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/SourceFile.java @@ -28,8 +28,6 @@ public class SourceFile { // https://regexr.com/60n3d public static final Pattern functionDeclaration = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{"); - public static final Pattern versionDetector = Pattern.compile("#version[^\\n]*"); - public final ResourceLocation name; private final String source; private final ShaderSources parent; @@ -150,7 +148,24 @@ public class SourceFile { return builder.toString(); } - public static Stream lines(String s) { - return new BufferedReader(new StringReader(s)).lines(); + private CharSequence elided = null; + public CharSequence getElidedSource() { + if (elided == null) { + StringBuilder out = new StringBuilder(); + + int lastEnd = 0; + + for (Span elision : elisions) { + out.append(source, lastEnd, elision.getStart()); + + lastEnd = elision.getEnd(); + } + + out.append(source, lastEnd, source.length()); + + elided = out.toString(); + } + + return elided; } } 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 03383b6f8..014cd0b19 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java +++ b/src/main/java/com/jozufozu/flywheel/backend/pipeline/WorldShaderPipeline.java @@ -4,20 +4,37 @@ import java.util.List; import javax.annotation.Nullable; +import com.jozufozu.flywheel.backend.ShaderSources; 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 WorldShaderPipeline

{ - @Nullable // TODO: temporary null return - public P compile(SourceFile file) { + private final ShaderSources sources; + public WorldShaderPipeline(ShaderSources sources) { + this.sources = sources; + } + + @Nullable // TODO: temporary null return + public IMultiProgram

compile(ProgramSpec spec) { + + SourceFile file = sources.source(spec.vert); + + return compile(file, spec.getStates()); + } + + @Nullable + public IMultiProgram

compile(SourceFile file, List variants) { PipelineProgramBuilder builder = new PipelineProgramBuilder(); builder.includeAll(Includer.recurseIncludes(file)); builder.include(file); + builder.build(); return null; } diff --git a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java index ca7016aa0..7f856dc94 100644 --- a/src/main/java/com/jozufozu/flywheel/core/WorldContext.java +++ b/src/main/java/com/jozufozu/flywheel/core/WorldContext.java @@ -7,6 +7,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; +import javax.annotation.Nullable; + import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.ResourceUtil; import com.jozufozu.flywheel.backend.ShaderContext; @@ -21,7 +23,7 @@ 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.StateSensitiveMultiProgram; +import com.jozufozu.flywheel.core.shader.GameStateProgram; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import com.jozufozu.flywheel.core.shader.spec.ProgramState; @@ -149,12 +151,11 @@ public class WorldContext

extends ShaderContext

{ private void loadSpec(ProgramSpec spec) { try { - StateSensitiveMultiProgram.Builder

builder = new StateSensitiveMultiProgram.Builder<>(factory.create(loadAndLink(spec, null))); + GameStateProgram.Builder

builder = GameStateProgram.builder(compile(spec, null)); for (ProgramState state : spec.states) { - Program variant = loadAndLink(spec, state); - builder.withVariant(state.getContext(), factory.create(variant, state.getExtensions())); + builder.withVariant(state.getContext(), compile(spec, state)); } programs.put(spec.name, builder.build()); @@ -166,6 +167,13 @@ public class WorldContext

extends ShaderContext

{ } } + private P compile(ProgramSpec spec, @Nullable ProgramState state) { + if (state != null) + return factory.create(loadAndLink(spec, state), state.getExtensions()); + else + return factory.create(loadAndLink(spec, null)); + } + public interface TemplateFactory { ProgramTemplate create(ShaderSources loader); } diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/StateSensitiveMultiProgram.java b/src/main/java/com/jozufozu/flywheel/core/shader/GameStateProgram.java similarity index 77% rename from src/main/java/com/jozufozu/flywheel/core/shader/StateSensitiveMultiProgram.java rename to src/main/java/com/jozufozu/flywheel/core/shader/GameStateProgram.java index dbd1e2dc4..9b67fdf37 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/StateSensitiveMultiProgram.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/GameStateProgram.java @@ -8,12 +8,12 @@ import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.core.shader.spec.IGameStateCondition; import com.jozufozu.flywheel.util.Pair; -public class StateSensitiveMultiProgram

implements IMultiProgram

{ +public class GameStateProgram

implements IMultiProgram

{ private final List> variants; private final P fallback; - protected StateSensitiveMultiProgram(List> variants, P fallback) { + protected GameStateProgram(List> variants, P fallback) { this.variants = variants; this.fallback = fallback; } @@ -38,6 +38,10 @@ public class StateSensitiveMultiProgram

implements IMultiPr fallback.delete(); } + public static

Builder

builder(P fallback) { + return new Builder<>(fallback); + } + public static class Builder

{ private final P fallback; private final List> variants = new ArrayList<>(); @@ -52,7 +56,7 @@ public class StateSensitiveMultiProgram

implements IMultiPr } public IMultiProgram

build() { - return new StateSensitiveMultiProgram<>(ImmutableList.copyOf(variants), fallback); + return new GameStateProgram<>(ImmutableList.copyOf(variants), fallback); } } } diff --git a/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java b/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java index 5ecdd6a20..3ae7d9430 100644 --- a/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java +++ b/src/main/java/com/jozufozu/flywheel/core/shader/spec/ProgramSpec.java @@ -12,11 +12,14 @@ import net.minecraft.util.ResourceLocation; public class ProgramSpec { // TODO: Block model style inheritance? - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group(ResourceLocation.CODEC.fieldOf("vert") - .forGetter(ProgramSpec::getVert), ResourceLocation.CODEC.fieldOf("frag") - .forGetter(ProgramSpec::getFrag), ProgramState.CODEC.listOf() - .optionalFieldOf("states", Collections.emptyList()) - .forGetter(ProgramSpec::getStates)) + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + ResourceLocation.CODEC.fieldOf("vert") + .forGetter(ProgramSpec::getVert), + ResourceLocation.CODEC.fieldOf("frag") + .forGetter(ProgramSpec::getFrag), + ProgramState.CODEC.listOf() + .optionalFieldOf("states", Collections.emptyList()) + .forGetter(ProgramSpec::getStates)) .apply(instance, ProgramSpec::new)); public ResourceLocation name; diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/model.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/model.glsl new file mode 100644 index 000000000..b5ec6955c --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/shaders/model.glsl @@ -0,0 +1,58 @@ +#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); +} +