Camera Clear Flags "Don't Clear" and "Depth Only" don't work as expected on WebGL

I have a project with a Camera’s Clear Flags set to “Depth Only”.
In the editor, this works as expected, with each frame drawing upon the last.
When I export for WebGL, it clears to black each frame.

Is it possible to keep WebGL from clearing each frame? I’ve tried several shader approaches as well, writing the frame to a RenderTexture and accessing that on the next frame. That also works in the editor but gives a blank (black) output in a WebGL build.

It’s a bug and here is the public tracker for it:
https://issuetracker.unity3d.com/issues/clear-flags-doesnt-work-properly-on-webgl

I expect the fix to be in 5.6 and in a 5.5 patch in the coming weeks.

Thanks for reporting the issue.

oh It didn’t fix in 5.6. I got it in 5.6

3104751--234529--upload_2017-6-12_19-54-12.png

This is result when i try to set depth only for cube camera.

Disable the AA on your depth camera to solve the problem until we got a patch.

I should have provided an update on this issue. TLTR: We had to revert the fix before 5.6 release because of performance concerns, in fact if you look at the bug tracker, it will say that the bug will not be fixed. However, it’s possible to workaround it.

By default, the browser always clears the main render buffer. This is because it is more efficient to do so, than to preserve the image from the current frame to the next. This default behavior can be modified on webgl context creation via preserveDrawingBuffer attribute.

At the moment, there is no way to change this attribute via scripting/ui, however, you can workaround it:

  • open PlaybackEngines/WebGLSupport/BuildTools/Emscripten/src/library_html5.js from Unity installation folder
  • search for preserveDrawingBuffer assignment in emscripten_webgl_init_context_attributes
  • change it’s value from 0 to 1
    as follows:
{{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.preserveDrawingBuffer, 1, 'i32') }}};

A cleaner solution is to use an additional camera (which will not clear) to render your scene to a render texture, then blit the image to the main camera.

Thanks you roka. Your suggest work fine.

Thanks Marco-Trivellator : I not yet tried your suggest. Anyway, thanks you for your help.

On the version 5.6.1P4, my solution “Disable the AA on your depth camera to solve the problem until we got a patch.” do not work anymore, if we enable the AA on the quality setting and if we have 2 camera , the Orthographic camera do not render in all clear flag.

Are there any news on this problem? Will this be fixed in one of the 2017 Versions?

Will this be fixed in one of the 2019 versions?

@Marco-Trivellato I don’t know if I’m doing this correctly, but the only way I can get a Mac OSX build to render as in the Editor is to create 2 cameras and a render texture. This seems like a complicated way to do what should be easier and fast. The Render texture is slow when I increase the resolution.

Am I missing something? Is there a way to just have one camera in the scene and not have to use a rendertexture when the desired look is to have the camera clear flags set to depth only?

bump, this isn’t working in 2019.4 also as far as I can tell, tried both editting index.html and .js in webgl to preserve buffers, requiring the usage of rendertextures and more memory. Is there still no fix to this for WebGL?

It isn’t working in 2020 version. I’ve tried disabling AA but it doesn’t fix it. I tried a RenderTexture too, but now the problem appears even in PC version, not only WebGL.

We are not currently tracking an active WebGL specific bug regarding camera color clearing. Does the workaround mentioned in the bug link above not work? If it does not, please raise a bug report with a test case.

It’s this bug apparently.

In that bug it was suggested that the preserveDrawingBuffer parameter should be used to keep color from clearing. That should still be the case. That is why I am asking whether the workaround posted in the bug link works or not?

2020 1.2f.1 Still now…

I have finished solved this error.

Use “Raw Image” and “Render Texture”

version : 2020.2.1f1

Routing via a render texture is certainly one option.

I am surprised about there being a relatively large number of people reporting this issue. To understand the problem better, can someone illustrate what kind of rendering feature/use case you are doing that requires not clearing the color buffer across frames?

There are three major difficulties with implementing support for this to WebGL: tile-based renderer performance, browser compositing performance, and web capabilities.

First, on the web, WebGL API has a built-in behavior that the canvas color target is cleared to black between rendered frames. This is a built-in feature that can be worked around/disabled via that preserveDrawingBuffer: true flag. However that flag is applied at game/page startup time, and not something that can be toggled at runtime. So if that flag is enabled, then all cameras in the application will never clear the color, independent to what the Unity Camera setting is set to. This means that we are unable to map the Camera Clear option to preserveDrawingBuffer: false/true at runtime.

Then, there is the issue with browser compositing performance. Browser compositors have been designed with the preserveDrawingBuffer: false option in mind. There is a browser rendering performance loss (apparently small, but still there) with enabling preserveDrawingBuffer: true in a browser. According to Google, the option should be used primarily for debugging, and main reason that preserveDrawingBuffer: true exists in the first place is to let ease the development of WebGL unit test suites.

Then, there is another issue with tile based GPUs (primarily mobile devices). Tile-based GPUs have very fast dedicated but small “tile memory” on the GPU die, and then larger and slower DRAM memory that is generally shared with the main CPU. The way that these GPUs work is that they hold framebuffers on the fast tile memory on the GPU. When a frame starts, if it can be started with a clear/black framebuffer state, the GPU can issue a very fast “load this render target with clear color=(0,0,0,0)” to start rendering. If the previous frame should be preserved, then it GPU should issue a “load this image from the slow DRAM” operation instead. This loses performance (not much, but still a loss)

To implement support for disabling Camera Clear Color on web builds, we could always build with preserveDrawingBuffer: true and take a performance impact, or we could implement a manual indirection via a render to texture based option, which would be even slower. That brings me back to the original question: how many users need this, and for what purpose?

To my understanding the most general use case for omitting camera color clear at frame start would be to optimize GPU memory copies on non-tile-based GPUs. I.e. to optimize performance. If that is the desired use case, then the existing behavior in Unity is already optimal, hence the reason that the issue was WontFixed. Are there some other use cases that I am missing?

Note that all of the above explanation specifically only applies to the back buffer of the web Canvas element. If we are dealing with offscreen render targets, those should allow color clearing options as usual, because they are not tied to the browser’s canvas element compositor in any way.

1 Like

Thanks a lot for all those details ! It makes the problem much easier to understand.

We use that feature to render one frame and display it continuously to the user. Pretty much like a camera snapshot. To implement that, we simply redirect using a render texture and it works great for us.

1 Like