美文网首页
cocos2d源码分析(八):Sprite的draw函数

cocos2d源码分析(八):Sprite的draw函数

作者: 奔向火星005 | 来源:发表于2019-01-12 19:22 被阅读0次

前面的渲染流程一篇说过,每个Node节点的渲染都是在自己的draw函数中生成渲染命令,然后添加到渲染队列中。我们看下Sprite的draw函数。

void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    if (_texture == nullptr)
    {
        return;
    }

#if CC_USE_CULLING
    // Don't calculate the culling if the transform was not updated
    auto visitingCamera = Camera::getVisitingCamera();
    auto defaultCamera = Camera::getDefaultCamera();
    if (visitingCamera == nullptr) {  //如果没有观察的摄像头,则默认可见
        _insideBounds = true;
    }
    else if (visitingCamera == defaultCamera) {  //判断待渲染的纹理是否在可见区域
        _insideBounds = ((flags & FLAGS_TRANSFORM_DIRTY) || visitingCamera->isViewProjectionUpdated()) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;
    }
    else
    {
        // XXX: this always return true since
        _insideBounds = renderer->checkVisibility(transform, _contentSize);
    }

    if(_insideBounds)
#endif
    {
        //初始化_trianglesCommand
        _trianglesCommand.init(_globalZOrder,
                               _texture,
                               getGLProgramState(),
                               _blendFunc,
                               _polyInfo.triangles,
                               transform,
                               flags);
        
        //添加到渲染队列
        renderer->addCommand(&_trianglesCommand);
    }
}

从代码中看到,draw函数比较简单,大致分为两步,第一步首先判断该sprite是否可见,第二部是初始化渲染命令_trianglesCommand并加入队列中。

我们看下可见性判断函数Renderer::checkVisibility(),代码如下

bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
{
    auto director = Director::getInstance();
    auto scene = director->getRunningScene();  //获取当前场景
    
    //If draw to Rendertexture, return true directly.
    // only cull the default camera. The culling algorithm is valid for default camera.
    if (!scene || (scene && scene->_defaultCamera != Camera::getVisitingCamera()))
        return true;  //如果默认摄像头不是visiting摄像头,则表示当前是离屏渲染?

    //visibleRect是当前场景的可视化区域
    Rect visibleRect(director->getVisibleOrigin(), director->getVisibleSize());
    
    // transform center point to screen space
    float hSizeX = size.width/2;  
    float hSizeY = size.height/2;
    Vec3 v3p(hSizeX, hSizeY, 0);      //v3p是要显示对象的矩形的中点
    transform.transformPoint(&v3p);  //对v3p做变换
    Vec2 v2p = Camera::getVisitingCamera()->projectGL(v3p);  //透视投影到屏幕空间

    // convert content size to world coordinates //将对象的宽和高转换到世界坐标系
    float wshw = std::max(fabsf(hSizeX * transform.m[0] + hSizeY * transform.m[4]), fabsf(hSizeX * transform.m[0] - hSizeY * transform.m[4]));
    float wshh = std::max(fabsf(hSizeX * transform.m[1] + hSizeY * transform.m[5]), fabsf(hSizeX * transform.m[1] - hSizeY * transform.m[5])); //
    
    // enlarge visible rect half size in screen coord
    visibleRect.origin.x -= wshw;  //扩大它的可视化区域
    visibleRect.origin.y -= wshh;
    visibleRect.size.width += wshw * 2;
    visibleRect.size.height += wshh * 2;
    bool ret = visibleRect.containsPoint(v2p); //判断是否包含在可视化区域
    return ret;
}

分析在注释里,比如下图:


图中最大的矩形是扩大后的可见区域,较小的矩形是没扩展前的可见区域,可以理解为屏幕。阴影矩形是要显示的对象,由图可知,虽然它的中点v2p在屏幕之外,但是因为它在扩展后的可见区域内,它还是有一部分是可见的。

相关文章

网友评论

      本文标题:cocos2d源码分析(八):Sprite的draw函数

      本文链接:https://www.haomeiwen.com/subject/wfpcdqtx.html