OpenGL ES简介

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。

OpenGL ES 是从 OpenGL 裁剪定制而来的,去除了 glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POLYGONS)等复杂图元等许多非绝对必要的特性。经过多年发展,现在主要有两个版本,OpenGL ES 1.x 针对固定管线硬件的,OpenGL ES 2.x 针对可编程管线硬件。OpenGL ES 1.0 是以 OpenGL 1.3 规范为基础的,OpenGL ES 1.1 是以 OpenGL 1.5 规范为基础的,它们分别又支持 common 和 common lite 两种profile。lite profile只支持定点定点实数,而common profile既支持定点数又支持浮点数。 OpenGL ES 2.0 则是参照 OpenGL 2.0 规范定义的,common profile发布于2005-8,引入了对可编程管线的支持。

OpenGL ES 还有一个safety-critical profile。

===================================================================

OpenGl ES参考手册:http://www.khronos.org/opengles/documentation/opengles1_0/html/

OpenGl 参考手册:http://www.cs.sfu.ca/~haoz/teaching/openglman.html

====================================================================
这篇文章主要向已经接触过桌面OpenGL的程序员介绍如何使用OpenGL ES在S60上进行开发。
Contents
[hide]
 1 简介
  1.1 所需文件
 2 教程:如何开始OpenGL ES之旅
  2.1 获得手机屏幕
  2.2 初始化OpenGL ES
  2.3 选择一个OpenGL ES配置
  2.4 生成OpenGL ES context
  2.5 激活context
  2.6 关闭OpenGL ES
 3 OpenGL和OpenGL ES的一些区别
 4 OpengL ES贴士
 5 附录:完整的类

 

简介
OpenGL ES是专为内嵌和移动设备设计的一个2D/3D轻量图形库,它是基于OpenGL API设计的。OpenGL ES 1.0版基于OpenGL 1.3,而OpenGL ES 1.1则是基于OpenGL 1.5的。现在主要由Khronos Group来负责管理OpenGL ES的开发维护。
OpenGL ES定义了一个概念,名为profile,它定义了基于原始OpenGL的一组子功能,以及针对OpenGL ES的增强功能,例
如:
 Common Profile: 这个profile在移动设备如电话或pda中完成;
 Common-Lite Profile: 这个限制较多,规定了运行3D图形程序所需最少的功能。这个主要针对安全性要求高的设备,它们的可靠性成了最需要考虑的东西。
OpenGL ES同样定义了和窗口系统(定义为EGL)的一个接口。这个EGL API是所有使用OpenGL ES的手机所需的,但是它的完成是硬件相关的。
所需文件
S60第二版FP2之后已经有了编写OpenGL ES 1.0应用程序所需的文件。OpenGL ES 1.1则在S60第三版FP1 SDK中出现下列头文件是运行OpenGL ES所需的:


#include <GLES/egl.h>
#include <GLES/gl.h>


OpenGL ES由一个DLL完成,因此程序需要这个链接库:


libgles_cm.lib
ws32.lib


第一个文件关系到OpenGL ES和EGL,Common Profile。S60手机不支持Common-Lite Profile。第二个文件是关于Symbian OS
Window server的。在Carbide.c++中,当为手机编译时,这些文件应该有.dso后缀。


教程:如何开始OpenGL ES之旅


下面是开展OpenGL ES之旅的步骤:
1. 获得缺省的现实设备;
2. 初始化OpenGL ES;
3. 选择一个OpenGL ES配置
4. 生成一个OpenGL ES context
5. 生成一个可绘制的surface
6. 激活OpenGL ES context.


作为一个示例,我们使用如下定义的类来完成我们的目的:


#include <e32base.h>
#include <w32std.h>
 
#include "GLES/egl.h"
#include "GLES/gl.h"
 
class CGLRender: public CBase
{
  public:
 
    // method to create an instance of this class
    static CGLRender* NewL (RWindow & aWindow);
 
  public:
 
    // destructor
    ~CGLRender ();
 
    // double buffering, more on this later
    void SwapBuffers ();
 
  private:
 
   // constructor
   CGLRender (RWindow& aWindow); 
 
   // second part of the two-phase constructor, where
   // OpenGL ES is initialized
   void ConstructL();
 
  private:
 
   RWindow     iWindow;
 
   EGLDisplay  iEglDisplay;  
   EGLConfig   iEglConfig;    
   EGLContext  iEglContext;  
   EGLSurface  iEglSurface; 
};


