概述
cocos2d-x底层实现依赖OpenGL,这是一个图形库,可以操作显卡,因此,在处理比较复杂的游戏,消耗较大的游戏时,处理的效率会很高。而像android自带的canvas工具,就不能提供这种效率,因为它不是直接操作显卡的。当然,android自带的一些画图工具,可以做一些简单的游戏开发,如下棋,贪食蛇,连连看等。
OpenGL1.0是固定管线的,内置functions设置所有渲染状态:灯光,顶点,颜色,摄像机。
OpenGL2.0是针对可编程管线的,需要手动设置着色器(shader)。shader包括vertexShader和textureShader,可以处理顶点和纹理的数值,这样,在显卡将要显示前,就可以对对象的坐标和颜色进行修改,轻易地实现很多特效:如波纹。可以通过shader对灯光、阴影的细节进行处理,而1.0是无法对这些细节进行处理的。
cocos2d-x使用的OpenGL技术,大概就如下面所述,因为是2d图形引擎,所以,比较少用到3D的OpenGL API,因此,本文算是粗略涵盖了cocos2d-x涉及到OpenGL的内容。
cocos2d-x也使用了DirectX库,其实和OpenGL的渲染流程,原理是一样的,只是API的命名方式不同。因此,可以从OpenGL中借鉴设计原理。
使用流程
1.准备view,如android中的MySurfaceView
2.创建OpenGl context
3.创建render buffer
是OpenGL对象,用于存放渲染过的图像。屏幕区域这么大的尺寸作为约束。
4.创建frame buffer
是OpenGL对象,存放帧,它包含了render buffer . depth buffer , stencil buffer 和 accumulation buffer
深度缓冲区depth buffer:3D渲染时候,受到Z轴影响,会有遮挡现象,需要保存深度信息进行深度比较,以保证遮挡关系正确。
渲染流程
注意渲染流程的一个特点:先传入指针,再传入值。所以,我们会看到多次对顶点,或者对某个变量进行操作。我所指的指针,可能是glxxxHandle,glxxxLocation,glxxxPointer。然后把先前准备好的数值:glBufferData,glUniform4fv。这些变量的意思会在下面看到。
编写着色器——shader程序
包括顶点着色器vertex.sh和片元着色器frag.sh。直接由显卡GPU执行,而不是由CPU执行。GPU的图形处理能力高于CPU的,因此openg2.0 比 1.0效率高好多。shader程序可以保存在任意文档格式中,甚至可以保存在字符串里,因为我们只需要获取程序内容,而不管它是什么格式。
顶点着色器中
1.使用了4个变量存放顶点位置,这是因为在进行矩阵运算时候,比x,y,z多一个变量w“方便矩阵运算”。
2.
使用了varing对颜色进行声明,该关键字的功能是可以实现“渐变色”,即我们虽然只指定了4个顶点的颜色,但是顶点间的区域是按照顶点间的色差进行渐变的。
片元着色器中
varing lowp vec4 DestinationColor;
//表示低精度运算的向量,把lowp改为highp关键字,则表示高精度运算..一般手机进行低精度运算即可。
这两个着色器,是在运行的时候才编译,而且是通过OpenGL库来编译的。因为OpenGL是跨平台的,进行运行时编译,比较适合,这样可以把编译出来的代码兼容到不同的平台。
OpenGL系统函数
glCreateShader
glShaderSource //获取shader源码
glCompileShader //编译shader
glGetShaderiv/glGetShaderInfoLog //检测编译是否成功,得到错误信息
glCreateProgram //创建program
glAttachShader //绑定两个shader到program
glLinkProgram //将两个shader链接成一个完成的program
glGetProgramiv,glGetProgramInfoLog //检测是否链接成功
glUseProgram //让OpenGl执行Program
glGetAttribLocation //获取shader中的传入变量,后期将传递值到shader中计算
glEnableVertexAttribArray //启用数据,不启用的话,glGetAttribLocation的数据就不会被传入program
顶点数据(准备阶段)
glGenBuffers //创建顶点缓冲对象
glBindBuffer //绑定缓冲区,告诉OpenGL这是指GL_ARRAY_BUFFER数组缓冲区
glBufferData //绑定数据到缓冲区
渲染图形(着色阶段)
glVertexAttribPointer // 向shader提供输入参数值(上面的只是准备了顶点数据,还没输入到着色器)
glDrawElement // 绘制图形,每个顶点都会调用vertex shader , 每个“像素”都会调用frag shader
这样就完成渲染了。
投影矩阵
uniform mat4 Projection; //mat4是4个变量的矩阵变量,
uniform关键字会影响所有的顶点的位置变量。
gl_Position = Projection * Position;
glGetUniformLocation ; //获取vertex shader中的Projection的指针(下面的函数会为这个指针传入值)
glUniformMatrix4fv //为shader传入变量的值
模型视图矩阵
unifrom mat4 ModelView;
gl_Position = Projection* ModelView*Position;
每个物体都有一个模型视图矩阵,用来控制模型的旋转/平移/缩放。
纹理数据
attribute vec2 TexCoordIn;
varying vec2 TexCoordOut;
TexCoordOut = TexCoordIn;
varying lowp vec2 TexCoordOut;
unifrom sampler2D Texture ; // 读取一张图片
gl_FragColor = DesitinationColor * texture2D(Texture, TexCoordOut); //调用系统函数texture2D,根据纹理坐标TexCoordOut,显示Texuture图片(二维数组)。//DestinationColor是原来的颜色,乘不乘都可以,只是一个混合运算。
glGenTexutures ; //创建纹理(指针)
glBindTexture ; //绑定纹理后,下面的代码都使用该纹理,直至重新调用一次该绑定glBindTexture
glTexParameteri; //设置纹理过滤(纹理比对象小或者大时候的处理方式,min map 等)
glTexImage2D; // 设置纹理数据 (读取一个二位数组,即图形的数据)
glActiveTexture; //激活纹理数据(绘制)
glBindTexture; //再次绑定纹理
glUnifrom1i ; //向frag shader 传递纹理“数据”
至此,图片就能被成功贴到对象上
OpenGL的文本显示
一般是通过每个平台下的drawString把文字绘制到图片上,然后把这个图片纹理贴到四方形上。android调用的是canvas,windows上是调用GDI绘制,cocos2d调用xx二维API绘制。