[resolved] Share Depth Buffer

Hi.

I’m trying to create a multi-passes pipeline for shaders.

At the moment I create a new camera with base.makeCamera (and base.win.makeTextureBuffer for its buffer) for every object I want to render with a different effect on it. I play with setCameraMask and hide/showTrough to render the nodes only on their camera and not on the others.
Then I create some camera2d for the passes with base.makeCamera2d (and base.win.makeTextureBuffer for their buffer).
Finally the last pass buffer is rendered in a fullscreen card on the main camera.

It works, but it’s not perfect. The main problem is this system doesn’t share depth information between the cameras.

So I give a try to shareDepthBuffer. I create a new camera (new_cam) which have the same size that the buffers and for each camera (current_camera) I call:

buffer_of_the_current_cam.shareDepthBuffer(new_cam.node().getDisplayRegion(0).getWindow())

But this does nothing.

Does anyone have an idea of what is going wrong?

Hmm, I don’t have a lot of experience with shareDepthBuffer(). What is the return value of that call? It’s supposed to return true on success, or false on failure.

What kind of buffer did you end up with? You can query buffer.getType(). I think only certain types of buffer are likely to support shareDepthBuffer() properly.

Another, slightly clumsier, approach would be to render all the effects into the same buffer, clearing them (except for the depth buffer) after each operation, and then copying the data (rather than binding it) into its target texture. This will probably incur some slight performance penalty, though, for the cost of having to copy the data in and out of the buffer several times each frame.

David

Thanks for your response David.

I’ve made a little example with 3 models, and shareDepthBuffer.

There’s the main camera which have a cameramask of 0.

I create a camera for the two smiley.egg.pz which have a cameramask of 1. The two models are hidden for other cameras.

I create a camera for the frowney.egg.pz model which have a cameramask of 2. The model is hidden for other cameras.

Then I share the depth buffer of camera 1 with the camera 2.

Finally I render the camera 1 and camera 2 into cards in the main camera.

from pandac.PandaModules import *
import direct.directbase.DirectStart

base.cam.node().setCameraMask(BitMask32.bit(0))




# camera 1
buffer_1 = base.win.makeTextureBuffer('camera', 1024, 1024)
buffer_1.setClearColor(Vec4(0,0,0,0))
cam = base.makeCamera(buffer_1, lens=base.cam.node().getLens())
cam.reparentTo(base.cam)
cam.node().setCameraMask(BitMask32.bit(1))

card_maker = CardMaker('')
card_maker.setFrameFullscreenQuad()
filter_ = NodePath(card_maker.generate())
filter_.setTexture(buffer_1.getTexture())
filter_.setTransparency(True)
filter_.reparentTo(render2d)


# camera 2
buffer_2 = base.win.makeTextureBuffer('camera', 1024, 1024)
buffer_2.setClearColor(Vec4(0,0,0,0))
cam2 = base.makeCamera(buffer_2, lens=base.cam.node().getLens())
cam2.reparentTo(base.cam)
cam2.node().setCameraMask(BitMask32.bit(2))

card_maker2 = CardMaker('')
card_maker2.setFrameFullscreenQuad()
filter_2 = NodePath(card_maker2.generate())
filter_2.setTexture(buffer_2.getTexture())
filter_2.setTransparency(True)
filter_2.reparentTo(render2d)


# we share the depth buffer
foo = buffer_2.shareDepthBuffer(cam.node().getDisplayRegion(0).getWindow())

# debug
print 'shareDepthBuffer() returns', foo
print 'buffer_1 is a', buffer_1.getType()
print 'buffer_2 is a', buffer_2.getType()
print 'cam.node().getDisplayRegion(0).getWindow() is a', cam.node().getDisplayRegion(0).getWindow().getType()


# models
a = loader.loadModel('smiley.egg.pz')
a.reparentTo(render)
a.setPos(-2.0, 20.0, 2.0)
a.hide(~BitMask32.bit(1))

b = loader.loadModel('frowney.egg.pz')
b.reparentTo(render)
b.setPos(-1.0, 15.0, 1.0)
b.hide(~BitMask32.bit(2))

c = loader.loadModel('smiley.egg.pz')
c.reparentTo(render)
c.setPos(0.0, 10.0, 0.0)
c.hide(~BitMask32.bit(1))


run()

The output of this script is:

As we can see if we run this script, the blue smiley is not displayed between the two yellow smileys although he is between them.

Ah, I see a couple of issues:

(1) First, you are not specifying the relative draw order of buffer_1 and buffer_2. If you don’t specify this, they will be drawn in a random order with respect to each other, which might not be the order you have in mind; and order is important when you are talking about sharing depth buffers. You can ensure that the windows are drawn in the order buffer_1, buffer_2, main window with something like:

buffer_1.setSort(-20)
buffer_2.setSort(-10)

I picked negative numbers because the default sort for the main window is 0.

(2) Second, the default behavior for a buffer is to clear its depth buffer at the start of the frame. So even though buffer_1 and buffer_2 are sharing the depth buffer, both of them are also clearing it before they draw. You need to turn off this clear on the second buffer to be drawn, which is now buffer_2:

buffer_2.setClearDepthActive(False)

Also, but probably not important to your problem, it’s easier to call shareDepthBuffer() like this:

foo = buffer_2.shareDepthBuffer(buffer_1)

David

These are exactly the reasons of my problem. Now it works correctly.

Thanks a lot David.