Performant soft shadows THREE Js

Hello,

I was wondering if there is a way in THREE Js to get very performant soft shadows for indoor scenes without the need to bake them to texture with a 3D render software.

As I see it SSAO works pretty good in THREE Js to achieve the result I’m after, but needs to calculate every frame. My scenes are static (no animation or repositioning of objects) but the SSAO seems to be dynamic. Not sure if this can be made static as well while the user navigates through the scene.

Another option would be baking the SSAO to texture once when the scene is loaded. But not sure how to achieve this and is dynamic UV unwrap possible to bake the data?

I want the soft shadows to run super smooth on mobile devices for indoor scenes with approximately 20000 tris. Some meshes are textured. So when using a baking technique the effect needs to multiply the existing texture.

If there are better ways in THREE to achieve the result I’m after, please share.

everything i tried is expensive and riddled with limitations, but for smaller models it could work. since your scenes are static i don’t see why you not want to bake them, that is the only truly performant choice and will look better than anything that’s calculated runtime. if you still want to try, here are a few methods you can experiment with, they’re react but the shaders are plain three universal:

baked shadows: Threejs journey - CodeSandbox
contact shadows: Shoe configurator - CodeSandbox
dynamic lightmaps: Adaptive lightmaps - CodeSandbox
percent closer soft shadows: Soft shadows - CodeSandbox
faking soft shadows w/ ssao dialed up to 11: Performance scaling - CodeSandbox
low resolution + pointlights: Minecraft - CodeSandbox

5 Likes

Hi drcmda,
Progressive LightMapping seems very interesting to me.
I’ll have a closer look into this.

Thanks for the info.

Maybe this could help :3

render.shadowMap.autoUpdate = false;
render.shadowMap.needsUpdate= true;

this take and shows the first frame of your shadows and then they become static

4 Likes

For real? I had no idea we can do that :heart_eyes:

I implemented it as follow. When all data is loaded I wait for 100 milliseconds to disable dynamic shadows

    loadingManager.onProgress = ( url, itemsLoaded, itemsTotal ) =>
    {
      if(itemsLoaded == itemsTotal)
        setTimeout(()=>{renderer.shadowMap.autoUpdate = false;}, 100);
    }

When a sunlight repositions, also causing to call a render pass, I use

renderer.shadowMap.needsUpdate = true;

Now I dive into AO techniques to fake soft shadows GI effects.

Thanks for the info

Dynamic lightmapping and soft shadows looks very promising to me. Great job!
Are these techniques usable without react? Are there examples or so?

they are just shaders. you find both in the official three examples, though you have to untangle them from the example code they’re wired into, they’re not readily usable ootb.

for softShadows i’ve made a small vanilla abstraction: GitHub - pmndrs/drei: 🌭 useful helpers for react-three-fiber you can use in your project as is, it mutates THREE.ShaderChunk.shadowmap_pars_fragment:

import { softShadows } from '@react-three/drei'

softShadows()

this won’t add react or any other dependency to your bundle. you could also just copy the code: drei/softShadows.tsx at 2088076e77d636cf001317475173fc44ae2071ac · pmndrs/drei · GitHub

the other one, the lightmap, that’s more complex and needs lots of things functioning around it, it is best abstracted into a component. but i find it pretty much unusable, it has countless of issues depending on your models, uvs and so on.

3 Likes

Would it be possible to use this dynamic path tracing technique:
https://erichlof.github.io/THREE.js-PathTracing-Renderer/Gltf_Viewer.html

And bake it to a texture in three js for all meshes after lets say 200 samples to make the bake static?

if you want soft shadow, use a light array with a diameter, obvious … the very attribute of the Sun making soft shadows…the very thing that proves the staged Apollo landing pics - shadows too tight.

If Three does NOT do it, I’d look at POVray code and implement in next release. There ought to be like 3 levels.

1 Like

Hi all,

I find this topic very interesting. I saw this example : three.js webgl - progressive lightmap accumulation

I wonder if it could be possible to modify this code, only for static scene, to save the result of this lighting and shadow and be able to reaload it after ?

It could be very interesting for static scene to calculate something like GI and save it (as lighting texture or something equivalent)…

Thanks to all !

2 Likes

Hello :slight_smile: I am also interested in achieving the same effect. The user will upload a gltf model and Id like to add a shadow under the model. The scene is static so the shadow only needs to be calculated once. I want to avoid calculations happening on each frame. Right now I am looking into the threejs progressive lightmap example to try and understand how i can use it for baking the shadow only once, and I came across this post.

I thought it might be helpful to poke you guys again and ask for your current opinion on the matter. Whats the best method to achieve this ? Thank you :smiley:

it’s not so easy, it wouldn’t work with most models due to missing uvs (i’ve tried). basically the same effort is required as with baking (uv-unwrap), and if you spend 6 hours to unwrap a model then straight up baking isn’t that much more effort.

i’ve created a runtime version of it that accumulates shadows, only for ground shadows though, but it looks fantastic and is perfect for viewer-type applications. it can accumulate shadows frame by frame instead of freezing until completion.

there is also a new pcss implementation by @N8Three which needs fewer samples, with just 6 samples is creates results that look similar to the old impl with 24+ samples. and it’s finally side-effect free, it can be toggled on/off. paired with a performance monitor it can always fallback to normal shadows if the device is too weak.

we released both for vanilla three in vanilla-drei GitHub - pmndrs/drei-vanilla: 🍦 drei-inspired helpers for threejs

2 Likes