这里的iEglDisplay变量表示手机屏幕. 而OpenGL ES配置信息存放在iEglConfig. 而iEglContext变量则表示OpenGL ES的context。最后iEglSurface表示绘制surface。


获得手机屏幕


iEglDisplay = eglGetDisplay (EGL_DEFAULT_DISPLAY);
if (iEglDisplay == EGL_NO_DISPLAY)
 User::Panic (_L("Unable to find a  suitable EGLDisplay"), 0);


这里EGL_DEFAULT_DISPLAY指向缺省的手机屏幕(一般来说只有一个),如果程序运行失败,那么该函数将会返回
EGL_NO_DISPLAY.


初始化OpenGL ES


if (!eglInitialize (iEglDisplay, 0, 0) )
 User::Panic (_L("Unable to initialize EGL"), 0);


最后两个参数是EGL完成的版本。如果你对此不需要,可以传递0进去。否则,他们将返回如下值:


EGLint major, minor;
 
eglInitialize (iEglDisplay, & major, &minor);
例如版本1.0,则 major为1,而minor为0


选择一个OpenGL ES配置
接下来,需要指定一个程序所需最小配置


EGLint numConfigs;
 
if (!eglChooseConfig (iEglDisplay, attribList, &iEglConfig, 1, &numConfigs) )
  User::Panic (_L("Unable to choose EGL config"), 0);


这里attribList参数指明了程序运行所需的属性列表,该函数将在iEglConfig参数中返回一个与属性列表配套的可用配置。这个列表的大小被第四个参数所限制(这里我们只需要一个配置),而numConfigs参数则在程序返回后告知有多少个匹配的配置。这个属性列表定义了一组[attribute, value]数组。EGL指定所有支持的属性。如,我们将选择color depth和z-buffer大小:


// attribute list
EGLint attribList [] =
{
 EGL_BUFFER_SIZE, 0,  // color depth
 EGL_DEPTH_SIZE, 15,  // z-buffer
 EGL_NONE
}; 
 
 
// here we use the same color depth as the device
// iWindow is a RWindow object
switch (iWindow.DisplayMode() )
{
 case EColor4K:
  attribList [1] = 12;
  break;
 case EColor64K:
  attribList [1] = 16;
  break;
 
 case EColor16M:
  attribList [1] = 24;
  break;
 default:
  attribList [1] = 32;
}


上述列表要以EGL_NONE常量结尾。

生成OpenGL ES context


iEglContext = eglCreateContext (iEglDisplay, iEglConfig, EGL_NO_CONTEXT, 0);
 
if (iEglContext == 0)
 User::Panic (_L("Unable to create EGL context"), 0);


第三个参数表明用来共享texture对象的context。这里,我们使用了EGL_NO_CONTEXT,它表明没有context可用。最后一个函数表明映射到新context上的属性列表。但在这里没有这样的一个列表存在。


激活context
要让OpenGL ES命令生效,我们需要激活context,让它成为当前可使用的。在OpenGL ES,一次只能有一个context生效。

 
eglMakeCurrent (iEglDisplay, iEglSurface, iEglSurface, iEglContext);
关闭OpenGL ES


