Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGPURenderer: Introduce TiledLighting #29642

Merged
merged 11 commits into from
Oct 14, 2024
Merged

Conversation

sunag
Copy link
Collaborator

@sunag sunag commented Oct 13, 2024

Description

The main idea of ​​having a lighting system is to open up the possibility for contributors to add their own lighting system like clustered lighting, which is why I added TiledLighting in addons.

About TiledLighting, there are still improvements to be made, such as sorting the lights according to the proximity of the camera to obtain better indexes, adding disposes, math optimizations and mainly added WebGLBackend support.

API

The user does not need to manipulate anything special, such as shaders or uniforms, just define the class for light system.

const lighting = new TiledLighting(); // ( maxLights = 1024, tileSize = 32 )

renderer = new THREE.WebGPURenderer();
renderer.lighting = lighting; // set lighting system

Or define per material.

import { tiledLights } from 'three/addons/tsl/lighting/TiledLightsNode.js';

const lightsNode = tiledLights();
lightsNode.setLights( [ ...pointLights ] );

const materialA = new THREE.NodeMaterial();
materialA.lightsNode = lightsNode; 

const materialB = new THREE.NodeMaterial();
materialB.lightsNode = lightsNode; 

Process summary

  1. Store all the light data in a texture. It's position, color, distance...

  2. Create a buffer that represents pieces of the image, the tiles. Each tile will have the indexes of the lights that are visible in that piece.

  3. Instead of processing all the lights on the entire screen, we will only process the lights that are present in the indexes of each tile, I made each tile store 8 indexes. It is as if it had only 8 lights to calculate per pixel.

  4. There is a pre-renderer stage where the compute-shader will project the position and radius of light to screen space where we can check for intersection with the tiles using AABB and thus bind the light, indexing it in the tile buffer.

As I limited it to 8 indexes per tile and we do not have a sort lights, the system may fail if too many lights are added close to each other.

three.js.webgpu.-.tiled.lighting.-.Google.Chrome.2024-10-13.07-36-53.mp4

Commits

@sunag sunag added this to the r170 milestone Oct 13, 2024
Copy link

github-actions bot commented Oct 13, 2024

📦 Bundle size

Full ESM build, minified and gzipped.

Before After Diff
WebGL 689.92
170.93
689.92
170.93
+0 B
+0 B
WebGPU 814.81
219.39
815.27
219.76
+465 B
+372 B
WebGPU Nodes 814.32
219.25
814.78
219.63
+465 B
+373 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Before After Diff
WebGL 462.94
111.81
462.94
111.81
+0 B
+0 B
WebGPU 537.62
145.06
538.01
145.26
+392 B
+198 B
WebGPU Nodes 493.74
134.79
494.13
135.13
+392 B
+338 B

@sunag sunag marked this pull request as ready for review October 14, 2024 00:02
@sunag sunag merged commit 25ff4db into mrdoob:dev Oct 14, 2024
12 checks passed
@sunag sunag deleted the dev-tiled-lights branch October 14, 2024 23:38
@RenaudRohlinger
Copy link
Collaborator

Am I the only one with 5fps on the webgpu_lights_tiled example when using 100 lights, and having both my Chrome and Chrome Canary completely crashing when using 1000?

Also the demo looks odd, maybe related to the recent changes on the transmission pass of the Renderer:
Screenshot 2024-10-22 at 15 14 02

/cc @sunag

@Mugen87
Copy link
Collaborator

Mugen87 commented Oct 22, 2024

On dev I have a black screen and see the following warning in Chrome:

Error creating pipeline state Fragment function exceeds available stack space
at InitializeImpl (../../third_party/dawn/src/dawn/native/metal/RenderPipelineMTL.mm:449)

@mrdoob
Copy link
Owner

mrdoob commented Oct 22, 2024

It hangs Chrome here (M1 Pro) and eventually I get this in the console:

Screenshot 2024-10-22 at 5 43 57 PM

@sunag
Copy link
Collaborator Author

sunag commented Oct 22, 2024

I ended up turning it off after an unsuccessful cleanup, here it is again
#29722

@mrdoob
Copy link
Owner

mrdoob commented Oct 22, 2024

@mrdoob
Copy link
Owner

mrdoob commented Oct 22, 2024

Looks good on ChromeOS!

Screenshot 2024-10-23 08 57 46

@sunag
Copy link
Collaborator Author

sunag commented Oct 23, 2024

This is how it looks like now on a Pixel 8:

Could it be cache?

@mrdoob
Copy link
Owner

mrdoob commented Oct 23, 2024

This is how it looks like now on a Pixel 8:

Could it be cache?

I think it was yeah.
Just tried again and it works properly 🎉

@ligaofeng0901
Copy link
Contributor

If a directional light is added into scene, some area that point light not covered lose directional light. I add a directional light with red color, it appear like this below:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants