cocos2d / cocos2d-x

Cocos2d-x is a suite of open-source, cross-platform, game-development tools utilized by millions of developers across the globe. Its core has evolved to serve as the foundation for Cocos Creator 1.x & 2.x.
https://www.cocos.com/en/cocos2d-x
18.24k stars 7.06k forks source link

Renderer::render() seems to be called too earlier in Scene::render() #9329

Open silwings opened 9 years ago

silwings commented 9 years ago

Calling Renderer::render() right after Scene::visit() in Scene::render() may cause problem under below scenario:

Assuming we need to render all the scene graph into a RenderTexture for post processing or screen capturing. A common way would be register two EventListener, one for EVENT_AFTER_UPDATE and one for EVENT_AFTER_VISIT.

    Director::getInstance()->getEventDispatcher()->addCustomEventListener(Director::EVENT_AFTER_UPDATE, beforeDraw);
    Director::getInstance()->getEventDispatcher()->addCustomEventListener(Director::EVENT_AFTER_VISIT, afterDraw);

Then call RenderTexture::begin and RenderTexture::end in these two listeners' callback.

    auto beforeDraw = [this](EventCustom* event) {
        renderTexture->begin();
    };
    auto afterDraw = [this](EventCustom* event) {
        renderTexture->end();
    };

But during runtime, Renderer::render() will be called before RenderTexture::end(), then the Renderer will consume the GroupCommand inserted by RenderTexture::onBegin(), causing RenderTexture::onEnd(), which is on the new inserted RenderQueue, never be executed.

Currently, a simple workaround is to comment the Renderer::render() in Scene::render() at Line 146 and Line 159 in CCScene.cpp. Although not been thoroughly tested, it seems harmless both in logic and actual running, because Renderer::render() will be called shortly after Scene:render at Line 306 in CCDirector.cpp

darkdukey commented 9 years ago

@dabingnn @super626 is there any reason we should call render separately with camera? multiple viewports?

super626 commented 9 years ago

@silwings and @darkdukey Thanks.

The camera has effect on the render texture. I am thinking better way to use render texture.

The reason we call Renderer::render() early is that one object can be seen by many cameras, these cameras can have same viewport or different viewports. Because the render command we push during visit is pointer, we should render it after single visit routine. It may be modified by the second camera otherwise.

silwings commented 9 years ago

@super626 Another workaround that doesn't have to change cocos2d-x would be to insert RenderTexture's begin() and end() at the start and end of a node's visit(). It may render the node and all its children to the FBO. I will give it a try.

super626 commented 9 years ago

Ok, thanks.

On Wed, Dec 3, 2014 at 3:10 PM, Wang Cong notifications@github.com wrote:

@super626 https://github.com/super626 Another workaround that doesn't have to change cocos2d-x would be to insert RenderTexture's begin() and end() at the start and end of a node's visit(). It may render all the node and its children to the FBO. I will give it a try.

— Reply to this email directly or view it on GitHub https://github.com/cocos2d/cocos2d-x/issues/9329#issuecomment-65364295.

walzer commented 9 years ago

Add to unplanned roadmap because we're redesigning the render queue in v3.7