View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0005850 | The Dark Mod | Graphics | public | 21.12.2021 17:16 | 19.11.2022 11:10 |
Reporter | stgatilov | Assigned To | stgatilov | ||
Priority | normal | Severity | normal | Reproducibility | N/A |
Status | resolved | Resolution | fixed | ||
Product Version | TDM 2.10 | ||||
Target Version | TDM 2.11 | Fixed in Version | TDM 2.11 | ||
Summary | 0005850: Volumetric lights: render to texture then blur | ||||
Description | The reason why original volumetric lights achieved good performance with plausible quality is dithering. While they look nice overall, in some cases (especially with shadows) the dithering becomes apparent. Ideally, we should render each volumetric light to off-screen framebuffer, then blend it on top of the main framebuffer. This allows for several things: 1) Volumetric light can go through low-pass filter (e.g. blur) to make dithering less noticeable. 2) Volumetric light can be rendered with lower resolution, allowing us to use more samples (e.g. 2x lower resolution means 4x more samples). Of course, the operations of the new framebuffer should only affect a subrectangle defined by light scissor. Make sure we don't blur or blit the whole framebuffer for small lights, otherwise there will be huge penalty for having many small lights on screen. | ||||
Tags | No tags attached. | ||||
I started working on this, and realized that the stuff proposed here is not entirely straight-forward. Yes, the volumetric light itself is often low-frequency, but there are edges of light frustum, and edges of geometry (via depth buffer). The blur/lowres code here should take depth discontinuity into account. I looked a few articles on the internet: https://www.alexandre-pestana.com/volumetric-lights/ https://youtu.be/RdN06E6Xn9E?t=557 http://c0de517e.blogspot.com/2016/02/downsampled-effects-with-depth-aware.html Apparently, people usually implement volumetric light with both techniques included: * raymarching on downscaled FBO (1/2 size) * dithering: either Bayer matrix or blue noise Step-by-step: 1) render raymarched volumetric lights with dithering into half-size FBO 2) depth-aware blur of half-size FBO (apparently keeping half-size) 3) depth-aware upsampling and compositing While depth-aware ("bilateral") blur and upsampling are standard techniques today, they are many implementation details which might differ. I especially like the last link in this regard: http://c0de517e.blogspot.com/2016/02/downsampled-effects-with-depth-aware.html The important details are: 1) When computing downscaled data, we usually consider a point in the middle of 2x2 pixel block... However we should not just take average depth of 4 pixels: better take nearest depth. 2) When doing the blur, we probably should not separate horizontal/vertical passes, since depth-aware blur is not separable =( 3) When upscaling the data, we take four 2x2 blocks as data sources. Then we do bilinear interpolation of their values, but with additional weights deduced from the difference between fullres depth and the depth used during downscaled rendering. Unfortunately, all four weights might be close to zero, so if total weight is low, then probably just take closest 2x2 block as single source?... Most likely, I will have to make half-size FBO for depth buffer too. So the plan is: 1) Move code to separate class. 2) Add full-size FBO and separate raymarching from compositing. 3) Try to blur FBO (will need another FBO for ping-pong). 4) Try to make FBO half-res, with all the downscaling/upscaling issues. |
|
Committed new implementation in svn rev 10146. The implementation is exactly as described above: half-resolution 8 samples per pixel with Bayer dithering depth-aware blur depth-aware upsampling * The blur is separable (i.e. separate horizontal and vertical passes). It is not equivalent to single-pass Gauss blur, but it blurs pretty well and it much cheaper. * Speaking of depth downsampling, I did not do anything special. Apparently, filtering is set to "nearest" on depth texture, so when I fetch at the middle of 2x2 block, some pixel is selected automatically. * The problem of zero total weight is alleviated by selecting between bilinear filtering and taking nearest sample. And there is a bunch of cvars now. Listing them with their current defaults and values to achieve old behavior: r_volumetricSamples 8 r_volumetricDither 1 r_volumetricBlur now: 2 old: 0 r_volumetricLowres now: 1 old: 0 So if you set the last two to 0, FBOs will NOT be used, and you'll get the exact picture from 2.10. |
|
The performance is better in general, dithering pattern is gone. Some artifacts are visible occasionally: 1) If I look through volumetric light at a far point of ideally horizontal planar ground, I see some bits of noise. That's because depth-aware blur does not blur the noise perfectly. It cannot do that because the change in viewZ is very high when stepping up in blur shader --- greater than depth tolerance. I don't think I can fix it reliably: it's better to have some mess at far distance, then blurred edges of objects at near distance. 2) If you have a cubic volumetric light with constant light intensity, and look approximately along its face, then you see some low-resolution aliasing. I could not find a satisfactory solution against it: that's the case when volumetric light becomes non-smooth despite smooth depth, so blurring is not enough to hide low-resolution mess. 3) The effect is still not friendly with multisampling: if AA is on, then you can see 1-pixel wide dotted lines at the edge of objects. Or if you don't, then you can see the aliasing on the edge as if AA was off. The reason for this is that the effect totally ignores multisampling. In principle, the issue with multisampling can be fixed the following way: 1) Make multisampled depth texture available in volumetric light compositing shader. 2) Use gl_SampleID (needs GL4.0, so check for extension) to force compositing shader to run for every sample, instead of for every pixel. 3) For each sample, fetch its depth and use it in depth-aware upsampling. |
|
The aliasing is really bad on anything in front of the effect. | |
It's very noticeable in motion too. | |
I'm afraid you'll have to record a short video and share it as file. Otherwise it is hard to understand which issue you are talking about... |
|
https://www.youtube.com/watch?v=L7xFCVFky1s As the Zombie walks in through the door, he's outlined by the volumetric light. You can see pixelation all around him. |
|
I noticed bad artifacts of depth-aware blur/upsampling, which resulted from round-off errors. That's because I sampled depth texture in the center of low-res pixel, which is exactly in-between 4 high-res texels... meaning that it was uncertain which of them were selected. Now I have added a half-pixel shift, and the issue is gone. That's svn rev 10147. |
|
New issue, the artifacts are now showing up with r_volumetricLowres 0, but go away when set to 1. r_volumetricLowres 0 https://i.imgur.com/wRZXzN9.png r_volumetricLowres 1 https://i.imgur.com/2ql9Gso.png |
|
Yeah, subpixel shift should not be applied with full-res effect. Fixed in svn rev 10148. |
|
Some more changes: r10151 Cap depth/distance by backfaces of frustum. r10152 Don't forget to shutdown volumetric singleton, otherwise it crashes on first use after engine reload. r10156 Disable volumetric lights ins subviews. The point 1 of the above list of artefacts is fixed, since now I cap depth values by depth of frustum's backfaces. I'd say this issue is finished. |
|
More improvements from Daft Mugi's feedback: r10161 Use FBO of format GL_R11F_G11F_B10F instead of GL_RGBA8. r10162 Fixed bug that depthToZ returned -infty instead of +infty for depth = 1. r10163 Increased r_volumetricSamples from 8 to 24. |
|
More fixes due to Daft Mugi feedback. Fixing shadows of portal sky pyramids in Hazard Pay: r10164 Never force huge lights to shadow maps, even if they have volumetrics. r10165 Force-disable volumetrics in subviews: do it early in frontend, not in backend. Allow players to tweak volumetrics if they so much want it: r10166 Added r_volumetricDustMultiplier cvar that allows player to tweak strength of volumetric to his liking. |
|
Date Modified | Username | Field | Change |
---|---|---|---|
21.12.2021 17:16 | stgatilov | New Issue | |
21.12.2021 17:17 | stgatilov | Relationship added | related to 0005816 |
31.10.2022 19:38 | stgatilov | Assigned To | => stgatilov |
31.10.2022 19:38 | stgatilov | Status | new => assigned |
31.10.2022 20:03 | stgatilov | Note Added: 0015384 | |
05.11.2022 18:26 | stgatilov | Note Added: 0015390 | |
05.11.2022 18:37 | stgatilov | Note Added: 0015391 | |
05.11.2022 18:54 | AluminumHaste | Note Added: 0015392 | |
05.11.2022 18:54 | AluminumHaste | File Added: hazard (2022-11-05 14-52-42) (3955.46 1357.27 -83.37).png | |
05.11.2022 18:54 | AluminumHaste | File Added: hazard (2022-11-05 14-52-40) (3931.78 1358.65 -80.32).png | |
05.11.2022 18:54 | AluminumHaste | File Added: hazard (2022-11-05 14-52-38) (3930.18 1358.8 -114.3).png | |
05.11.2022 18:55 | AluminumHaste | Note Added: 0015393 | |
05.11.2022 19:37 | stgatilov | Note Added: 0015394 | |
05.11.2022 19:58 | AluminumHaste | Note Added: 0015395 | |
05.11.2022 22:38 | stgatilov | Note Added: 0015396 | |
06.11.2022 01:27 | AluminumHaste | Note Added: 0015397 | |
06.11.2022 06:37 | stgatilov | Note Added: 0015399 | |
10.11.2022 22:26 | stgatilov | Note Added: 0015414 | |
10.11.2022 22:26 | stgatilov | Status | assigned => resolved |
10.11.2022 22:26 | stgatilov | Resolution | open => fixed |
10.11.2022 22:26 | stgatilov | Fixed in Version | => TDM 2.11 |
18.11.2022 21:24 | stgatilov | Note Added: 0015451 | |
19.11.2022 11:10 | stgatilov | Note Added: 0015454 |