Skip to content

WebGLRenderer: Add .renderShadowMap(). - #23585

Open
Oletus wants to merge 2 commits into
mrdoob:devfrom
higharc:shadowmap-manual-update
Open

Oletus wants to merge 2 commits into
mrdoob:devfrom
higharc:shadowmap-manual-update

Conversation

@Oletus

@Oletus Oletus commented Feb 24, 2022 •

Copy link
Copy Markdown
Contributor

This can be used to manually update shadow maps, which can be convenient in case the user wants to set up the scene differently for shadow map rendering. This can be useful for example when showing a cutout view.

Fixed #23461

This contribution is funded by Higharc.

Comment thread src/renderers/WebGLRenderer.js
Comment thread src/renderers/WebGLRenderer.js
@Mugen87

Mugen87 commented Mar 1, 2022 •

Copy link
Copy Markdown
Collaborator

The example needs to be added to files.json. Otherwise it does not appear in the side menu.

And please add the respective E2E screenshot via:

npm run make-screenshot webgl_shadowmap_manual_update

The PR checks should then be successful.

@Mugen87 Mugen87 changed the title Add WebGLRenderer.renderShadowMap() WebGLRenderer: Add .renderShadowMap(). Mar 1, 2022
@Oletus
Oletus force-pushed the shadowmap-manual-update branch from 8f3fba9 to b6fd65e Compare March 3, 2022 14:01
@Oletus

Oletus commented Mar 3, 2022

Copy link
Copy Markdown
Contributor Author

@Mugen87 Added the file to the examples listing and added the screenshot, PR checks passed now!

@WestLangley

Copy link
Copy Markdown
Collaborator

I had to diff the example in this PR to find the 3 lines which differ from the original example upon which it is based.

I think this will be confusing to users.

This can be useful for example when showing a cutout view.

Why not create an example of that, instead?

if ( _clippingEnabled === true ) clipping.beginShadows();

shadowMap.needsUpdate = true;
shadowMap.render( lightsWithShadows, scene, camera, clipping );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clipping parameter does not exist in the ShadowMap render method

@RenaudRohlinger

RenaudRohlinger commented Mar 20, 2022 •

Copy link
Copy Markdown
Collaborator

I did give a try to this feature. It works like a charm. I was able to bake a static shadow on the whole scene in 4k and then render a small dynamic shadow in 1k that calls renderShadowMap only on a few meshes:

(In this video the giant shadow camera helper is the shadow camera of the scene, and the small shadow camera helper is the dynamic that only renders the characters through renderShadowMap)

shadowbake.mov

Also, to make full usage of it I would recommend a 4th parameter forceUpdate

Like so:

this.renderShadowMap = function ( lightsWithShadows, scene, camera, forceUpdate )

That will allow being able to manually force to render an object even though autoUpdate and needsUpdate are set to false. We need to disable both these values if with use renderShadowMap otherwise it would clash with the natural state of how shadowmap.render works and call both methods per render.

In that case, the render method of WebGLShadowMap would have a third condition in order to prevent the render of the shadow:
if ( shadow.autoUpdate === false && shadow.needsUpdate === false && forceUpdate === undefined ) continue;

@mrdoob

mrdoob commented Mar 21, 2022

Copy link
Copy Markdown
Owner

Why not create an example of that, instead?

Agreed. This needs a simple example.

@mrdoob mrdoob added this to the r140 milestone Mar 21, 2022
@RenaudRohlinger

Copy link
Copy Markdown
Collaborator

With that new feature it would be very interesting to also introduce Array usage on top of Mesh.Group for the second parameter of WebGLShadowMap.render.

It will allow to prevent a complex filtering of the meshes that we want to apply shadow to. That way, instead of doing scene.traverse(), we can just renderShadowMap(lights, [meshA, meshB], camera, true)

It could look like this:

