@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
156 lines (114 loc) • 5.1 kB
Markdown
Data is organized into 3 main textures:
- Clusters. `type: UINT, format: RGBA, dimension: 3D, filtering: nearest(none)`
- R - Offset into lookup texture for lights
- G - number of lights
- B - Offset into lookup texture for decals
- A - number of decals
- Lookup. `type: UINT, format: R, dimensions: 2D, filtering: nearest(none)`
- R - encoded reference into data texture, where actual lighting information is stored
- Data. `type: FLOAT, format: RGBA, dimensions: 2D, filtering: nearest(none)`
- RGBA - single `word` of data, you can think of it as a collection of `VEC4`s
Below is a glsl snippet with initialization of uniforms for these textures:
```glsl
uniform usampler3D fp_t_light_clusters;
uniform usampler2D fp_t_light_lookup;
uniform sampler2D fp_t_light_data;
```
Each light is represented as a collection of `VEC4`s inside the `Data` texture.
- Point Light:
- `[ position.x, position.y, position.z, radius ]`
- `[ color.r, color.g, color.b, intensity ]`
- Directional Light:
- `[ direction.x, direction.y, direction.z, UNUSED ]`
- `[ color.r, color.g, color.b, intensity ]`
Lookup texture contains integers that encode both the address of light data, and the type of light found at that address, this is done by encoding light type into lower 2 bits of a UINT32
Light type codes:
- 0 - PointLight
- 1 - Directional Light
- 2 - Spotlight
Encoding snippet in JavaScript:
```js
/**
*
* @param {number} address
* @param {AbstractLight} light
* @returns {number}
*/
function encode_light_descriptor(address, light) {
const light_type = encode_light_type(light);
return light_type | (address << 2);
}
```
Decoding snippet in GLSL
```glsl
ivec2 address_to_data_texture_coordinates(uint address){
// Lookup texture has 128 width
uint lookup_index_x = address % 128u;
uint lookup_index_y = address >> 7;
return ivec2(int(lookup_index_x),int(lookup_index_y));
}
// ...
uint light_descriptor = texelFetch(fp_t_light_lookup, address_to_data_texture_coordinates(lookup_index), 0 ).r;
uint type = (light_descriptor) & 0x3u;
uint light_address = light_descriptor >> 2;
```
Convert projection-space depth to linear space
```glsl
float convert_depth_to_linear(in float d){
float d_n = 2.0*d - 1.0;
float f = fp_f_camera_far;
float n = fp_f_camera_near;
float fn = f*n;
float z_diff = f - n;
float denominator = (f + n - d_n * z_diff );
float z_view = (2.0*fn) / denominator;
return (z_view - n) / z_diff;
}
```
Fetching cluster information from fragment shader inside a forward pass
```glsl
// v3_cluster_resolution is resolution of our cluster 3d texture
ivec3 v3_cluster_resolution = textureSize(fp_t_light_tiles, 0);
ivec3 v3_cluster_position = ivec3( clip_v.x * float(v3_cluster_resolution.x), clip_v.y*float(v3_cluster_resolution.y), (clip_v.z)*float(v3_cluster_resolution.z) );
uvec4 fp_cluster_metadata = texelFetch( fp_t_light_tiles, v3_cluster_position, 0 ).rgba;
```
Perform lighting (point-light only)
```glsl
// read light data
for(uint i=0u; i < fp_cluster_metadata.y; i++){
uint lookup_index = fp_cluster_metadata.x + i;
uint light_descriptor = texelFetch(fp_t_light_lookup, address_to_data_texture_coordinates(lookup_index), 0 ).r;
uint type = (light_descriptor) & 0x3u;
uint light_address = light_descriptor >> 2;
if(type == 0u){
// point light
vec4 light_data_0 = texelFetch(fp_t_light_data, address_to_data_texture_coordinates(light_address), 0);
vec4 light_data_1 = texelFetch(fp_t_light_data, address_to_data_texture_coordinates(light_address+1u), 0);
vec3 light_position = light_data_0.xyz;
float light_radius = light_data_0.w;
vec3 light_color = light_data_1.xyz;
float light_intensity = light_data_1.w;
PointLight pointlight;
pointlight.position = light_position;
pointlight.distance = light_radius;
pointlight.color = light_color*light_intensity;
pointlight.decay = 1.0;
fp_getPointDirectLightIrradiance( pointlight, directLight, vViewPosition );
RE_Direct( directLight, geometry, material, reflectedLight );
} else if(type == 1u){
// directional light
// ...
}
}
```
- [Dr.Strangelight or: How I learned to Stop Worrying and Love the Cluster](https://discourse.threejs.org/t/dr-strangelight-or-how-i-learned-to-stop-worrying-and-love-the-cluster/23104)
- [Practical Clustered Shading by Emil Persson](http://www.humus.name/Articles/PracticalClusteredShading.pdf)
---
Author: Alexander Goldring, Company Named Limited
Private and confidential, copyright (c) Company Named Limited, 2022