http://blog.xulingmin.com/cocos2d-x-%E6%B8%B2%E6%9F%93/

首页

分类 标签 OPENGL 链接 留言 电视剧 CPLUSPLUS CPPMAN CMAN 视频解析 关于 订阅 2014-04-28| 分类cocos2d-x| 标签cocos2d-x-2.2.3

本文主要针对于2.2.3 cocos2d-x渲染做一分析,TestCpp ios项目启动,⾸先运行的当然就是main.m这个类了啊

  
  
main(int argc, char *argv[]){ NSAutoreleasePool pool =[[ alloc] init]; retVal UIApplicationMain(argc argvnil@"AppController");[pool releasereturn retVal;}

现在跟进到AppController,这里的AppController并不是cocos2d-x中的AppController,而是ios项目中的,找到- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法,在该方法中有这么一句话cocos2d::CCApplication::sharedApplication()->run(),好了咱得去找CCApplication了。

CCApplication run方法中

  • CCApplication::run()ifapplicationDidFinishLaunching()) CCDirectorCaller sharedDirectorCaller startMainLoop];//启动了线程} 0
  • 跟进到startMainLoop中

  • displayLink invalidatedisplayLink ;//实例化CAdisplayLink[NSClassFromString(@"CAdisplayLink") displayLinkWithTarget:self selector:@selectordoCaller:)];//回调doCaller:displayLink setFrameInterval:self.interval];displayLink addToRunLoop:[NSRunLoop currentRunLoop forMode:NSDefaultRunLoopMode];
  • CAdisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CAdisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CAdisplayLink指定的target发送一次指定的selector消息, CAdisplayLink类对应的selector就会被调用一次。

    在doCaller:这个回调方法中,也就这么一句话cocos2d::CCDirector::sharedDirector()->mainLoop(),终于找到了党,CCDirector熟悉了吧。话说CCDirector没有直接实现mainLoop()这个方法,而是请他小弟CCdisplayLinkDirector来实现的。

    CCdisplayLinkDirector的mainLoop()

  • m_bPurgeDirecotorInNextLoop)//m_bPurgeDirecotorInNextLoop在end()方法中设置为true m_bPurgeDirecotorInNextLoop false; purgeDirector();}else(! m_bInvalid) drawScene();//重点还是drawScene()这个方法 // release the objectsCCPoolManagersharedPoolManager()->pop();//每次回调都要清除下pool池
  • 接下来还是先讨论下关于CCDirector吧。在初始化CCDirector方法中,真正的初始化值是sSharedDirector,也就是说在CCDirecor包裹了一成皮,里面真正干事的是它的子类CCdisplayLinkDirector,`static CCdisplayLinkDirector *sSharedDirector = NULL;`

    CCDirecotr的sharedDirector(void)方法

  • s_SharedDirector s_SharedDirector newCCdisplayLinkDirector s_SharedDirector->init//实现是在CCDirector中//真正返回的是CCdisplayLinkDirector
  • 跟进到CCDirecotr的init()方法

  • setDefaultValues//设置默认初始值,从CCConfiguration中读取初始值// 关于scene相关属性m_pRunningScene NULL//正在运行的场景m_pNextScene m_pNotificationNode //可以通过该Node设置悬浮窗或者过渡的节点,该节点不在场景中draw,是单独出来画的m_pobScenesStack CCArraym_pobScenesStack//初始化保存scene的栈// projection delegate if "Custom" projection is usedm_pProjectionDelegate //CCDirectorDelegate类只有当ccDirectorProjection为kCCDirectorProjectionCustom时候才实现运行该类// FPSm_fAccumDt 0.0fm_fFrameRate m_pFPSLabel m_pSPFLabel m_pDrawsLabel m_uTotalFrames m_uFrames m_pszFPS char[10m_pLastUpdate struct cc_timevalm_fSecondsPerFrame // paused ?m_bPaused //在CCDirector::pause(void)设置为true,CCDirector::resume(void)设置为false// purge ?m_bPurgeDirecotorInNextLoop //CCDirector::end()中设置为truem_obWinSizeInPoints CCSizeZerom_pobOpenGLView //CCEGLViewm_fContentScaleFactor 1.0f//缩放因子// schedulerm_pScheduler CCScheduler//CCScheduler定时调度器,// action managerm_pActionManager CCActionManager//Action的管理器m_pSchedulerscheduleUpdateForTargetm_pActionManager kCCPrioritySystem);//将CCActionManager根据nPriority>0,-0,<0分别放到_listEntry类型的m_pUpdatesPosList,m_pUpdates0List,m_pUpdatesNegList。具体逻辑都在CCScheduler中的update()方法中,在后文会具体介绍CCScheduler// touchdispatcherm_pTouchdispatcher CCTouchdispatcher//初始化CCTouchdispatcher,在cclayer的setToucherEnable()中可以通过CCTouchdispatcher::addStandardDelegate(CCTouchDelegate *pDelegate,int nPriority)或者CCTouchdispatcher::addTargetedDelegate(CCTouchDelegate *pDelegate,int nPriority,bool bSwallowstouches)方法将CCTouchDelegate注册到CCTouchdispatcherm_pTouchdispatcher// Keypaddispatcherm_pKeypaddispatcher CCKeypaddispatcher//同上,关于实体键// Accelerometerm_pAccelerometer CCAccelerometer//加速度// create autorelease poolpush//CCPoolManager管理多个CCAutoreleasePool,将CCAutoreleasePool放到CCPoolManager中的m_pReleasePoolStacktrue;
  • 好了,也不讲关于CCDirector的初始化了,还是说说drawScene()吧。

    挺近大别山CCDirecotr的drawScene()方法

  • // calculate "global" dtcalculateDeltaTime//距离上次main loop的时间//tick before glClear: issue #533 m_bPaused//如果暂停 m_pSchedulerupdatem_fDeltaTime//就是刚才在init中所说的CCScheduler的update}/**glClear()函数的作用是用当前缓冲区清除值,也就是glClearColor或者glClearDepth、 glClearIndex、glClearStencil、glClearaccum等函数所指定的值来清除指定的缓冲区,也可以使用glDrawBuffer一次清除多个颜色缓存。比如:glClearColor(0.0,0.0,0.0,0.0);glClear(GL_COLOR_BUFFER_BIT);第一条语句表示清除颜色设为黑色,第二条语句表示实际完成了把整个窗口清除为黑色的任务,glClear()的唯一参数表示需要被清除的缓冲区**/glClearGL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);m_pNextScene setNextScene//初始化场景相关工作,如onEnter()或onExit()kmGLPushmatrix//矩阵压栈// draw the scenem_pRunningScene m_pRunningScenevisit//遍历正在运行的Scene,先遍历的是CCNode的visit(),因为CCScene没有实现该方法// draw the notifications nodem_pNotificationNode m_pNotificationNode//遍历m_pNotificationNode,可以通过该m_pNotificationNode绘制特殊的节点m_bdisplayStats showStats//左下角的fpskmGLPopMatrix//从矩阵栈中弹出m_uTotalFrames++;// swap buffersm_pobOpenGLView m_pobOpenGLViewswapBuffers calculateMPF}
  • OpenGL ES 2.0 已经放弃了固定的渲染流水线,取而代之的是自定义 的各种着色器,在这种情况下变换操作通常需要由开发者来维护。所幸引擎也引入了一套第三方库 Kazmath,它使得我们几 乎可以按照原来 OpenGL ES 1.0 所采用的方式进行开发

    Cocos2d-x2.0中矩阵函数的替代函数

    上诉是关于OpenGL ES 1.0和Kazmath比对图

    跟进到CCNode的visit()方法

  • m_bVisible//如果不可见,则直接返回,不递归迭代return//压入矩阵m_pGrid && m_pGridisActive())//处理CCGridBase的特效beforeDrawthistransform//进行坐标系的变换,没有坐标系的变换,则无法在正确的位置绘制出纹理.变换矩阵等价于坐标系变换.变换矩阵是如何根据当前节点的位置、旋转角度和 缩放比例等属性计算出来的了。形象地讲,transform 方法的任务就是根据当前节点的属性计算出如何把绘图坐标系变换为 新坐标系的矩阵CCNode pNode ;unsigned i ifm_pChildren m_pChildrencount()>//遍历子类 sortAllChildren// draw children zOrder < 0 ccArray arrayData data;先遍历zOrder <的子类for arrayDatanum i++(*)arri pNodem_nZOrder 0break// self drawdraw//绘制自身//遍历剩下的CCNodepNodeelse// 恢复工作m_uOrderOfArrival afterDraw);//出栈
  • 下面继续跟进到transform()方法

  • kmMat4 transfrom4x4// Convert 3x3 into 4x4 matrixCCAffineTransform tmpAffine nodetoParentTransform//获取节点相对于父节点的变换矩阵CGAffinetoGL(&tmpAffine transfrom4x4mat//具体转换transfrom4x414 m_fVertexZ//设置 z 坐标kmGLMultMatrix&transfrom4x4 //右乘一个矩阵transfrom4x4// 处理m_pGrid特效平移相关 m_pCamera != NULL !(bool translate m_obAnchorPointInPointsx 0.0f|| m_obAnchorPointInPointsy kmGLTranslatefRENDER_IN_SUBPIXELx),255)"> RENDER_IN_SUBPIXELy m_pCameralocate(-}
  • 仿射变换

    一般来说游戏中会大量使用旋转,缩放,平移等仿射变换( 所谓仿射变换是指在线性变换的基础上加上平移,平移不是线性变换)。2D计算机图形学中的仿射变换通常是通过和3x3齐次矩阵相乘来实现的。cocos2d中的仿射变换使用了Quartz 2D中的CGAffineTransform类来表示:

  • CGAffineTransformCGFloat a b c d tx ty};typedefCGAffineTransform;
  • CGAffineTransform类表示的齐次矩阵如下,由于变换矩阵最后一列总是[0,0,1],所以被省略了:

    由于cocos2d的绘制使用了OpenglES,因此CGAffineTransform只是用来表示2D仿射变换,最终还是要转化成OpenglES的4x4变换矩阵(Opengl是3D的世界,因此它接受的齐次矩阵是4x4的)。转换工作由CGAffinetoGL(const CGAffineTransform *t,GLfloat *m)来完成,Opengl的变换矩阵以一维数组表示,它和CGAffineTransform的映射关系如下:

  • // | m[0] m[4] m[8] m[12] | | m11 m21 m31 m41 | | a c 0 tx |// | m[1] m[5] m[9] m[13] | | m12 m22 m32 m42 | | b d 0 ty |// | m[2] m[6] m[10] m[14] | <=> | m13 m23 m33 m43 | <=> | 0 0 1 0 |// | m[3] m[7] m[11] m[15] | | m14 m24 m34 m44 | | 0 0 0 1 |m2 m367891115 ta4c12tx1b5d13ty;
  • 变换相关的方法:

    "节点坐标系"指的是以一个节点作为参考而产生的坐标系,换句话说,它的任何一个子节点的坐标值都是 由这个坐标系确定的,通过以上方法,我们可以方便地处理触摸点,也可以方便地计算两个不同坐标系下点之间的方向关系。例如,若我们需要判断一个点在另一坐标系下是否在同一个矩形之内,则可以把此点转换为世界坐标系,再从世界坐 标系转换到目标坐标系中,此后只需要通过 contentSize 属性进行判断即可,相关代码如下:

    IsInBoxCCPoint point pointWorld node1convertToWorldspacepoint pointTarget node2convertToNodeSpacepointWorldCCSize contentSize getContentSize(<= pointTarget contentSizewidthheight

    下面就接着讲draw()方法,在CCNode中,实现方法是空的,我们现在就看下CCSpirit的draw()方法:

  • voidCCSpritevoid CC_PROFILER_START_CATEGORYkCCProfilerCategorySprite "CCSprite - draw"//准备工作,具体啥意思不晓得/** getShaderProgram()->use(); getShaderProgram()->setUniformsForBuiltins(); **/ CC_NODE_DRAW_SETUP//CC_NODE_DRAW_SETUP宏函数用于准备绘制相关环境,设置着色器 ccGLBlendFunc m_sBlendFuncsrcdst //颜色混合函数,与贴图渲染的方式有关 ccGLBindTexture2D m_pobTexturegetName//绑定纹理 enum { kCCVertexAttribFlag_None = 0, kCCVertexAttribFlag_Position = 1 << 0,235)"> kCCVertexAttribFlag_Color = 1 << 1,235)"> kCCVertexAttribFlag_TexCoords = 1 << 2,235)"> kCCVertexAttribFlag_PosColorTex = ( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_Color | kCCVertexAttribFlag_TexCoords ),235)"> }; ccGLEnabLevertexAttribs kCCVertexAttribFlag_PosColorTex //设置OpenGL在后面的渲染中用到顶点位置,定点颜色,纹理坐标属性#define kQuadSize sizeofm_squadbl#ifdef EMSCRIPTENlong offset setGLBufferData4 kQuadSize#elselong)&#endif// EMSCRIPTEN// vertex diff offsetof ccV3F_C4B_T2F vertices glVertexAttribPointerkCCVertexAttrib_Position GL_FLOAT GL_FALSEoffset + diff));//顶点坐标// texCoods texCoordskCCVertexAttrib_TexCoords*)(//纹理坐标// color colorskCCVertexAttrib_Color GL_UNSIGNED_BYTE GL_TRUE//顶点颜色 /* BeginMode */ GL_POINTS //把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制N个点 GL_LInes //把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n条线段,总共绘制N/2条线段 GL_LINE_LOOP //绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制n-1条线段 GL_LINE_STRIP //绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,总共绘制n条线段 GL_TRIANGLES //把每个顶点作为一个独立的三角形,顶点3n-2、3n-1和3n定义了第n个三角形,总共绘制N/3个三角形 GL_TRIANGLE_STRIP //绘制一组相连的三角形,对于奇数n,顶点n、n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1、n和n+2定义了第n个三角形,总共绘制N-2个三角形 GL_TRIANGLE_FAN **/ glDrawArraysGL_TRIANGLE_STRIP//绘制图形 CHECK_GL_ERROR_DEBUG//调试相关处理#if CC_SPRITE_DEBUG_DRAW == 1// draw bounding Box]={ ccptlverticesbrtr}; ccDrawpoly#elif CC_SPRITE_DEBUG_DRAW ==2// draw texture Box s getTextureRect().size offsetPix getoffsetPositionoffsetPixswidth// CC_SPRITE_DEBUG_DRAW CC_INCREMENT_GL_DRAWS CC_PROFILER_STOP_CATEGORY//结束工作}
  • 好了,上诉就是关于cocos2d-x整体绘制过程,从mainloop,到visit(),再到draw(),这就是绘制的一条线。

    青春是一场大雨,即使感冒了,还盼回头再淋一次......微笑永远是一个人身上最好看的东西...

    cocos2d-x 渲染的更多相关文章

    1. three.js模拟实现太阳系行星体系功能

      这篇文章主要介绍了three.js模拟实现太阳系行星体系功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

    2. HTML利用九宫格原理进行网页布局

      这篇文章主要介绍了HTML利用九宫格原理进行网页布局,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    3. HTML5页面无缝闪开的问题及解决方案

      这篇文章主要介绍了HTML5页面无缝闪开方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

    4. ios – 为什么,将nil作为参数从Objc C发送到swift类初始化器,用新对象替换nil参数

      除非属性本身被声明为nonnull:

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

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

    6. ios – 在Swift中对MKCircle进行子类化

      我想通过添加另一个String属性来继承MKCircle,我们称之为“代码”.这个属性不是可选的和常量的,所以我必须从初始化器设置它,对吧?有没有办法定义一个单一的便利初始化器,在这种情况下需要3个参数?本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

    7. ios – 围绕x轴旋转AVAssetWriter的输出180度

      我正在使用AVAssetWriter创建一个Quicktime电影文件.目前输出视频是“倒置”.理论上,我可以通过围绕水平轴旋转180度来纠正这个问题.最好的方法是什么?Appledocs和wikipedia都没有明确说明仿射变换矩阵是如何工作的.并且可能有更好的方式.解决方法如果要围绕z轴旋转视频180度,或者如果你想在x轴上反射

    8. ios – AVAudioPlayer不再使用Swift 2.0/Xcode 7 beta

      对于我的iPhone应用程序中的vartestAudio声明,我在这里收到错误“调用可以抛出,但错误不能从属性初始化程序中抛出”当我转到Xcode7测试版时,就发生了这种情况.如何在Swift2.0中使用此音频剪辑?

    9. ios – 斯威夫特.在初始化所有存储的属性之前在方法调用中使用’self’

      解决方法在初始化所有非可选实例变量之前,您无法在self上调用方法.有几种方法可以解决这个问题.>将属性更改为选项或隐式解包选项(不建议)>使buildCircle()方法静态或只是一个在文件中运行并为所有圆圈调用addSubview()在所有属性初始化并且您调用之后super.init()等等.你必须避免在自己之前打电话给自己class已初始化.

    10. ios – Objective-C警告未找到超类“-init”的指定的初始化程序的方法覆盖

      我在一个应用程序中清理警告,我收到了两次这个警告对于这行代码和这一行我相当新的Objective-C和谷歌这个警告,只是不明白的解决方案我的问题是如何摆脱这些警告?

    随机推荐

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

    返回
    顶部