上一章跟踪了 cocos2d-x调用CCScene::draw()的过程,直到访问子节点以及渲染,本章就具体看看几个类的渲染。

void Scene::render(Renderer* renderer)
{
    auto director = Director::getInstance();
    Camera* defaultCamera = nullptr;
    const auto& transform = getNodetoParentTransform();
    if (_cameraOrderDirty)
    {
        stable_sort(_cameras.begin(),_cameras.end(),camera_cmp);
        _cameraOrderDirty = false;
    }

    for (const auto& camera : _cameras)
    {
        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());       
        //visit the scene
        visit(renderer,transform,0);
        renderer->render();</strong>
        //
        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
    }

    Camera::_visitingCamera = nullptr;
}

visit递归访问该场景的子节点,传递transform(当前节点相对父节点的变换矩阵)和flags(该节点transform是否改变和大小变化)给子节点,子节点根据父节点的transform以及自身的参数来渲染,通过2种方式:直接执行opengl命令和将opengl传递给render对象
renderer->render()会执行渲染对象render的opengl渲染命令,对象render通过队列来存储opengl渲染命令。
通过一下类的draw(),可以很明显看出来。

0.CCSprite类

void Sprite::draw(Renderer *renderer,const Mat4 &transform,uint32_t flags)
{
  //根据父节点flags(是否变化,位移、大小),自身的transform flag以及是否可见来判定是否渲染
#if CC_USE_CULLING
     _insideBounds = (flags & FLAGS_TRANSFORM_DIRTY) ? renderer->checkVisibility(transform,_contentSize) : _insideBounds;

    if(_insideBounds)
#endif
    {
        //初始化渲染参数
        _quadCommand.init(_globalZOrder,_texture->getName(),getGLProgramState(),_blendFunc,&_quad,1,flags);
        //将渲染命令添加到队列中
        renderer->addCommand(&_quadCommand);

#if CC_SPRITE_DEBUG_DRAW
        _debugDrawNode->clear();
        Vec2 vertices[4] = {
            Vec2( _quad.bl.vertices.x,_quad.bl.vertices.y ),Vec2( _quad.br.vertices.x,_quad.br.vertices.y ),Vec2( _quad.tr.vertices.x,_quad.tr.vertices.y ),Vec2( _quad.tl.vertices.x,_quad.tl.vertices.y ),};
        _debugDrawNode->drawpoly(vertices,4,true,Color4F(1.0,1.0,1.0));
#endif //CC_SPRITE_DEBUG_DRAW
    }
}

1.SpriteBatchNode类

void SpriteBatchNode::draw(Renderer *renderer,const Mat4 &transform,uint32_t flags)
{
    // Optimization: Fast dispatch
   //判断是否有quads(V3F_C4B_T2F_Quad结构,记录顶点,纹理和颜色3种数据)
    if( _textureAtlas->getTotalQuads() == 0 )
    {
        return;
    }


    for (const auto &child : _children)
    {
#if CC_USE_PHYSICS
        auto physicsBody = child->getPhysicsBody();
        if (physicsBody)
        {
            child->updateTransformFromPhysics(transform,flags);
        }
#endif
       //有子节点的情况下,先更新子节点的transform
        child->updateTransform();
    }
    //opengl渲染,初始化渲染命令
    _batchCommand.init(_globalZOrder,getGLProgram(),_textureAtlas,flags);
    //添加渲染函数到render对象
    renderer->addCommand(&_batchCommand);
}

为什么要先调用子类updateTransform(),以后有机会再谈。这里谈下Sprite和SpriteBatchNode的关系SpriteBatchNode一般用于多个Sprite使用相同的纹理,可以将这些Sprite加入SpriteBatchNode,这样渲染的时候就仅仅需要渲染一次.Node在visit的时候,针对其子节点,会先排序,排完后仅递归访问zorder<0的子节点。而排序函数会使用变量变量_reorderChildDirty标志位。当Sprite加入SpriteBatchNode的时候,会处理次标志位,这样加入SpriteBatchNode的Sprite就不会递归visit了。
可以看到SpriteBatchNode的渲染方式是通过添加Opengl的命令到render进程的。

