Cocos2d-x2.0 -- 从点,线,面学起

[Cocos2d-x相关教程来源于红孩儿的游戏编程之路 CSDN博客地址:http://blog.csdn.net/honghaier] 

本章为我的Cocos2d-x教程一书初稿。望各位看官多提建议!

                                            钓鱼岛自古以来属于中国!



         Cocos2d-x  2.0 -- 从 点,线,面学起
             本节所用Cocos2d-x版本:cocos2d-2.0-x-2.0.2

         一个图形引擎,总是由构建点,线,面的绘制功能写起来的。点,线,面。构成了最初的图形基础。所以说,掌握点,线,面是掌握引擎的基础。



         在Cocos2d-x 1.0版本中,提供了使用OpenGL API来创建点,线,面的例子DrawPrimitivesTest。而在2.0中,同样的例子名称,而内部实现却差别巨大。我们知道,在Cocos2d-x 2.0版本,相较于1.0,增加了shader的支持,而DrawPrimitivesTest这个例子,就是学习基础Shader的最好教程。



学前提示:

        OpenGL着色语言(GLSL――OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。



       打开TestCpp工程,找到Classes下的DrawPrimitivesTest目录。打开两个文件:

DrawPrimitivesTest.h/cpp

[cpp] view plaincopy
#ifndef _DRAW_PRIMITIVES_TEST_H_ 
#define _DRAW_PRIMITIVES_TEST_H_ 
//包含Cocos2d头文件 
////----#include "cocos2d.h" 
//使用TestScene这个CCScene类 
#include "../testBasic.h" 
//定义派生于CCLayer的类DrawPrimitivesTest,重载draw用于进行手动渲染处理 
class DrawPrimitivesTest : public CCLayer 

public: 
//构造 
    DrawPrimitivesTest(); 
    //析构 
virtual void draw(); 
}; 
//定义派生于TestScene的类DrawPrimitiveTestScene,做为TestCpp工程中TestController类集中管理的各个小功能例子的场景 
class DrawPrimitivesTestScene : public TestScene 

public: 
//重载启动此功能例子的场景函数 
    virtual void runThisTest(); 
}; 
 
#endif 



OK,头文件看完了,现在看CPP文件:

[cpp] view plaincopy
#include "DrawPrimitivesTest.h" 
//构造函数 
DrawPrimitivesTest::DrawPrimitivesTest() 


//手动处理的渲染函数 
void DrawPrimitivesTest::draw() 

//取得屏幕大小 
    CCSize s = CCDirector::sharedDirector()->getWinSize(); 
//检测是否有OpenGL错误发生,如果有则打印错误 
    CHECK_GL_ERROR_DEBUG(); 
 
    //平滑模式,即高洛德着色 
//    glEnable(GL_LINE_SMOOTH); 
//绘制一条件,参1为起点,参2为终点,ccp为生成CCPoint的宏 
    ccDrawLine( ccp(0, 0), ccp(s.width, s.height) ); 
 
//检测是否有OpenGL错误发生,如果有则打印错误 
    CHECK_GL_ERROR_DEBUG(); 
 
    //设置线宽 
glLineWidth( 5.0f ); 
//设置后面要进行绘制时所用的色彩 
ccDrawColor4B(255,0,0,255); 
//绘制线条 
ccDrawLine( ccp(0, s.height), ccp(s.width, 0) ); 
 
//检测是否有OpenGL错误发生,如果有则打印错误 
    CHECK_GL_ERROR_DEBUG(); 
 
    //设置点的大小 
ccPointSize(64); 
//设置后面要进行绘制时所用的色彩 
ccDrawColor4B(0,0,255,128); 
//绘制一个点 
    ccDrawPoint( ccp(s.width / 2, s.height / 2) ); 
//检测是否有OpenGL错误发生,如果有则打印错误 
    CHECK_GL_ERROR_DEBUG(); 
 
// 绘制四个点 
    //这里创建位置点数组 
CCPoint points[] = { ccp(60,60), ccp(70,70), ccp(60,70), ccp(70,60) }; 
ccPointSize(4); 
//设置后面要进行绘制时所用的色彩 
ccDrawColor4B(0,255,255,255); 
//使用位置点数组做为四个顶点的位置进行绘制 
    ccDrawPoints( points, 4); 
//检测是否有OpenGL错误发生,如果有则打印错误 
    CHECK_GL_ERROR_DEBUG(); 
 
//绘制一个绿色圆 
glLineWidth(16); 
//设置后面要进行绘制时所用的色彩 
ccDrawColor4B(0, 255, 0, 255); 
    //绘制圆函数,参1是中心点,参2为半径,参3为圆的逆时针旋转角度,参4为圆的平均切分段数,最后一个参数是指定是否从圆分段起止点位置向圆中心连线,这里不进行连线 
    ccDrawCircle( ccp(s.width/2,  s.height/2), 100, 0, 10, false); 
//检测是否有OpenGL错误发生,如果有则打印错误 
    CHECK_GL_ERROR_DEBUG(); 
 
//绘制一个蓝色圆,进行连线 
glLineWidth(2); 
//设置后面要进行绘制时所用的色彩 
ccDrawColor4B(0, 255, 255, 255); 
//这里使用了一个宏CC_DEGREES_TO_RADIANS把角度值转为弧度。转动了90度,目的是为了让中心连线垂直显示。 
    ccDrawCircle( ccp(s.width/2, s.height/2), 50, CC_DEGREES_TO_RADIANS(90), 50, true); 
//继续检错 
     CHECK_GL_ERROR_DEBUG(); 
 
// 绘制多边形线框。 
    ccDrawColor4B(255, 255, 0, 255); 
    glLineWidth(10); 
CCPoint vertices[] = { ccp(0,0), ccp(50,50), ccp(100,50), ccp(100,100), ccp(50,100) }; 
//这里绘制多边形线框函数,使用上面的顶点数组做为多边形线框的顶点位置,第二个参数为顶点数量,第三个参数指定是否首尾自动连接形成封闭线框。 
//注:其实这个函数拆成两个函数比较好,一个是去掉最后一个参数的ccDrawPoly,用于绘制默认封闭的多边形线框。另一个ccDrawLineList用于绘制线段列。 
    ccDrawPoly( vertices, 5, false); 
