How To Combine Cameras For Performance (built-in pipeline)

Hello,

I have made a post-processing effect that uses render textures that have objects rendered from specific layers.

Render Texture #1 has all objects in Layer A
Render Texture #2 has all objects in Layers A and B
Render Texture #3 has all objects in Layers A, B, and C
Render Texture #4 has all objects in Layers A, B, C, and D

Right now, I have one camera render all objects in Layer A, then copy that output to Render Texture #1.
Then a second camera renders all objects in Layer B. Its Clear Flag is set to None so it adds Layer B to the already rendered Layer A. Then output is then copied to Render Texture #2.
Then the same thing happens with Layers C and D, resulting in 4 Cameras each rendering one layer.

Unfortunately, all the extra cameras seem to be hurting performance. Is there a way to combine all these renders into one camera and still get the required results?

Or is there a better method of going about this?

(everything is rendered with a custom unlit material if that helps anything)

Thanks in advance

According to your description, you are rendering the objects in layer A four times each, Layer B three times each, etc. Why is this necessary?

Each camera actually renders each layer once. Because the Clear Flags are set to None, it doesn’t clear what has already been rendered and instead adds to it. Then after each Camera, it will copy the output to a render texture so I can use it later.

I need to render the layers like this because I need these render textures for some post processing effects:

This was just the best way I could think to get those textures, but I’d be happy to hear any alternative suggestions.

Ok, so it sounds like you’re actually rendering each layer once.

Have you profiled the scene to find out what your actual performance issue is?

Camera stacking in-and-of-itself shouldn’t have any performance impact, but 4 levels of post processing definitely could.

Also, make sure that each render texture is the lowest resolution you can get away with. Rendering at a higher resolution than your screen output is probably just wasteful.

I don’t have much experience with the profiler so I wasn’t able to get any useful information beyond what I already knew. The scene is very simple, there’s no scripts running or physics or anything so it’s clear the framerate is directly linked to the performance of the rendering and post-processing.

I just did a separate test and layering cameras definitely causes a large performance hit, even if they’re each just rendering one cube. Also, the post processing is all custom through Graphics.Blit and is only done once after everything is rendered.

Also, the render textures are the same size as the screen’s resolution.

You have to understand a basic principle. What you are doing is what we call “camera stacking”, as kdgalla stated. Now normally that wouldnt really cause a big perf hit. Your using the best version of Unity to camera stack with (BuiltIn), cause you aint doing it with URP or HDRP.

So its down to what every/any camera can see (render), including post process/camera effects, included layers, etc. Ive seen cases with imported assets (that have a PPE profile), mess things up. Check your core settings of every camera, and back-trace, youll find it…

One note, you said: " Also, the render textures are the same size as the screen’s resolution.", Umm, thats still not an answer, and could be your prob. If your using 4k/8k textures cause your screen resolution is that, not good. Its not about your (windows) resolution is, its about what Unity renders, and how it looks…

I did a test in a new project with a blank scene and multiple cameras definitely do effect performance. At least in version 2021.3.3f1.



9394442--1314566--cam2.jpg 9394442--1314569--cam1.jpg As you can see, the frame-rate is significantly less in the first screenshot. I tried disabling the directional light and the frames went up to around 320 (with the 11 cameras). One camera without the directional light has around 500 fps.

I have 1920x1080 resolution. When the game launches, I Screen.SetResolution() to the largest 16:9 resolution that will fit inside the monitor (I might add quality settings later). Then the render textures use that resolution of course. Should I not be doing this?

Yeah, but in the second screen shot, you’re probably rendering the same cube over and over again. You should only render the cube with one camera using layer masks. Are you doing that?

Rendering an 8 vertex cube 10 times should not decrease the framerate by that much unless the camera stacking itself is costing performance.

I’m not sure how it is in BiRP lately but in URP multiple camera rendering has a massive performance impact due to a lot of overhead on the CPU. I’m not entirely sure what all it entails these days but for my scenario I’m trying to keep it under a dozen cameras at the worst case and usually only three to four on average. Looking at the profiler I cans ee that Unity is doing a massive amount of work to prepare each camera for rendering. Once I hit the eight to ten range I’m easily dipping below 60 fps at that point. Again this in in URP, I haven’t tried much with BiRP in the last year.

One thing to note is that, if you have shadows on, Unity will re-render the scenes shadows for every camera. This will inevitably add a LOT of overhead. A theoretical way to circumvent this is to use a custom shader and use one camera to render the whole scene to steal the shadow map from it (use a command buffer with a commandBuffer.CopyTexture(BuiltinRenderTextureType.CurrentActive, targetRenderTexture) and add it to the light with light.AddCommandBuffer), disable the lights ability to cast shadows, and then render the rest of the cameras with your new shadow map. But that entirely depends on how feasible it is for you to use custom shaders for this, and also depends on you not wanting accurate shadows for things being rendered behind other things, due to how Unity renders shadows.

Of course you could also just forego all this and turn off shadows entirely.

Ah, that makes sense. Would it be easier to completely disable shadows for a camera? I’m using a bunch of custom shaders for post-processing so I only need one camera to render with shadows.