RenderTargetTexture - problems rendering a scene to a texture

I am trying to create a spritesheet in my system. I had this working previously in Three.js and now I am trying to get it going again in babylon and I am having many difficulties.

So user uploads a bunch of images, they get created as materials and put on a set of planes. (working)
A RenderTargetTexture is created and those planes are added to it and render is called.
A new material is created using that texture.
A new plane is created showing that texture on screen. This comes out a mess. Not sure where to start asking about this.

I want to create a new scene and have the rendertargettexture render that scene, but it looks like I have to render the planes to screen (the main visible scene) or it wonā€™t work. I really want offscreen rendering like I used to have - does babylon support this?

Iā€™m really very lost at this point after days of working on this. Does anyone have a simple example of rendering a texture to a multiple planes, onto a rendertexture and then rendering that plane to screen?

You can do something like that:

https://playground.babylonjs.com/#M7KDM6

The objects you put in the RTT.renderList array are rendered in the RTT whatever their layerMask / the camera layerMask is.

So, you can set a layer mask on the camera so that these objects are only rendered into the RTT and not to the screen. For the object(s) you want to be rendered to the screen (like the plane in the PG), you must set a layer mask compatible with the camera layer mask.

1 Like

Thanks, thats helpful. I ended up solving the problem by waiting for the render loop to complete and then making the other planes invisible, but it seemed like a really hacky workaround. But so does your method - now I have to set all visible objects to some strange layerMask value. (I deal with a lot of objects all over my app, so this is actually a big change to a lot of code to support one small part).

I tried setting the layerMask on just the RTT objects, but no that doesnā€™t work either.

I donā€™t understand why this wouldnā€™t be simple - create a different scene and add all the objects you want to render to the RTT. Why does it have to be the main scene?

You can use two scenes:

https://playground.babylonjs.com/#AQRQSE

But the objects must be created in the scene you want to be rendered in the RTT. If you create the objects in the main scene, they will also be rendered in the main scene. In a given scene, if you want some objects to be rendered in the RTT and not in the default output, I think thereā€™s no other way than using the layerMask property.

3 Likes

Yes thanks - I actually think this is how three.js did it, now I understand things better.

Thanks for the help.

With this method, the scene draw calls will be doubled, and itā€™s very inefficient for large scenes. Is there any ways to avoid the draw calls doubling?

You can remove the meshes from scene.meshes. In the double scene PG, you can do scene.meshes = []:

You can also set scene.autoClear = false as you donā€™t generate anything in the default framebuffer from this scene.

2 Likes

This works really well. Thanks a lot.
But I meet a new problem.
The particles and the post processing in the first scene cannot be synchronized to the RTT.
Is there any ways to solve the problems?

Particle systems are not rendered to RTT by default. To render particle systems in a RTT, set rtt.renderParticles = true.

Regarding post processes, you can either set rtt.useCameraPostProcesses = true to apply the post processes attached to the camera used to render the RTT, or rtt.addPostProcess() to directly add post processes to the RTT.

2 Likes

Thank you very much for your help.
Iā€™ve solved the post processes rending in a RTT, and the effect is excellent;
Although I 've setted rtt.renderParticles = true ļ¼Œparticle systems are still not rendered to RTT.
Looking forward to your reply.

I think we have some weird behavior for the rendering of particle systems in RTT for a long time, letā€™s see if this PR will go in:

If itā€™s merged, it will fix your problems. Note that you donā€™t need to set renderParticles = true because itā€™s the default value - I was wrong above, by default particle systems are (should be) rendered.

If the fix is merged, you will notice that your GPU particle system runs way too fast. Thatā€™s because, for historical reasons, the update of particles is done in the render function, and because this function is called 5 times per frame in your PG (main path + 4 RTTs), it runs 5 times faster.

You can set ps2.updateInAnimate = true; to have the update function called from the animate function instead of render. That way, it will be called a single time (because animate is called once per frame). However, thereā€™s a bug in this case, that this PR will fix:

With both fixes, this PG will work as expected:

2 Likes

Thank you very much for your help .
With your help I have achieved everything I wanted to achieve. :smiling_face_with_three_hearts: