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
This commit is contained in:
Jozufozu 2024-07-05 19:27:26 -07:00
parent 495c047968
commit b7c8604898
16 changed files with 74 additions and 50 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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];
}

View File

@ -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);

View File

@ -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[];

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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
}

View File

@ -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);

View File

@ -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;

View File

@ -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();