Can i change viewport of camera without creating fbo?

Hello folks. I 'd found this code on CCCamera.cpp

void Camera::applyViewport()
{
    glGetIntegerv(GL_VIEWPORT, _oldViewport);

    if(nullptr == _fbo)
    {
        glViewport(getDefaultViewport()._left, getDefaultViewport()._bottom, getDefaultViewport()._width, getDefaultViewport()._height);
    }
    else
    {
        glViewport(_viewport._left * _fbo->getWidth(), _viewport._bottom * _fbo->getHeight(),
                   _viewport._width * _fbo->getWidth(), _viewport._height * _fbo->getHeight());
    }
}

And because that frame buffer is always nullptr it never uses the viewport i 'd set.

I only want to create 2 cameras to follow 2 players and set viewports like dividing the screen.

Do i really need that fbo? how do i create it?

Any help will be appreciated.

thanks!

I found a way to do it, something like, i created 2 layers and added a camera to each layer, but then when i move one camera of one layer the entire scene moves the default camera, moving all layers cameras.

Is that the design of the engine? most probably is i’m doing something wrong. Can anyone explain cameras please? i cant find how! :thinking:

Each scene has a default camera. I don’t use this camera. I create additional cameras to use as needed.

Have you reviewed the code in cpp-tests?

We have some docs here: https://docs.cocos2d-x.org/cocos2d-x/v3/en/3d/camera.html

Thank you for the answer.

Yes i know the cpp tests. and i read them all the time for everything.

I ll give you the update:

Right now i found the frame buffer object test and i did it on my project.

everything works fine except when i apply a custom view port to the camera.

then i have a black screen.

auto sizeInpixels = Director::getInstance()->getWinSizeInPixels();
auto size = Director::getInstance()->getWinSize();
auto fboSize = Size(sizeInpixels.width, sizeInpixels.height);
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);
auto sprite = Sprite::createWithTexture(fbo->getRenderTarget()->getTexture());
sprite->setFlippedY(true);
sprite->setPosition(size.width / 2, size.height / 2);
scene->addChild(sprite);

m_camera = Camera::create();
m_camera->setDepth(-1);
m_camera->setFrameBufferObject(fbo);
m_camera->setCameraFlag(CameraFlag::USER2);

m_layer->addChild(m_camera);
m_layer->setCameraMask(static_cast<int>(CameraFlag::USER2));
// if uncomment this i get a black screen with nothing, 
//but in the stats there are the same gl calls and gl verts that are in the game. So the game is working is something with that viewPort`
//experimental::Viewport vp = experimental::Viewport(0.0f, 0.0f, size.width, size.height / 2);
//m_camera->setViewport(vp);

I found out how to divide the screen. But it cost a significant amount of performance.

if anyone has a better solution and want to share will be apreciated.

I ll share mine so anyone can use it or test it:

//first i create the fbo size dividing the screen sizeInpixels.y/ 2);
auto sizeInpixels = Director::getInstance()->getWinSizeInPixels();
auto size = Director::getInstance()->getWinSize();
auto fboSize = Size(sizeInpixels.x, sizeInpixels.y/ 2);
auto fbo = experimental::FrameBuffer::create(1, fboSize.width, fboSize.height);

//then create the fbo size with his target
auto rt = experimental::RenderTarget::create(fboSize.width, fboSize.height);
auto rtDS = experimental::RenderTargetDepthStencil::create(fboSize.width, fboSize.height);
fbo->attachRenderTarget(rt);
fbo->attachDepthStencilTarget(rtDS);


m_camera = Camera::create();
//this texture has the size of the fbo size so i set the position on down part of the screen
auto sprite = Sprite::createWithTexture(fbo->getRenderTarget()->getTexture());
sprite->setFlippedY(true);
sprite->setPosition(0.0f, 0.0f);
sprite->setAnchorPoint(Vec2(0.0f, 0.0f));
//and then i set to the sprite a camera that will not move
sprite->setCameraMask(static_cast<int>(CameraFlag::USER1));
scene->addChild(sprite, 3);

m_camera->setDepth(-1);
m_camera->setFrameBufferObject(fbo);
m_camera->setCameraFlag(CameraFlag::USER2);

m_layer3D->addChild(m_camera);
m_layer3D->setCameraMask(static_cast<int>(CameraFlag::USER2));

//so i dont need to use a viewport
//experimental::Viewport vp = experimental::Viewport(0.0f, 0.0f, size.width, size.height / 2);
//m_camera->setViewport(vp);

m_camera->setPosition3D(Vec3(0.f, 0.f, 0.0f));
m_camera->lookAt(Vec3::ZERO);
m_camera->setRotation3D(Vec3::ZERO);

m_scene->addChild(m_layer3D 0);

i ll add some screenshot later

then i do the same with the other half of the screen

I created a repository on github with the demo:

2 Likes