Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
af9c99b
update readme
conswang Jan 13, 2023
9633131
show shader linting for javascript strings
conswang Jan 14, 2023
6f49446
can't use glsl string highlighting
conswang Jan 14, 2023
74cec96
finally fix linting...
conswang Jan 14, 2023
411f543
add notes
conswang Jan 15, 2023
10a7bfe
typescript works
conswang Jan 15, 2023
d7f86dc
untested frustum testing, it runs though
conswang Jan 15, 2023
fb28304
jesting
conswang Jan 15, 2023
11f2882
fix bug with corners, still failing test
conswang Jan 15, 2023
7cb9cb6
don't let vector3 func modify the original vector
conswang Jan 15, 2023
d744199
use top left origin for slice indexing
conswang Jan 15, 2023
3ed403a
normal calc tests
conswang Jan 15, 2023
d5a4847
near and far normals pointing wrong way
conswang Jan 15, 2023
b9d5612
test working for frustum slices
conswang Jan 16, 2023
dc2cbcf
attempt
conswang Jan 16, 2023
f4ee197
cleanup 3js versions, add horrendously slow light texture logic
conswang Jan 16, 2023
f141643
get cluster index
conswang Jan 28, 2023
657c184
failure
conswang Jan 28, 2023
5f3ea78
incorrect, blocky output
conswang Jan 28, 2023
d185819
i see something and it still looks wrong but at least its faster
conswang Feb 5, 2023
b85cb90
index error
conswang Feb 5, 2023
6689da9
fix light indexing, still have weird tiles
conswang Feb 5, 2023
0f5cdc0
correct the z cluster calculation
conswang Feb 5, 2023
5942886
unhelpful debugging
conswang Feb 5, 2023
87a4216
fix off by 1 index, correct num lights to max lights per cluster
conswang Feb 6, 2023
b794bca
fix last cluster index wrongly filtered edge case
conswang Feb 7, 2023
47bb321
fix light debug position logging
conswang Feb 7, 2023
0012c34
fix texture height calculation forward+ shader
conswang Feb 7, 2023
149cced
working deferred clustered
conswang Feb 7, 2023
aeff4de
remove unused imports
conswang Feb 7, 2023
d8a6f66
bloom shaders done, untested, not sure how to connect pipeline
conswang Feb 7, 2023
b66cb08
we're rendering something but it looks a little strange
conswang Feb 7, 2023
8ff624f
not working, fix race condition from read/write to same texture + add…
conswang Feb 8, 2023
f58d5fd
setup fbo for each render pass
conswang Feb 8, 2023
e71e08a
fix shader bugs, working bloom
conswang Feb 8, 2023
71a7882
not working g buffer opt
conswang Feb 8, 2023
2b5f9c6
update readme
conswang Feb 8, 2023
6e98671
format
conswang Feb 8, 2023
c08cb38
fix deploy
conswang Feb 8, 2023
cd9e842
add live link
conswang Feb 8, 2023
d55c681
readme
conswang Feb 8, 2023
ed494df
it was a minus sign all along...
conswang Feb 8, 2023
ec12917
README
conswang Feb 8, 2023
a50506c
big readme commit
conswang Feb 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 74 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,90 @@ WebGL Forward+ and Clustered Deferred Shading

**University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 5**

* (TODO) YOUR NAME HERE
* Tested on: (TODO) **Google Chrome 222.2** on
Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
Constance Wang
* [LinkedIn](https://www.linkedin.com/in/conswang/)

Tested on AORUS 15P XD laptop with specs:
- Windows 11 22000.856
- 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz 2.30 GHz
- NVIDIA GeForce RTX 3070 Laptop GPU

This project implements two optimized rendering methods for scenes with a large number of lights: 1) Forward+ rendering which uses clustering to optimize the search for lights that contribute a noticeable effect to each pixel and 2) Clustered Deferred rendering which implements the clustering method from Forward+ in a deferred shader. These two methods are compared to forward rendering as a baseline.

Additional features:
- Bloom filter using two post-process passes
- G-buffer optimizations: reconstruct position from depth and pack values into vec4