当我们使用OpenGL ES后,需要释放所有资源,记住,这个非常重要!
CGLRender::~CGLRender()
{
 eglMakeCurrent (iEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 eglDestroySurface (iEglDisplay, iEglSurface);
 eglDestroyContext (iEglDisplay, iEglContext);
 eglTerminate (iEglDisplay);
}


第一行代码用来关闭当前context。这样surface和context就可以被释放。最后一行表明结束OpenGL ES。
OpenGL和OpenGL ES的一些区别
缺省,OpenGL ES使用双缓冲,这里是处理代码:


void CGLRender::SwapBuffers ()
{
  eglSwapBuffers (iEglDisplay, iEglSurface);
}


因为内嵌设备的限制,OpenGL ES不能包括很多OpenGL的多余操作,如不能在OpenGL ES使用一个表明几何形式的临时模式。因此,如下代码在OpenGL ES是无效的:


glBegin (GL_TRIANGLES);
  glVertex3f (0,1,0);
  glVertex3f (-1,0,0);
  glVertex3f (1,0,0);
glEnd();


OpenGL ES从vertex数组中渲染所有的几何模型。因此如果要在OpenGL ES中渲染一个三角形,需要如下代码:


const GLbyte KVertices []=
{
 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(浮点运算处理器)的设备一样,OpenGL ES profile只定义了可以接收整型数值的函数。整型运算是将浮点数用整数表示的一种技巧。当我们使用整型数时,这个整数会被分成2个部分:一个用来存储真正的整数部分,而剩余的用来存储小数部分。OpenGL ES工作在16:16的32位字节数上。它表明有16位是整数,而剩余的16位是小数。更多相关信息请参考here.


这里有是一个可接收整型或浮点型函数的示例:
glTranslatex (20 << 16, 0, 0, 1 << 16);
 
// same as
// glTranslatef (20.0f, 0.0f, 0.0f, 1.0f);


只能接收整型参数的函数,会有一个'x'后缀。此外,OpenGL ES还引进了GLfixed类型用来表示整型数。有一些值得一提的区别是:
 OpenGL ES中不存在哪些有所有的相同作用的,但有不同的缩写(如glVertex3{fsidv})的函数。但是有些如glColor4{fx}还是存在的;
 OpenGL ES只支持RGBA颜色模式(你不需要选择)
 OpenGL ES不绘制线框或点(只绘制实心填充);
 无需询问OpenGL ES 1.0中的动态属性(如当前颜色);
 没有GLU(OpenGL Utility Library),但可以找到GLU函数的内部完成,这些是OpenGL ES才有的;
 GL_QUADS, GL_QUAD_STRIP和GL_POLYGON是不支持的。
OpengL ES贴士
 eglSwapBuffers函数不应该在View类的Draw方法中调用。实际的渲染将会被另一个方法处理。应该由一个timer类或活动对话来唤醒这个方法,如一个回调函数。
 建议使用全屏模式来显示OpenGL ES程序,因为如果不采用全屏,有时程序可能只能刷新一半(手机上)。我们用以通过在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();
 
 return instance;
}
 
//_____________________________________________________________________________
 
void CGLRender::ConstructL()
{
 // attribute list
 EGLint attribList [] =
 {
  EGL_BUFFER_SIZE, 0,
  EGL_DEPTH_SIZE, 15,
  EGL_NONE
 }; 
 
 
 // get device color depth
 switch (iWindow.DisplayMode() )
 {
  case EColor4K:
   attribList [1] = 12;
   break;
  case EColor64K:
   attribList [1] = 16;
   break;
 
  case EColor16M:
   attribList [1] = 24;
   break;
  default:
   attribList [1] = 32;
 }
 
 // step 1
 iEglDisplay = eglGetDisplay (EGL_DEFAULT_DISPLAY);
 
 if (iEglDisplay == EGL_NO_DISPLAY)
  User::Panic (_L("Unable to find a  suitable EGLDisplay"), 0);
 
 // step 2
 if (!eglInitialize (iEglDisplay, 0, 0) )
  User::Panic (_L("Unable to initialize EGL"), 0);
 
        // step 3
 EGLint numConfigs;
 
 if (!eglChooseConfig (iEglDisplay, attribList, &iEglConfig, 1, &numConfigs) )
  User::Panic (_L("Unable to choose EGL config"), 0);
 
 // step 4
 iEglContext = eglCreateContext (iEglDisplay, iEglConfig, EGL_NO_CONTEXT, 0);
 
 if (iEglContext == 0)
  User::Panic (_L("Unable to create EGL context"), 0);
 
 
 // step 5
 iEglSurface = eglCreateWindowSurface (iEglDisplay, iEglConfig, &iWindow, 0); 
 
 if (iEglSurface == NULL)
 User::Panic (_L("Unable to create EGL surface"), 0);
 
 // step 6
 eglMakeCurrent (iEglDisplay, iEglSurface, iEglSurface, iEglContext); 
}
 
//_____________________________________________________________________________
 
void CGLRender::EnforceContext ()
{
 eglMakeCurrent (iEglDisplay, iEglSurface, iEglSurface, iEglContext); 
}
 
//_____________________________________________________________________________
 
void CGLRender::SwapBuffers ()
{
 eglSwapBuffers (iEglDisplay, iEglSurface);
}

 

OpenGL ES 3.0 英文版 第1章——OpenGL ES 3.0简介   第1章简单介绍OpenGL ES,概述了OpenGL ES 3.0图形管线,讨论了OpenGL ES 3.0的设计理念和限制,最后介绍了OpenGL ES 3.0中使用的一些约定和类型。   第2章——你好,三角形:一个OpenGL ES 3.0示例   第2章介绍绘制三角形的一个简单OpenGL ES 3.0示例。我们的目的是说明OpenGL ES 3.0程序的样子,向读者介绍一些API概念,并说明如何构建和运行OpenGL ES 3.0示例程序。   第3章——EGL简介   第3章介绍EGL——为OpenGL ES 3.0创建表面和渲染上下文的API。我们说明与原生窗口系统通信、选择配置和创建EGL渲染上下文及表面的方法,传授足够多的EGL知识,你可以了解到启动OpenGL ES 3.0进行渲染所需的所有知识。   第4章——着色器和程序   着色器对象和程序对象是OpenGL ES 3.0中最基本的对象。第4章介绍创建着色器对象、编译着色器和检查编译错误的方法。这一章还说明如何创建程序对象、将着色器对象连接到程序对象以及链接最终程序对象的方法。我们讨论如何查询程序对象的信息以及加载统一变量(uniform)的方法。此外,你将学习有关源着色器和程序二进制代码之间的差别以及它们的使用方法。   第5章——OpenGL ES着色语言   第5章介绍编写着色器所需的着色语言的基础知识。这些着色语言基础知识包括变量和类型、构造器、结构、数组、统一变量、统一变量块(uniform block)和输入/输出变量。该章还描述着色语言的某些更细微的部分,例如精度限定符和不变性。   第6章——顶点属性、顶点数组和缓冲区对象   从第6章开始(到第11章为止),我们将详细介绍管线,教授设置和编程图形管线各个部分的方法。这一旅程从介绍几何形状输入图形管线的方法开始,包含了对顶点属性、顶点数组和缓冲区对象的讨论。   第7章——图元装配和光栅化   在前一章讨论几何形状输入图形管线的方法之后,第7章将讨论几何形状如何装配成图元,介绍OpenGL ES 3.0中所有可用的图元类型,包括点精灵、直线、三角形、三角形条带和三角扇形。此外,我们还说明了在顶点上进行坐标变换的方法,并简单介绍了OpenGL ES 3.0管线的光栅化阶段。   第8章——顶点着色器   我们所介绍的管线的下一部分是顶点着色器。第8章概述了顶点着色器如何融入管线以及OpenGL ES 着色语言中可用于顶点着色器的特殊变量,介绍了多个顶点着色器的示例,包括逐像素照明和蒙皮(skinning)。我们还给出了用顶点着色器实现OpenGL ES 1.0(和1.1)固定功能管线的示例。   第9章——纹理   第9章开始介绍片段着色器,描述OpenGL ES 3.0中所有可用的纹理功能。该章提供了创建纹理、加载纹理数据以及纹理渲染的细节,描述了纹理包装模式、纹理过滤、纹理格式、压缩纹理、采样器对象、不可变纹理、像素解包缓冲区对象和Mip贴图。该章介绍了OpenGL ES 3.0支持的所有纹理类型:2D纹理、立方图、2D纹理数组和3D纹理。   第10章——片段着色器   第9章的重点是如何在片段着色器中使用纹理,第10章介绍编写片段着色器所需知道的其他知识。该章概述了片段着色器和所有可用的特殊内建变量,还演示了用片段着色器实现OpenGL ES 1.1中所有固定功能技术的方法。多重纹理、雾化、Alpha测试和用户裁剪平面的例子都使用片段着色器实现。   第11章——片段操作   第11章讨论可以适用于整个帧缓冲区或者在OpenGL ES 3.0片段管线中执行片段着色器后适用于单个片段的操作。这些操作包括剪裁测试、模板测试、深度测试、多重采样、混合和抖动。本章介绍OpenGL ES 3.0图形管线的最后阶段。   第12章——帧缓冲区对象   第12章讨论使用帧缓冲区对象渲染屏幕外表面。帧缓冲区对象有多种用法,最常见的是渲染到一个纹理。本章提供API帧缓冲区对象部分的完整概述。理解帧缓冲区对象对于实现许多高级特效(如反射、阴影贴图和后处理)至关重要。   第13章——同步对象和栅栏   第13章概述同步对象和栅栏,它们是在OpenGL ES 3.0主机应用和GPU执行中同步的有效图元。我们讨论同步对象和栅栏的使用方法,并以一个示例作为结束。   第14章——OpenGL ES 3.0高级编程   第14章是核心章节,将本书介绍的许多主题串联在一起。我们已经选择了高级渲染技术的一个样本,并展示了实现这些功能的示例。该章包含使用法线贴图的逐像素照明、环境贴图、粒子系统、图像后处理、程序纹理、阴影贴图、地形渲染
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值