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
- #ifndef _DRAW_PRIMITIVES_TEST_H_
- #define _DRAW_PRIMITIVES_TEST_H_
-
-
-
- #include "../testBasic.h"
-
- class DrawPrimitivesTest : public CCLayer
- {
- public:
-
- DrawPrimitivesTest();
-
- virtual void draw();
- };
-
- class DrawPrimitivesTestScene : public TestScene
- {
- public:
-
- virtual void runThisTest();
- };
-
- #endif
OK,头文件看完了,现在看CPP文件:
- #include "DrawPrimitivesTest.h"
-
- DrawPrimitivesTest::DrawPrimitivesTest()
- {
- }
-
- void DrawPrimitivesTest::draw()
- {
-
- CCSize s = CCDirector::sharedDirector()->getWinSize();
-
- CHECK_GL_ERROR_DEBUG();
-
-
-
-
- ccDrawLine( ccp(0, 0), ccp(s.width, s.height) );
-
-
- CHECK_GL_ERROR_DEBUG();
-
-
- glLineWidth( 5.0f );
-
- ccDrawColor4B(255,0,0,255);
-
- ccDrawLine( ccp(0, s.height), ccp(s.width, 0) );
-
-
- CHECK_GL_ERROR_DEBUG();
-
-
- ccPointSize(64);
-
- ccDrawColor4B(0,0,255,128);
-
- 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) };
- ccPointSize(4);
-
- ccDrawColor4B(0,255,255,255);
-
- ccDrawPoints( points, 4);
-
- CHECK_GL_ERROR_DEBUG();
-
-
- glLineWidth(16);
-
- ccDrawColor4B(0, 255, 0, 255);
-
- ccDrawCircle( ccp(s.width/2, s.height/2), 100, 0, 10, false);
-
- CHECK_GL_ERROR_DEBUG();
-
-
- glLineWidth(2);
-
- ccDrawColor4B(0, 255, 255, 255);
-
- 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( 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
下面是绘制二次贝塞尔曲线,类似下图,图是从维基百科上找来的,恕我没那个能力画图了暂拿来用讲原理

-
- ccDrawQuadBezier(ccp(0,s.height), ccp(s.width/2,s.height/2), ccp(s.width,s.height), 50);
-
- CHECK_GL_ERROR_DEBUG();
然后是绘制高阶贝塞尔曲线,类似下图

-
- 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();
再继续
-
- 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();
- }
-
- void DrawPrimitivesTestScene::runThisTest()
- {
-
- CCLayer* pLayer = new DrawPrimitivesTest();
- addChild(pLayer);
- pLayer->release();
-
- CCDirector::sharedDirector()->replaceScene(this);
- }
好吧,运行一下,看图:

一个一个来对照代码看一看,我们发现,其在调用ccPointSize进行点的大小设置时根本就不管用。 有点无语,可见这一版扣扣二弟放出来还是有点仓促~
大家先看罢,吾上WC下,一会儿见。
约过了五分钟………..
现在大家看懂照截图看懂代码了吧。那我们更深入一步吧。
既然画点有点问题咱就先看画点。在ccDrawPoint函数调用处加断点。F11进入CCDrawingPrimitives.cpp:
- void ccDrawPoint( const CCPoint& point )
- {
-
- lazy_init();
-
-
- ccVertex2F p;
- p.x = point.x;
- p.y = point.y;
-
- ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
-
- s_pShader->use();
-
- s_pShader->setUniformForModelViewProjectionMatrix();
-
- s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
-
- s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize);
-
- glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, &p);
-
- glDrawArrays(GL_POINTS, 0, 1);
-
- CC_INCREMENT_GL_DRAWS(1);
- }
回头看lazy_init,作者命名lazy_init的原因难道是说:我懒,初始化的相关处理就不每次写了,放函数里用多省心~。
要看函数,先看文件最上部作者定义的静态变量。
- static bool s_bInitialized = false;
- static CCGLProgram* s_pShader = NULL;
- static int s_nColorLocation = -1;
- static ccColor4F s_tColor = {1.0f,1.0f,1.0f,1.0f};
- static int s_nPointSizeLocation = -1;
- static GLfloat s_fPointSize = 1.0f;
然后分析这个函数:
- static void lazy_init( void )
- {
-
- if( ! s_bInitialized ) {
-
-
- s_pShader = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_Position_uColor);
-
- s_nColorLocation = glGetUniformLocation( s_pShader->getProgram(), "u_color");
-
- CHECK_GL_ERROR_DEBUG();
-
-
- 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,这里定义了不少字符串变量:
- #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缓冲。代码不多,详细解之:
- #ifndef __CCSHADERCACHE_H__
- #define __CCSHADERCACHE_H__
-
-
- #include "cocoa/CCDictionary.h"
-
- NS_CC_BEGIN
-
- class CCGLProgram;
-
- class CC_DLL CCShaderCache : public CCObject
- {
- public:
-
- CCShaderCache();
-
- virtual ~CCShaderCache();
-
- static CCShaderCache* sharedShaderCache();
-
-
- static void purgeSharedShaderCache();
-
-
- void loadDefaultShaders();
-
-
- void reloadDefaultShaders();
-
-
- CCGLProgram * programForKey(const char* key);
-
-
- void addProgram(CCGLProgram* program, const char* key);
-
- private:
-
- bool init();
-
- void loadDefaultShader(CCGLProgram *program, int type);
-
- CCDictionary* m_pPrograms;
-
- };
-
- NS_CC_END
-
- #endif /* __CCSHADERCACHE_H__ */
Cpp文件:
- #include "CCShaderCache.h"
- #include "CCGLProgram.h"
- #include "ccMacros.h"
- #include "ccShaders.h"
-
- NS_CC_BEGIN
-
- enum {
- kCCShaderType_PositionTextureColor,
- kCCShaderType_PositionTextureColorAlphaTest,
-
- kCCShaderType_PositionColor,
-
- kCCShaderType_PositionTexture,
-
- kCCShaderType_PositionTexture_uColor,
-
- kCCShaderType_PositionTextureA8Color,
-
- kCCShaderType_Position_uColor,
-
-
- kCCShaderType_MAX,
- };
-
-
- static CCShaderCache *_sharedShaderCache = 0;
-
-
- 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();
-
- loadDefaultShaders();
- return true;
- }
-
- void CCShaderCache::loadDefaultShaders()
- {
-
- CCGLProgram *p = new CCGLProgram();
-
- loadDefaultShader(p, kCCShaderType_PositionTextureColor);
-
- m_pPrograms->setObject(p, kCCShader_PositionTextureColor);
- p->release();
-
-
- p = new CCGLProgram();
- loadDefaultShader(p, kCCShaderType_PositionTextureColorAlphaTest);
-
- m_pPrograms->setObject(p, kCCShader_PositionTextureColorAlphaTest);
- p->release();
-
-
- p = new CCGLProgram();
- loadDefaultShader(p, kCCShaderType_PositionColor);
-
- m_pPrograms->setObject(p, kCCShader_PositionColor);
- p->release();
-
-
- p = new CCGLProgram();
- loadDefaultShader(p, kCCShaderType_PositionTexture);
-
- m_pPrograms->setObject(p, kCCShader_PositionTexture);
- p->release();
-
-
- p = new CCGLProgram();
- loadDefaultShader(p, kCCShaderType_PositionTexture_uColor);
-
- m_pPrograms->setObject(p ,kCCShader_PositionTexture_uColor);
- p->release();
-
-
- p = new CCGLProgram();
- loadDefaultShader(p, kCCShaderType_PositionTextureA8Color);
-
- m_pPrograms->setObject(p, kCCShader_PositionTextureA8Color);
- p->release();
-
-
- p = new CCGLProgram();
- loadDefaultShader(p, kCCShaderType_Position_uColor);
-
- m_pPrograms->setObject(p, kCCShader_Position_uColor);
- p->release();
- }
-
-
- void CCShaderCache::reloadDefaultShaders()
- {
-
-
- CCGLProgram *p = programForKey(kCCShader_PositionTextureColor);
-
- p->reset();
-
- loadDefaultShader(p, kCCShaderType_PositionTextureColor);
-
-
- 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);
- }
-
-
- void CCShaderCache::loadDefaultShader(CCGLProgram *p, int type)
- {
- switch (type) {
- case kCCShaderType_PositionTextureColor:
-
-
- p->initWithVertexShaderByteArray(ccPositionTextureColor_vert, ccPositionTextureColor_frag);
-
- p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
-
- p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
-
- p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
-
- break;
- case kCCShaderType_PositionTextureColorAlphaTest:
-
-
-
- p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
-
- p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
-
- p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
-
- break;
- case kCCShaderType_PositionColor:
-
- p->initWithVertexShaderByteArray(ccPositionColor_vert ,ccPositionColor_frag);
-
-
-
-
- break;
- case kCCShaderType_PositionTexture:
-
-
- p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
-
- p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
-
- break;
- case kCCShaderType_PositionTexture_uColor:
-
-
- p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
-
- p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
-
- break;
- case kCCShaderType_PositionTextureA8Color:
-
-
- p->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
-
- p->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
-
- p->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
-
- break;
- case kCCShaderType_Position_uColor:
- p->initWithVertexShaderByteArray(ccPosition_uColor_vert, ccPosition_uColor_frag);
-
- p->addAttribute("aVertex", kCCVertexAttrib_Position);
- break;
- default:
-
- CCLOG("cocos2d: %s:%d, error shader type", __FUNCTION__, __LINE__);
- return;
- }
-
- p->link();
-
- p->updateUniforms();
-
- CHECK_GL_ERROR_DEBUG();
- }
-
- CCGLProgram* CCShaderCache::programForKey(const char* key)
- {
- return (CCGLProgram*)m_pPrograms->objectForKey(key);
- }
-
- 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:
-
- 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:
-
- //如果使用的是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顶点大小的代码加上:
-
- ccPointSize(64);
-
- ccDrawColor4B(0,0,255,128);
-
-
- 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) };
-
- ccPointSize(4);
-
- ccDrawColor4B(0,255,255,255);
-
- ccDrawPoints( points, 4);
-
- glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
-
- CHECK_GL_ERROR_DEBUG();
可以看到中心的半透明蓝色圆点和左下方四个小青圆点。

看完ccDrawPoint函数,我们重新进入 CCDrawingPrimitives.cpp看其它的绘制图形函数:
-
-
-
- void ccDrawPoints( const CCPoint *points, unsigned int numberOfPoints )
- {
-
- lazy_init();
-
- ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
-
- s_pShader->use();
-
- s_pShader->setUniformForModelViewProjectionMatrix();
-
- s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
-
- s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize);
-
-
- ccVertex2F* newPoints = new ccVertex2F[numberOfPoints];
-
-
- if( sizeof(CCPoint) == sizeof(ccVertex2F) )
- {
-
- glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, points);
- }
- else
- {
-
-
-
- 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);
- }
-
- glDrawArrays(GL_POINTS, 0, (GLsizei) numberOfPoints);
-
-
- CC_SAFE_DELETE_ARRAY(newPoints);
-
- CC_INCREMENT_GL_DRAWS(1);
- }
-
-
-
-
- void ccDrawLine( const CCPoint& origin, const CCPoint& destination )
- {
-
- lazy_init();
-
- ccVertex2F vertices[2] = {
- {origin.x, origin.y},
- {destination.x, destination.y}
- };
-
- s_pShader->use();
-
- CHECK_GL_ERROR_DEBUG();
-
- s_pShader->setUniformForModelViewProjectionMatrix();
- CHECK_GL_ERROR_DEBUG();
-
- s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
- CHECK_GL_ERROR_DEBUG();
-
- s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize);
- CHECK_GL_ERROR_DEBUG();
-
- ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
- CHECK_GL_ERROR_DEBUG();
-
- glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices);
- CHECK_GL_ERROR_DEBUG();
-
- glDrawArrays(GL_LINES, 0, 2);
-
- CC_INCREMENT_GL_DRAWS(1);
- }
-
-
-
- void ccDrawRect( CCPoint origin, CCPoint destination )
- {
-
-
- 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));
- }
-
-
-
-
- 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 );
- }
-
-
-
-
- void ccDrawPoly( const CCPoint *poli, unsigned int numberOfPoints, bool closePolygon )
- {
-
- lazy_init();
-
- s_pShader->use();
-
- s_pShader->setUniformForModelViewProjectionMatrix();
-
- s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
-
- ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
-
-
- ccVertex2F* newPoli = new ccVertex2F[numberOfPoints];
-
-
- if( sizeof(CCPoint) == sizeof(ccVertex2F) )
- glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, poli);
-
- else
- {
-
- for( unsigned int i=0; i<numberOfPoints;i++) {
- newPoli[i].x = poli[i].x;
- newPoli[i].y = poli[i].y;
- }
-
- 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);
- }
-
-
-
-
- void ccDrawSolidPoly( const CCPoint *poli, unsigned int numberOfPoints, ccColor4F color )
- {
-
- lazy_init();
-
- lazy_init();
-
- s_pShader->use();
-
- s_pShader->setUniformForModelViewProjectionMatrix();
-
- s_pShader->setUniformLocationWith4fv(s_nColorLocation,(GLfloat*) &s_tColor.r, 1);
-
- ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
-
-
- ccVertex2F* newPoli = new ccVertex2F[numberOfPoints];
- if( sizeof(CCPoint) == sizeof(ccVertex2F) )
- {
- glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, poli);
- }
- else
- {
-
- 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);
- }
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) numberOfPoints);
-
- CC_SAFE_DELETE_ARRAY(newPoli);
- CC_INCREMENT_GL_DRAWS(1);
- }
-
-
-
-
-
-
- void ccDrawCircle( const CCPoint& center, float radius, float angle, unsigned int segments, bool drawLineToCenter)
- {
-
- lazy_init();
-
- int additionalSegment = 1;
-
- if (drawLineToCenter)
- additionalSegment++;
-
-
- const float coef = 2.0f * (float)M_PI/segments;
-
- GLfloat *vertices = (GLfloat*)calloc( sizeof(GLfloat)*2*(segments+2), 1);
- if( ! vertices )
- return;
-
- 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;
- }
-
- 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);
-
- glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) segments+additionalSegment);
-
- free( vertices );
- CC_INCREMENT_GL_DRAWS(1);
- }
-
-
-
-
-
- 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;
-
- 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);
- }
-
-
-
-
- void ccDrawCatmullRom( CCPointArray *points, unsigned int segments )
- {
- ccDrawCardinalSpline( points, 0.5f, segments );
- }
-
-
-
-
- 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;
-
-
- if( dt == 1 ) {
- p = config->count() - 1;
- lt = 1;
- } else {
- p = dt / deltaT;
- lt = (dt - deltaT * (float)p) / deltaT;
- }
-
-
- 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);
- }
在本例程中,没有展示基数样条,我稍做了下改动,在绘制图形的函数加入了:
-
- 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));
-
- ccDrawColor4B(0,255,0,255);
- ccDrawCatmullRom(tpSplinePtArray,50);
-
-
- glLineWidth(1);
- ccDrawColor4B(255,255,255,255);
- ccPointSize(1);
- 运行后可以看到多了一条绿色基数样条。

然后继续:
-
-
-
-
-
-
- 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);
- }
-
- 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;
- }
-
- void ccPointSize( GLfloat pointSize )
- {
- s_fPointSize = pointSize * CC_CONTENT_SCALE_FACTOR();
-
- }
-
- 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中
增加线宽:左边是原代码,右边是改后代码

优化画圆