//继续检错 
    CHECK_GL_ERROR_DEBUG(); 
     
    //绘制实体多边形 
    glLineWidth(1); 
    CCPoint filledVertices[] = { ccp(0,120), ccp(50,120), ccp(50,170), ccp(25,200), ccp(0,170) }; 
    //这里绘制内部填充指定色彩的多边形 
    ccDrawSolidPoly(filledVertices, 5, ccc4f(0.5f, 0.5f, 1, 1 ) ); 
 
    // 绘制封闭多边形线框,这里就是个三角形线框了。 
    ccDrawColor4B(255, 0, 255, 255); 
    glLineWidth(2); 
    CCPoint vertices2[] = { ccp(30,130), ccp(30,230), ccp(50,200) }; 
    ccDrawPoly( vertices2, 3, true); 
 
    CHECK_GL_ERROR_DEBUG(); 


        后面绘制贝塞尔曲线,要了解贝塞尔曲线,请在维基百科里学习一下

http://zh.wikipedia.org/zh-cn/貝茲曲線#.E4.BA.8C.E6.AC.A1.E6.96.B9.E8.B2.9D.E8.8C.B2.E6.9B.B2.E7.B7.9A



        下面是绘制二次贝塞尔曲线,类似下图,图是从维基百科上找来的,恕我没那个能力画图了暂拿来用讲原理







[cpp] view plaincopy
//这个就是cocos2d-x2.0绘制二次贝塞尔曲线函数,三个参数分别如图中P0,P1,P2,不过在咱们这个例子中,正好与之上下镜像。最后一个是曲线构成所用的线段数,当然,线段数越多曲线越平滑。 
ccDrawQuadBezier(ccp(0,s.height), ccp(s.width/2,s.height/2), ccp(s.width,s.height), 50); 
//检错 
CHECK_GL_ERROR_DEBUG(); 

        然后是绘制高阶贝塞尔曲线,类似下图





[cpp] view plaincopy
//前四个参数应该对应的是P0,P1,P3,P4,图上的P2可以省去。最后一个是曲线构成所用的线段数。 
    ccDrawCubicBezier(ccp(s.width/2, s.height/2), ccp(s.width/2+30,s.height/2+50), ccp(s.width/2+60,s.height/2-50),ccp(s.width, s.height/2),100); 
 
    CHECK_GL_ERROR_DEBUG(); 



再继续



[cpp] view plaincopy
    //绘制黄色实心四边形色块。 
     CCPoint vertices3[] = {ccp(60,160), ccp(70,190), ccp(100,190), ccp(90,160)}; 
    ccDrawSolidPoly( vertices3, 4, ccc4f(1,1,0,1) ); 
 
    // 重置绘制状态 
     glLineWidth(1); 
    ccDrawColor4B(255,255,255,255); 
    ccPointSize(1); 
 
    CHECK_GL_ERROR_DEBUG(); 



[cpp] view plaincopy
//启动场景 
void DrawPrimitivesTestScene::runThisTest() 

    //用new 创建一个DrawPrimitivesTest实例对象做为场景中要显示的层。 
    CCLayer* pLayer = new DrawPrimitivesTest(); 
    addChild(pLayer); 
    pLayer->release(); 
    //替换当前正在运行的基它实例场景 
    CCDirector::sharedDirector()->replaceScene(this); 





好吧,运行一下,看图:



      一个一个来对照代码看一看,我们发现,其在调用ccPointSize进行点的大小设置时根本就不管用。 有点无语,可见这一版扣扣二弟放出来还是有点仓促~

      大家先看罢,吾上WC下,一会儿见。



      约过了五分钟………..



      现在大家看懂照截图看懂代码了吧。那我们更深入一步吧。



      既然画点有点问题咱就先看画点。在ccDrawPoint函数调用处加断点。F11进入CCDrawingPrimitives.cpp:



[cpp] view plaincopy
void ccDrawPoint( const CCPoint& point ) 

    //Shader初始化函数,一会儿再解。 
    lazy_init(); 
 
    //定义顶点变量,填充位置 
    ccVertex2F p; 
    p.x = point.x; 
    p.y = point.y; 
    //设置OpenGL在后面的渲染中用到顶点位置属性。 
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
//这里对下面的渲染使用了Shader 
s_pShader->use(); 
//设置Shader的输入参数:最终矩阵结果值(世界x观察x投影矩阵)。     
    s_pShader->setUniformForModelViewProjectionMatrix(); 
    //设置Shader的输入参数:色彩。取s_tColor.r地址做为float4参数值的地址传入。实际Shader使用的是s_tColor的所有四个float值。 
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); 
//设置Shader的输入参数:点大小 
    s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize); 
    //将p设置为使用的顶点位置参数 
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, &p); 
//绘制顶点数组,参1为要绘制的图形为点,参2为顶点起始索引,参3为顶点数量 
    glDrawArrays(GL_POINTS, 0, 1); 
    //渲染批次(DrawCall)统计 
    CC_INCREMENT_GL_DRAWS(1); 




       回头看lazy_init,作者命名lazy_init的原因难道是说:我懒,初始化的相关处理就不每次写了,放函数里用多省心~。

      要看函数,先看文件最上部作者定义的静态变量。



[cpp] view plaincopy
static bool s_bInitialized = false; //用于标记是否初始化 
static CCGLProgram* s_pShader = NULL;  //Shader代码程式 
static int s_nColorLocation = -1;       //Shader输入色彩的变量位置索引 
static ccColor4F s_tColor = {1.0f,1.0f,1.0f,1.0f};  //色彩值 
static int s_nPointSizeLocation = -1;                   //Shader 输入的大小的变量位置索引 
static GLfloat s_fPointSize = 1.0f;                 //大小值 



