mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.55k stars 35.29k forks source link

Take dot product of face normal and light direction into account when calculating shadows. #2454

Closed mrdoob closed 8 years ago

mrdoob commented 11 years ago

Details here: http://stackoverflow.com/questions/12600256/three-js-shadow-on-opposite-side-of-light

@alteredq Were you considering implementing this or would it slow down the computation a lot?

WestLangley commented 11 years ago

material.side plays a role in this, too. It's a little messy.

alteredq commented 11 years ago

I'm aware of the issue, didn't think yet about some fix.

This problem comes from a different shadowmap fix, where we use front face culling to avoid self-shadowing artefacts.

If you turn it off then these artefacts should go away (or more precisely, shadowing should be more uniform across all faces, including ones facing away from the light, which should be completely in the shadow):

renderer.shadowMapCullFrontFaces = false;

Just then you will get different artefacts:

http://jsfiddle.net/c8zbT/4/

That's the thing with shadowmaps - it's always playing a whack-a-mole with one or other artefact, all game developers hate it and there is no perfect solution.

Also, implementing fix using light direction and face normal will not be easy - shadows as implemented now are independent of lights.

The reason is that there isn't one-to-one correspondence between lights and shadows - lights can be without casting shadows and single light can cast multiple shadows (because of cascading shadows), so in shaders you don't know which shadow corresponds to which light.

I was already hitting this with shadows for SpotLights where there is a similar problem of combining darkening from shadows with darkening from SpotLight fall-off.

ghost commented 11 years ago

I'm young in WebGL and the calculation of shadows is a subject that I still have to study and learn to handle.

Perhaps I didn't fully understand what you mean, but I seem to see fewer errors and a better effect by turning off the "shadowMapSoft" and allowing the front faces culling technique:

    renderer.shadowMapSoft = false;
    renderer.shadowMapCullFrontFaces = true;

http://jsfiddle.net/gc4af/2/

Although the shadow of the small cube is still not casted exactly ( zoom in to see..)

rastafermo commented 11 years ago

hi guys, i'm pretty new on webgl and threejs and i just find out that my shadows have the same problem you are discussing here. my renderer is something like this:

renderer.shadowMapEnabled = true; renderer.shadowMapSoft = true; renderer.shadowMapCullFrontFaces = false;

and i'va also tried to set it just like roriz87 (soft = false, cullfrontface true), but nothing. I wonder if someone got newer solutions. Thank you very much schermata 2013-07-24 alle 11 47 21

jox81 commented 10 years ago

Same issue, don't know how to stop that...

chopper commented 9 years ago

I have the same issue - any updates or workarounds for this?

chopper commented 9 years ago

Actually - the following just fixed my issue (r71):

renderer.shadowMapCullFace = THREE.CullFaceBack;

benoitgrelard commented 9 years ago

Hi there,

I am having the same issue in the game I am working on. It seems like shadows are not so reliable. What is the recommendation? Not use them at all? Fake them with some geometry? Has anybody managed to fix it?

@chopper I have just tried what you mentioned before and it doesn't cut it for me (r71 too)

erichlof commented 9 years ago

Hi @artisologic , If you can live with simple (but correct) planar-shadows - shadows that reside in a single plane like the ground, or a wall, then your game might benefit from the ShadowMesh object I added to Three.js a while back. Here is the GitHub homepage for it, along with several demos, and detailed instructions on how to stick the ShadowMeshes into your project: https://github.com/erichlof/ShadowMesh-Demo

I am already using them with good effect (and fast performance) in my current game based on the 1982 movie Tron lightcycle sequence. Since they are sharp shadows, they give the look of the ray-traced original graphics from the early 1980's. Here's the game's homepage: https://github.com/erichlof/3dLightCycles

Good luck with your game! :)

benoitgrelard commented 9 years ago

Hi @erichlof,

Sounds like I could probably live with that. So your library essentially creates fake shadows out of projected flat geometry?

I guess I was more wondering how people deal with shadows in Three.js at all cause it seems like prety much a deal breaker, everybody must be hitting that problem right?

Just to confirm the issue, you can see here how the spheres seem to project a shadow through the cubes: http://www.artisologic.com/battle-royale/

That's the same issue right?

Thanks!

MasterJames commented 9 years ago

I looked at the link and it seems fine in Chrome "Version 42.0.2311.135 m" on windows 8. I see a shadow on the cubes, and then they turn upside down but no circular shadow is on the opposite side of those cubes if I'm understanding your problem correctly I'm not seeing anything wrong.

benoitgrelard commented 9 years ago

Hi,

You wouldn't see the shadow artefact once they have turned around because the spotlight is shining from the top of the scene. But if you look closely when the spheres are back on top, you can see the shadows projected on cube's top face (correct shadows) but also the artefacts bleeding shadows on the sides of said cubes too (incorrect shadows).

MasterJames commented 9 years ago

Right I see that now. This seems major, maybe there's a glitch in the scene that can straighten this out. Alternative thoughts. What if the spheres are smaller, or the light angle is different (changes with camera)? Maybe assigning a different shader or flipping the cube geometry. Also I'm wondering about a texture mapping on the cubes, and if that could make a difference. Are the normals all okay?

The game is good, nice job. Took me a bit to figure out it was battleship. I thought a slightly faster transition between the ability to click picks might be a good suggestion.

benoitgrelard commented 9 years ago

Thanks @MasterJames,

I'm fairly new with all this so not sure I completely understand all your suggestions. I will try to setup a simpler example to look at rather than the whole scene.

benoitgrelard commented 9 years ago

There @MasterJames, I have created a distilled simpler example of my scene but maintaining all the exact parameters. You can clearly see the problem here (you can rotate around using your mouse).

http://jsbin.com/futate/1/edit?js,output

I don't feel like I am doing anything out of the ordinary: it's basic primitives, basic materials, basic lighting. Not sure what is going wrong...

MasterJames commented 9 years ago

What happens if you put a cube inside the cube just a little smaller? Double sided? Inside out?

WestLangley commented 9 years ago

As stated in the guidelines, help requests should be directed to stackoverflow. This board is for bugs and feature requests.

Please, let's not hijack this thread.

benoitgrelard commented 9 years ago

Hi @WestLangley,

Sorry about that but is this not a bug then?

WestLangley commented 9 years ago

Sorry, @artisologic, I did not mean to come down so hard on you. Let's keep the discussion in this thread to changes we can make to three.js.

As a work-around, you can shorten the shadow camera far distance. I know that is not a perfect solution for your specific app.

mrdoob commented 8 years ago

shadowDarkness was the one to blame here...