在SymbianV3上的OpenGLES开发.docx
- 文档编号:15554056
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:21
- 大小:21.89KB
在SymbianV3上的OpenGLES开发.docx
《在SymbianV3上的OpenGLES开发.docx》由会员分享,可在线阅读,更多相关《在SymbianV3上的OpenGLES开发.docx(21页珍藏版)》请在冰点文库上搜索。
在SymbianV3上的OpenGLES开发
这篇文章主要向已经接触过桌面OpenGL的程序员介绍如何使用OpenGLES在S60上进行开发。
Contents
1简介
1.1所需文件
2教程:
如何开始OpenGLES之旅
2.1获得手机屏幕
2.2初始化OpenGLES
2.3选择一个OpenGLES配置
2.4生成OpenGLEScontext
2.5激活context
2.6关闭OpenGLES
3OpenGL和OpenGLES的一些区别
4OpengLES贴士
5附录:
完整的类
简介
OpenGLES是专为内嵌和移动设备设计的一个2D/3D轻量图形库,它是基于OpenGLAPI设计的。
OpenGLES1.0版基于OpenGL1.3,而OpenGLES1.1则是基于OpenGL1.5的。
现在主要由KhronosGroup来负责管理OpenGLES的开发维护。
OpenGLES定义了一个概念,名为profile,它定义了基于原始OpenGL的一组子功能,以及针对OpenGLES的增强功能,例
如:
CommonProfile:
这个profile在移动设备如电话或pda中完成;
Common-LiteProfile:
这个限制较多,规定了运行3D图形程序所需最少的功能。
这个主要针对安全性要求高的设备,它们的可靠性成了最需要考虑的东西。
OpenGLES同样定义了和窗口系统(定义为EGL)的一个接口。
这个EGLAPI是所有使用OpenGLES的手机所需的,但是它的完成是硬件相关的。
所需文件
S60第二版FP2之后已经有了编写OpenGLES1.0应用程序所需的文件。
OpenGLES1.1则在S60第三版FP1SDK中出现下列头文件是运行OpenGLES所需的:
#include
#include
OpenGLES由一个DLL完成,因此程序需要这个链接库:
libgles_cm.lib
ws32.lib
第一个文件关系到OpenGLES和EGL,CommonProfile。
S60手机不支持Common-LiteProfile。
第二个文件是关于SymbianOS
Windowserver的。
在Carbide.c++中,当为手机编译时,这些文件应该有.dso后缀。
教程:
如何开始OpenGLES之旅
下面是开展OpenGLES之旅的步骤:
1.获得缺省的现实设备;
2.初始化OpenGLES;
3.选择一个OpenGLES配置
4.生成一个OpenGLEScontext
5.生成一个可绘制的surface
6.激活OpenGLEScontext.
作为一个示例,我们使用如下定义的类来完成我们的目的:
#include
#include
#include"GLES/egl.h"
#include"GLES/gl.h"
classCGLRender:
publicCBase
{
public:
//methodtocreateaninstanceofthisclass
staticCGLRender*NewL(RWindow&aWindow);
public:
//destructor
~CGLRender();
//doublebuffering,moreonthislater
voidSwapBuffers();
private:
//constructor
CGLRender(RWindow&aWindow);
//secondpartofthetwo-phaseconstructor,where
//OpenGLESisinitialized
voidConstructL();
private:
RWindowiWindow;
EGLDisplayiEglDisplay;
EGLConfigiEglConfig;
EGLContextiEglContext;
EGLSurfaceiEglSurface;
};
这里的iEglDisplay变量表示手机屏幕.而OpenGLES配置信息存放在iEglConfig.而iEglContext变量则表示OpenGLES的context。
最后iEglSurface表示绘制surface。
获得手机屏幕
iEglDisplay=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(iEglDisplay==EGL_NO_DISPLAY)
User:
:
Panic(_L("UnabletofindasuitableEGLDisplay"),0);
这里EGL_DEFAULT_DISPLAY指向缺省的手机屏幕(一般来说只有一个),如果程序运行失败,那么该函数将会返回
EGL_NO_DISPLAY.
初始化OpenGLES
if(!
eglInitialize(iEglDisplay,0,0))
User:
:
Panic(_L("UnabletoinitializeEGL"),0);
最后两个参数是EGL完成的版本。
如果你对此不需要,可以传递0进去。
否则,他们将返回如下值:
EGLintmajor,minor;
eglInitialize(iEglDisplay,&major,&minor);
例如版本1.0,则major为1,而minor为0
选择一个OpenGLES配置
接下来,需要指定一个程序所需最小配置
EGLintnumConfigs;
if(!
eglChooseConfig(iEglDisplay,attribList,&iEglConfig,1,&numConfigs))
User:
:
Panic(_L("UnabletochooseEGLconfig"),0);
这里attribList参数指明了程序运行所需的属性列表,该函数将在iEglConfig参数中返回一个与属性列表配套的可用配置。
这个列表的大小被第四个参数所限制(这里我们只需要一个配置),而numConfigs参数则在程序返回后告知有多少个匹配的配置。
这个属性列表定义了一组[attribute,value]数组。
EGL指定所有支持的属性。
如,我们将选择colordepth和z-buffer大小:
//attributelist
EGLintattribList[]=
{
EGL_BUFFER_SIZE,0,//colordepth
EGL_DEPTH_SIZE,15,//z-buffer
EGL_NONE
};
//hereweusethesamecolordepthasthedevice
//iWindowisaRWindowobject
switch(iWindow.DisplayMode())
{
caseEColor4K:
attribList[1]=12;
break;
caseEColor64K:
attribList[1]=16;
break;
caseEColor16M:
attribList[1]=24;
break;
default:
attribList[1]=32;
}
上述列表要以EGL_NONE常量结尾。
生成OpenGLEScontext
iEglContext=eglCreateContext(iEglDisplay,iEglConfig,EGL_NO_CONTEXT,0);
if(iEglContext==0)
User:
:
Panic(_L("UnabletocreateEGLcontext"),0);
第三个参数表明用来共享texture对象的context。
这里,我们使用了EGL_NO_CONTEXT,它表明没有context可用。
最后一个函数表明映射到新context上的属性列表。
但在这里没有这样的一个列表存在。
激活context
要让OpenGLES命令生效,我们需要激活context,让它成为当前可使用的。
在OpenGLES,一次只能有一个context生效。
eglMakeCurrent(iEglDisplay,iEglSurface,iEglSurface,iEglContext);
关闭OpenGLES
当我们使用OpenGLES后,需要释放所有资源,记住,这个非常重要!
CGLRender:
:
~CGLRender()
{
eglMakeCurrent(iEglDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
eglDestroySurface(iEglDisplay,iEglSurface);
eglDestroyContext(iEglDisplay,iEglContext);
eglTerminate(iEglDisplay);
}
第一行代码用来关闭当前context。
这样surface和context就可以被释放。
最后一行表明结束OpenGLES。
OpenGL和OpenGLES的一些区别
缺省,OpenGLES使用双缓冲,这里是处理代码:
voidCGLRender:
:
SwapBuffers()
{
eglSwapBuffers(iEglDisplay,iEglSurface);
}
因为内嵌设备的限制,OpenGLES不能包括很多OpenGL的多余操作,如不能在OpenGLES使用一个表明几何形式的临时模式。
因此,如下代码在OpenGLES是无效的:
glBegin(GL_TRIANGLES);
glVertex3f(0,1,0);
glVertex3f(-1,0,0);
glVertex3f(1,0,0);
glEnd();
OpenGLES从vertex数组中渲染所有的几何模型。
因此如果要在OpenGLES中渲染一个三角形,需要如下代码:
constGLbyteKVertices[]=
{
0,1,0,
-1,0,0,
1,0,0
};
...
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_BYTE,0,KVertices);
glDrawArrays(GL_TRIANGLES,0,3);
和大多数没有FPU(浮点运算处理器)的设备一样,OpenGLESprofile只定义了可以接收整型数值的函数。
整型运算是将浮点数用整数表示的一种技巧。
当我们使用整型数时,这个整数会被分成2个部分:
一个用来存储真正的整数部分,而剩余的用来存储小数部分。
OpenGLES工作在16:
16的32位字节数上。
它表明有16位是整数,而剩余的16位是小数。
更多相关信息请参考here.
这里有是一个可接收整型或浮点型函数的示例:
glTranslatex(20<<16,0,0,1<<16);
//sameas
//glTranslatef(20.0f,0.0f,0.0f,1.0f);
只能接收整型参数的函数,会有一个'x'后缀。
此外,OpenGLES还引进了GLfixed类型用来表示整型数。
有一些值得一提的区别是:
OpenGLES中不存在哪些有所有的相同作用的,但有不同的缩写(如glVertex3{fsidv})的函数。
但是有些如glColor4{fx}还是存在的;
OpenGLES只支持RGBA颜色模式(你不需要选择)
OpenGLES不绘制线框或点(只绘制实心填充);
无需询问OpenGLES1.0中的动态属性(如当前颜色);
没有GLU(OpenGLUtilityLibrary),但可以找到GLU函数的内部完成,这些是OpenGLES才有的;
GL_QUADS,GL_QUAD_STRIP和GL_POLYGON是不支持的。
OpengLES贴士
eglSwapBuffers函数不应该在View类的Draw方法中调用。
实际的渲染将会被另一个方法处理。
应该由一个timer类或活动对话来唤醒这个方法,如一个回调函数。
建议使用全屏模式来显示OpenGLES程序,因为如果不采用全屏,有时程序可能只能刷新一半(手机上)。
我们用以通过在UI中生成view时传递ApplicationRect()参数指明全屏模式。
使用整型数指明几何模型,因为很多手机都没有FPU的。
要注意避免很多状态的改变,例如混合了有纹理映射和没有纹理映射的多边形将会降低性能,这种情况下,最好的解决方案是生成2组多边形,分别绘制。
远距离物体不用进行透视矫正,因为这样效果并不明显。
尽量减少或不要使用太远而不能被注意到的特效。
光照很酷,但会增加处理负荷,所以要小心使用。
如果有可能将多幅图片达到一个素材中,这样素材的变化将会最小。
如果可能,尽量在一次单独调用中提交多个多边形,要比针多次调用好。
附录:
完整的类
下面是完整的实现文件
#include"CGLRender.h"
//_____________________________________________________________________________
CGLRender:
:
CGLRender(RWindow&aWindow)
:
iWindow(aWindow)
{}
//_____________________________________________________________________________
CGLRender:
:
~CGLRender()
{
eglMakeCurrent(iEglDisplay,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
eglDestroySurface(iEglDisplay,iEglSurface);
eglDestroyContext(iEglDisplay,iEglContext);
eglTerminate(iEglDisplay);
}
//_____________________________________________________________________________
CGLRender*CGLRender:
:
NewL(RWindow&aWindow)
{
CGLRender*instance=new(ELeave)CGLRender(aWindow);
CleanupStack:
:
PushL(instance);
instance->ConstructL();
CleanupStack:
:
Pop();
returninstance;
}
//_____________________________________________________________________________
voidCGLRender:
:
ConstructL()
{
//attributelist
EGLintattribList[]=
{
EGL_BUFFER_SIZE,0,
EGL_DEPTH_SIZE,15,
EGL_NONE
};
//getdevicecolordepth
switch(iWindow.DisplayMode())
{
caseEColor4K:
attribList[1]=12;
break;
caseEColor64K:
attribList[1]=16;
break;
caseEColor16M:
attribList[1]=24;
break;
default:
attribList[1]=32;
}
//step1
iEglDisplay=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(iEglDisplay==EGL_NO_DISPLAY)
User:
:
Panic(_L("UnabletofindasuitableEGLDisplay"),0);
//step2
if(!
eglInitialize(iEglDisplay,0,0))
User:
:
Panic(_L("UnabletoinitializeEGL"),0);
//step3
EGLintnumConfigs;
if(!
eglChooseConfig(iEglDisplay,attribList,&iEglConfig,1,&numConfigs))
User:
:
Panic(_L("UnabletochooseEGLconfig"),0);
//step4
iEglContext=eglCreateContext(iEglDisplay,iEglConfig,EGL_NO_CONTEXT,0);
if(iEglContext==0)
User:
:
Panic(_L("UnabletocreateEGLcontext"),0);
//step5
iEglSurface=eglCreateWindowSurface(iEglDisplay,iEglConfig,&iWindow,0);
if(iEglSurface==NULL)
User:
:
Panic(_L("UnabletocreateEGLsurface"),0);
//step6
eglMakeCurrent(iEglDisplay,iEglSurface,iEglSurface,iEglContext);
}
//_____________________________________________________________________________
voidCGLRender:
:
EnforceContext()
{
eglMakeCurrent(iEglDisplay,iEglSurface,iEglSurface,iEglContext);
}
//_____________________________________________________________________________
voidCGLRender:
:
SwapBuffers()
{
eglSwapBuffers(iEglDisplay,iEglSurface);
}
Retrievedfrom"
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SymbianV3 OpenGLES 开发