首先是一些基础概念和经验分享:
1、OpenGL是一个跨平台的图形渲染标准
2、OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。
OpenGL ES 是从 OpenGL 裁剪定制而来的,去除了 glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POLYGONS)等复杂图元等许多非绝对必要的特性。现在主要有两个版本,OpenGL ES 1.1针对固定管线硬件的,是以 OpenGL 1.5 规范为基础的。OpenGL ES 2.x 针对可编程管线硬件,参照 OpenGL 2.0 规范定义。
3、egl提供了opengles和本地窗口之间的关联
4、OpenGLES模拟器,这里的模拟器仅仅是一套api和dll(要与android模拟器区分开)。主要用于非嵌入式平台(如windows)下运行opengles代码。
============================================正文==============================================================
1、头文件:
#if !defined(HAVE_GLES) #include <GL/gl.h> #else #include <GLES/gl.h> #endif
2、windows下可以使用eglport(http://sourceforge.net/p/eglport/code-0/3/tree/trunk/),android和ios下各有其对应实现,如果使用了SDL的话,基础框架如下:
#if !defined(HAVE_GLES) #include <GL/gl.h> #else #include <GLES/gl.h> #include "eglport.h" #endif #include <SDL/SDL.h> int main( void ) { // other stuff here SDL_Init( SDL_INIT_VIDEO ); #if defined(HAVE_GLES) if (EGL_Open()) exit(1); #endif // some more initialisations SDL_Surface* screen; #if !defined(HAVE_GLES) screen = SDL_SetVideoMode( 800, 600, 0, SDL_HWSURFACE | SDL_OPENGL | SDL_FULLSCREEN); #else screen = SDL_SetVideoMode( 800, 480, 0, SDL_SWSURFACE | SDL_FULLSCREEN ); EGL_Init(); #endif // the event loop while( quit == 0 ) { // management of the even and the game #if !defined(HAVE_GLES) SDL_GL_SwapBuffers(); #else EGL_SwapBuffers(); #endif } // probably some more clean-ups here #if defined(HAVE_GLES) EGL_Close(); #endif SDL_Quit(); return 0; }
注意EGL_xxx系列函数的位置。
3、一些宏定义:
gles只支持浮点型
#define GLdouble GLfloat #define GL_CLAMP GL_CLAMP_TO_EDGE #define glClearDepth glClearDepthf #define glOrtho glOrthof #define glFrustum glFrustumf
#define glColor4fv(a) glColor4f(a[0], a[1], a[2], a[3]) #define glColor3fv(a) glColor4f(a[0], a[1], a[2], 1.0f) #define glColor3f(a,b,c) glColor4f(a, b, c, 1.0f)
4、具体代码移植示例,因为gles去除了glBegin等函数,所以贴图、顶点绘制、画线等代码都有可能需要进行修改
a、没有颜色的普通矩形:
#if !defined(HAVE_GLES) glBegin(GL_QUADS); glVertex2f(-10,-10); glVertex2f(10,-10); glVertex2f(10,10); glVertex2f(-10,10); glEnd(); #else GLfloat q3[] = { -10,-10, 10,-10, 10,10, -10,10 }; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, q3); glDrawArrays(GL_TRIANGLE_FAN,0,4); glDisableClientState(GL_VERTEX_ARRAY); #endif
b、贴图
glBindTexture(GL_TEXTURE_2D, carac->TextureName); #if !defined(HAVE_GLES) glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex3f(pos[0]-tailleX/2, pos[1]-tailleY/2, 0); glTexCoord2f(1,0); glVertex3f(pos[0]+tailleX/2, pos[1]-tailleY/2, 0); glTexCoord2f(1,1); glVertex3f(pos[0]+tailleX/2, pos[1]+tailleY/2, 0); glTexCoord2f(0,1); glVertex3f(pos[0]-tailleX/2, pos[1]+tailleY/2, 0); glEnd(); #else GLfloat vtx1[] = { pos[0]-tailleX/2, pos[1]-tailleY/2, 0, pos[0]+tailleX/2, pos[1]-tailleY/2, 0, pos[0]+tailleX/2, pos[1]+tailleY/2, 0, pos[0]-tailleX/2, pos[1]+tailleY/2, 0 }; GLfloat tex1[] = { 0,0, 1,0, 1,1, 0,1 }; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vtx1); glTexCoordPointer(2, GL_FLOAT, 0, tex1); glDrawArrays(GL_TRIANGLE_FAN,0,4); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif
c、颜色渐变:
#if !defined(HAVE_GLES) glBegin(GL_QUADS); glColor3d( .1, .1, .7); glVertex3d(0, 0, 0); glVertex3d(0, -pbarheight, 0); glColor3d( 0, 0, 0.5); glVertex3d((startupProgress / startupProgressSteps) * pbarwidth, -pbarheight, 0); glVertex3d((startupProgress / startupProgressSteps) * pbarwidth, 0, 0); glEnd(); #else GLfloat vtx1[] = { 0, 0, 0, 0, -pbarheight, 0, (startupProgress / startupProgressSteps) * pbarwidth, -pbarheight, 0, (startupProgress / startupProgressSteps) * pbarwidth, 0, 0 }; GLfloat col1[] = { .1, .1, .7, 1.0f, .1, .1, .7, 1.0f, 0, 0, 0.5, 1.0f, 0, 0, 0.5, 1.0f }; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vtx1); glColorPointer(4, GL_FLOAT, 0, col1); glDrawArrays(GL_TRIANGLE_FAN,0,4); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); #endif
d、三角形扇面:
#if !defined(HAVE_GLES) glBegin(GL_QUAD_STRIP); // Front glVertex3f(-left, 0, front); // bottom left glVertex3f(-left-wider, height, front+wider); // top left glVertex3f( right, 0, front); // bottom right glVertex3f( right+wider, height, front+wider); // top right // Right glVertex3f( right, 0,-back); // bottom r glVertex3f( right+wider, height,-back-wider); // top r // Back glVertex3f(-left, 0, -back); // bottom right glVertex3f(-left-wider, height, -back-wider); // top right // Left glVertex3f(-left, 0, front); // bottom r glVertex3f(-left-wider, height, front+wider); // top r glEnd(); #else { GLfloat vtx1[] = {-left, 0, front, -left-wider, height, front+wider, right, 0, front, right+wider, height, front+wider}; GLfloat vtx2[] = {right, 0, front, right+wider, height, front+wider, right, 0,-back, right+wider, height,-back-wider}; GLfloat vtx3[] = {right, 0,-back, right+wider, height,-back-wider, -left, 0, -back, -left-wider, height, -back-wider}; GLfloat vtx4[] = {-left, 0, -back, -left-wider, height, -back-wider, -left, 0, front, -left-wider, height, front+wider}; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vtx1); glDrawArrays(GL_TRIANGLE_FAN,0,4); glVertexPointer(3, GL_FLOAT, 0, vtx2); glDrawArrays(GL_TRIANGLE_FAN,0,4); glVertexPointer(3, GL_FLOAT, 0, vtx3); glDrawArrays(GL_TRIANGLE_FAN,0,4); glVertexPointer(3, GL_FLOAT, 0, vtx4); glDrawArrays(GL_TRIANGLE_FAN,0,4); glDisableClientState(GL_VERTEX_ARRAY); } #endif
e、使用int/short
#if !defined(HAVE_GLES) glBegin(GL_QUADS); glTexCoord2i(0, 1); glVertex2i(-256, -256); glTexCoord2i(0, 0); glVertex2i(-256, 256); glTexCoord2i(1, 0); glVertex2i(256, 256); glTexCoord2i(1, 1); glVertex2i(256, -256); glEnd(); #else GLshort vtx1[] = { -256, -256, -256, 256, 256, 256, 256, -256 }; GLshort tex1[] = { 0, 1, 0, 0, 1, 0, 1, 1 }; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_SHORT, 0, vtx1); glTexCoordPointer(2, GL_SHORT, 0, tex1); glDrawArrays(GL_TRIANGLE_FAN,0,4); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif
f、glRect
#ifndef HAVE_GLES glRecti ( dx + min[0], dy + min[1], dx + max[0], dy + max[1] ) ; #else GLshort vtx1[] = { dx + min[0], dy + min[1], dx + min[0], dy + max[1], dx + max[0], dy + max[1], dx + max[0], dy + min[1]}; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_SHORT, 0, vtx1); glDrawArrays(GL_TRIANGLE_FAN,0,4); glDisableClientState(GL_VERTEX_ARRAY); #endif
5、glDrawArrays渲染模式对应关系
GL_POINTS -> GL_POINTS GL_TRIANGLES -> GL_TRIANGLES (or GL_LINE_LOOP if glPolygonMode is set to GL_LINE) GL_QUADS -> GL_TRIANGLE_FAN GL_LINE_STRIP -> GL_LINE_STRIP GL_LINE -> GL_LINE GL_POLYGON -> GL_TRIANGLE_FAN
6、所有贴图必须是2的整次幂,某些特殊情况会有更高的需求(如powervr显卡使用pvr贴图必须是正方形以及2的整次幂大小)。