From b7c8604898b8b0c2efdc6f68101ef14a5e3a3322 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Fri, 5 Jul 2024 19:27:26 -0700 Subject: [PATCH] Light in the shade - Expose light in the shader api - flw_light - for builtin smooth lighting, faster than can be implemented by materials alone - flw_lightFetch - for materials that want to go crazy, access to raw data --- .../backend/compile/ContextShader.java | 3 ++- .../flywheel/flywheel/internal/api_impl.frag | 1 + .../flywheel/flywheel/internal/api_impl.glsl | 7 +++++++ .../flywheel/flywheel/internal/api_impl.vert | 1 + .../flywheel/flywheel/internal/common.frag | 9 --------- .../flywheel/internal/indirect/light.glsl | 17 +++++++++++++++++ .../flywheel/internal/indirect/main.frag | 18 +----------------- .../flywheel/internal/indirect/main.vert | 1 + .../flywheel/internal/instancing/light.glsl | 12 ++++++++++++ .../flywheel/internal/instancing/main.frag | 13 +------------ .../flywheel/internal/instancing/main.vert | 1 + .../flywheel/flywheel/internal/light_lut.glsl | 18 +++++++++++++++--- .../flywheel/flywheel/material/default.frag | 6 ++++++ docs/shader-api/common.glsl | 7 +++++++ docs/shader-api/fragment.glsl | 5 +---- docs/shader-api/vertex.glsl | 5 +---- 16 files changed, 74 insertions(+), 50 deletions(-) create mode 100644 common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl create mode 100644 common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/light.glsl create mode 100644 common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/light.glsl create mode 100644 docs/shader-api/common.glsl diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java index 6d3fede7a..7c8aac5dd 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/ContextShader.java @@ -13,7 +13,8 @@ public enum ContextShader { DEFAULT(null, $ -> { }), CRUMBLING("_FLW_CRUMBLING", program -> program.setSamplerBinding("_flw_crumblingTex", Samplers.CRUMBLING)), - EMBEDDED("_FLW_EMBEDDED", $ -> {}); + EMBEDDED("FLW_EMBEDDED", $ -> { + }); @Nullable private final String define; diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.frag b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.frag index dc8334916..af16b80e2 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.frag @@ -1,4 +1,5 @@ #include "flywheel:internal/material.glsl" +#include "flywheel:internal/api_impl.glsl" #include "flywheel:internal/uniforms/uniforms.glsl" in vec4 flw_vertexPos; diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl new file mode 100644 index 000000000..9362c693d --- /dev/null +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.glsl @@ -0,0 +1,7 @@ +/// Get the light at the given world position. +/// This may be interpolated for smooth lighting. +bool flw_light(vec3 worldPos, out vec2 light); + +/// Fetches the light value at the given block position. +/// Returns false if the light for the given block is not available. +bool flw_lightFetch(ivec3 blockPos, out vec2 light); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.vert b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.vert index d9934d42e..d1e751929 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.vert +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/api_impl.vert @@ -1,4 +1,5 @@ #include "flywheel:internal/material.glsl" +#include "flywheel:internal/api_impl.glsl" #include "flywheel:internal/uniforms/uniforms.glsl" out vec4 flw_vertexPos; 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 2cfa92e96..23df5b7e9 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/common.frag @@ -13,8 +13,6 @@ uniform sampler2D _flw_crumblingTex; in vec2 _flw_crumblingTexCoord; #endif -bool _flw_embeddedLight(vec3 worldPos, out vec2 lightCoord); - flat in uint _flw_instanceID; out vec4 _flw_outputColor; @@ -37,13 +35,6 @@ void _flw_main() { flw_fragOverlay = flw_vertexOverlay; flw_fragLight = flw_vertexLight; - #ifdef _FLW_EMBEDDED - vec2 embeddedLight; - if (_flw_embeddedLight(flw_vertexPos.xyz, embeddedLight)) { - flw_fragLight = max(flw_fragLight, embeddedLight); - } - #endif - flw_materialFragment(); #ifdef _FLW_CRUMBLING diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/light.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/light.glsl new file mode 100644 index 000000000..bd688ef28 --- /dev/null +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/light.glsl @@ -0,0 +1,17 @@ +#include "flywheel:internal/light_lut.glsl" + +layout(std430, binding = _FLW_LIGHT_LUT_BINDING) restrict readonly buffer LightLut { + uint _flw_lightLut[]; +}; + +layout(std430, binding = _FLW_LIGHT_SECTIONS_BINDING) restrict readonly buffer LightSections { + uint _flw_lightSections[]; +}; + +uint _flw_indexLut(uint index) { + return _flw_lightLut[index]; +} + +uint _flw_indexLight(uint index) { + return _flw_lightSections[index]; +} 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 1711390a6..b1dbb0822 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 @@ -1,25 +1,9 @@ #include "flywheel:internal/common.frag" -#include "flywheel:internal/light_lut.glsl" #include "flywheel:internal/indirect/buffer_bindings.glsl" +#include "flywheel:internal/indirect/light.glsl" flat in uvec3 _flw_packedMaterial; -layout(std430, binding = _FLW_LIGHT_LUT_BINDING) restrict readonly buffer LightLut { - uint _flw_lightLut[]; -}; - -layout(std430, binding = _FLW_LIGHT_SECTIONS_BINDING) restrict readonly buffer LightSections { - uint _flw_lightSections[]; -}; - -uint _flw_indexLut(uint index) { - return _flw_lightLut[index]; -} - -uint _flw_indexLight(uint index) { - return _flw_lightSections[index]; -} - void main() { _flw_uberMaterialFragmentIndex = _flw_packedMaterial.x; _flw_unpackUint2x16(_flw_packedMaterial.y, _flw_uberCutoutIndex, _flw_uberFogIndex); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert index 55bd8fc0f..a95d31662 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/indirect/main.vert @@ -2,6 +2,7 @@ #include "flywheel:internal/packed_material.glsl" #include "flywheel:internal/indirect/buffer_bindings.glsl" #include "flywheel:internal/indirect/draw_command.glsl" +#include "flywheel:internal/indirect/light.glsl" layout(std430, binding = _FLW_TARGET_BUFFER_BINDING) restrict readonly buffer TargetBuffer { uint _flw_instanceIndices[]; diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/light.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/light.glsl new file mode 100644 index 000000000..f023322a4 --- /dev/null +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/light.glsl @@ -0,0 +1,12 @@ +#include "flywheel:internal/light_lut.glsl" + +uniform usamplerBuffer _flw_lightLut; +uniform usamplerBuffer _flw_lightSections; + +uint _flw_indexLut(uint index) { + return texelFetch(_flw_lightLut, int(index)).r; +} + +uint _flw_indexLight(uint index) { + return texelFetch(_flw_lightSections, int(index)).r; +} 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 80a4402ea..89b09b37f 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 @@ -1,19 +1,8 @@ #include "flywheel:internal/common.frag" -#include "flywheel:internal/light_lut.glsl" +#include "flywheel:internal/instancing/light.glsl" uniform uvec4 _flw_packedMaterial; -uniform usamplerBuffer _flw_lightLut; -uniform usamplerBuffer _flw_lightSections; - -uint _flw_indexLut(uint index) { - return texelFetch(_flw_lightLut, int(index)).r; -} - -uint _flw_indexLight(uint index) { - return texelFetch(_flw_lightSections, int(index)).r; -} - void main() { _flw_uberMaterialFragmentIndex = _flw_packedMaterial.y; _flw_unpackUint2x16(_flw_packedMaterial.z, _flw_uberCutoutIndex, _flw_uberFogIndex); diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert index 8c4b9d6a3..4b6914eae 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/instancing/main.vert @@ -1,5 +1,6 @@ #include "flywheel:internal/common.vert" #include "flywheel:internal/packed_material.glsl" +#include "flywheel:internal/instancing/light.glsl" uniform uvec4 _flw_packedMaterial; uniform int _flw_baseInstance = 0; diff --git a/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl b/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl index e6abff4fa..f79b5a20a 100644 --- a/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl +++ b/common/src/backend/resources/assets/flywheel/flywheel/internal/light_lut.glsl @@ -64,7 +64,21 @@ vec2 _flw_lightAt(uint sectionOffset, uvec3 blockInSectionPos) { return vec2(block, sky); } -bool _flw_embeddedLight(vec3 worldPos, out vec2 lightCoord) { +bool flw_lightFetch(ivec3 blockPos, out vec2 lightCoord) { + uint lightSectionIndex; + if (_flw_chunkCoordToSectionIndex(blockPos >> 4, lightSectionIndex)) { + return false; + } + // The offset of the section in the light buffer. + uint sectionOffset = lightSectionIndex * _FLW_LIGHT_SECTION_SIZE_INTS; + + uvec3 blockInSectionPos = (blockPos & 0xF) + 1; + + lightCoord = _flw_lightAt(sectionOffset, blockInSectionPos) / 15.; + return true; +} + +bool flw_light(vec3 worldPos, out vec2 lightCoord) { // Always use the section of the block we are contained in to ensure accuracy. // We don't want to interpolate between sections, but also we might not be able // to rely on the existence neighboring sections, so don't do any extra rounding here. @@ -72,8 +86,6 @@ bool _flw_embeddedLight(vec3 worldPos, out vec2 lightCoord) { uint lightSectionIndex; if (_flw_chunkCoordToSectionIndex(blockPos >> 4, lightSectionIndex)) { - // TODO: useful debug mode for this. - // flw_fragOverlay = ivec2(0, 3); return false; } // The offset of the section in the light buffer. 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 68dfe9a5b..42b1ac1fc 100644 --- a/common/src/lib/resources/assets/flywheel/flywheel/material/default.frag +++ b/common/src/lib/resources/assets/flywheel/flywheel/material/default.frag @@ -1,2 +1,8 @@ void flw_materialFragment() { + #ifdef FLW_EMBEDDED + vec2 embeddedLight; + if (flw_light(flw_vertexPos.xyz, embeddedLight)) { + flw_fragLight = max(flw_fragLight, embeddedLight); + } + #endif } diff --git a/docs/shader-api/common.glsl b/docs/shader-api/common.glsl new file mode 100644 index 000000000..9362c693d --- /dev/null +++ b/docs/shader-api/common.glsl @@ -0,0 +1,7 @@ +/// Get the light at the given world position. +/// This may be interpolated for smooth lighting. +bool flw_light(vec3 worldPos, out vec2 light); + +/// Fetches the light value at the given block position. +/// Returns false if the light for the given block is not available. +bool flw_lightFetch(ivec3 blockPos, out vec2 light); diff --git a/docs/shader-api/fragment.glsl b/docs/shader-api/fragment.glsl index a99837c25..e13ec6588 100644 --- a/docs/shader-api/fragment.glsl +++ b/docs/shader-api/fragment.glsl @@ -1,4 +1,5 @@ #include "flywheel:api/material.glsl" +#include "flywheel:api/common.glsl" /*const*/ vec4 flw_vertexPos; /*const*/ vec4 flw_vertexColor; @@ -24,10 +25,6 @@ vec4 flw_fogFilter(vec4 color); // To be implemented by discard shaders. bool flw_discardPredicate(vec4 finalColor); -// To be implemented by the context shader. -void flw_beginFragment(); -void flw_endFragment(); - sampler2D flw_diffuseTex; sampler2D flw_overlayTex; sampler2D flw_lightTex; diff --git a/docs/shader-api/vertex.glsl b/docs/shader-api/vertex.glsl index 338923540..5dcab38e7 100644 --- a/docs/shader-api/vertex.glsl +++ b/docs/shader-api/vertex.glsl @@ -1,4 +1,5 @@ #include "flywheel:api/material.glsl" +#include "flywheel:api/common.glsl" vec4 flw_vertexPos; vec4 flw_vertexColor; @@ -17,7 +18,3 @@ void flw_transformBoundingSphere(in FlwInstance i, inout vec3 center, inout floa // To be implemented by the material vertex shader. void flw_materialVertex(); - -// To be implemented by the context shader. -void flw_beginVertex(); -void flw_endVertex();