This PR adds client-side colored lights that works via flood fill propagation. The light source data is gathered from the Block Light API, which falls back to Item Light API, then finally vanilla MC light level.
Light propagation hooks to region (chunk) building for block updates, which was already optimized through occlusion culling. This ensures minimal memory usage.
The actual propagation and texture uploads are done in the Render Thread. Only queued regions are updated to minimize impact on frame time.
API
Below is the description of the API. You may also find a basic implementation of the API in this PR's files and by turning on the Abstract pipeline.
Block Light API
Is described as .json files located in namespace:lights/block and namespace:lights/fluid paths.
The design of the json API is based on both Material Map and Item Light APIs.
There are two root objects: "defaultLight", which specifies the default light values, and "variants" which specifies light values for each block state variant.
The light values are described with "red", "green", and "blue", but with one main difference which is that light intensity is specified as "lightLevel" and uses values of 0-15. Each field is optional and will fall back to the "defaultLight" value when absent. If "lightLevel" is absent from "defaultLight", it will fall back to the server-side value.
Note that as this feature is client-side, it obviously won't affect server-side light levels. To achieve harmony between visuals and gameplay, mods need to synchronize server-side light level via other means. Care needs to be taken as luminance is perceived differently in colored lights than vanilla lighting.
Pipeline API
To enable colored lights, the pipeline needs to contain a coloredLights json object. It may have one optional field useOcclusionData to declare whether the pipeline intends to use occlusion data. Note that occlusion data isn't guaranteed to be available, see the Shader API section for the specifics.
Example json:
coloredLights: {
useOcclusionData: false
}
Pipeline pass shaders may access the light data by passing "frex:textures/auto/colored_lights" to a Sampler2D sampler. For material shaders, see the Shader API section.
Pipeline pass shaders may access the light data by passing "frex:textures/auto/colored_lights" to a Sampler2D sampler.
Shader usage technical limitations
Due to the nature of rendering, surfaces need to sample the light volume at a tiny offset based on surface normal (e.g. fragPos + normal * 0.05). Volumetric sampling should be unaffected
Technical Details
TBA (Grondag mostly knows these already as he came up with some of it)
Region building hook
Sparse allocation
Propagation / Region light updates
Future Performance Considerations
The following are features that are not part of this PR, but may be implemented in the future:
Using swap texture to prevent pipeline stalling
Currently not considered due to the rarity of light texture update. This could be beneficial however in situations where light is changed very often, e.g. TNT explosion or multiplayer with many on-screen players.
Doing light propagation in a separate thread
This could help with initial chunk building time by not committing texture update until light propagation finishes in a background thread. Texture and uniform updates still need to happen in the Render thread, naturally.
Light data caching on the disk
This might help alleviate long propagation times by saving and loading propagation results. This however could pose a problem as unlike vanilla lighting, colored lights is client-side and is easily changed through resource packs. Therefore, any form of light cache are expected to be invalidated frequently and care needs to be taken to minimize these invalidation as to not defeat the purpose of having a cache.
In addition to that, this requires benchmarks so that caching (specifically the disk read/write part) is actually faster than computing on-the-fly.
Lastly, it's important to note that this system is non-trivial to implement against the current "volatile" data management system.
Additional Changes
In addition to colored flood fill, there are some incidental changes:
PipelineDescription now loads every pipeline fully to assess the usage of Fabulous (no purpose, but was there from the beginning), Shadows, and Colored Lights.
Necessary to determine whether to reload all chunks when switching pipelines. Fast pipeline switching is good when possible
This impacts resource reload times "slightly"
Assuming the user don't have many pipelines as active resourcepack, or only has the active pipeline as active resourcepack, then the impact on resource reload is negligible.
Added space before folder path in shader compile error log so IntellijIDEA can recognize it and turn it into hyperlink
Overview
This PR adds client-side colored lights that works via flood fill propagation. The light source data is gathered from the Block Light API, which falls back to Item Light API, then finally vanilla MC light level.
Light propagation hooks to region (chunk) building for block updates, which was already optimized through occlusion culling. This ensures minimal memory usage.
The actual propagation and texture uploads are done in the Render Thread. Only queued regions are updated to minimize impact on frame time.
API
Below is the description of the API. You may also find a basic implementation of the API in this PR's files and by turning on the Abstract pipeline.
Block Light API
Is described as
.json
files located innamespace:lights/block
andnamespace:lights/fluid
paths.The design of the json API is based on both Material Map and Item Light APIs.
There are two root objects:
"defaultLight"
, which specifies the default light values, and"variants"
which specifies light values for each block state variant.The light values are described with
"red"
,"green"
, and"blue"
, but with one main difference which is that light intensity is specified as"lightLevel"
and uses values of 0-15. Each field is optional and will fall back to the"defaultLight"
value when absent. If"lightLevel"
is absent from"defaultLight"
, it will fall back to the server-side value.Example json:
Note that as this feature is client-side, it obviously won't affect server-side light levels. To achieve harmony between visuals and gameplay, mods need to synchronize server-side light level via other means. Care needs to be taken as luminance is perceived differently in colored lights than vanilla lighting.
Pipeline API
To enable colored lights, the pipeline needs to contain a
coloredLights
json object. It may have one optional fielduseOcclusionData
to declare whether the pipeline intends to use occlusion data. Note that occlusion data isn't guaranteed to be available, see the Shader API section for the specifics.Example json:
Pipeline pass shaders may access the light data by passing
"frex:textures/auto/colored_lights"
to aSampler2D
sampler. For material shaders, see the Shader API section.Shader API
TODO: explain
frex:shaders/api/sampler.glsl
For material and pipeline write shaders:
frex:shaders/api/light.glsl
For pipeline pass shaders:
Pipeline pass shaders may access the light data by passing
"frex:textures/auto/colored_lights"
to aSampler2D
sampler.Shader usage technical limitations
fragPos + normal * 0.05
). Volumetric sampling should be unaffectedTechnical Details
TBA (Grondag mostly knows these already as he came up with some of it)
Region building hook
Sparse allocation
Propagation / Region light updates
Future Performance Considerations
The following are features that are not part of this PR, but may be implemented in the future:
Using swap texture to prevent pipeline stalling
Currently not considered due to the rarity of light texture update. This could be beneficial however in situations where light is changed very often, e.g. TNT explosion or multiplayer with many on-screen players.
Doing light propagation in a separate thread
This could help with initial chunk building time by not committing texture update until light propagation finishes in a background thread. Texture and uniform updates still need to happen in the Render thread, naturally.
Light data caching on the disk
This might help alleviate long propagation times by saving and loading propagation results. This however could pose a problem as unlike vanilla lighting, colored lights is client-side and is easily changed through resource packs. Therefore, any form of light cache are expected to be invalidated frequently and care needs to be taken to minimize these invalidation as to not defeat the purpose of having a cache.
In addition to that, this requires benchmarks so that caching (specifically the disk read/write part) is actually faster than computing on-the-fly.
Lastly, it's important to note that this system is non-trivial to implement against the current "volatile" data management system.
Additional Changes
In addition to colored flood fill, there are some incidental changes: