1开始,先创建一个LayerColor

Scene *scene=Scene::create();
director->runWithScene(scene);
//目标
auto layer = LayerColor::create(Color4B(, , , ), , );
//主要的步骤就是设置了node 的 _position
layer->setPosition(,);
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 = ; i<sizeof(_squareVertices) / sizeof( _squareVertices[]); 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[].x = size.width;
_squareVertices[].y = size.height;
_squareVertices[].x = size.width;
_squareVertices[].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,作为最顶部的最新的modelviewTransform
//有的地方会用到这个,比如RenderTexture,她的孩子用不到,因为直接从_modelViewTransform传就可以了
//
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform); int i = ; if(!_children.empty())
{
sortAllChildren();
// draw children zOrder < 0
for( ; i < _children.size(); i++ )
{
auto node = _children.at(i); if ( node && node->_localZOrder < )
node->visit(renderer, _modelViewTransform, flags);
else
break;
}
// self draw
this->draw(renderer, _modelViewTransform, flags); for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer, _modelViewTransform, flags);
}
else
{
this->draw(renderer, _modelViewTransform, flags);
} /*
画完了就退出战,是兼容2.0的时候,把最顶部最新计算的modeviewtrnasform退出去
矩阵的转换都在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;
}

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 = ; i < ; ++i)
{
Vec4 pos;
//四个顶点的设计分辨率坐标
pos.x = _squareVertices[i].x; pos.y = _squareVertices[i].y; pos.z = _positionZ;
pos.w = ;//齐次坐标
//得出来的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[]); flush(); clean(); }
void Renderer::visitRenderQueue(const RenderQueue& queue)
{
ssize_t size = queue.size(); for (ssize_t index = ; 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, * sizeof(Vec3), );
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , ); setGLBufferData(_squareColors, * sizeof(Color4F), );
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, , GL_FLOAT, GL_FALSE, , );
#else //找到顶点的索引 _noMVPVertices为世界坐标中的四个顶点的值,存在了cpu中,没有存到显存
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , _noMVPVertices); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, , GL_FLOAT, GL_FALSE, , _squareColors);
#endif // EMSCRIPTEN //混合,源和目标 颜色的混合
GL::blendFunc( _blendFunc.src, _blendFunc.dst ); //画这四个点
glDrawArrays(GL_TRIANGLE_STRIP, , ); //这是记录图元和顶点吗
// CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,4);
auto __renderer__ = Director::getInstance()->getRenderer();
__renderer__->addDrawnBatches();
__renderer__->addDrawnVertices(); }

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

												

cocos源码分析--LayerColor的绘制过程的更多相关文章

  1. MyBatis 源码分析 - 映射文件解析过程

    1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...

  2. Spring源码分析之`BeanFactoryPostProcessor`调用过程

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 本文内容: AbstractApplicationContext#refresh前部分的一点小内容 ...

  3. Spring Ioc源码分析系列--Bean实例化过程(一)

    Spring Ioc源码分析系列--Bean实例化过程(一) 前言 上一篇文章Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理已经完成了对 ...

  4. Spring Ioc源码分析系列--Bean实例化过程(二)

    Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...

  5. MyBatis 源码分析 - SQL 的执行过程

    * 本文速览 本篇文章较为详细的介绍了 MyBatis 执行 SQL 的过程.该过程本身比较复杂,牵涉到的技术点比较多.包括但不限于 Mapper 接口代理类的生成.接口方法的解析.SQL 语句的解析 ...

  6. 【Netty源码分析】发送数据过程

    前面两篇博客[Netty源码分析]Netty服务端bind端口过程和[Netty源码分析]客户端connect服务端过程中我们分别介绍了服务端绑定端口和客户端连接到服务端的过程,接下来我们分析一下数据 ...

  7. 【Canal源码分析】parser工作过程

    本文主要分析的部分是instance启动时,parser的一个启动和工作过程.主要关注的是AbstractEventParser的start()方法中的parseThread. 一.序列图 二.源码分 ...

  8. tomcat8 源码分析 | 组件及启动过程

    tomcat 8 源码分析 ,本文主要讲解tomcat拥有哪些组件,容器,又是如何启动的 推荐访问我的个人网站,排版更好看呦: https://chenmingyu.top/tomcat-source ...

  9. Spark 源码分析 -- task实际执行过程

    Spark源码分析 – SparkContext 中的例子, 只分析到sc.runJob 那么最终是怎么执行的? 通过DAGScheduler切分成Stage, 封装成taskset, 提交给Task ...

随机推荐

  1. [转]总结@Autowired 和@Resource

    @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按byName自动注入罢了. @Resource有两个属性是比较重要的,分 ...

  2. storage 事件监听

    在公司的一次内部分享会上, 偶然知道了这个H5的新事件, 解决了我之前的一个bug. 事情是这样的, 第A网页上显示的数量的总和, 点击去是B页面, 可以进行管理, 增加或者删除, 当用户做了增删操作 ...

  3. Elasticsearch的数据导出和导入操作(elasticdump工具),以及删除指定type的数据(delete-by-query插件)

    Elasticseach目前作为查询搜索平台,的确非常实用方便.我们今天在这里要讨论的是如何做数据备份和type删除.我的ES的版本是2.4.1. ES的备份,可不像MySQL的mysqldump这么 ...

  4. ecstore-安装提示flock,即使绕过检测,安装成功后还是提示t function 解决办法

    安装时先绕过去 安装好后,修改config.php里的TMP_DIR,指向网站目录下的data目录(用绝对路径) 分析:应该是php的运行用户没有对tmp目录的写权限.中电云集的管理工具就出现过

  5. Usbhub驱动编译

    在3g 4g的usb驱动基础上,加入以下部分,就可以驱动hub了 kmod-usb-hid 3.3.8-1 kmod-usbip 3.3.8-1 kmod-usbip-client 3.3.8-1 k ...

  6. ASP防止SQL注入

    '防止SQL注入'http://0.0.0.0/bzhs/login.asp?logType=edit';WAITFOR DELAY '0:0:5' --logType = Replace(Repla ...

  7. webGL之three.js入门3--材料篇

    这几天在看李鹏程翻译的[美]Jos Dirksen的<Three.js开发指南>,看到第八章了,现在来总结一下threejs中材料的相关知识.顺带也看完了上海交大的张雯莉出的<thr ...

  8. Java ArrayList排序方法详解

    由于其功能性和灵活性,ArrayList是 Java 集合框架中使用最为普遍的集合类之一.ArrayList 是一种 List 实现,它的内部用一个动态数组来存储元素,因此 ArrayList 能够在 ...

  9. 黄聪:JQUERY的datatables插件,Date range filter时间段筛选功能

    需配合moment插件实现:http://momentjs.com/ 演示:http://live.datatables.net/zuciyawi/1/edit HTML代码 <!DOCTYPE ...

  10. 火狐对SVG的兼容性

    使用d3在SVG中画流程图,需要获取流程图的宽,高,来给流程图居中布局.在Chrome中 正常显示,可是在火狐中svg流程图在容器内偏移,查看很不方便.在网上百度了,找不到火狐对d3的兼容性,所以就自 ...