然后分析这个函数:



[cpp] view plaincopy
static void lazy_init( void ) 

    //如果尚未初始化,则进行初始化,已经初始化则略过 
    if( ! s_bInitialized ) { 
 
        //通过字符串参数找到所对应Shader文件的Shader代码程式 
        s_pShader = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_Position_uColor); 
        //取得Shader对应变量"u_color"在程式片段中的位置索引,返回给s_nColorLocation。 
        s_nColorLocation = glGetUniformLocation( s_pShader->getProgram(), "u_color"); 
    //检错 
CHECK_GL_ERROR_DEBUG(); 
    //取得Shader对应变量"u_pointSize"在程式片段中的位置索引,返回给s_nPointSizeLocation。 
 
        s_nPointSizeLocation = glGetUniformLocation( s_pShader->getProgram(), "u_pointSize"); 
    //检错 
    CHECK_GL_ERROR_DEBUG(); 
        //设置初始化完成 
        s_bInitialized = true; 
    } 




         lazy_init函数指明了当前这些绘制点,线,面所用的Shader为字符串变量kCCShader_Position_uColor所对应的Shader。在kCCShader_Position_uColor上按F12进入CCGLProgram.h,这里定义了不少字符串变量:





[cpp] view plaincopy
#define kCCShader_PositionTextureColor            "ShaderPositionTextureColor" 
#define kCCShader_PositionTextureColorAlphaTest    "ShaderPositionTextureColorAlphaTest" 
#define kCCShader_PositionColor                    "ShaderPositionColor" 
#define kCCShader_PositionTexture                "ShaderPositionTexture" 
#define kCCShader_PositionTexture_uColor        "ShaderPositionTexture_uColor" 
#define kCCShader_PositionTextureA8Color        "ShaderPositionTextureA8Color" 
#define kCCShader_Position_uColor                "ShaderPosition_uColor" 



        Shader程序在哪呢?我们追查一下CCShaderCache::sharedShaderCache()->programForKey函数。进入到CCShaderCache.cpp文件,这里有一个CCShaderCache类,顾名思义,Shader缓冲。代码不多,详细解之:



[cpp] view plaincopy
#ifndef __CCSHADERCACHE_H__ 
#define __CCSHADERCACHE_H__ 
 
//使用到目录相关处理类 
#include "cocoa/CCDictionary.h" 
//使用Cocos2d命名空间 
NS_CC_BEGIN 
//声明使用类CCGLProgram 
class CCGLProgram; 
//由CCObject派生类CCShaderCache 
class CC_DLL CCShaderCache : public CCObject  

public: 
    //构造函数 
    CCShaderCache(); 
    //析构 
    virtual ~CCShaderCache(); 
    //返回单件类实例指针 
    static CCShaderCache* sharedShaderCache(); 
 
   //释放所管理的所有Shader代码片段 
    static void purgeSharedShaderCache(); 
 
    //从相关文件载入默认的一些Shader代码片段 
    void loadDefaultShaders(); 
     
   //从相关文件重新载入默认的一些Shader代码片段 
    void reloadDefaultShaders(); 
 
   //从容器中查询指定名称的Shader代码片段 
    CCGLProgram * programForKey(const char* key); 
 
    //将一个Shader代码片段指定名称放入容器 
    void addProgram(CCGLProgram* program, const char* key); 
 
private: 
    //初始化 
bool init(); 
//按照顶点格式类型载入相应的Shader代码片段 
    void loadDefaultShader(CCGLProgram *program, int type); 
    //目录管理类 
    CCDictionary* m_pPrograms; 
 
}; 
 
NS_CC_END 
 
#endif /* __CCSHADERCACHE_H__ */ 



Cpp文件:



[cpp] view plaincopy
#include "CCShaderCache.h" 
#include "CCGLProgram.h" 
#include "ccMacros.h" 
#include "ccShaders.h" 
 
NS_CC_BEGIN 
//枚举,Shader代码片段中的一些顶点格式类型 
enum {   
    kCCShaderType_PositionTextureColor, //顶点格式为位置+纹理UV+材质色 
    kCCShaderType_PositionTextureColorAlphaTest,    //顶点格式为顶点格式为位置+纹理UV+材质色+用于AlphaTest的ALPHA值 
 
    kCCShaderType_PositionColor,// 顶点格式为位置+材质色 
 
    kCCShaderType_PositionTexture, //顶点格式为位置+纹理UV  
 
    kCCShaderType_PositionTexture_uColor, //顶点格式为位置+纹理UV+材质色 
 
    kCCShaderType_PositionTextureA8Color, //顶点格式为位置+纹理UV+灰度 
 
    kCCShaderType_Position_uColor, //顶点格式为位置+材质色 
 
     
    kCCShaderType_MAX,  //枚举结束值 
}; 
 
//静态Shader缓冲指针 
static CCShaderCache *_sharedShaderCache = 0; 
 
//取得Shader缓冲单件实例指针 
CCShaderCache* CCShaderCache::sharedShaderCache() 

    if (!_sharedShaderCache) { 
        _sharedShaderCache = new CCShaderCache(); 
        if (!_sharedShaderCache->init()) 
        { 
            CC_SAFE_DELETE(_sharedShaderCache); 
        } 
    } 
    return _sharedShaderCache; 

//释放 
void CCShaderCache::purgeSharedShaderCache() 

    //安全释放并置空 
    CC_SAFE_RELEASE_NULL(_sharedShaderCache); 

 
//构造 
CCShaderCache::CCShaderCache() 
: m_pPrograms(0) 

 

//析构 
CCShaderCache::~CCShaderCache() 

    CCLOGINFO("cocos2d deallocing 0x%X", this); 
    m_pPrograms->release(); 

//初始化 
bool CCShaderCache::init() 

    //创建目录管理器 
m_pPrograms = new CCDictionary(); 
//从相关Shader文件载入默认的Shader代码片段 
    loadDefaultShaders(); 
    return true; 