2.Layer类渲染函数没有具体的实现,因为它仅仅作为个承载类,用来处理触摸事件以及对scene分层的作用。

3.LayerColor类

void LayerColor::draw(Renderer *renderer,uint32_t flags)
{
   //这里的渲染有点不同,它有个回调
    _customCommand.init(_globalZOrder,flags);
    _customCommand.func = CC_CALLBACK_0(LayerColor::onDraw,this,flags);

    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;
        _modelViewTransform.transformVector(&pos);
        _noMVPVertices[i] = Vec3(pos.x,pos.y,pos.z)/pos.w;
    }
}
void LayerColor::onDraw(const Mat4& transform,uint32_t flags) { //gluseProgram(program) getGLProgram()->use();
    //设置uniform矩阵的
    getGLProgram()->setUniformsForBuiltins(transform);
    //打开OPENGL的状态
    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,0);
     //设置数据
    setGLBufferData(_squareColors,4 * sizeof(Color4F),1);
    //颜色渲染
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,0);
#else
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,_noMVPVertices);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,_squareColors);
#endif // EMSCRIPTEN
    //颜色混合
    GL::blendFunc( _blendFunc.src,_blendFunc.dst );
   //从数组中读取顶点数据
    glDrawArrays(GL_TRIANGLE_STRIP,4);
    // auto __renderer__ = Director::getInstance()->getRenderer(); 
     // __renderer__->addDrawnBatches(__drawcalls__); 
     // __renderer__->addDrawnVertices(__vertices__);
    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,4);
}

上面的回调函数是直接调用openglAPI 进行渲染了。
补充说明opengl相关的东西:
Node会存储一个GLProgramState指针_glProgramState,该指针持有其成员指针GLPromgram的“状态”(我理解成值,即uniforms和attributes)。
uniform变量是外部application程序传递给(vertex和fragment)shader的变量,一般用来表示:变换矩阵,材质,光照参数和颜色等信息。
attribute变量是只能在vertex shader中使用的变量,一般用来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。

4.Label

void Label::draw(Renderer *renderer,const Mat4 &transform,uint32_t flags)
{
    // Don't do calculate the culling if the transform was not updated
    bool transformUpdated = flags & FLAGS_TRANSFORM_DIRTY;
#if CC_USE_CULLING
    _insideBounds = transformUpdated ? renderer->checkVisibility(transform,_contentSize) : _insideBounds;

    if(_insideBounds)
#endif
    {
        _customCommand.init(_globalZOrder,flags);
        //渲染回调
        _customCommand.func = CC_CALLBACK_0(Label::onDraw,this,transformUpdated);

        renderer->addCommand(&_customCommand);
    }
}
通过代码可以看出,Label的渲染方式与ColorLayer类似,重点在于起回调函数onDraw.
oid Label::onDraw(const Mat4& transform,bool transformUpdated)
{
    CC_PROFILER_START("Label - draw");

    // Optimization: Fast dispatch
    if( _batchNodes.size() == 1 && _textureAtlas->getTotalQuads() == 0 )
    {
        return;
    }
    //获取Label的GLProgram
    auto glprogram = getGLProgram();
    //gluseProgram(program), installs the program object specified by program as part //of current rendering state.安装program作为当前渲染状态
    glprogram->use();
    GL::blendFunc( _blendFunc.src,_blendFunc.dst );

    if (_currentLabelType == LabelType::TTF)
    {
        glprogram->setUniformlocationWith4f(_uniformTextColor,_textColorF.r,_textColorF.g,_textColorF.b,_textColorF.a);
    }
//描边或者发光效果
    if (_currLabelEffect == LabelEffect::OUTLINE || _currLabelEffect == LabelEffect::GLOW)
    {
         glprogram->setUniformlocationWith4f(_uniformEffectColor,_effectColorF.r,_effectColorF.g,_effectColorF.b,_effectColorF.a);
    }
    //阴影效果
    if(_shadowEnabled && _shadowBlurRadius <= 0)
    {
        drawShadowWithoutBlur();
    }
    //设置uniforms矩阵
    glprogram->setUniformsForBuiltins(transform);
   //下面的2个for循环类似域Sprite和SpirteBatchNode的渲染
    for(const auto &child: _children)
    {
        if(child->getTag() >= 0)
            child->updateTransform();
    }

    for (const auto& batchNode:_batchNodes)
    {
        batchNode->getTextureAtlas()->drawQuads();
    }

    CC_PROFILER_STOP("Label - draw");
}

