Skip to main content
Inspiring
October 23, 2012
Question

Why is Context3D::clear() imperative before drawTriangles() ?

  • October 23, 2012
  • 1 reply
  • 1991 views

Hi,

I would like to do an accumulation effect, using Stage3D, by drawing into the backbuffer without clearing it, first ( to do trails, etc. ).  This type of accumulation effect, where the previous, uncleared, backbuffer serves as the destination for the next render call, is frequently seen in music visualizers for instance.

With Molehill, apparently, it is is impossible to call drawTriangles() wihout doing a clear(), first.  You actually get an error ( not a warning ), if you try to do so.  You get this error regardless if you are rendering to the back buffer or to a texture buffer ( via setRenderToTexture() ).

The only way I can think of for doing this accumulation effect is to do a Context3D::drawToBitmapData().  Unfortunately, according to the AS3 doc, we are warned that drawToBitmapData() is slow, and can take up to a second!

Any ideas?

Also to the Molehill team:  do we really need to clear() every time before drawTriangles() ?

This topic has been closed for replies.

1 reply

Inspiring
October 23, 2012

Actually, I just thought of a way that might work ( untested ):

0) setRenderToBackBuffer()

1) clear()

2) render a fullscreen quad with accumulation shader whose image input is previously rendered frame ( is a transparent texture on first frame )

3) render assets to the backbuffer on top of quad

4) present()

5) setRenderToTexture() -- texture target is the same size as backbuffer

6) Repeat 1 through 4, but this time rendering to texture.  This texture gets passed to acculation shader in the next frame.

What would have helped ( missing in API ):

A way to copy the backbuffer to a Texture ( not to a BitmapData <-- apparently drawToBitmapData() is slow).  This would have saved us the extra step of re-rendering everything to the texture buffer in steps 5 and 6.

Participant
February 2, 2013

Any results?

Inspiring
February 5, 2013

The technique works, overall -- though details may differ from the steps I indicated above.

Basically the concept is to ping pong between 2 texture buffers ( switching texture targets every frame ), with the previous frame's target texture buffer going through an "accumulation shader" ( dimming + fading-out texture and what not ), and the current frame's 'data' ( ex: particles ) being drawn on top of the 'accumulated' previous texture buffer.

Still, it's annoying ( and I don't see any reason why ) one should be forced to do a clear(), each time we set a new render target ( via setRenderToTexture() or setRenderToBackbuffer() ) and wish to draw triangles onto it.  There are times when I would like to draw on top of a texture buffer that I used earlier in my render pipeline, without having to clear it ( which causes me to loose what was drawn to it ).

Example:

1) setRenderToTexture ( FrameBuffer1 )

2) clear()

3) drawTriangles()

4) drawTriangles() <-- we can have as many of these as we want, switching shaders and vertex buffers as needed, as long as we don't change the render target

5) setRenderToTexture ( FrameBuffer2 ) // we're now going to FB2 to do some stuff

6) clear()

6) drawTriangles()

7) setRenderToTexture ( FrameBuffer1 ) <-- We're back to using FB1

8) clear() <--- this shouldn't be required, bc I loose what I drew in 3) and 4).

9) drawTriangles()

10 ) setRenderToBackBuffer() // let's close the render loop

11 ) clear()

12 ) drawTriangles()

13) present()