gkjohnson / three-gpu-pathtracer

Path tracing renderer and utilities for three.js built on top of three-mesh-bvh.
https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/index.html
MIT License
1.28k stars 125 forks source link

"invisible" area lights #469

Closed robertoranon closed 6 months ago

robertoranon commented 7 months ago

Hi :)

when rendering interiors, it can be sometimes useful to add "fill lights" to get faster convergence, less noise, and also better illuminate darker spots. However, these lights should not be visible in the scene, but current area lights basically show up as emissive surfaces. Do you think it would be possible to have an option for invisible area lights? I could have a go and implement it, but would like to know what you think about this feature. Also, if you have ideas on how to implement it / where to look, I'd be grateful :)

Roberto

gkjohnson commented 7 months ago

Hey Robert! The ability to toggle the visibility of the light would be a good thing to add, I think. One issue right now, though, is that area lights effectlvey behave as solid objects / blockers so they can cast shadows from a light behind them. I think ideally the lights themselves would not cast shadows. So I think a full implementation of this feature would include both of the following:

This might require a bit of reorganizing and I'll have to think about it a bit more but the areas to start familiarizing yourself with are here (logic for a light hit) for the first item. And here (MIS light contribution calculation which also traces the scene to check if it's blocked by something including other lights).

Are you able to run the MIS code path on any machine atm?

robertoranon commented 7 months ago

Hi, thanks for the reply. Not, I am not able to run the MIS code path, so I'll see what I can do for the non MIS path, for now.

gkjohnson commented 7 months ago

Okay sounds good - if you can get non-MIS working and help address some of the things mentioned above I can get the MIS path functioning on my Windows machine.

robertoranon commented 7 months ago

I began to tinker with the code, and started by modifying the following lines in PhysicalPathTracingMaterial.js:

if ( hitType == LIGHT_HIT ) {
   if ( state.firstRay || state.transmissiveRay ) {
      gl_FragColor.rgb += lightRec.emission * state.throughputColor;
}

to

if ( hitType == LIGHT_HIT ) {
   if ( state.firstRay || state.transmissiveRay ) {
     // gl_FragColor.rgb += lightRec.emission * state.throughputColor;
}

and the successive break a few lines down is substituted by

ray.origin = ray.origin + ray.direction * surfaceHit.dist;
continue

so that a new ray that basically passes through the light is generated. My logic is that, in case a light is hit, we just ignore it if it is a camera ray (or a ray through a transmissive surface), or add the light contribution if it's another ray. I should probably be doing this just for the area lights .... This, in the area lights demo, removes the "glow" of the lights, but the light rects are still visible (black) against the env map (and I don't understand why ...), if one turns up the env map intensity. And "fainted" rects are still somehow visible (see images). Can you help me understand why?

Also, I discovered that all other lights (point, spot) do not work at all on Mac (both Chrome and Safari), no crashes, it's just as if their intensity is zero, but that's another story

Screenshot 2023-11-24 at 13 35 52 Screenshot 2023-11-24 at 13 35 21
gkjohnson commented 7 months ago

Do you mind making a PR with the changes so I can take a look? It'll be easier to understand what's happening, I think.

robertoranon commented 7 months ago

sure! Also, while experimenting with break/continue statements in that shader, it was very easy to provoke the "webgl context lost" issue that plagues the MIS enabled version on Macs - just an FYI that hopefully brings us closer to understand exactly why the webgl context is lost

gkjohnson commented 6 months ago

Closed with #470