渲染暂时就写这么多,关于更多的类,大家可以自己进代码看下,以及更加详细的调用都可以直接看到。opengl的使用以及原理可以查看下面的网址:
http://www.jb51.cc/article/p-ytwajipz-so.html
http://www.jb51.cc/article/p-xacaethn-tc.html
http://www.songho.ca/opengl/gl_transform.html

cocos-2dx 渲染3的更多相关文章

  1. HTML实现代码雨源码及效果示例

    这篇文章主要介绍了HTML实现代码雨源码及效果示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. 吃透移动端 1px的具体用法

    这篇文章主要介绍了吃透移动端 1px的具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. html5开发三八女王节表白神器

    一年一度的三八女王节马上来临,今天小编基于html5给大家开发一个表白神器,做一个 浪漫的程序猿,具体代码大家参考下本文

  4. html5实现图片转圈的动画效果——让页面动起来

    这篇文章主要介绍了html5实现图片转圈的动画效果——让页面动起来的相关资料,需要的朋友可以参考下

  5. HTML5 3D书本翻页动画的实现示例

    这是一款十分炫酷的HTML5 3D书本翻页动画,效果相对比较简单,拖拽鼠标模拟用手翻页,需要的朋友们下面随着小编来一起学习学习吧

  6. html5简介及新增功能介绍

    这篇文章主要介绍了html5简介及新增功能介绍,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  7. HTML5 图片悬停放大的实现代码示例

    这篇文章主要介绍了HTML5 图片悬停放大的实现代码示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  8. ios – 痛苦地减慢软件向量,特别是CoreGraphics与OpenGL

    )在这个实验之后,我切换到了OpenGL和MonkVG库,我感到非常高兴.我现在可以在没有任何帧速率下降的情况下同时渲染HUNDREDS曲线,对保真度的影响很小.>我是否有可能以某种方式滥用CoreGraphics,或者性能真的那么糟糕?我的预感是问题在于CoreGraphics,基于StackOverflow/论坛问题的数量以及有关CG性能的答案.从技术上讲,为什么会这样呢?>如果CoreGraphics真的那么慢,Safari究竟如何顺利地工作?OpenGL在早餐时吃这个测试.矢量绘图怎么可能如此慢得

  9. ios – 相机图像旋转问题

    我在这里遇到一个非常奇怪的问题.当我以纵向模式单击图像并上传它然后再次获取它时,显示逆时针旋转90度.但是当我在相机胶卷中看到它时,它会以正确的方向显示.我已经尝试了几乎所有可能的链接/代码来解决这个问题,但似乎没有任何帮助.我以JPEG格式保存图像.请帮助这个人.提前致谢!!解决方法解决方法是在UIImage上创建一个类别,并根据其元数据EXIF缩放和旋转图像.这是一段神奇的代码:

  10. 为什么这个OpenGL ES 2.0着色器不能在iOS上使用我的VBO?

    如果有人能够了解这里出了什么问题,也许是对gl命令或其他一些不兼容的命令序列的错误排序,我将非常感谢你的帮助.尽管谷歌在“OpenGLES2.0编程指南”中进行了大量研究和研究,但我一直试图让这段代码整天都没有成功.我正在尝试在iPhone上的OpenGLES2.0中使用顶点缓冲区对象和自定义着色器.我试图交错来自以下类型的一系列自定义结构的顶点数据:位置,半径和颜色字节分别考虑顶点位置,点大小和

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部