Hello dear community,
On the PC if you have a display with 1920x1080, you can set your game resolution to 1280x720 or even lower. People do this if their computers are relatively slow to increase the frame rate. I want to implement the same thing in a cocos game. Could you advice me something please?
Motivation: Recently I discovered that some games I’m developing run e.g. perfectly fast on 4 years old Samsung Note 2 (720p) but lag on the new Samsung S6 (1440p). The only reason I can think of is that the new device renders 4 times more points, but it is not 4 times faster. Maybe this is only a recent Samsung’s problem.
Maybe someone knows a simpler solution, or one that’s has better results, or whatever.
One initial though is just lowering the design resolution and using the same source art assets. If that doesn’t improve anything then you’ll have to work on reducing the load somewhere else.
You can change the design resolution, but I don’t believe that necessarily reduces the number of pixels being rendered with the potentially complex shaders and likely duplicated as one sprite overdraws another sprite. One method for improving performance in this area is by creating an off-screen frame buffer that you render the game into at a 1/2 (anti-aliased art) or 1/4 or 1/8 (pixel art) resolution size. Then render this frame buffer into the final visible frame buffer as a single quad blit with the simplest shader possible.
The naive approach might be something like creating Camera::User1 and set it up to render to a RenderTexture (RT) with a given width/height of 1/2 or 1/4 the device resolution size. Then create a sprite with RT’s texture and attach it to the Camera::Default which is setup to render full screen (shouldn’t need any actual setup as this is default). Also make sure to set its texture rect and content size to fill the entire screen.
One major unknown is the touch/mouse input handling system. I don’t know how easy it is to do this and retain the fidelity of touches triggering events with the same accuracy.
We should get a formal implementation and documentation of this at least as an entry in the programmer guide. Or maybe rather a tutorial. It’d go good with discussion of other aspects of multi-resolution handling.
Definitely something everyone should be aware of for the next year or two because even if GPU performance is still benefitting from moore’s law I think you are correct that it’s not a 4x improvement for a 4x rendering load.
???
Hi, how to do this? Sorry, but I am not very familiar with OpenGL but I would really need this kind of information. Thank you.
This coding would be also very interesting.
My current code looks like this in init of scene:
// create FrameBuffer
auto lFrameBufferSize = Size(320, 240);
auto lFrameBuffer = experimental::FrameBuffer::create(1, lFrameBufferSize.width, lFrameBufferSize.height);
lFrameBuffer->setClearColor(Color4F(0, 0, 0, 255));
auto lRenderTarget = experimental::RenderTarget::create(lFrameBufferSize.width, lFrameBufferSize.height, Texture2D::PixelFormat::RGB5A1);
lFrameBuffer->attachRenderTarget(lRenderTarget);
lFrameBuffer->getRenderTarget()->getTexture()->setAliasTexParameters();
mFrameBuffer = lFrameBuffer;
// create texture from FrameBuffer
mFrameBufferSprite = Sprite::createWithTexture(lFrameBuffer->getRenderTarget()->getTexture());
mFrameBufferSprite->getTexture()->setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGB5A1);
mFrameBufferSprite->getTexture()->setAliasTexParameters();
mFrameBufferSprite->setPosition(iGameLayerSize.width / 2, iGameLayerSize.height / 2);
// create render texture
mRTex = RenderTexture::create(iGameLayerSize.width, iGameLayerSize.height, Texture2D::PixelFormat::RGB5A1);
mRTex->setPosition(iGameLayerSize.width / 2, iGameLayerSize.height / 2);
mRTex->retain();
Sprite* lRTexSprite = Sprite::createWithTexture(mRTex->getSprite()->getTexture());
lRTexSprite->setPosition(iGameLayerSize.width / 2, iGameLayerSize.height / 2);
mGameLayer->addChild(lRTexSprite);
// create camera and set new viewport to zoom in and show picture with maximal height
auto camera = Camera::create();
camera->setCameraFlag(CameraFlag::USER1);
camera->setName("FrameBufferCamera");
camera->setDepth(-1);
camera->setFrameBufferObject(lFrameBuffer);
// calculate correct viewpoint
float viewPortRectWidthRatio = static_cast<float>(lWinSize.width) / static_cast<float>(iGameLayerSize.width);
float viewPortRectHeightRatio = static_cast<float>(lWinSize.height) / static_cast<float>(iGameLayerSize.height);
float viewPortW = ceilf(viewPortRectWidthRatio * (float)1000.0) / (float)1000.0;
float viewPortH = ceilf(viewPortRectHeightRatio * (float)1000.0) / (float)1000.0;
experimental::Viewport lViewPort = experimental::Viewport(0, 0, viewPortW, viewPortH);
camera->setViewport(lViewPort);
mGameLayer->addChild(camera);
in scene::draw override
mRTex->begin();
mFrameBufferSprite->visit();
mRTex->end();
This code above displays the frame buffer content a bit distorted and the FPS drops down to 35 FPS.
Anything wrong with my code?