cocos2dx源码分析:渲染指令收集

来源:互联网 发布:淘宝垃圾客服 编辑:程序博客网 时间:2024/05/16 17:38

cocos2dx中渲染分两步进行,第一步收集渲染指令,第二步完成渲染
渲染起始于场景的render函数

void Scene::render(Renderer* renderer){    auto director = Director::getInstance();    Camera* defaultCamera = nullptr;    const auto& transform = getNodeToParentTransform();    /*对于场景中的每一个相机都要走一遍渲染流程*/    for (const auto& camera : getCameras())    {        if (!camera->isVisible())            continue;        Camera::_visitingCamera = camera;        if (Camera::_visitingCamera->getCameraFlag() == CameraFlag::DEFAULT)        {            defaultCamera = Camera::_visitingCamera;        }        /*使相机生效*/        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);        director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, Camera::_visitingCamera->getViewProjectionMatrix());        camera->apply();        //clear background with max depth        camera->clearBackground();        //visit the scene        /*遍历场景树,收集渲染指令*/        visit(renderer, transform, 0);#if CC_USE_NAVMESH        if (_navMesh && _navMeshDebugCamera == camera)        {            _navMesh->debugDraw(renderer);        }#endif        /*渲染*/        renderer->render();        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);    }#if CC_USE_3D_PHYSICS && CC_ENABLE_BULLET_INTEGRATION    if (_physics3DWorld && _physics3DWorld->isDebugDrawEnabled())    {        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);        director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, _physics3dDebugCamera != nullptr ? _physics3dDebugCamera->getViewProjectionMatrix() : defaultCamera->getViewProjectionMatrix());        _physics3DWorld->debugDraw(renderer);        renderer->render();        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);    }#endif    Camera::_visitingCamera = nullptr;    experimental::FrameBuffer::applyDefaultFBO();}

遍历场景树,收集渲染指令的过程是一个递归的过程

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    /*入栈变换矩阵,相机矩阵已经入栈,这里只需入栈mv矩阵*/    _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())    {        /*使用zorder排序孩子节点*/        sortAllChildren();        /*先收集zorder<0的孩子节点的渲染指令*/        // 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);        /*收集zorder>0的孩子节点的渲染指令*/        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;}

Node中使用draw收集自己的渲染指令,一个继承自Node的对象如果可渲染就需要重写这个函数,下面是Sprite的draw实现

void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags){    /*sprite必须有texture才能可渲染*/    if (_texture == nullptr)    {        return;    }#if CC_USE_CULLING    /*可见性剔除*/    // Don't do calculate the culling if the transform was not updated    auto visitingCamera = Camera::getVisitingCamera();    auto defaultCamera = Camera::getDefaultCamera();    if (visitingCamera == defaultCamera) {        _insideBounds = ((flags & FLAGS_TRANSFORM_DIRTY)|| visitingCamera->isViewProjectionUpdated()) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;    }    else    {        _insideBounds = renderer->checkVisibility(transform, _contentSize);    }    if(_insideBounds)#endif    {        /*创建自己的渲染指令,并发送到渲染器中。cocos2dx中有多种渲染指令,sprite使用的渲染指令是TrianglesCommand*/        _trianglesCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, _polyInfo.triangles, transform, flags);        renderer->addCommand(&_trianglesCommand);#if CC_SPRITE_DEBUG_DRAW        _debugDrawNode->clear();        auto count = _polyInfo.triangles.indexCount/3;        auto indices = _polyInfo.triangles.indices;        auto verts = _polyInfo.triangles.verts;        for(ssize_t i = 0; i < count; i++)        {            //draw 3 lines            Vec3 from =verts[indices[i*3]].vertices;            Vec3 to = verts[indices[i*3+1]].vertices;            _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x,to.y), Color4F::WHITE);            from =verts[indices[i*3+1]].vertices;            to = verts[indices[i*3+2]].vertices;            _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x,to.y), Color4F::WHITE);            from =verts[indices[i*3+2]].vertices;            to = verts[indices[i*3]].vertices;            _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x,to.y), Color4F::WHITE);        }#endif //CC_SPRITE_DEBUG_DRAW    }}

至此渲染指令收集完毕,下一步就是执行renderer->render(),完成渲染

0 0
原创粉丝点击