How can i "bake" a shadow onto a planeGeometry?

I saw this: 3D showcase

I think this is probably close to what ContactShadows do. So it would be limited to a plane, one directional light, and it renders the shadows into a a WebGLRenderTarget multiple times without clearing it, jiggling the light randomly. After a few frames are overlaid its “baked” and mapped as a texture.

But i wonder, how can it “catch” the shadow? And if i come that far, how would i map the texture so that it fits the plane and the objects that sit on it? I guess THREE.ShadowMaterial does something like that, too, but i don’t want it to be runtime, i want it to be static after a few renders.

Could anybody help me figure this out?

1 Like

You’re basically looking for this three.js example, no?

https://threejs.org/examples/?q=shadow#webgl_shadowmap_progressive

Yes and no. The example you linked does a lot more i think, didn’t it potpack into a texture atlas, write into model textures etc. I guess i want something similar to contact-shadows, a single plane, but instead of filming from below and blurring the result i’d like to shine a light, wiggle it for a few frames, and overlay frames to create the illusion of soft shadows (that part is similar to progressive lightmaps again).

Yes but the principle is the same. You can take a look at the progressive light map class to see how it’s working and apply it to what you need. Arguably the progressive lightmap class could be improved to remove the potpack logic (or at least made optional) so it can be used with and without generating the the new UV maps.

Generally it works by just rendering to a render target using UV coordinates instead of UV positions and and averaging new renders over multiple frames. So other than the atlas generation that example is exactly what you want. No matter what, though, in order to get this effect you’re going to need to render into a lightmap texture to use this.

Here’s the important shader adjustment:

2 Likes

thanks @gkjohnson ! this helped a lot. i’ve forked it and almost have something working. i removed the potpack as well. i still need to make it understand that i only want the plane to be affected but that will be manageable.

maybe one last thing i am very curious about, why must it be a lightmap? can’t it work like THREE.ShadowMaterial? or a generic texture like contact-shadows?

can’t it work like THREE.ShadowMaterial? or a generic texture like contact-shadows?

It doesn’t necessarily have to be. You could likely pass the resulting texture into to diffuse map of mesh basic material or something with alpha enabled if you want it to behave like that. Otherwise something like a custom shader would do. If you want to use this with the built materials, though, you should use a lightmap.

i still need to make it understand that i only want the plane to be affected but that will be manageable.

It looks like the class is designed to be a bit all-encompassing - ie handle uv packing, rendering the shadows, and assigning the textures (which you probably don’t want). I’d think it would be best to refactor the class to be more flexible so you can specify which geometry UV coordinates to render in to and which geometry should be casting shadows.

3 Likes

i made it a diffusemap and i try to stamp out unaffected parts so now it behaves like THREE.ShadowMaterial. but it all still feels awfully hacky: baking soft shadows - CodeSandbox

my main concerns are that i have to switch all scene lights off or else they affect the uvmaterial. and the transparency, i wonder how i can stamp the shadows out, currently i am using the red channel and multiply it by a fixed cutoff value …

gl_FragColor = vec4(gl_FragColor.rgb, 1.0 - gl_FragColor.r * cutoff)

that probably is a bit weird, too. it looks good though …

2 Likes