Camera with FBO does not clear DepthBuffer

Hello
I’m trying to implement a kind of CCTV window, showing 3d scene.

For the test, added code bellow in
\cocos2d-x-3.17.2\tests\cpp-tests\Classes\Camera3DTest
Camera3DTest.cpp Camera3DTestDemo::onEnter() - line 351

    if (_camera == nullptr)
    {
        _camera=Camera::createPerspective(60, (GLfloat)s.width/s.height, 1, 1000);
        _camera->setCameraFlag(CameraFlag::USER1);
        _layer3D->addChild(_camera);
        // added code-----------------------------------------------------------------------------
        Size fboSize = Size(512,384);
        auto fbo = experimental::FrameBuffer::create(1, fboSize.width, fboSize.height);
        auto rt = experimental::RenderTarget::create(fboSize.width, fboSize.height);
        auto rtDS = experimental::RenderTargetDepthStencil::create(fboSize.width, fboSize.height);
        fbo->attachRenderTarget(rt);  
        fbo->attachDepthStencilTarget(rtDS); // commenting this line will render 3d scene without depth test 
        fbo->setClearColor(Color4F(0.25,0.25,0.25,1));
        _camera->setFrameBufferObject(fbo);

        auto sprite_scr = Sprite::createWithTexture(fbo->getRenderTarget()->getTexture());
        sprite_scr->setFlippedY(true);
        sprite_scr->setPosition(Vec2(s.width/2, s.height/2));
        addChild(sprite_scr,-2);
        // ----------------------------------------------------------------------------------------
    }

It just renders grey window with this code.
case_with_depthbuffer

but, without depthbuffer by commenting this line
fbo->attachDepthStencilTarget(rtDS);

renders 3d scene without depth test.
case_without_depthbuffer

It seems like depth buffer is not working.
or Am I missing some setup code?

Any Help would be appreciated.

I doubt your machine supports GL_EXT_packed_depth_stencil or GL_OES_packed_depth_stencil.

RenderTargetDepthStencil depends upon above extensions but cocos2dx does not gracefully handle this if platform does have these extension support.

1 Like

Hi @mudio93,

Do share the part of your code that you actually call the function to clear depth in each new frame.
Eg, if i’m using RenderTexture i’d call this function. I’m using v4 so haven’t really looked into the equivalent of that in Framebuffer (doesn’t exist in v4).

1 Like

I simply added code in cocos2d-x-3.17.2 / cpp-tests project.
Actual code is from Camera3DTest.cpp / CameraFrameBufferTest
debugging info shows clear depth at FrameBuffer::clearFBO() every frame,
but it seems not clearing properly.

I’ve just taken a look at this and compared it with your code
Seems like there is something here that i don’t find in your code.
camera->setDepth(-1);

Can this be what is causing the issue?

If you run the CameraFrameBufferTest does it behave correctly?

1 Like

I’ve reviewed this, this function is for camera order, like node zorder.
not related to depthbuffer.

Yes, it works fine. Only difference is CameraFrameBufferTest is rendering 2d sprite.

How about if you uncomment the codes for testing 3d sprite and comment the 2d sprite instead, then does it work?

1 Like

Uncommented code bellow

    {
        std::string filename = "Sprite3DTest/girl.c3b";
        auto sprite = Sprite3D::create(filename);
        sprite->setScale(1.0);
        auto animation = Animation3D::create(filename);
        if (animation)
        {
            auto animate = Animate3D::create(animation);
        
            sprite->runAction(RepeatForever::create(animate));
        }
        sprite->setPosition(Vec2(100,100));
        addChild(sprite);
    }

It renders Sprite3D normaly in 2d position with default camera.
case1_default_camera

and changed Sprite3D camera mask to camera with fbo

    {
        std::string filename = "Sprite3DTest/girl.c3b";
        auto sprite = Sprite3D::create(filename);
        sprite->setScale(1.0);
        auto animation = Animation3D::create(filename);
        if (animation)
        {
            auto animate = Animate3D::create(animation);
        
            sprite->runAction(RepeatForever::create(animate));
        }
        // sprite->setPosition(Vec2(100,100));          // [ case1 ] 2d position
        sprite->setPosition3D(Vec3(0,0,0));             // [ case2 ] 3d position
        addChild(sprite);                                  
        sprite->setCameraMask((unsigned short)CameraFlag::USER1); // to camera with fbo 
    }

It does not render Sprite3D, both [ case1 ], [ case2 ]
case2_camera_fbo

additionally, removed depthbuffer from CameraFrameBufferTest

    auto rt = experimental::RenderTarget::create(fboSize.width, fboSize.height);
    auto rtDS = experimental::RenderTargetDepthStencil::create(fboSize.width, fboSize.height);
    fbo->attachRenderTarget(rt);
    // fbo->attachDepthStencilTarget(rtDS); // [case3] without depthbuffer
    auto sprite = Sprite::createWithTexture(fbo->getRenderTarget()->getTexture());
    sprite->setScale(0.3f);
    sprite->runAction(RepeatForever::create(RotateBy::create(1, 90)));
    sprite->setPosition(size.width/2, size.height/2);
    addChild(sprite);

without depthbuffer, it renders Sprite3D without depth test.
case3_no_depth

I’ve changed GL_DEPTH24_STENCIL8 related code like bellow

RenderTargetDepthStencil::init

 // GL_DEPTH24_STENCIL8 to GL_DEPTH_COMPONENT16
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);

FrameBuffer::applyFBO()

 // commented stencil setup
 //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, nullptr == _rtDepthStencil ? 0 : _rtDepthStencil->getBuffer());

FrameBuffer::clearFBO()

    // commented clear stencil
    // glClearStencil(_clearStencil);
    // glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

But the result has the same issue.

Hi, i’ve just tried the Sprite3D on Cpp-Test and there is no issue, it is rendering fine on Windows 32 build.
What platform are you running it on?

EDIT:
these are the output values i have when the app starts

gl.version: 4.6.0 - Build 26.20.100.7323
gl.supports_NPOT : true
gl.max_texture_size : 16384
gl.supports_OES_packed_depth_stencil : false
gl.supports_ETC1 : false
gl.supports_S3TC : true
gl.supports_PVRTC : false
gl.supports_BGRA8888 : false
gl.supports_discard_framebuffer : false
gl.supports_OES_depth24 : false
1 Like

Ok. So I figured it out issue is with FBO depth mask state.
For more inromation refer to patch: https://github.com/shivmsit/cocos2d-x/commit/40b81a26743f4c3a9341a5dceb5dfe4bb16bf393
So, you can apply aforementioned patch for v3 branch and your sample code should work.

@slackmoehrle I made a pull request https://github.com/cocos2d/cocos2d-x/pull/20573 too for same.

1 Like

Cool. Thanks. I’ll ask the team to review.

1 Like

This solved the issue.
I tested Windows10 64bit and Android device,
Sprite3D renders correctly.
I appreciate you all.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.