第三周总结:
1. 熟悉cocos2d-x的画图函数
(1)绘制一条线,参1为起点,参2为终点,ccp为生成CCPoint的宏
ccDrawLine( ccp(0, 0), ccp(s.width, s.height) );
(2)设置点大小,参数就是需要设定的大小值
ccPointSize(10);在OpenGL 中通常是采用glPointSize设定
(3)设置后面要进行绘制时所用的色彩
ccDrawColor4B(255,0,0,255);在OpenGL中通常采用glColor来进行设定
(4) 设定线宽
glLineWidth(5.0f);
(5)绘制一个点 ,参数即为点位置
ccDrawPoint( ccp(s.width / 2, s.height / 2) );
(6)绘制多个点
CCPoint points[] = { ccp(60,60), ccp(70,70), ccp(60,70), ccp(70,60) };
ccDrawPoints( points, 4);
(7)绘制圆函数,参1是中心点,参2为半径,参3为圆的逆时针旋转角度,参4为圆的平均切分段数,最后一个参 数是指定是否从圆分段起止点位置向圆中心连线,这里不进行连线
ccDrawCircle( ccp(s.width/2, s.height/2), 100, 0, 10, false);
(8)绘制多边形线框函数,使用上面的顶点数组做为多边形线框的顶点位置,第二个参数为顶点数量,第三个参 数指定是否首尾自动连接形成封闭线框。
CCPoint vertices[] = { ccp(0,0), ccp(50,50), ccp(100,50), ccp(100,100), ccp(50,100) };
ccDrawPoly( vertices, 5, false);
(9)这里绘制内部填充指定色彩的多边形
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 ) );
(10)就是cocos2d-x2.0绘制二次贝塞尔曲线函数,三个参数分别如图中P0,P1,P2,不过在咱们
这个例子中,正好与之上下镜像。最后一个是曲线构成所用的线段数,当然,线段数越多
曲线越平滑。
ccDrawQuadBezier(ccp(0,height/2), ccp(width/2, height), ccp(width,height/2), 50);
(11) 前四个参数应该对应的是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);
2. 熟悉opengl shader
固定管线的渲染方式
可编程管线的渲染方式
OpenGL shaker的编写流程(右侧的两个文件就是vertex和fragment文件)
3. 使用opengl shader编写一个示例
//vertex.h中的内容
" \n\
attribute vec4 a_position; \n\
attribute vec2 a_texCoord; \n\
//uniform mat4 CC_MVPMatrix; \n\
#ifdef GL_ES \n\
varying lowp vec2 v_texCoord; \n\
#else \n\
varying vec2 v_texCoord; \n\
#endif \n\
void main() \n\
{ \n\
gl_Position = CC_MVPMatrix * a_position; \n\
v_texCoord = a_texCoord; \n\
}";
//fragment.h中的内容
" \n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec2 v_texCoord; \n\
uniform sampler2D CC_TEXTURE1; \n\
void main() \n\
{ \n\
gl_FragColor = texture2D(CC_TEXTURE1, v_texCoord); \n\
\n\
//gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0); \n\
}";
//关于上面两个文件的注意点描述,上面两个文件内容加载到程序中均为字符串的形式进行加载,这就是为什么
在前后要加上双引号,并且在字符串赋值后就相当于是一个赋值语句,这就是为什么在最后要加上分号,当然 程序在读取文件内容的方式一:通过#include“文件”方式把里面的东西赋值给一个字符指针(这种方式在
window下不行),方式二:通过读取文件的方式进行读取, 方式三:直接把文件中的内容赋值到程序中赋值 给字符指针。
//对于里面的一些书写格式和变量类型可以参考OpenGL Shader相关知识
//CocoaLigature0 此CocoaLigature1 函数中的两个参数就是vertex文件和fragment文件中的内容
void UserShaderMgr::createProgramAndSave(const char* vShader, const char* fShader)
{
GLuint VerSID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(VerSID, 1, &vShader, NULL);
glShaderSource(FragID, 1, &fShader, NULL);
glCompileShader(VerSID);
glCompileShader(FragID);
GLuint PID = glCreateProgram();
glAttachShader(PID, VerSID);
glAttachShader(PID, FragID);
glLinkProgram(PID);
GLint status = GL_TRUE;
glGetProgramiv(PID, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
CCLOG("cocos2d: ERROR: Failed to link program: %i", PID);
glDeleteProgram(PID);
PID = 0;
}
glDeleteShader(VerSID);
glDeleteShader(FragID);
glUseProgram(PID);
}
在继承自CCNode的类中draw函数中加入以下代码:
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
//GLuint programID = UserShaderMgr::sharedMgr()->getProgramByIndex(0);
//programID就是上面glCreateProgram()获得的返回值
glEnableVertexAttribArray(kCCVertexAttrib_Position);
glEnableVertexAttribArray(kCCVertexAttrib_TexCoords);
//下面两句就是对Program中vertex文件中的两个变量绑定位置,并且这里有个注意点,就是在绑定过后一定需要对你的程序需要重新Link,否则无效;
glBindAttribLocation(programID, kCCVertexAttrib_Position, "a_position");
glBindAttribLocation(programID, kCCVertexAttrib_TexCoords, "a_texCoord");
glLinkProgram(programID);
glUseProgram(programID);
//下面的内容是对Fragment文件中的纹理赋值,这里注意对纹理赋值一定要在glUseProgram下面,否则无效;
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_texture2D->getName());
int uIT = glGetUniformLocation(programID, "CC_TEXTURE1");
glUniform1f(uIT, 0);
//下面的内容是获取cocos2dx环境下的当前的矩阵,得到该矩阵后把值赋给vertex文件中CC_MVPMatrix变量,以便点的位置能够正确显示;
int uPV = glGetUniformLocation(programID, "CC_MVPMatrix");
kmMat4 matrixP;
kmMat4 matrixMV;
kmMat4 matrixMVP;
kmGLGetMatrix(KM_GL_PROJECTION, &matrixP);
kmGLGetMatrix(KM_GL_MODELVIEW, &matrixMV);
kmMat4Multiply(&matrixMVP, &matrixP, &matrixMV);
glUniformMatrix4fv(uPV, 1, GL_FALSE, matrixMVP.mat);
//如果是在其他的框架环境下,上述的大部分是不需要改变的,需要改变的地方只是变换矩阵获取方式,比如在 xcode中的GLKView中可以通过下面方式进行获取:
int MVPMatrix = glGetUniformLocation(m_uProgramID, "CC_MVPMatrix");
glUniformMatrix4fv(MVPMatrix, 1, GL_FALSE,
GLKMatrix4Multiply(self.baseEffect.transform.projectionMatrix,
baseEffect.transform.modelviewMatrix).m);
4. 熟悉cocos2d-x shader机制
(1)cocos2d-x shader机制就是基于OpenGl的,在cocos2d-x shader中对于OpenGL shader进行了封装, 在程序起来的时候,把几个预定义好的shader通过CCShaderCache加载完成,需要使用时只需要简单的调用就 行了。
5. 使用cocos2d-x shader实现4中示例
(1)m_glProgram = CCShaderCache::sharedShaderCache()-
>programForKey(kCCShader_PositionTexture);
setShaderProgram(m_glProgram);
//通过Key找到预定义好的Shader
//在draw函数中调用下述代码
getShaderProgram()->use();
ccGLBindTexture2D(m_texture2D->getName());
//上述的m_texture2D就是需要加载的纹理对象
m_glProgram->setUniformsForBuiltins();
6. 输出OpenGL 坐标与cocos2d-x坐标映射关系
(1)OpenGL和coco2d-x的坐标系都是基于右手坐标系的,原点是在屏幕的左下角;
(2)在OpenGL中的坐标系可以分为 世界坐标系, 局部坐标系, 视点坐标系等,在opengl中需要描述的对象经过 一系列的矩阵相乘,转换成对应位置点,最终经过投影,显示在屏幕上;
(3)投影方式有三种,正投影, 平行投影,透视投影,可以查看相关资料进行详细了解。
7. 实践cocos2d-x中OpenGL 上下文设置,搞清楚设置作用
EAGLContex* context_ = [[EAGLContext alloc]
initWithAPI:kEAGLRenderingAPIOpenGLES2];
上面创建之后,还要设置成当前的contex
[EAGLContext setCurrentContext: context_];