Reusing depth values from FBO

Suppose I have a 2D scene to render (orthographic projection), which I render with depth testing enabled. This scene is composed of lots and lots of small tiles, so I render it in bigger chunks to FBOs, to avoid re-rendering lots of triangles every frame.

Now, when I render contents of those FBOs, I also would like to preserve the depth value of every of its pixels/texels.
How should I go about that?

GL ES 2.0 / WebGL compatible solution would be appreciated.

Firstly, why are you using depth testing for 2D? If your sprites are semi transparent it probably isn’t worth it.

Secondly, have you actually benchmarked and found that you are vertex bound? If there is no bottleneck, or the bottleneck lies elsewhere, you will probably just further degrade performance.

A sprite batcher and texture atlases should be fast enough to render hundreds of thousands of triangles. Introducing FBO binds means less batching and more state switches, ie. generally worse performance. So it’s best to just avoid them if you don’t need them.

[quote]If your sprites are semi transparent it probably isn’t worth it.
[/quote]
They are not semi transparent.

[quote]Introducing FBO binds means less batching and more state switches
[/quote]
When zoomed out, it’s better to have a few prerendered chunks, than half milion of tiles. (yet they need their depth values preserved)
I even packed tile mesh to VBO. New machines don’t have a problem with million tris, but it really is a bottleneck on older ones.

I appreciate your advices, but I already know that stuff :wink: (sprite batching and texture atlases)

but you can’t always fit all your sprites into one atlas. Terrain has it’s separate atlas and I don’t want to switch between objects and terrain atlases, depth buffer solved that so far. (and terrain is not flat, some objects can be behind some parts of terrain)

It’s more of a testing ground, and I have a few ideas on my mind.
I’m going off to sleep now and I hoped that meanwhile someone would share what they know about FBO usage.
How to render FBO’s content preserving it’s depth values is all I’m asking for.

Depth texture is what you want. But not all gles2.0 devices does support those.(ios does)

Well, interesting problem. :slight_smile:

For older devices that don’t support depth textures, another idea is to use a “multi texture” batch like so:
http://webglsamples.googlecode.com/hg/sprites/readme.html

I wrote a version in JavaScript that dramatically reduced my draw calls per frame in a pretty large game (with hundreds of assets that would not fit in a small number of sprite sheets).

I managed to do what I wanted, more or less. I post it here, so maybe someone will find it useful.

Since GLES/WebGL do not support depth textures out of box (extensions exist, but I don’t use them), I did it in fragment shader by storing depth value in alpha channel.

while rendering to FBO

color.a = gl_FragCoord.z;

and while rendering that FBO to the screen

gl_FragDepth = color.a;
color.a = 1.0;

Also, to avoid doing that with completely transparent pixels, in both shaders add

if(color.a == 0) discard;

before doing anything.

That wouldn’t work well with semi transparent tiles, as devades mentioned.

Also

[quote]For older devices that don’t support depth textures, another idea is to use a “multi texture” batch like so:
[/quote]
I also though of that, but as I also mentioned earlier, I want to be able to zoom out ver far, so I have to prerender some chunks of terrain into texture anyway. (one could argue that with such zoom out I shouldn’t also be displaying any objects, so depth stops being relevant, but whatever :stuck_out_tongue: )

gl_FragDepth is really on supported in GLES3, or in GLES2 through an extension:
http://www.khronos.org/registry/gles/extensions/EXT/EXT_frag_depth.txt

Most desktops running WebGL should support this extension, though.

Yeah, you’re right. It’s not part of webgl…

Wonder if there is another way of doing this