//从相关Shader文件载入默认的Shader代码片段 
void CCShaderCache::loadDefaultShaders() 

    //新建一个Shader代码片段 
CCGLProgram *p = new CCGLProgram(); 
//通过类型枚举值kCCShaderType_PositionTextureColor加载相应的Shader文件到Shader代码片段中,这里是加载kCCShaderType_PositionTexture_uColor类型 
    loadDefaultShader(p, kCCShaderType_PositionTextureColor); 
    //将Shader代码片段与代码片段字符串名称进行绑定存入容器 
    m_pPrograms->setObject(p, kCCShader_PositionTextureColor); 
    p->release(); 
 
    //同上,创建Shader代码片段并加载其它类型 
    p = new CCGLProgram(); 
    loadDefaultShader(p, kCCShaderType_PositionTextureColorAlphaTest); 
 
    m_pPrograms->setObject(p, kCCShader_PositionTextureColorAlphaTest); 
    p->release(); 
 
   //新建第三种Shader代码片段 
    p = new CCGLProgram(); 
    loadDefaultShader(p, kCCShaderType_PositionColor); 
 
    m_pPrograms->setObject(p, kCCShader_PositionColor); 
    p->release(); 
 
   //新建第四种Shader代码片段 
    p = new CCGLProgram(); 
    loadDefaultShader(p, kCCShaderType_PositionTexture); 
 
    m_pPrograms->setObject(p, kCCShader_PositionTexture); 
    p->release(); 
 
   //新建第五种Shader代码片段 
    p = new CCGLProgram(); 
    loadDefaultShader(p, kCCShaderType_PositionTexture_uColor); 
 
    m_pPrograms->setObject(p ,kCCShader_PositionTexture_uColor); 
    p->release(); 
 
   //新建第六种Shader代码片段 
    p = new CCGLProgram(); 
    loadDefaultShader(p, kCCShaderType_PositionTextureA8Color); 
     
    m_pPrograms->setObject(p, kCCShader_PositionTextureA8Color); 
    p->release(); 
 
   //新建第七种Shader代码片段 
    p = new CCGLProgram(); 
    loadDefaultShader(p, kCCShaderType_Position_uColor); 
     
    m_pPrograms->setObject(p, kCCShader_Position_uColor); 
    p->release();     

 
//重新载入 
void CCShaderCache::reloadDefaultShaders() 

//通过字符串名称找到对应的Shader代码片段 
// 
CCGLProgram *p = programForKey(kCCShader_PositionTextureColor);     
//重置 
p->reset(); 
//重新载入 
    loadDefaultShader(p, kCCShaderType_PositionTextureColor); 
 
    // 同上,重新载入其它类型的Shader代码片段 
    p = programForKey(kCCShader_PositionTextureColorAlphaTest); 
    p->reset();     
    loadDefaultShader(p, kCCShaderType_PositionTextureColorAlphaTest); 
     
    p = programForKey(kCCShader_PositionColor); 
    p->reset(); 
    loadDefaultShader(p, kCCShaderType_PositionColor); 
     
    p = programForKey(kCCShader_PositionTexture); 
    p->reset(); 
    loadDefaultShader(p, kCCShaderType_PositionTexture); 
     
    p = programForKey(kCCShader_PositionTexture_uColor); 
    p->reset(); 
    loadDefaultShader(p, kCCShaderType_PositionTexture_uColor); 
     
    p = programForKey(kCCShader_PositionTextureA8Color); 
    p->reset(); 
    loadDefaultShader(p, kCCShaderType_PositionTextureA8Color); 
     
    p = programForKey(kCCShader_Position_uColor); 
    p->reset(); 
    loadDefaultShader(p, kCCShaderType_Position_uColor);   

 
//按照顶点格式类型载入相应的Shader文件,组成代码片段 
void CCShaderCache::loadDefaultShader(CCGLProgram *p, int type) 

    switch (type) { 
        case kCCShaderType_PositionTextureColor: 
            //顶点格式为位置+纹理UV+材质色 
              //从“ccShader_PositionTextureColor_vert.h”和“ccShader_PositionTextureColor_frag.h”中为Shader代码片段加载VS和PS 
p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionTextureColor_frag); 
            //将Shader代码的输入位置参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 
            //将Shader代码的输入色彩参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); 
//将Shader代码的输入纹理坐标参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 
             
            break; 
        case kCCShaderType_PositionTextureColorAlphaTest: 
            //顶点格式为位置+纹理UV+材质色+用于AlphaTest的A通道 
           //从 p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionTextureColorAlphaTest_frag); 
           //将Shader代码的输入位置参数名称与索引进行绑定  
            p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 
           //将Shader代码的输入色彩参数名称与索引进行绑定  
            p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); 
             //将Shader代码的输入玟理坐标参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 
 
            break; 
        case kCCShaderType_PositionColor:   
            //顶点格式为位置+材质色 
p->initWithVertexShaderByteArray(ccPositionColor_vert ,ccPositionColor_frag); 
             
            //将Shader代码的输入位置参数名称与索引进行绑定 p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 
            //将Shader代码的输入色彩参数名称与索引进行绑定p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); 
 
            break; 
        case kCCShaderType_PositionTexture: 
            //顶点格式为位置+纹理坐标p->initWithVertexShaderByteArray(ccPositionTexture_vert ,ccPositionTexture_frag); 
           //将Shader代码的输入位置参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 
           //将Shader代码的输入色彩参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 
 
            break; 
        case kCCShaderType_PositionTexture_uColor: 
            //顶点格式为位置+纹理坐标p->initWithVertexShaderByteArray(ccPositionTexture_uColor_vert, ccPositionTexture_uColor_frag); 
           //将Shader代码的输入位置参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 
            //将Shader代码的输入纹理坐标参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 
 
            break; 
        case kCCShaderType_PositionTextureA8Color: 
             //顶点格式为位置+灰度值p->initWithVertexShaderByteArray(ccPositionTextureA8Color_vert, ccPositionTextureA8Color_frag); 
            //将Shader代码的输入位置参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); 
