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

RT: Global illumination #510

Open
Try opened this issue Aug 24, 2023 · 19 comments
Open

RT: Global illumination #510

Try opened this issue Aug 24, 2023 · 19 comments

Comments

@Try
Copy link
Owner

Try commented Aug 24, 2023

Concept

  • Aim for to one ray-pixel budget. In theory 2rpp is may work for low-poly game.
  • Micro-probes or surfels or hybrid
  • Assume that game-level is static for now (special case for MoveTriggers maybe)
  • Build g-buffer (or hit-list) per probe.
    • Ray queries can be cached, until something changes in world;
    • Probe g-buffer can be relight every-frame - except for shadow-ray it's cheap

First prototype (branch: https://github.com/Try/OpenGothic/tree/gi-rendering)

изображение

and probes(~30k):
изображение

Reference materials:

Lumen: https://advances.realtimerendering.com/s2022/SIGGRAPH2022-Advances-Lumen-Wright%20et%20al.pdf
изображение

Combination of screen-space probes and world-space cache, for HW-RT part. In paper there is a lot about SDF and software ray-tracing, yet we wont do it, as so requires precomputational part in asset-pipeline

  • one probe per 4x4 tile. (64 rays per probe, accumulated over 4 frames)

EA-surfels: https://www.youtube.com/watch?v=h1ocYFrtsM4
изображение

  • Surfel is directional and spawns on g-buffer geometry. No light leaks!
  • Doesn't really work for grass (need to span surfel per grass-blade)
  • Doesn't really work for animated objects (even with single-bone tracking surfel data becomes obsolete immediately on move)
  • Cubemap-like acceleration structure for surfels

PRT probes: http://mrakobes.com/Nikolay.Stefanov.GDC.2016.pdf
изображение

  • probes do represent computed irradiance
  • surfels act like a sparse g-buffer + 1 bit to cache last known shadowmap test
  • 4m spacing between probes
  • 2-level hash-grid to store surfels
  • hacky solution for multibounce GI

Personally prefer this workflow (except we will have to do ray-casting in runtime)

Good summary on light-leaks :
https://handmade.network/p/75/monter/blog/p/7288-engine_work__global_illumination_with_irradiance_probes

Nice open-source project with multiple techniques implemented:
https://github.com/EmbarkStudios/kajiya/blob/main/docs/gi-overview.md

@Try Try pinned this issue Aug 25, 2023
@Try
Copy link
Owner Author

Try commented Aug 26, 2023

Added probe-caching; continue cleaning-up lightingcode:
изображение

~3k probes are recalculated each frame
~27k in total
No SSAO/Bent-normal integration (yet?)

Need to refine caching scheme: cache ray-hit instead of irradicance

Try added a commit that referenced this issue Aug 26, 2023
Try added a commit that referenced this issue Aug 27, 2023
@Try
Copy link
Owner Author

Try commented Aug 27, 2023

Some more screenshoots:
изображение
изображение
изображение

@Try
Copy link
Owner Author

Try commented Aug 31, 2023

Rework for probe-grid lod:
изображение

Now probes do have almost consistent distribution in screen-space with similar budget

@Try
Copy link
Owner Author

Try commented Sep 5, 2023

Still working on secondary bounces. More screenshots:
изображение
изображение
изображение
изображение

@Try
Copy link
Owner Author

Try commented Sep 5, 2023

black-and-white version
изображение

@Try Try mentioned this issue Sep 14, 2023
Try added a commit that referenced this issue Sep 14, 2023
* GI probes initial

* beautify debug view

* probe irradiance

* GI lighting with probes

* hacks cleanup

* probe caching initial

* performance: FREE_BIT

* probe lighting cleanup

#510

* probe hash-map: colision resolver

#510

* avoid ultra-dark spits in woods

* GI in progress: probe-gbuffer

* probe lighting in progress

* rework probes allocation

* updates to rt-scene

* improved integration; fix overflow in probes atlas

* improve probe distribution; tune lighting

* move probesLighting data into 11-bit float image

* multibounce initial

TODO: fix r/w race in probesLightingPrev

* probes in progress; fix race in lighting pass

* use sky irradiance as fallback, if we hvae no probes

* probe integration in progress

* improve bad-probe rejection

* fixup

* fix z-fighting in probes

* GI: check gpu limits

* generalize GI vs nonGI ambient

* more light in forrest
@clort81
Copy link

clort81 commented Nov 16, 2023

Wanted to play with RT for ages and never found a FOSS implementation i liked.
Following your work here, and very thankful to read your notes and results.

Try added a commit that referenced this issue Dec 28, 2023
@Try
Copy link
Owner Author

Try commented Dec 28, 2023

Metal backend also works now:
изображение

Not much FPS on M1, yet still happy that Metal-backed now has less bugs :)

@Try
Copy link
Owner Author

Try commented Feb 29, 2024

Updated albedo-fetch heuristics:
изображение