### Live Online
[https://conswang.github.io/Project5-WebGL-Forward-Plus-and-Clustered-Deferred/](https://conswang.github.io/Project5-WebGL-Forward-Plus-and-Clustered-Deferred/)

Note: had to use 'copy-webpack-plugin' to copy the entire models folder into the build folder, as webpack can't really detect files referenced by gltf files.

[![](img/thumb.png)](http://TODO.github.io/Project5-WebGL-Forward-Plus-and-Clustered-Deferred)

### Demo Video/GIF
### Demo
![](images/bloom.gif)
[full video here](images/sponza-bloom.mp4)

### Performance
In each of these tests, forward+ and deferred used cluster dimensions of 15 x 15 x 15, with the cluster depth ranging from 0.1 to 300. The scene is `sponza.gltf` with coloured lights generated randomly around the scene.

![](images/Performance%20of%20Forward,%20Forward+%20and%20Clustered%20Deferred%20rendering%20on%20different%20numbers%20of%20lights%20(higher%20is%20better).png)

![](images/Performance%20of%20Forward,%20Forward+%20and%20Clustered%20Deferred%20rendering%20for%20100%20lights%20with%20varying%20radius%20(higher%20is%20better).png)

Overall, the performance of clustered deferred > forward+ >> forward rendering. This makes sense, since forward+'s optimization makes the most expensive step of lighting calculations (iterating through all the lights) less expensive by culling many lights outside the pixel's cluster. Clustered deferred rendering takes advantage of this optimization, and on top of that, reduces the total number of these still-expensive calculations needed from one per fragment to one per pixel.

However, forward+ rendering does better than clustered deferred for tiny lights (radius = 1 or 2) and/or smaller number of lights (< 100). The number of fragments affected by the lights would be relatively small in these cases, so the performance gain from deferred shading does not outweigh the overhead of computing two render passes.

On the other hand, the performance of forward rendering becomes intolerable pretty quickly as the number of lights increases. However, since the calculations are independent of radius, forward rendering's frame rate is constant no matter how much we increase the radius, making it a reasonable option if all the lights take up a large portion of the screen.

Memory consumption: in theory, clustered deferred > forward+ > forward. Forward rendering doesn't require any extra buffers. Forward+ requires a cluster buffer and light buffer. Clustered deferred requires both buffers, as well as per-pixel g-buffers. However, in practice I found the memory usage difference not to be very significant, with forward rendering at 45 MB of allocated memory, and clustered sometimes at 50, sometimes at 60 MB.

### Bloom Filter
I added a bloom filter effect to the clustered deferred shader - set `SHOW_BLOOM` in `clusteredDeferred.js` to toggle the feature. After the deferred render pass, we write to two render targets: the rendered texture, and a "bright" texture which only contains pixels above a certain brightness threshold. The bright texture is then Gaussian blurred in a second fragment shader and added to the rendered texture to create an effect of light bleeding through edges.

| Bright texture | Gaussian blur |
| --- | ----|
![](images/bloom-bright.png) | ![](images/bloom-blur.png) |

| Render texture | Final result |
| --- | ----|
|![](images/bloom-render.png) | ![](images/bloom-result.png) |

At 100 lights of radius 5, adding the Bloom filter slows down the frame rate from 58 fps to 35 fps. This makes sense due to the addition of two post-process passes which run in parallel.

The runtime of Bloom itself is not affected much by the number of lights or light radii, since the post-processing passes work the same way regardless of variables. Allocated memory increases from 50-60 MB to around 60-70 MB, which makes sense due to the additional textures.

Possible enhancements:
- replacing Gaussian blur with A-trous to have a larger kernel for cheaper (would need to measure to see if Gaussian is slow enough for this to be worth it).
- visual improvements: Bloom would look more realistic with high definition rendering, would have to change the colour texture format to implement this

### G-Buffer Optimizations
My unoptimized clustered deferred renderer uses 3 g-buffers containing albedo, normals, and positions as vec4s in separate textures.

I optimized the g-buffers by replacing the position buffer with a single depth value, and using the camera's inverse view matrix to reconstruct the position from depth. Set `G_BUFFER_NO_POSITION` to true to enable this. I also packed the depth as the fourth component of the albedo g-buffer, reducing the total number of g-buffers to 2.

Debug views:
| Position (divided by 10) | Depth (divided by 10) |
|---|---|
| ![](images/position.png) | ![](images/depth.png) |

| Normals | Albedo |
|---|--|
|![](images/normal.png) | ![](images/albedo.png) |

[![](img/video.png)](TODO)
![](images/Effect%20of%20g-buffer%20optimization%20on%20performance.png)

### (TODO: Your README)
The performance gain was more noticeable around 100-300 lights with radius of 5. It may be that with more lights, the compute time of processing the clusters was the more significant factor.

*DO NOT* leave the README to the last minute! It is a crucial part of the
project, and we will not be able to grade you without a good README.
Further improvements: I calculated the position by adding depth * forward vector to the camera position, then adjusting for the xy pixel offset using the left and up vectors. It might be faster to calculate camera position + view vector * distance, I saw some methods [here](https://mynameismjp.wordpress.com/2010/09/05/position-from-depth-3/). We could also try sampling the hardware depth buffer and adjust the calculations accordingly, saving more g-buffer space.

This assignment has a considerable amount of performance analysis compared
to implementation work. Complete the implementation early to leave time!
### Oops
c o l o u r s y n t h (wrong position buffer)
![](images/goodaesthetic.gif)

[and many more here (´。_。`)](https://docs.google.com/document/d/1BJmclri4VJY_IXbsLU8Er_CQihQnfmzTQRi5cz9FthM/edit#heading=h.xsr527b9gzdk)

### Credits

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/albedo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/bloom-blur.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/bloom-bright.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/bloom-render.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/bloom-result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/bloom.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/depth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/goodaesthetic.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/normal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/position.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/sponza-bloom.mp4
Binary file not shown.
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
Loading