//将Shader代码的输入色彩参数名称与索引进行绑定  
            p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); 
            //将Shader代码的输入纹理坐标参数名称与索引进行绑定 
            p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); 
 
            break; 
        case kCCShaderType_Position_uColor: 
            p->initWithVertexShaderByteArray(ccPosition_uColor_vert, ccPosition_uColor_frag);     
            //将Shader代码的输入位置参数名称与索引进行绑定 
            p->addAttribute("aVertex", kCCVertexAttrib_Position);     
            break; 
        default: 
            //如果是其它打印错误 
            CCLOG("cocos2d: %s:%d, error shader type", __FUNCTION__, __LINE__); 
            return; 
    } 
    //将VS与PS进行连接 
p->link(); 
//更新输入参数 
    p->updateUniforms(); 
    //检错 
    CHECK_GL_ERROR_DEBUG(); 

//通过字符串键值查询出相应的Shader代码片段。 
CCGLProgram* CCShaderCache::programForKey(const char* key) 

    return (CCGLProgram*)m_pPrograms->objectForKey(key); 

//将一个新的Shader代码片段设置字符串键值存储到容器中 
void CCShaderCache::addProgram(CCGLProgram* program, const char* key) 

    m_pPrograms->setObject(program, key); 

 
NS_CC_END 



         好了,从这个文件我们可以知道。Shader缓冲类是对游戏中用到的Shader文件和代码片段进行统一的管理。

        看明白了,自然找一下相应的Shader文件。

        可以在ccShaders.cpp中的相应VS,PS的名称上右键弹出菜单第一项打开相应的Shader文件,也可以到Cocos2d-x解压目录下的cocos2dx\shaders目录下找到这些h文件,文件不多,那既然画点,线,面用到的Shader是"ShaderPosition_uColor",在CCShaderCache::loadDefaultShader函数中我们得知其对应的VS文件是:ccShader_Position_uColor_vert.h,PS文件是:ccShader_Position_uColor_frag.h

        注:作者用.h来做为扩展名,其实这个用什么做扩展名都无所谓,总之是文本形式的文件就OK!

我们找来看一下:ccShader_Position_uColor_vert.h:

[html] view plaincopy
                                                    
attribute vec4 a_position;          //定义vec4接口变量a_position                      
uniform    mat4 u_MVPMatrix;       //传入mat4参数u_MVPMatrix,World矩阵乘View矩阵乘Proj矩阵的累积矩阵         
uniform    vec4 u_color;           //传入vec4参数u_color,用于色彩 
uniform float u_pointSize;         //传入float 参数u_pointSize,用于点的大小                    
//如果使用的是OpenGL的ES版本,使用低精度的vec4变量 v_fragmentColor                                                    
#ifdef GL_ES                                         
varying lowp vec4 v_fragmentColor;                     
#else   
//如果使用的是OpenGL,使用高精度的vec4变量 v_fragmentColor                                               
varying vec4 v_fragmentColor;                         
#endif                                                 
//VS的入口函数                                                     
void main()                                             
{              
//顶点x矩阵u_MVPMatrix,将结果设置为VS返回屏幕最终显示位置                                     
gl_Position = u_MVPMatrix * a_position;  
//使用变量v_fragmentColor设置为VS输出的顶点大小            
gl_PointSize = u_pointSize; 
//设置色彩变量值                         
    v_fragmentColor = u_color;                         
}                                                     
"; 



ccShader_Position_uColor_frag.h:



[html] view plaincopy
    
//如果使用的是OpenGL的ES版本,float精度设为低精度                                     
#ifdef GL_ES                             
precision lowp float;                     
#endif                                     
//这里vec4变量 v_fragmentColor,跟据OpenGL版本选择使用精度。                     
varying vec4 v_fragmentColor;             
//PS的入口函数                          
void main()                                 
{                                         
    //使用变量v_fragmentColor设为Opengl的PS输出色彩值 
gl_FragColor = v_fragmentColor;         
}                                         
"; 





        前边我们说过,此例程有个BUG。虽然传入了点的大小,但是实际却没有设置成功。作者应该是忘了在渲染前打开启用VS顶点大小功能,回到DrawPrimitivesTest.cpp,把开启和闭闭VS顶点大小的代码加上:



[cpp] view plaincopy
// 设置点大小64 
ccPointSize(64); 
//半透明的的蓝色 
ccDrawColor4B(0,0,255,128); 
//glEnable(GL_POINT_SPRITE_ARB);加上此句为正方形,否则为圆形 
//此处启用VS顶点大小功能 
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); 
//绘制点 
ccDrawPoint( ccp(s.width / 2, s.height / 2) );   
//检错 
CHECK_GL_ERROR_DEBUG(); 
// 绘制四个点 
CCPoint points[] = { ccp(60,60), ccp(70,70), ccp(60,70), ccp(70,60) }; 
//点大小为4 
ccPointSize(4); 
//纯青色 
ccDrawColor4B(0,255,255,255); 
//绘制四个点 
ccDrawPoints( points, 4); 
//此处关闭VS顶点大小功能 
    glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); 
//glDisable(GL_POINT_SPRITE_ARB);    
    CHECK_GL_ERROR_DEBUG(); 



可以看到中心的半透明蓝色圆点和左下方四个小青圆点。





       看完ccDrawPoint函数,我们重新进入 CCDrawingPrimitives.cpp看其它的绘制图形函数:



[cpp] view plaincopy
//绘制多个点 
//参1为顶点位置数组 
//参2为顶点数量 
void ccDrawPoints( const CCPoint *points, unsigned int numberOfPoints ) 

//初始化 
lazy_init(); 
//Shader使用顶点位置属性 
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
//后面的渲染应用Shader 
s_pShader->use(); 
//设置Shader中的最终结果矩阵参数 
s_pShader->setUniformForModelViewProjectionMatrix(); 
//设置Shader中的色彩参数,取s_tColor.r地址做为float4参数值的地址传入。实际Shader使用的是s_tColor的所有四个float值。 
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); 
//设置Shader中的大小参数 
    s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize); 
 