Notes:
albedo-fetch is a horrible hack that enables usage photo-texture of vanilla game, and attempts to extract usable color information

@Try
Copy link
Owner Author

Try commented Mar 3, 2024

Working on narrowing down, what is not working. When similar view-angle rendered with albedo=0.9 image look correct:
изображение

@Try
Copy link
Owner Author

Try commented Mar 3, 2024

Still tuning textures/color-bleeding.
GI:
изображение
No-GI:
изображение

Try added a commit that referenced this issue Mar 4, 2024
Try added a commit that referenced this issue Mar 10, 2024
@Try
Copy link
Owner Author

Try commented Mar 13, 2024

Going thru https://physicallybased.info

Sun (above atmosphere): 143'000.f -> 128'000.f
Sun (on land): engine results in ~100.000f, matches real world observation
Sky (median) was ~3% of sun-light (too low), after changing ground albedo factor (0.1 -> 0.3), becomes ~4.7% (correct)

Uniform-ambient is estimated as:
sun * transmissioni * ang * p * 0.5 * 2pi - bunch of hacks; TODO.

After many adjustment:
изображение

@toolatetotheparty
Copy link

The latest screenshot looks more and less physically correct at the same time. The intensity of direct sunlight looks less clipped, but the GI deep inside the building looks gone, allowing that ghastly blueish fake GI they did to show through. 🤔

upd.
Though, on a second thought, there wouldn't be enough energy for indirect sunlight to bounce so many times and color everything orange... Anyways, some AO feeding on your GI implementation is also needed. Removing the effects of these blue-tinted light probes would do wonders for the general aesthetics.

@Try
Copy link
Owner Author

Try commented Mar 13, 2024

Main issue with GI (or lighting in general), when it comes to gothic, are materials. Or should I say - lack there of.

GI (and diffuse lighting) needs albedo data, but only thing we have in assets is a "photo-texture".
For the sake of rendering I have heuristics here:

  • assume that photo_texture = gamma(tonemapping(exposure*pbr(material)))
  • if we inverse gamma&tonemap, we will get exposure * pbr(material)
  • if we assume only diffuse lobe (specular is way to hard anyway): exposure * (1/PI) * dot(N,L) * albedo
  • since it's a photo - assume dot(N,L)=1.0, simplify and we have C * albedo, where C is some constant

This is path one. Part 2: this heuristic has to be symmetrical with engine lighting.

  • gamma(tonemapping((engine_lighting(albedo))) ~= photo_texture - this is formal way to say image should be similar to vanilla,
  • this restricts constant C, to be something close to 1.0

Part 3. Due to the way inverse-tonemapping works, acesTonemapInv(1.0/*white*/) = inf

  • We can't just use acesTonemapInv, resulting in this abomination:
vec3 textureAlbedo(vec3 rgb) {
  const vec3 linear = srgbDecode(rgb);
  return acesTonemapInv(linear*0.78+0.001)*5.0; // adjusted to have 'realistic' albedo values
  }

... and now it violate P2, to avoid inf

@Try
Copy link
Owner Author

Try commented Mar 13, 2024

Anyways, some AO feeding on your GI implementation is also needed

I do simply multiply GI by AO (what is not correct, but give at least some detail). Here is AO
изображение

Probably it would be better to use output bent-normal, from AO pass and use it intead

@Try
Copy link
Owner Author

Try commented Mar 14, 2024

Is it possible to further adjust AO so that it would work not only by seeking intersecting geometry but also volumetrically, with respect to how your GI works by gradually shading the whole interior?

Sorry, I don't know what do you mean. If AO is by definition ratio of ray-hit/ray-miss, and if shader checking not only intersection - than it's not AO

@Try
Copy link
Owner Author

Try commented Mar 14, 2024

gradually shading the whole interior?

Scene above is not interior:
изображение

When it comes to castle wall, it expected to be split 50:50, between ray-misses (samples sky-color) and hit on street floor.
Street-floor has no direct component (it's in shadow), and indirect is also sky*albedo

@Try
Copy link
Owner Author

Try commented Mar 14, 2024

2k shadowmap unfortunately not good enough to take care of shadow-term. Also secondary-bounces are disabled, as I'm debugging atm.
изображение
изображение

almost like lumen:
изображение

Try added a commit that referenced this issue Apr 7, 2024
@Try
Copy link
Owner Author

Try commented Apr 7, 2024

Debug view of ray-hits (needed to evaluate solution for secondary bounces):
изображение

изображение

@Try
Copy link
Owner Author

Try commented May 4, 2024

Been evaluating different approaches for iradiance cache and secondary bounces. Unlike Lumen, in OpenGothic we cannot do offline baking, and have to have runtime solution for gi-scene.
Here example of hash-map of primitives that been touched by rays:
изображение
изображение

Every colored triangle is a single cache-entry and small primitives are also tessellated by bird-curve, to improve resolution a bit. Still not OK unfortunately: too much memory (~200+MB) and too low res

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

No branches or pull requests

3 participants