RenderTexture截屏原理

来源:互联网 发布:淘宝店铺怎么做广告 编辑:程序博客网 时间:2024/06/01 19:21
void RenderTexture::begin(){    Director* director = Director::getInstance();    CCASSERT(nullptr != director, "Director is null when seting matrix stack");        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);    _projectionMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);    _transformMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);        if(!_keepMatrix)    {        director->setProjection(director->getProjection());                const Size& texSize = _texture->getContentSizeInPixels();                // Calculate the adjustment ratios based on the old and new projections        Size size = director->getWinSizeInPixels();                float widthRatio = size.width / texSize.width;        float heightRatio = size.height / texSize.height;                Mat4 orthoMatrix;        Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1, 1, &orthoMatrix);        director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);    }    _groupCommand.init(_globalZOrder);    Renderer *renderer =  Director::getInstance()->getRenderer();    renderer->addCommand(&_groupCommand);    renderer->pushGroup(_groupCommand.getRenderQueueID());    _beginCommand.init(_globalZOrder);    _beginCommand.func = CC_CALLBACK_0(RenderTexture::onBegin, this);    Director::getInstance()->getRenderer()->addCommand(&_beginCommand);}void RenderTexture::end(){    _endCommand.init(_globalZOrder);    _endCommand.func = CC_CALLBACK_0(RenderTexture::onEnd, this);    Director* director = Director::getInstance();    CCASSERT(nullptr != director, "Director is null when seting matrix stack");        Renderer *renderer = director->getRenderer();    renderer->addCommand(&_endCommand);    renderer->popGroup();        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);    director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);}


void Node::visit(){    auto renderer = _director->getRenderer();    auto& parentTransform = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);    visit(renderer, parentTransform, true);}

void Node::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags){    // quick return if not visible. children won't be drawn.    if (!_visible)    {        return;    }    uint32_t flags = processParentFlags(parentTransform, parentFlags);    // IMPORTANT:    // To ease the migration to v3.0, we still support the Mat4 stack,    // but it is deprecated and your code should not rely on it    _director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);    _director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);        bool visibleByCamera = isVisitableByVisitingCamera();    int i = 0;    if(!_children.empty())    {        sortAllChildren();        // draw children zOrder < 0        for( ; i < _children.size(); i++ )        {            auto node = _children.at(i);            if (node && node->_localZOrder < 0)                node->visit(renderer, _modelViewTransform, flags);            else                break;        }        // self draw        if (visibleByCamera)            this->draw(renderer, _modelViewTransform, flags);        for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)            (*it)->visit(renderer, _modelViewTransform, flags);    }    else if (visibleByCamera)    {        this->draw(renderer, _modelViewTransform, flags);    }    _director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);        // FIX ME: Why need to set _orderOfArrival to 0??    // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920    // reset for next frame    // _orderOfArrival = 0;}


截屏代码:

Sprite* HelloWorld::createScreenshotSprite(){    Size visibleSize = Director::getInstance()->getVisibleSize();        RenderTexture* renderTexture = RenderTexture::create(visibleSize.width, visibleSize.height);        renderTexture->begin();//    Director::getInstance()->getRunningScene()->visit();    this->visit();    renderTexture->end();        Texture2D* texture = renderTexture->getSprite()->getTexture();    Sprite* sprScreenshot = Sprite::createWithTexture(texture);    sprScreenshot->setFlippedY(true);    sprScreenshot->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2));    return sprScreenshot;}




方法2:

Sprite* HelloWorld::createScreenshotSprite(){    GLView* glview = Director::getInstance()->getOpenGLView();    Size frameSize = glview->getFrameSize();        const int dataLength = frameSize.width * frameSize.height * 4;    char* pixelData = new char[dataLength];    glReadPixels(0, 0, frameSize.width, frameSize.height, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);        Texture2D* texture = new Texture2D();    texture->initWithData(pixelData, dataLength, Texture2D::PixelFormat::RGBA8888, frameSize.width, frameSize.height, frameSize);        Sprite* sprScreenshot = Sprite::createWithTexture(texture);    sprScreenshot->setScaleX(1 / glview->getScaleX());    sprScreenshot->setScaleY(1 / glview->getScaleY());    sprScreenshot->setFlippedY(true);        CC_SAFE_RELEASE(texture);    delete[] pixelData;        sprScreenshot->setPosition(Vec2(frameSize.width/1.3, frameSize.height/1.2));        return sprScreenshot;}