cocos源码分析--LayerColor的绘制过程

cocos源码分析--LayerColor的绘制过程,第1张

概述1开始,先创建一个LayerColor Scene *scene=Scene::create(); director->runWithScene(scene); //目标 auto layer = LayerColor::create(Color4B(0, 255, 0, 255), 100, 100); //主要的步骤就是设置了node 的 _positi

1开始,先创建一个Layercolor

Scene *scene=Scene::create();    director->runWithScene(scene);    //目标    auto layer = Layercolor::create(color4B(0,255,0,255),100,100);    //主要的步骤就是设置了node 的 _position    layer->setposition(10,10);    scene->addChild(layer);

2 看一下Layercolor的初始化方法

bool Layercolor::initWithcolor(const color4B& color,GLfloat w,GLfloat h){    if (Layer::init())    {        // default blend function        //指定混合模式        _blendFunc = BlendFunc::Alpha_NON_PREMulTIPLIED;        /*         realcolor和displayedcolor 记录元素本身的颜色属性         displayedcolor和displayedOpacity方法用于表示和父亲元素叠加过后的最终绘制颜色         sprite用于父亲颜色和自己纹理的混合,Laycolor默认一致,不叠加颜色         */        _displayedcolor.r = _realcolor.r = color.r;        _displayedcolor.g = _realcolor.g = color.g;        _displayedcolor.b = _realcolor.b = color.b;        _displayedOpacity = _realOpacity = color.a;               //四个顶点 初始化        for (size_t i = 0; i<sizeof(_squareVertices) / sizeof( _squareVertices[0]); i++ )        {            _squareVertices[i].x = 0.0f;            _squareVertices[i].y = 0.0f;        }         //四个顶点的颜色归一化,颜色是一样的        updatecolor();        //w,h 为 设计分辨率,设置顶点的范围        setContentSize(Size(w,h));       /*        每个node拥有一个GLProgramState实例        查找这种类型的shader GLProgram SHADER_name_position_color_NO_MVP        */        GLProgramState* state=GLProgramState::getorCreateWithGLProgramname(GLProgram::SHADER_name_position_color_NO_MVP);                setGLProgramState(state);        return true;    }    return false;}
/// overrIDe contentSizevoID Layercolor::setContentSize(const Size & size){    //没有赋值的为0,也就是 0(0,0) 1(w,0) 2 (0,h) 3(w,h)    //绘制顺序为012  213    _squareVertices[1].x = size.wIDth;    _squareVertices[2].y = size.height;    _squareVertices[3].x = size.wIDth;    _squareVertices[3].y = size.height;        Layer::setContentSize(size);}voID Node::setContentSize(const Size & size){    if ( ! size.equals(_contentSize))    {        _contentSize = size;        //得到锚点在本地坐标系下的坐标        _anchorPointInPoints = Vec2(_contentSize.wIDth * _anchorPoint.x,_contentSize.height * _anchorPoint.y );        //告诉该更新了        _transformUpdated = _transformDirty = _inverseDirty = _contentSizeDirty = true;    }}

3 Director::drawScene方法为正式绘图,如下

voID Director::drawScene(){     //省略部分代码    glClear(GL_color_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         //兼容cocos2.0,暂时忽略    pushmatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);    // draw the scene    if (_runningScene)    {//正式访问        _runningScene->visit(_renderer,Mat4::IDENTITY,false);//第一次的矩阵是单位矩阵                _eventdispatcher->dispatchEvent(_eventAfterVisit);    }     //开始真正的opengl    _renderer->render();         popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);    _totalFrames++;    // swap buffers    if (_openGLVIEw)    {        _openGLVIEw->swapBuffers();//这个之后再看    }    if (_displayStats)    {        calculateMPF();//不知道啥意思    }}

标红不分为开始遍历节点,但不进行opengl绘制,进入代码如下:

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    /*     为了便于迁移到v3.0,我们仍然支持Mat4堆栈,           但它已被弃用,您的代码不应该依赖它     */    Director* director = Director::getInstance();    director->pushmatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);    //把刚生产的模型视图矩阵加入到顶部的modevIEw【对scene来说,执行下面代码之前,里面已经有3个modelvIEw】    //这个代码针对2.0的,对3.1没啥意义了    director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW,_modelVIEwtransform);    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        this->draw(renderer,flags);        for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)            (*it)->visit(renderer,flags);    }    else    {        this->draw(renderer,flags);    }       /*     画完了就退出战,是兼容2.0的时候,现在不需要这个了     矩阵的转换都在GPU的shader中了    */    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;}
uint32_t Node::processparentFlags(const Mat4& parenttransform,uint32_t parentFlags){    uint32_t flags = parentFlags;//先把父亲的改动标志传过来      //如果转置矩阵 变化了, 标记为脏数据,要更新    flags |= (_transformUpdated ? FLAGS_transform_DIRTY : 0);    //如果大小改变了,标记为脏数据,要更新    flags |= (_contentSizeDirty ? FLAGS_CONTENT_SIZE_DIRTY : 0);    //    if(_usingnormalizedposition && (flags & FLAGS_CONTENT_SIZE_DIRTY)) {        CCASSERT(_parent,"setnormalizedposition() doesn‘t work with orphan nodes");        auto s = _parent->getContentSize();        _position.x = _normalizedposition.x * s.wIDth;        _position.y = _normalizedposition.y * s.height;        _transformUpdated = _transformDirty = _inverseDirty = true;    }    //转置矩阵和大小其中一个变了    if(flags & FLAGS_DIRTY_MASK)        _modelVIEwtransform = this->transform(parenttransform);//节点自己的转换矩阵,节点的本地坐标乘以这个矩阵就会得到世界坐标    //更新完毕,标记为false    _transformUpdated = false;    _contentSizeDirty = false;    return flags;}

self->draw为绘制自己,但不是真的绘制,而是让自己关联一个绘制命令Command,Layercolor的draw方法重写如下:

//transform为本地坐标转世界坐标的矩阵voID Layercolor::draw(Renderer *renderer,const Mat4 &transform,uint32_t flags){    _customCommand.init(_globalZOrder);     //回调函数    _customCommand.func = CC_CALLBACK_0(Layercolor::onDraw,this,transform,flags);    //把绘制命令的东西放到renderer里面    renderer->addCommand(&_customCommand);        for(int i = 0; i < 4; ++i)    {        Vec4 pos;        //四个顶点的设计分辨率坐标        pos.x = _squareVertices[i].x; pos.y = _squareVertices[i].y; pos.z = _positionZ;        pos.w = 1;//齐次坐标        //得出来的pos就是世界坐标下的pos了        _modelVIEwtransform.transformVector(&pos);        //pos.w 世界坐标的w始终为1        //这个世界坐标会在shader内乘以相机矩阵和裁剪矩阵,得出最后的视口需要的坐标        _noMVPVertices[i] = Vec3(pos.x,pos.y,pos.z)/pos.w;    }}

代码把需要绘制的信息加入到了customCommand里面。

4 _renderer->render(); 负责执行command内的opengl绘制命令,代码如下:

voID Renderer::render(){            //Process render commands        //1. Sort render commands based on ID        //renderGroups包括若干rederqueue,默认使用第一个,        //renderquque包括若干个rendercommand        for (auto &renderqueue : _renderGroups)        {            renderqueue.sort();        }                visitRenderQueue(_renderGroups[0]);                flush();            clean();    }
voID Renderer::visitRenderQueue(const RenderQueue& queue){    ssize_t size = queue.size();        for (ssize_t index = 0; index < size; ++index)    {        auto command = queue[index];        auto commandType = command->getType();                 if(RenderCommand::Type::CUSTOM_COMMAND == commandType)//比如 Layercolor        {            flush();            auto cmd = static_cast<CustomCommand*>(command);            cmd->execute();//会调用Layercolor::onDraw,直接开始绘图        }                  }}

5 cmd->execute会调用customCommand的回调函数,在Layercolor中为onDraw,代码如下:

//通过自定义方法进行回调 transform为 本地坐标转世界坐标的旋转矩阵voID Layercolor::onDraw(const Mat4& transform,uint32_t flags){    getGLProgram()->use();//layercolor 的tansform为相机矩阵*裁剪矩阵    getGLProgram()->setUniformsForBuiltins(transform);//设置顶点着色器中全局变量的值,如MVP矩阵     //启用 顶点坐标和颜色    GL::enabLevertexAttribs( GL::VERTEX_ATTRIB_FLAG_position | GL::VERTEX_ATTRIB_FLAG_color );    //    // Attributes    //#ifdef EMSCRIPTEN    setGLBufferData(_noMVPVertices,4 * sizeof(Vec3),0);    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_position,3,GL_float,GL_FALSE,0);    setGLBufferData(_squarecolors,4 * sizeof(color4F),1);    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_color,4,0);#else        //找到顶点的索引 _noMVPVertices为世界坐标中的四个顶点的值,存在了cpu中,没有存到显存    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_position,3,0,_noMVPVertices);    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_color,_squarecolors);#endif // EMSCRIPTEN       //混合,源和目标 颜色的混合    GL::blendFunc( _blendFunc.src,_blendFunc.dst );        //画这四个点    glDrawArrays(GL_TRIANGLE_STRIP,4);    //这是记录图元和顶点吗   // CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,4);    auto __renderer__ = Director::getInstance()->getRenderer();    __renderer__->addDrawnBatches(1);    __renderer__->addDrawnVertices(4);    }

Layercolor绘制过程比较简单,没有纹理设置,只有顶点和颜色,通过glDrawArrays绘制完成

总结

以上是内存溢出为你收集整理的cocos源码分析--LayerColor的绘制过程全部内容,希望文章能够帮你解决cocos源码分析--LayerColor的绘制过程所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/998936.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-21
下一篇2022-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存