2

I have a simple scene with room, several light sources and player. Player mesh should always be rendered on top of room meshes. Following the accepted answer from this question I should create two different scenes: one for room and one for player. Indeed in this case everything works fine except one thing - player mesh will no longer be affected by light sources from room scene. Of course I can duplicate light sources on the player scene but it seems to me like a poor decision (there will be troubles with shadows I suppose).

Is there any simple solution to this issue?

Community
  • 1
  • 1
briarheart
  • 1,906
  • 2
  • 19
  • 33
  • 1
    The solution to your problem may not be the answer to your question. Try this with one scene: `player.renderOrder = 999; player.onBeforeRender = function( renderer ) { renderer.clearDepth(); };` – WestLangley May 17 '17 at 14:30
  • @WestLangley It gave me the same effect that when setting of `depthTest` to `false` on each mesh material. I like this idea but as I mentioned in one of the comments below my player mesh is a `SkinnedMesh` with different materials and I do not know how to set `renderOrder` for different parts of this mesh. – briarheart May 17 '17 at 15:07
  • It can't be the same. Setting `depthTest` to `false` on a mesh will cause all sorts of artifacts because the mesh won't depth-test against itself. – WestLangley May 17 '17 at 15:21
  • @WestLangley It turns out that I cannot just call `clearDepth` every time the listener is called. Fifth argument of `onBeforeRender` function is one of the mesh materials. I started calling `clearDepth` only when the given material is the topmost material of the mesh. It gave me the desired behavior. Now I have a little concern: does this approach have any significant impact on perfromance comparing to calling `clearDepth` between render passes? – briarheart May 17 '17 at 17:35
  • 1
    I expect not, and I expect you are not seeing any. – WestLangley May 17 '17 at 18:50

2 Answers2

1

Not directly, you will have to duplicate the lighting. And shadows might indeed give artifacts (but with 3D objects magically floating in front of the rest of the scene, one might wonder how to define the expected behaviour of shadows :-).

If you want to force one object on top, but still be part of the same scene, you should probably look into modifying renderOrder and disabling z-testing for that object. See using renderOrder in three.js , for instance.

Community
  • 1
  • 1
Paul-Jan
  • 16,746
  • 1
  • 63
  • 95
  • Thank you for the answer! Actually my player mesh is a `SkinnedMesh` with different materials. When I set `depthTest` to `false` on one or all player materials it causes artifacts. I tried to set different values of `renderOrder` for every bone of mesh but nothing changed. Is it possible at all? – briarheart May 17 '17 at 12:38
1

what about using the layer property of Object3d in combination with a Layers object? I haven't tried working with it too much but from the documentation, the layers property says that you could have an object be a member of multiple layers.

So you could have the lights be members of layer 0 and 1, have most objects only layer 0, and the player only layer 1. This way you should be able to do basically the same technique as with two scenes, only you have 1 scene, and 2 layers, where the lights are members of both 0 and 1, and the rest belongs only to 1 category.

Then you render scene with layer 0 selected, switch to 1, render again. I havent worked with this property much, but I think it could work for your needs - this way you define everything once and just toggle between layers. For shadows on the level from player, you could probably create an invisible version of the player that just casts shadows without being rendered and put that on the same layer as the level.

OtterFamily
  • 803
  • 4
  • 10
  • Thanks for suggestion! Layers are interesting thing but they do not solve the main issue - player mesh should always be on top of other meshes (maybe title of this question is a bit confusing). That's why I came to using of two different scenes. Between render passes I call `clearDepth` so every mesh from the second scene will be rendered on top of all meshes from the first scene. Layers do not allow to achive such effect. – briarheart May 17 '17 at 13:59
  • It seems that I rejected the idea of layers too early. There was a mistake in my code. Now everything works as expected. But issue with shadows is still relevant (lights being rendered in the second pass do not take into account walls of the room and illuminate player mesh). – briarheart May 17 '17 at 14:54
  • try adding duplicates of the things that need to cast shadows that reference the same geometry, but have a material that only casts shadows but is not visible. Also mark as answered if this solves the core question (the lighting issue), start a new thread for optimization questions. – OtterFamily May 18 '17 at 12:31
  • Actually for now I'm going to stick the approach suggested by @WestLangley (see the comments to the question). On the other hand using two render passes (either with layers or two scenes) along with invisible objects can do the trick. So I will accept your answer. – briarheart May 18 '17 at 15:35