//这里创建顶点位置数组,用于存储指定数量的顶点位置。这段代码放在这个位置有问题。看下一句分析。 
    ccVertex2F* newPoints = new ccVertex2F[numberOfPoints]; 
 
//如果是32位的系统(Iphone和32位Windows),这里似乎应该使用一个全局变量 
if( sizeof(CCPoint) == sizeof(ccVertex2F) ) 

//将参数指向的顶点位置数据与位置属性进行绑定 
        glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, points); 
    } 
    else 

//ccVertex2F* newPoints = new ccVertex2F[numberOfPoints]应该放在这里更好。因为如果是32位系统,则根本没有必要创建顶点数组。同样把后面的CC_SAFE_DELETE_ARRAY(newPoints);放在这个else的大括号内。 
 
        // 如果是64位的系统,则遍历填充数据 
        for( unsigned int i=0; i<numberOfPoints;i++) { 
            newPoints[i].x = points[i].x; 
            newPoints[i].y = points[i].y; 
        } 
//将新创建的顶点位置数组与位置属性进行绑定  
  glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, newPoints); 
    } 
//绘制顶点数组,参1为要绘制的图形为点,参2为顶点起始索引,参3为顶点数量 
    glDrawArrays(GL_POINTS, 0, (GLsizei) numberOfPoints); 
//释放申请的顶点数组占用内存。各位看官,这里可以研讨一下:我个人对在渲染时new这样一个数组后又delete的做法是感觉比较不妥的,可能产生碎片。如果没有多线程渲染,倒是不如直接在开始时就创建好一个固定长的数组,这里直接使用。缺点当然是定长可能会有浪费,但是所有渲染函数可以共用,避免了申请内存的时间开销,效率非常高,而且存的数据不多,占用不了太多的内存。 
 
    CC_SAFE_DELETE_ARRAY(newPoints); 
//统计渲染调用次数 
    CC_INCREMENT_GL_DRAWS(1); 

 
//画线函数 
//参1:起点位置 
//参2:终点位置 
void ccDrawLine( const CCPoint& origin, const CCPoint& destination ) 

//初始化 
    lazy_init(); 
//定义2个顶点的位置数组 
    ccVertex2F vertices[2] = { 
        {origin.x, origin.y}, 
        {destination.x, destination.y} 
    }; 
//设定后面的渲染使用Shader 
s_pShader->use(); 
//检错 
CHECK_GL_ERROR_DEBUG(); 
//设置Shader中的最终结果矩阵参数 
    s_pShader->setUniformForModelViewProjectionMatrix(); 
CHECK_GL_ERROR_DEBUG(); 
//设置Shader中的色彩参数,取s_tColor.r地址做为float4参数值的地址传入。实际Shader使用的是s_tColor的所有四个float值。 
    s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); 
CHECK_GL_ERROR_DEBUG(); 
//设置Shader中的大小参数 
    s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize); 
    CHECK_GL_ERROR_DEBUG(); 
//Shader使用顶点位置属性 
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
CHECK_GL_ERROR_DEBUG(); 
//将新创建的顶点位置数组与位置属性进行绑定  
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 
CHECK_GL_ERROR_DEBUG(); 
//绘制顶点数组,参1为要绘制的图形为线段,参2为顶点起始索引,参3为顶点数量 
    glDrawArrays(GL_LINES, 0, 2); 
//统计渲染调用次数 
    CC_INCREMENT_GL_DRAWS(1); 

//绘制矩形线框 
//参1:左下角位置点 
//参2:右上角位置点 
void ccDrawRect( CCPoint origin, CCPoint destination ) 

//绘制四条边,这样写倒是简单,不过效率不高,因为需要设多次渲染状态并渲染调用多次。不如在这里创建顶点数组调ccDrawPoly 效率高,设一次渲染状态,调用一次渲染处理就OK了。 
 
    ccDrawLine(CCPointMake(origin.x, origin.y), CCPointMake(destination.x, origin.y)); 
    ccDrawLine(CCPointMake(destination.x, origin.y), CCPointMake(destination.x, destination.y)); 
    ccDrawLine(CCPointMake(destination.x, destination.y), CCPointMake(origin.x, destination.y)); 
    ccDrawLine(CCPointMake(origin.x, destination.y), CCPointMake(origin.x, origin.y)); 

//绘制实心矩形 
//参1:左下角位置点 
//参2:右上角位置点 
//参3:填充色彩 
void ccDrawSolidRect( CCPoint origin, CCPoint destination, ccColor4F color ) 

//创建四个顶点的位置数组 
    CCPoint vertices[] = { 
        origin, 
        ccp(destination.x, origin.y), 
        destination, 
        ccp(origin.x, destination.y) 
    }; 
//使用顶点位置数组做为参数调用绘制填充多边形 
    ccDrawSolidPoly(vertices, 4, color ); 

//绘制多线形线框 
//参1:顶点位置数组 
//参2:顶点数组中的顶点数量 
//参3:是否封闭,即是否首尾相连 
void ccDrawPoly( const CCPoint *poli, unsigned int numberOfPoints, bool closePolygon ) 

//初始化 
    lazy_init(); 
//设定后面的渲染使用Shader 
s_pShader->use(); 
//设置Shader中的最终结果矩阵参数 
s_pShader->setUniformForModelViewProjectionMatrix(); 
//设置Shader中的顶点色彩参数 
    s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); 
//Shader使用顶点位置属性 
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
 
//无奈,又把new放判断外边了。 
    ccVertex2F* newPoli = new ccVertex2F[numberOfPoints]; 
 
    //32位系统,实际用不到newPoli ,将参数poli与顶点位置属性绑定即可 
    if( sizeof(CCPoint) == sizeof(ccVertex2F) ) 
        glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, poli); 
 
    else 
    { 
        //64位系统,填充一下数据 
        for( unsigned int i=0; i<numberOfPoints;i++) { 
            newPoli[i].x = poli[i].x; 
            newPoli[i].y = poli[i].y; 
        } 
//将newPoli与顶点位置属性绑定 
        glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, newPoli); 
    } 
