From 69411fb36f82963d4657f3cb8b3caa4152a1298f Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sat, 27 Jul 2024 15:31:08 -0700 Subject: [PATCH] Uber smooth - Add material shader component to specify smooth lighting behavior - Allows much easier composition of smooth lighting/material shader effects, and potentially gives backends the option to specialize shaders on the complexity of shader lighting - Pack fog, cutout, and light into a single uint --- .../flywheel/api/material/LightShader.java | 11 ++++++++++ .../flywheel/api/material/Material.java | 2 ++ .../backend/MaterialShaderIndices.java | 14 +++++++++++++ .../flywheel/backend/compile/FlwPrograms.java | 18 +++++++++++++++-- .../backend/engine/MaterialEncoder.java | 5 +++-- .../backend/engine/indirect/IndirectDraw.java | 4 ++-- .../instancing/InstancedDrawManager.java | 2 +- .../flywheel/flywheel/internal/common.frag | 10 ++++++---- .../flywheel/internal/components_header.frag | 1 + .../flywheel/internal/indirect/main.frag | 2 +- .../flywheel/internal/instancing/main.frag | 2 +- .../flywheel/internal/packed_material.glsl | 6 ++++++ .../flywheel/lib/material/LightShaders.java | 19 ++++++++++++++++++ .../lib/material/SimpleLightShader.java | 7 +++++++ .../flywheel/lib/material/SimpleMaterial.java | 20 +++++++++++++++++++ .../assets/flywheel/flywheel/light/flat.glsl | 6 ++++++ .../flywheel/flywheel/light/smooth.glsl | 6 ++++++ .../flywheel/light/smooth_when_embedded.glsl | 8 ++++++++ .../flywheel/flywheel/material/default.frag | 6 ------ .../engine_room/flywheel/impl/FlwImpl.java | 2 ++ 20 files changed, 132 insertions(+), 19 deletions(-) create mode 100644 common/src/api/java/dev/engine_room/flywheel/api/material/LightShader.java create mode 100644 common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java create mode 100644 common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleLightShader.java create mode 100644 common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl create mode 100644 common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl create mode 100644 common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl diff --git a/common/src/api/java/dev/engine_room/flywheel/api/material/LightShader.java b/common/src/api/java/dev/engine_room/flywheel/api/material/LightShader.java new file mode 100644 index 000000000..73de1ccc9 --- /dev/null +++ b/common/src/api/java/dev/engine_room/flywheel/api/material/LightShader.java @@ -0,0 +1,11 @@ +package dev.engine_room.flywheel.api.material; + +import dev.engine_room.flywheel.api.internal.FlwApiLink; +import dev.engine_room.flywheel.api.registry.Registry; +import net.minecraft.resources.ResourceLocation; + +public interface LightShader { + Registry REGISTRY = FlwApiLink.INSTANCE.createRegistry(); + + ResourceLocation source(); +} diff --git a/common/src/api/java/dev/engine_room/flywheel/api/material/Material.java b/common/src/api/java/dev/engine_room/flywheel/api/material/Material.java index 5fb6f740b..f77e396e8 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/material/Material.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/material/Material.java @@ -9,6 +9,8 @@ public interface Material { CutoutShader cutout(); + LightShader light(); + ResourceLocation texture(); /** diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/MaterialShaderIndices.java b/common/src/backend/java/dev/engine_room/flywheel/backend/MaterialShaderIndices.java index 8592a9e65..a67daaadb 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/MaterialShaderIndices.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/MaterialShaderIndices.java @@ -8,6 +8,7 @@ import dev.engine_room.flywheel.api.material.CutoutShader; import dev.engine_room.flywheel.api.material.FogShader; +import dev.engine_room.flywheel.api.material.LightShader; import dev.engine_room.flywheel.api.material.MaterialShaders; import dev.engine_room.flywheel.api.registry.Registry; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -25,6 +26,8 @@ public final class MaterialShaderIndices { private static Index fogSources; @Nullable private static Index cutoutSources; + @Nullable + private static Index lightSources; private MaterialShaderIndices() { } @@ -57,6 +60,13 @@ public static Index cutoutSources() { return cutoutSources; } + public static Index lightSources() { + if (lightSources == null) { + lightSources = indexFromRegistry(LightShader.REGISTRY, LightShader::source); + } + return lightSources; + } + public static int vertexIndex(MaterialShaders shaders) { return vertexSources().index(shaders.vertexSource()); } @@ -73,6 +83,10 @@ public static int cutoutIndex(CutoutShader cutoutShader) { return cutoutSources().index(cutoutShader.source()); } + public static int lightIndex(LightShader lightShader) { + return lightSources().index(lightShader.source()); + } + private static Index indexFromRegistry(Registry registry, Function sourceFunc) { if (!registry.isFrozen()) { throw new IllegalStateException("Cannot create index from registry that is not frozen!"); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java index 5a8f47086..9eb89b41c 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java @@ -46,15 +46,16 @@ static void reload(ResourceManager resourceManager) { var fragmentMaterialComponent = createFragmentMaterialComponent(loader); var fogComponent = createFogComponent(loader); var cutoutComponent = createCutoutComponent(loader); + var lightComponent = createLightComponent(loader); - if (stats.errored() || vertexComponentsHeader == null || fragmentComponentsHeader == null || vertexMaterialComponent == null || fragmentMaterialComponent == null || fogComponent == null || cutoutComponent == null) { + if (stats.errored() || vertexComponentsHeader == null || fragmentComponentsHeader == null || vertexMaterialComponent == null || fragmentMaterialComponent == null || fogComponent == null || cutoutComponent == null || lightComponent == null) { // Probably means the shader sources are missing. stats.emitErrorLog(); return; } List vertexComponents = List.of(vertexComponentsHeader, vertexMaterialComponent); - List fragmentComponents = List.of(fragmentComponentsHeader, fragmentMaterialComponent, fogComponent, cutoutComponent); + List fragmentComponents = List.of(fragmentComponentsHeader, fragmentMaterialComponent, fogComponent, cutoutComponent, lightComponent); var pipelineKeys = createPipelineKeys(); InstancingPrograms.reload(sources, pipelineKeys, vertexComponents, fragmentComponents); @@ -118,4 +119,17 @@ private static UberShaderComponent createCutoutComponent(SourceLoader loader) { .switchOn(GlslExpr.variable("_flw_uberCutoutIndex")) .build(loader); } + + @Nullable + private static UberShaderComponent createLightComponent(SourceLoader loader) { + return UberShaderComponent.builder(Flywheel.rl("light")) + .materialSources(MaterialShaderIndices.lightSources() + .all()) + .adapt(FnSignature.create() + .returnType("void") + .name("flw_shaderLight") + .build()) + .switchOn(GlslExpr.variable("_flw_uberLightIndex")) + .build(loader); + } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java index feef64c8d..36e7c6ba7 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java @@ -52,10 +52,11 @@ private static int bitMask(int bitLength, int bitOffset) { return ((1 << bitLength) - 1) << bitOffset; } - public static int packFogAndCutout(Material material) { + public static int packUberShader(Material material) { var fog = MaterialShaderIndices.fogIndex(material.fog()); var cutout = MaterialShaderIndices.cutoutIndex(material.cutout()); - return fog & 0xFFFF | (cutout & 0xFFFF) << 16; + var light = MaterialShaderIndices.lightIndex(material.light()); + return (light & 0x3FF) | (cutout & 0x3FF) << 10 | (fog & 0x3FF) << 20; } // Packed format: diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java index 093616337..9494b6ade 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java @@ -34,7 +34,7 @@ public IndirectDraw(IndirectInstancer instancer, Material material, MeshPool. this.materialVertexIndex = MaterialShaderIndices.vertexIndex(material.shaders()); this.materialFragmentIndex = MaterialShaderIndices.fragmentIndex(material.shaders()); - this.packedFogAndCutout = MaterialEncoder.packFogAndCutout(material); + this.packedFogAndCutout = MaterialEncoder.packUberShader(material); this.packedMaterialProperties = MaterialEncoder.packProperties(material); } @@ -88,7 +88,7 @@ public void writeWithOverrides(long ptr, int instanceIndex, Material materialOve MemoryUtil.memPutInt(ptr + 24, MaterialShaderIndices.vertexIndex(materialOverride.shaders())); // materialVertexIndex MemoryUtil.memPutInt(ptr + 28, MaterialShaderIndices.fragmentIndex(materialOverride.shaders())); // materialFragmentIndex - MemoryUtil.memPutInt(ptr + 32, MaterialEncoder.packFogAndCutout(materialOverride)); // packedFogAndCutout + MemoryUtil.memPutInt(ptr + 32, MaterialEncoder.packUberShader(materialOverride)); // packedFogAndCutout MemoryUtil.memPutInt(ptr + 36, MaterialEncoder.packProperties(materialOverride)); // packedMaterialProperties } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java index bc7610871..dfdc57808 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java @@ -206,7 +206,7 @@ public static void uploadMaterialUniform(GlProgram program, Material material) { int uniformLocation = program.getUniformLocation("_flw_packedMaterial"); int vertexIndex = MaterialShaderIndices.vertexIndex(material.shaders()); int fragmentIndex = MaterialShaderIndices.fragmentIndex(material.shaders()); - int packedFogAndCutout = MaterialEncoder.packFogAndCutout(material); + int packedFogAndCutout = MaterialEncoder.packUberShader(material); int packedMaterialProperties = MaterialEncoder.packProperties(material); GL32.glUniform4ui(uniformLocation, vertexIndex, fragmentIndex, packedFogAndCutout, packedMaterialProperties); } diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag index 23df5b7e9..52b013a52 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag @@ -47,6 +47,10 @@ void _flw_main() { vec4 color = flw_fragColor; + if (flw_discardPredicate(color)) { + discard; + } + float diffuseFactor = _flw_diffuseFactor(); color.rgb *= diffuseFactor; @@ -57,14 +61,12 @@ void _flw_main() { vec4 lightColor = vec4(1.); if (flw_material.useLight) { + flw_shaderLight(); + lightColor = texture(flw_lightTex, clamp(flw_fragLight, 0.5 / 16.0, 15.5 / 16.0)); color *= lightColor; } - if (flw_discardPredicate(color)) { - discard; - } - switch (_flw_debugMode) { case 1u: color = vec4(flw_vertexNormal * .5 + .5, 1.); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/components_header.frag b/common/src/backend/resources/assets/flywheel/flywheel/internal/components_header.frag index ef45f6d68..5c0550d60 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/components_header.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/components_header.frag @@ -1,3 +1,4 @@ uint _flw_uberMaterialFragmentIndex; uint _flw_uberFogIndex; uint _flw_uberCutoutIndex; +uint _flw_uberLightIndex; diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.frag b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.frag index b1dbb0822..a67cb47a2 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.frag @@ -6,7 +6,7 @@ flat in uvec3 _flw_packedMaterial; void main() { _flw_uberMaterialFragmentIndex = _flw_packedMaterial.x; - _flw_unpackUint2x16(_flw_packedMaterial.y, _flw_uberCutoutIndex, _flw_uberFogIndex); + _flw_unpackUint3x10(_flw_packedMaterial.y, _flw_uberFogIndex, _flw_uberCutoutIndex, _flw_uberLightIndex); _flw_unpackMaterialProperties(_flw_packedMaterial.z, flw_material); _flw_main(); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.frag b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.frag index 89b09b37f..6ada1a130 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.frag @@ -5,7 +5,7 @@ uniform uvec4 _flw_packedMaterial; void main() { _flw_uberMaterialFragmentIndex = _flw_packedMaterial.y; - _flw_unpackUint2x16(_flw_packedMaterial.z, _flw_uberCutoutIndex, _flw_uberFogIndex); + _flw_unpackUint3x10(_flw_packedMaterial.z, _flw_uberFogIndex, _flw_uberCutoutIndex, _flw_uberLightIndex); _flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material); _flw_main(); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/packed_material.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/packed_material.glsl index b56828c1f..892795e66 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/packed_material.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/packed_material.glsl @@ -53,3 +53,9 @@ void _flw_unpackUint2x16(uint s, out uint hi, out uint lo) { hi = (s >> 16) & 0xFFFFu; lo = s & 0xFFFFu; } + +void _flw_unpackUint3x10(uint s, out uint hi, out uint mi, out uint lo) { + hi = (s >> 20) & 0x3FFu; + mi = (s >> 10) & 0x3FFu; + lo = s & 0x3FFu; +} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java new file mode 100644 index 000000000..86c9a9db9 --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/LightShaders.java @@ -0,0 +1,19 @@ +package dev.engine_room.flywheel.lib.material; + +import org.jetbrains.annotations.ApiStatus; + +import dev.engine_room.flywheel.api.Flywheel; +import dev.engine_room.flywheel.api.material.LightShader; + +public class LightShaders { + public static final LightShader SMOOTH_WHEN_EMBEDDED = LightShader.REGISTRY.registerAndGet(new SimpleLightShader(Flywheel.rl("light/smooth_when_embedded.glsl"))); + public static final LightShader SMOOTH = LightShader.REGISTRY.registerAndGet(new SimpleLightShader(Flywheel.rl("light/smooth.glsl"))); + public static final LightShader FLAT = LightShader.REGISTRY.registerAndGet(new SimpleLightShader(Flywheel.rl("light/flat.glsl"))); + + private LightShaders() { + } + + @ApiStatus.Internal + public static void init() { + } +} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleLightShader.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleLightShader.java new file mode 100644 index 000000000..08158e741 --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleLightShader.java @@ -0,0 +1,7 @@ +package dev.engine_room.flywheel.lib.material; + +import dev.engine_room.flywheel.api.material.LightShader; +import net.minecraft.resources.ResourceLocation; + +public record SimpleLightShader(@Override ResourceLocation source) implements LightShader { +} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java index 4fe1daa11..cf271ed43 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterial.java @@ -3,6 +3,7 @@ import dev.engine_room.flywheel.api.material.CutoutShader; import dev.engine_room.flywheel.api.material.DepthTest; import dev.engine_room.flywheel.api.material.FogShader; +import dev.engine_room.flywheel.api.material.LightShader; import dev.engine_room.flywheel.api.material.Material; import dev.engine_room.flywheel.api.material.MaterialShaders; import dev.engine_room.flywheel.api.material.Transparency; @@ -14,6 +15,7 @@ public class SimpleMaterial implements Material { protected final MaterialShaders shaders; protected final FogShader fog; protected final CutoutShader cutout; + protected final LightShader light; protected final ResourceLocation texture; protected final boolean blur; @@ -33,6 +35,7 @@ protected SimpleMaterial(Builder builder) { shaders = builder.shaders(); fog = builder.fog(); cutout = builder.cutout(); + light = builder.light(); texture = builder.texture(); blur = builder.blur(); mipmap = builder.mipmap(); @@ -69,6 +72,11 @@ public CutoutShader cutout() { return cutout; } + @Override + public LightShader light() { + return light; + } + @Override public ResourceLocation texture() { return texture; @@ -128,6 +136,7 @@ public static class Builder implements Material { protected MaterialShaders shaders; protected FogShader fog; protected CutoutShader cutout; + protected LightShader light; protected ResourceLocation texture; protected boolean blur; @@ -147,6 +156,7 @@ public Builder() { shaders = StandardMaterialShaders.DEFAULT; fog = FogShaders.LINEAR; cutout = CutoutShaders.OFF; + light = LightShaders.SMOOTH_WHEN_EMBEDDED; texture = InventoryMenu.BLOCK_ATLAS; blur = false; mipmap = true; @@ -197,6 +207,11 @@ public Builder cutout(CutoutShader value) { return this; } + public Builder light(LightShader value) { + this.light = value; + return this; + } + public Builder texture(ResourceLocation value) { this.texture = value; return this; @@ -267,6 +282,11 @@ public CutoutShader cutout() { return cutout; } + @Override + public LightShader light() { + return light; + } + @Override public ResourceLocation texture() { return texture; diff --git a/common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl b/common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl new file mode 100644 index 000000000..365924db7 --- /dev/null +++ b/common/src/lib/resources/assets/flywheel/flywheel/light/flat.glsl @@ -0,0 +1,6 @@ +void flw_shaderLight() { + vec2 embeddedLight; + if (flw_lightFetch(ivec3(floor(flw_vertexPos.xyz)), embeddedLight)) { + flw_fragLight = max(flw_fragLight, embeddedLight); + } +} diff --git a/common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl new file mode 100644 index 000000000..6d6d83ef2 --- /dev/null +++ b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth.glsl @@ -0,0 +1,6 @@ +void flw_shaderLight() { + vec2 embeddedLight; + if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, embeddedLight)) { + flw_fragLight = max(flw_fragLight, embeddedLight); + } +} diff --git a/common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl new file mode 100644 index 000000000..d8dc6fd51 --- /dev/null +++ b/common/src/lib/resources/assets/flywheel/flywheel/light/smooth_when_embedded.glsl @@ -0,0 +1,8 @@ +void flw_shaderLight() { + #ifdef FLW_EMBEDDED + vec2 embeddedLight; + if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, embeddedLight)) { + flw_fragLight = max(flw_fragLight, embeddedLight); + } + #endif +} diff --git a/common/src/lib/resources/assets/flywheel/flywheel/material/default.frag b/common/src/lib/resources/assets/flywheel/flywheel/material/default.frag index f072c1849..68dfe9a5b 100644 --- a/common/src/lib/resources/assets/flywheel/flywheel/material/default.frag +++ b/common/src/lib/resources/assets/flywheel/flywheel/material/default.frag @@ -1,8 +1,2 @@ void flw_materialFragment() { - #ifdef FLW_EMBEDDED - vec2 embeddedLight; - if (flw_light(flw_vertexPos.xyz, flw_vertexNormal, embeddedLight)) { - flw_fragLight = max(flw_fragLight, embeddedLight); - } - #endif } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java index 5d8538b47..d1eafb15e 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImpl.java @@ -10,6 +10,7 @@ import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.material.CutoutShaders; import dev.engine_room.flywheel.lib.material.FogShaders; +import dev.engine_room.flywheel.lib.material.LightShaders; import dev.engine_room.flywheel.lib.material.StandardMaterialShaders; import dev.engine_room.flywheel.lib.util.ShadersModHandler; import dev.engine_room.flywheel.vanilla.VanillaVisuals; @@ -30,6 +31,7 @@ public static void init() { InstanceTypes.init(); CutoutShaders.init(); FogShaders.init(); + LightShaders.init(); StandardMaterialShaders.init(); // backend