function WebGLShadowMap( _renderer, _objects, _capabilities ) {

	this.render = function ( lights, scene, camera, forceUpdate ) {
              
              // bypass if we want to manually update the shadowmap for specific elements
              if ( scope.autoUpdate === false && scope.needsUpdate === false && forceUpdate === undefined ) return;
              
              // allow arrays
              const elements = Array.isArray( scene ) ? scene : [ scene ];
             
              for ( let vp = 0; vp < viewportCount; vp ++ ) {
                    //viewport
                    _frustum = shadow.getFrustum();
              
                    for ( let j = 0; j < elements.length; j ++ ) {
                    
	                    const element = elements[ j ];
	                    renderObject( element, camera, shadow.camera, light, this.type );
                    
                    }
              
              }
              
              //....

@mrdoob mrdoob modified the milestones: r140, r141 Apr 30, 2022
@Oletus

Oletus commented May 6, 2022

Copy link
Copy Markdown
Contributor Author

@mrdoob @Mugen87 Hey! Sorry that it took such a long time for me to get around to updating the example, but it should be much better now! The manually updated shadow map now includes an object that's not visible in normal rendering. DeepScan is complaining about an unrelated issue since this code was forked off of dev a while back - do I need to rebase this branch or merge dev into here?

@mrdoob mrdoob modified the milestones: r141, r142 May 26, 2022
Oletus added 2 commits June 8, 2022 16:04
This can be used to manually update shadow maps, which can be convenient in case the user wants to set up the scene differently for shadow map rendering. This can be useful for example when showing a cutout view.

This work is sponsored by Higharc https://higharc.com/
This example now includes one object that's in the shadow map, but isn't included in normal rendering. It's similar to a real use case where you'd disable a roof of a building when rendering an interior view, but still keep the whole building's shadow visible.
@Oletus
Oletus force-pushed the shadowmap-manual-update branch from 9caed87 to 8fbd7f5 Compare June 8, 2022 13:06
@Oletus

Oletus commented Jun 8, 2022

Copy link
Copy Markdown
Contributor Author

Rebased this to pass the tests and made sure that the patch still works, @mrdoob time to merge this? 😁 I'd be really happy if we got this change in, hope you're not too busy! 🙏

@mrdoob mrdoob modified the milestones: r142, r143 Jun 29, 2022
@mrdoob mrdoob modified the milestones: r143, r144 Jul 28, 2022
@mrdoob mrdoob modified the milestones: r144, r145 Aug 31, 2022
@mrdoob mrdoob removed this from the r145 milestone Sep 29, 2022
@mrdoob mrdoob added this to the r161 milestone Dec 22, 2023
@mrdoob mrdoob modified the milestones: r161, r162 Jan 31, 2024
@mrdoob mrdoob modified the milestones: r162, r163 Feb 29, 2024
@mrdoob mrdoob modified the milestones: r163, r164 Mar 29, 2024
@mrdoob mrdoob modified the milestones: r164, r165 Apr 25, 2024
@mrdoob mrdoob modified the milestones: r165, r166 May 31, 2024
@mrdoob mrdoob modified the milestones: r166, r167 Jun 28, 2024
@mrdoob mrdoob modified the milestones: r167, r168 Jul 25, 2024
@mrdoob mrdoob modified the milestones: r168, r169 Aug 30, 2024
@mrdoob mrdoob modified the milestones: r169, r170 Sep 26, 2024
@mrdoob mrdoob modified the milestones: r170, r171 Oct 31, 2024
@Samsy

Samsy commented Nov 18, 2024

Copy link
Copy Markdown
Contributor

+1 !

@mrdoob mrdoob modified the milestones: r171, r172 Nov 29, 2024
@Samsy

Samsy commented Dec 10, 2024 •

Copy link
Copy Markdown
Contributor

Hey there, reviving this topic @RenaudRohlinger @sunag
Could this still be work-able in the current state of the WebGPU backend ?

I did hack my way on a custom threejs on the webGLRenderer to have both baked and real time lighting, this should definitely be useful to select which shadow you'd like to update, but also :

Determining if a light should contribute of the color lighting output, or cast shadow only

Example for a scene, let say you have two directional lights :

1 used for baking shadows globally and for lighting color contribution

1 used for real time shadowing, but this one should not contribute to the color lighting as it would add up a second contribution, but on top affecting perfs since one light is only needed for the lighting color contribution

EDIT :

Found out we can now set light.shadow.autoUpdate to false, and call light.shaow.needsUpdate only when required
Will publish a feature request instead

@RenaudRohlinger

RenaudRohlinger commented Dec 10, 2024 •

Copy link
Copy Markdown
Collaborator

Didn't try but I'm pretty sure if you render a shadow once and then do light.shadow.autoUpdate = false and light.shadow.needsUpdate = false on it, it should work just fine.
Unlike the WebGLRenderer, in the WebGPURenderer each ShadowNode is isolated and has its own rendering pipeline. @Samsy

Also you probably need to use "three": "mrdoob/three.js#dev", in your dependency while waiting for a few fixes that will ship in r172:
#30081

@Samsy

Samsy commented Dec 10, 2024

Copy link
Copy Markdown
Contributor

@RenaudRohlinger Yes, It work this way indeed, I did edit the comment, I opened a feature request for the no-lightingcolor contribution

@Samsy

Samsy commented Dec 10, 2024

Copy link
Copy Markdown
Contributor

@RenaudRohlinger btw, about using "three": "mrdoob/three.js#dev", the builds are not updated

@mrdoob mrdoob modified the milestones: r172, r173 Dec 31, 2024

This branch has not been deployed

No deployments
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

Successfully merging this pull request may close these issues.

Add a way to trigger shadow map updates separately from rendering the scene

6 participants