//是否首尾相连 
    if( closePolygon ) 
        glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) numberOfPoints); 
    else 
        glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) numberOfPoints); 
//释放申请的顶点位置数组 
    CC_SAFE_DELETE_ARRAY(newPoli); 
//统计渲染调用次数 
    CC_INCREMENT_GL_DRAWS(1); 

//绘制填充色彩的多边形 
//参1:顶点数组 
//参2:顶点数量 
//参3:色彩值 
void ccDrawSolidPoly( const CCPoint *poli, unsigned int numberOfPoints, ccColor4F color ) 

//初始化 
    lazy_init(); 
//初始化 
    lazy_init(); 
//设定后面的渲染使用Shader 
s_pShader->use(); 
//设置Shader中的最终结果矩阵参数 
s_pShader->setUniformForModelViewProjectionMatrix(); 
//设置Shader中的顶点色彩参数 
    s_pShader->setUniformLocationWith4fv(s_nColorLocation,(GLfloat*) &s_tColor.r, 1); 
//Shader使用顶点位置属性 
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
 
    //不说了,你懂的 
    ccVertex2F* newPoli = new ccVertex2F[numberOfPoints]; 
    if( sizeof(CCPoint) == sizeof(ccVertex2F) ) 
    { 
        glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, poli); 
    } 
    else 
    { 
        // Mac on 64-bit 
        for( unsigned int i=0; i<numberOfPoints;i++) 
        { 
            newPoli[i] = vertex2( poli[i].x, poli[i].y ); 
        } 
        glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, newPoli); 
    }     
//这里参数1改为GL_TRIANGLE_FAN,即按扇面顺序方式绘制三角形。 
    glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) numberOfPoints); 
//你懂的 
    CC_SAFE_DELETE_ARRAY(newPoli); 
    CC_INCREMENT_GL_DRAWS(1); 

//绘制圆,在画圆算法中,圆其实是由多个小线段连线构成的封闭多边形线框。段数直多,就越像圆。 
//参1:圆心位置 
//参2:半径 
//参3:圆在逆时针方向的转动角度 
//参4:段数 
//参5:是否在段起止点处向圆心连线 
void ccDrawCircle( const CCPoint& center, float radius, float angle, unsigned int segments, bool drawLineToCenter) 

//初始化 
    lazy_init(); 
//这里设变量additionalSegment为增加段的数量,默认为1。即用来做最后尾部与首部相连以形成封闭线框的线段。 
int additionalSegment = 1; 
//如果在段起止点处向圆心连线,就再加一条线段。 
    if (drawLineToCenter) 
        additionalSegment++; 
 
    //通过圆周的弧度除以段数计算每个段所跨的弧度 
const float coef = 2.0f * (float)M_PI/segments; 
//申请相应的顶点数组,纳闷了这里为什么不用ccVertex2F而使用GLfloat来存顶点的位置,因为一个顶点的位置是二维点,有x,y两个float值才能表示。所以这里在计算内存大小时乘2,段数值它这里用了最大可能情况值(segments + 2),也可以改为segments + additionalSegment,这样如果不在段起止点处向圆心连线,内存申请会小一点,但后面储存圆心也需要做改动处理。 
    GLfloat *vertices = (GLfloat*)calloc( sizeof(GLfloat)*2*(segments+2), 1); 
    if( ! vertices ) 
        return; 
//for循环每一个段设置顶点位置 
    for(unsigned int i = 0;i <= segments; i++) { 
        float rads = i*coef; 
        GLfloat j = radius * cosf(rads + angle) + center.x; 
        GLfloat k = radius * sinf(rads + angle) + center.y; 
 
        vertices[i*2] = j; 
        vertices[i*2+1] = k; 

//存储圆心,这里也可以改动一下效率更好,判断一下additionalSegment是否大于1才处理。 
    vertices[(segments+1)*2] = center.x; 
    vertices[(segments+1)*2+1] = center.y; 
//你懂的,亲~ 
    s_pShader->use(); 
    s_pShader->setUniformForModelViewProjectionMatrix(); 
    s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); 
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 
//这里参数1指定按GL_LINE_STRIP顺序方式绘制线段。   
glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments+additionalSegment); 
//你懂的~ 
    free( vertices ); 
    CC_INCREMENT_GL_DRAWS(1); 

//绘制二次贝塞尔曲线 
//参1:起点 
//参2:控制点 
//参3:结束点 
//参4:构成曲线的线段数 
void ccDrawQuadBezier(const CCPoint& origin, const CCPoint& control, const CCPoint& destination, unsigned int segments) 

//初始化 
    lazy_init(); 
//创建顶点数组 
    ccVertex2F* vertices = new ccVertex2F[segments + 1]; 
//遍历每一段,用计算公式计算点的位置 
    float t = 0.0f; 
    for(unsigned int i = 0; i < segments; i++) 
    { 
        vertices[i].x = powf(1 - t, 2) * origin.x + 2.0f * (1 - t) * t * control.x + t * t * destination.x; 
        vertices[i].y = powf(1 - t, 2) * origin.y + 2.0f * (1 - t) * t * control.y + t * t * destination.y; 
        t += 1.0f / segments; 

//目标点 
    vertices[segments].x = destination.x; 
    vertices[segments].y = destination.y; 
//使用Shader进行渲染 
    s_pShader->use(); 
    s_pShader->setUniformForModelViewProjectionMatrix(); 
    s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); 
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 
//这里参数1指定按GL_LINE_STRIP顺序方式绘制线段。   
    glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1); 
    CC_SAFE_DELETE_ARRAY(vertices); 
    CC_INCREMENT_GL_DRAWS(1); 

