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

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 contentSize
void 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绘制完成

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是