//绘制默认曲率的基数样条。关于基数样条可以参看:http://technet.microsoft.com/zh-cn/4cf6we5y(v=vs.85) 
//基数样条是一连串单独的曲线,这些曲线连接起来形成一条较大的曲线。 样条由点的数组和张力参数指定。 基数样条平滑地经过数组中的每个点;曲线的陡度上没有尖角和突然的变化。 下面的插图显示了一组点和经过这一组点中每一点的基数样条。  
//参1:顶点位置数组 
//参2:构成曲线的线段数 
void ccDrawCatmullRom( CCPointArray *points, unsigned int segments ) 

    ccDrawCardinalSpline( points, 0.5f, segments ); 

//绘制可指定曲率的基数样条 
//参1:顶点位置数组 
//参2:曲率 
//参3:构成曲线的线段数 
void ccDrawCardinalSpline( CCPointArray *config, float tension,  unsigned int segments ) 

    lazy_init(); 
 
    ccVertex2F* vertices = new ccVertex2F[segments + 1]; 
 
    unsigned int p; 
    float lt; 
    float deltaT = 1.0f / config->count(); 
 
    for( unsigned int i=0; i < segments+1;i++) { 
 
        float dt = (float)i / segments; 
 
        // border 
        if( dt == 1 ) { 
            p = config->count() - 1; 
            lt = 1; 
        } else { 
            p = dt / deltaT; 
            lt = (dt - deltaT * (float)p) / deltaT; 
        } 
 
        // Interpolate 
        CCPoint pp0 = config->getControlPointAtIndex(p-1); 
        CCPoint pp1 = config->getControlPointAtIndex(p+0); 
        CCPoint pp2 = config->getControlPointAtIndex(p+1); 
        CCPoint pp3 = config->getControlPointAtIndex(p+2); 
 
        CCPoint newPos = ccCardinalSplineAt( pp0, pp1, pp2, pp3, tension, lt); 
        vertices[i].x = newPos.x; 
        vertices[i].y = newPos.y; 
    } 
 
    s_pShader->use(); 
    s_pShader->setUniformForModelViewProjectionMatrix();     
    s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*)&s_tColor.r, 1); 
 
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
 
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 
    glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1); 
 
    CC_SAFE_DELETE_ARRAY(vertices); 
    CC_INCREMENT_GL_DRAWS(1); 




在本例程中,没有展示基数样条,我稍做了下改动,在绘制图形的函数加入了:

[cpp] view plaincopy
    //这里创建5个顶点 
     CCPointArray*  tpSplinePtArray = CCPointArray::arrayWithCapacity(5); 
    //填充顶点 
    tpSplinePtArray->addControlPoint(ccp(0, 0)); 
    tpSplinePtArray->addControlPoint(ccp(60,100)); 
    tpSplinePtArray->addControlPoint(ccp(250,200)); 
    tpSplinePtArray->addControlPoint(ccp(350,100)); 
    tpSplinePtArray->addControlPoint(ccp(450,280)); 
//用默认曲率绘制段数为50的绿色基数样条 
ccDrawColor4B(0,255,0,255); 
    ccDrawCatmullRom(tpSplinePtArray,50);    
 
//重置绘制参数值 
glLineWidth(1); 
    ccDrawColor4B(255,255,255,255); 
    ccPointSize(1); 
运行后可以看到多了一条绿色基数样条。 





然后继续:

[cpp] view plaincopy
//绘制高阶贝赛尔曲线 
//参1:起点 
//参2:控制点1 
//参3:控制点2 
//参4:结束度 
//参5:构成曲线的线段数 
void ccDrawCubicBezier(const CCPoint& origin, const CCPoint& control1, const CCPoint& control2, const CCPoint& destination, unsigned int segments) 

    lazy_init(); 
 
    ccVertex2F* vertices = new ccVertex2F[segments + 1]; 
 
    float t = 0; 
    for(unsigned int i = 0; i < segments; i++) 
    { 
        vertices[i].x = powf(1 - t, 3) * origin.x + 3.0f * powf(1 - t, 2) * t * control1.x + 3.0f * (1 - t) * t * t * control2.x + t * t * t * destination.x; 
        vertices[i].y = powf(1 - t, 3) * origin.y + 3.0f * powf(1 - t, 2) * t * control1.y + 3.0f * (1 - t) * t * t * control2.y + t * t * t * destination.y; 
        t += 1.0f / segments; 
    } 
    vertices[segments].x = destination.x; 
    vertices[segments].y = destination.y; 
 
    s_pShader->use(); 
    s_pShader->setUniformForModelViewProjectionMatrix(); 
    s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); 
 
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 
 
    glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 
    glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments + 1); 
    CC_SAFE_DELETE_ARRAY(vertices); 
 
    CC_INCREMENT_GL_DRAWS(1); 

//设置静态色彩变量值s_tColor,因为很多绘制图形函数都用到这个值做为色彩参数传入Shader,故要更改色彩,在渲染前调用此函数进行设置即可。这里参数分别代表r,g,b,a,用0.0~1.0来表示0~255的值 
void ccDrawColor4F( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) 

    s_tColor.r = r; 
    s_tColor.g = g; 
    s_tColor.b = b; 
    s_tColor.a = a; 

//设置代表顶点大小的静态变量值,用于渲染点时传入Shader 
void ccPointSize( GLfloat pointSize ) 

    s_fPointSize = pointSize * CC_CONTENT_SCALE_FACTOR(); 
 

//设置静态色彩变量值s_tColor,这里参数用0~255。 
void ccDrawColor4B( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) 

    s_tColor.r = r/255.0f; 
    s_tColor.g = g/255.0f; 
    s_tColor.b = b/255.0f; 
    s_tColor.a = a/255.0f; 

另外,改动两个Cocos2d-x的底层代码:在cocos2dx目录的CCDrawingPrimitives.cpp中

增加线宽:左边是原代码,右边是改后代码


优化画圆


           好啦,啰啰嗦嗦总算是把这一章讲完了,希望大家学有所用。下次再见!

猜你喜欢

转载自wdp107.iteye.com/blog/1767533
今日推荐