OpenGL ES是OpenGL三维图形API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。 Ophone目前支持OpenGL ES 1.0 ,OpenGL ES 1.0 是以 OpenGL 1.3 规范为基础的,OpenGL ES 1.1 是以 OpenGL 1.5 规范为基础的。本文主要介绍利用OpenGL ES绘制图形方面的基本步骤。
本文内容由三部分构成。首先通过EGL获得OpenGL ES的编程接口;其次介绍构建3D程序的基本概念;最后是一个应用程序示例。
EGL
OpenGL ES 本质上是一个图形渲染管线的状态机,而 EGL 则是用于监控这些状态以及维护帧缓冲和其他渲染面的外部层。图1 是一个典型的 EGL 系统布局图。EGL 视窗设计是基于人们熟悉的用于 Microsoft Windows ( WGL )和 UNIX ( GLX )上的 OpenGL 的 Native 接口,与后者比较接近。 OpenGL ES 图形管线的状态被存储于 EGL 管理的一个上下文中。帧缓冲和其他绘制渲染面通过 EGL API 创建、管理和销毁。
EGL 同时也控制和提供了对设备显示和可能的设备渲染配置的访问。
图1
OpenGL ES 需要一个渲染上下文和渲染面。渲染上下文中存储OpenGL ES的状态信息,渲染面用于图元的绘制。编写OpenGL ES之前需要EGL的操作有:
-
查询设备可以支持的显示句柄,并初始化。
-
创建渲染面,绘制OpenGL ES图形。
-
创建渲染上下文。EGL需要创建OpenGL ES渲染上下文用于关联到某个渲染面。
Ophone中EGL包括4个类,分别是EGLDisplay:显示句柄、EGLConfig:配置类;EGLContext:渲染上下文;的类和EGLSurface:可渲染的视图类。
EGL可以认为成OpenGL ES和本地窗口系统之间的中间层。 本地窗口系统指GNU/Linux上X窗口系统,或者Mac OX X's Quartz等。在EGL确定渲染面的类型前,EGL需要和底层的窗口系统进行通讯。因为在不同的操作系统上的窗口系统的不同,EGL提供一个透明窗口类型,即EGLDisplay。它抽象了各种窗口系统。所以首先要创建、初始化一个EGLDisplay对象。
- EGL10egl=(EGL10)EGLContext.getEGL();
- EGLDisplaydpy=egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
- int[]version=newint[2];
- egl.eglInitialize(dpy,version);
每个 EGLDisplay 在使用前都需要初始化。初始化 EGLDisplay 的同时能够得到系统中 EGL 的实现版本号。通过版本号,合理运用相应OpenGL ES API,可以编写兼容性良好的程序,以适应更多的设备以及提供最大限度的移植性。初始化函数原型:
- booleaneglInitialize(EGLDisplaydisplay,int[]major_minor)
其中的display是一个有效的 EGLDisplay实例。函数调用完成时, major_minor将被赋予当前 EGL 版本号。比如 EGL1.0 , major_minor[0]为1,major_minor[1]为0。EGLSurface包含了EGL渲染面相关的所有信息。查询EGLSurface配置信息有两种方法,一是查询所有的配置信息,从中选择一个最为适合的;二是指定好配置信息,由系统给出最佳匹配结果。一般采用第二种方法。用户通过configSpec指定出希望获得的配置,函数eglChooseConfig通过参数Configs返回最佳的配置列表。之后利用已获得的Configs,调用eglCreateContext创建一个渲染上下文,该函数返回EGLContext结构。渲染面EGLSurface的创建通过函数eglCreateWindowSurface完成。一个应用程序可以创建多个EGLContext。
eglMakeCurrent就是将某个渲染上下文绑定到渲染面。查询函数eglGetCurrentContext,eglGetCurrentDisplay和eglGetCurrentSurface分别用于获得当前系统的渲染上下文、显示句柄和渲染面。最后EGLContext的静态方法getGL获得OpenGL ES的编程接口。下面的程序片段总结了上述内容。
- EGL10egl=(EGL10)EGLContext.getEGL();
- EGLDisplaydpy=egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);int[]version=newint[2];
- egl.eglInitialize(dpy,version);
- int[]configSpec={
- EGL10.EGL_RED_SIZE,5,
- EGL10.EGL_GREEN_SIZE,6,
- EGL10.EGL_BLUE_SIZE,5,
- EGL10.EGL_DEPTH_SIZE,16,
- EGL10.EGL_NONE
- };
- EGLConfig[]configs=newEGLConfig[1];
- int[]num_config=newint[1];
- egl.eglChooseConfig(dpy,configSpec,configs,1,num_config);
- EGLConfigconfig=configs[0];
- EGLContextcontext=egl.eglCreateContext(dpy,config,
- EGL10.EGL_NO_CONTEXT,null);
- EGLSurfacesurface=egl.eglCreateWindowSurface(dpy,config,
- sHolder,null);
- egl.eglMakeCurrent(dpy,surface,surface,context);
- GL10gl=(GL10)context.getGL();
构建3D图形
点
点是构建3D模型的基础。 OpenGL ES的内部计算是基于点的。 用点也可以表示光源的位置,物体的位置。一般我们用一组浮点数来表示点。 例如一个正方形的4个顶点可表示为:
- floatvertices[]={
- -1.0f,1.0f,0.0f,
- -1.0f,-1.0f,0.0f,
- 1.0f,-1.0f,0.0f,
- 1.0f,1.0f,0.0f,
- };
为了提高性能, 需要将浮点数组存入一个字节缓冲中。 所以有了下面的操作:
- ByteBuffervbb=ByteBuffer.allocateDirect(vertices.length*4);
- vbb.order(ByteOrder.nativeOrder());
- FloatBuffervertexBuffer=vbb.asFloatBuffer();
- vertexBuffer.put(vertices);
- vertexBuffer.position(0);
其中ByteOrder.nativeOrder()是获取本机字节顺序。OpenGL ES有操作图形渲染管线的函数,在默认情况下这些函数功能的使用状态是处于关闭的。 启用和关闭这些函数可以用glEnableClientState、glDisableClientState来完成。
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuffer);
- gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
边
边是连接两个点的一条线,是多边形面的边缘。
多边形
多边形是由边构成的单闭合环。 OpenGL ES中的多边形必须是凸多边形,即在多边形的内部任意取两点, 如果连接这两个点的线段都在多变的内部,这个多边形就是凸多边形。 绘制多边形时需要指定渲染的方向, 分为顺时针和逆时针。 因为方向决定了多边形的朝向, 即正面和背面。 避免渲染那些被遮挡的部分可以了有效提高程序性能。 函数glFrontFace定义了渲染顶点的方向。
- glFrontFace(GL_CCW);
- glFrontFace(GL_CW);
渲染
有了以上的概念讲解后,现在要进行最主要的工作—渲染。渲染是把物体坐标所指定的图元转化成帧缓冲区中的图像。图像和顶点坐标有着密切的关系。这个关系通过绘制模式给出。常用到得绘制模式有GL_POINTS、GL_LINE_STRIP、GL_LINE_LOOP、GL_LINES、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN。下面分别介绍:
GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制n个点。
GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n个线段,总共绘制N/2条线段。,如果N为奇数,则忽略最后一个顶点。
GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制N-1条线段。
GL_LINE_LOOP:绘制从定义第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点与第一个顶点相连。第n和n+1个顶点定义了线段n,然后最后一个线段是由顶点N和1之间定义,总共绘制N条线段。
GL_TRIANGLES:把每三个顶点作为一个独立的三角形。顶点3n-2,3n-1和3n定义了第n个三角形,总共绘制N/3个三角形。
GL_TRIANGLE_STRIP:绘制一组相连的三角形。对于奇数点n,顶点n,n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1,n和n+2定义了第n个三角形,总共绘制N-2个三角形。
GL_TRIANGLE_FAN:绘制一组相连的三角形。三角形是由第一个顶点及其后给定的顶点所确定。顶点1,n+1和n+2定义了第n个三角形,总共绘制N-2个三角形。
绘制函数:
void glDrawArrays(int mode, int first, int count)
void glDrawElements(int mode, int count, int type, Buffer indices)
glDrawArrays创建一个几何图元序列,使用每个被的数组中从first开始,到first + count – 1结束的数组元素, mode为绘制模式。
glDrawElements使用count个元素定义一个图元序列,type是indices数组中的数据类型,mode为绘制模式,indices数组存储顶点的索引值。
应用举例
利用上面讲解的内容给出一个Ophone上绘制一个3D球形的程序。效果图如下:
图2 球形示例
主要的绘制程序:
- staticprivateFloatBuffervertex;
- staticprivateFloatBuffernormal;
- float[]lightPos=newfloat[]{10.0f,10.0f,10.0f,1.0f};
- privatestaticfinalintSTEP=24;
- privatestaticfinalfloatRADIUS=1.0f;
- protectedvoidinit(GL10gl){
- gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
- gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_POSITION,lightPos,0);
- gl.glEnable(GL10.GL_LIGHTING);
- gl.glEnable(GL10.GL_LIGHT0);
- gl.glClearDepthf(1.0f);
- gl.glDepthFunc(GL10.GL_LEQUAL);
- gl.glEnable(GL10.GL_DEPTH_TEST);
- gl.glEnable(GL10.GL_CULL_FACE);
- gl.glShadeModel(GL10.GL_SMOOTH);
- }
- protectedvoiddrawFrame(GL10gl){
- gl.glClear(GL10.GL_COLOR_BUFFER_BIT|
- GL10.GL_DEPTH_BUFFER_BIT);
- gl.glMatrixMode(GL10.GL_MODELVIEW);
- gl.glLoadIdentity();
- GLU.gluLookAt(gl,0,0,7f,0f,0f,0f,0f,1.0f,0.0f);
- drawSphere(gl,RADIUS,STEP,STEP);
- }
public static void
gluLookAt(
GL10gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float
centerZ, float upX, float upY, float upZ)
它共接受三组坐标,分别为eye、 center和up。eye表示我们眼睛在"世界坐标系"中的位置,center表示眼睛"看"的那个点的坐标,up坐标表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,这里是正立方式,所以是{0,1,0}。
- privatestaticvoiddrawSphere(GL10gl,floatradius,
- intstacks,intslices){
- vertex=allocateFloatBuffer(4*6*stacks*(slices+1));
- normal=allocateFloatBuffer(4*6*stacks*(slices+1));
- inti,j,triangles;
- floatslicestep,stackstep;
- stackstep=((float)Math.PI)/stacks;
- slicestep=2.0f*((float)Math.PI)/slices;
- for(i=0;i<stacks;++i)
- {
- floata=i*stackstep;
- floatb=a+stackstep;
- floats0=(float)Math.sin(a);
- floats1=(float)Math.sin(b);
- floatc0=(float)Math.cos(a);
- floatc1=(float)Math.cos(b);
- floatnv;
- for(j=0;j<=slices;++j)
- {
- floatc=j*slicestep;
- floatx=(float)Math.cos(c);
- floaty=(float)Math.sin(c);
- nv=x*s0;
- normal.put(nv);
- vertex.put(nv*radius);
- nv=y*s0;
- normal.put(nv);
- vertex.put(nv*radius);
- nv=c0;
- normal.put(nv);
- vertex.put(nv*radius);
- nv=x*s1;
- normal.put(nv);
- vertex.put(nv*radius);
- nv=y*s1;
- normal.put(nv);
- vertex.put(nv*radius);
- nv=c1;
- normal.put(nv);
- vertex.put(nv*radius);
- }
- }
- normal.position(0);
- vertex.position(0);
- gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertex);
- gl.glNormalPointer(GL10.GL_FLOAT,0,normal);
- gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
- gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
- triangles=(slices+1)*2;
- for(i=0;i<stacks;i++)
- gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,
- i*triangles,triangles);
- gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
- gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
- }
- privatestaticFloatBufferallocateFloatBuffer(intcapacity){
- ByteBuffervbb=ByteBuffer.allocateDirect(capacity);
- vbb.order(ByteOrder.nativeOrder());
- returnvbb.asFloatBuffer();
- }
分享到:
相关推荐
构建3D图形,OpenGl ES 绘制3D图形的放回绘制2D的图形的大致方法
最后,一个完整的3D图形应用程序通常会包含以下部分:设置场景、加载模型数据、创建并初始化OpenGL ES环境、设置3D模型的属性(如颜色、纹理、光照)、绘制3D模型、并在每一帧结束后更新和刷新屏幕。 通过以上步骤...
在“opengles的一些图形绘制”这个主题中,我们主要关注的是如何使用OpenGL ES API来创建和绘制不同的几何形状。下面将详细介绍基于OpenGL ES的图形绘制技术: 1. **基础概念**:OpenGL ES是一个跨语言、跨平台的...
采用最新的图形管线理论,将OpenGL ES的3D图形管线绘制过程划分为七个管线绘制部分(这七个部分归属于三个绘制阶段),分析每个绘制部分的主要工作,在此基础上针对各个阶段提出了相应的优化方法。
在OpenGLES中绘制圆锥体是一个典型的3D图形编程任务,它涉及到多个关键知识点,包括顶点坐标、几何形状构建、光照模型以及纹理映射。让我们深入探讨这些概念。 首先,OpenGLES(OpenGL for Embedded Systems)是...
OpenGL ES 是一种在嵌入式设备上广泛使用的图形库,特别是在Android系统中,它用于创建高性能的2D和3D图形。在这个主题中,我们主要关注如何在Android平台上使用OpenGL ES绘制一个透明的三维/空间坐标系。这个过程...
OpenGL ES(OpenGL for Embedded Systems)是OpenGL的一个精简版本,专为嵌入式设备如智能手机、平板电脑等设计,用于2D和3D图形渲染。在Android系统中,OpenGL ES通常用于游戏开发、图像处理和其他视觉效果的实现。...
在Android平台上,OpenGL ES是一种广泛使用的图形库,用于在移动设备上实现高性能的2D和3D图形渲染。本文将深入探讨如何使用OpenGL ES来绘制圆点,并介绍一种方法来优化圆点边缘的锯齿问题,提升视觉效果。 首先,...
"opengles绘制灰度地形图"这个主题,主要涉及如何使用OpenGL ES来创建并渲染基于灰度值表示的3D地形。下面将详细讲解这个过程中的关键知识点。 1. **灰度图像**: 灰度图像是一种单通道图像,其中每个像素用一个...
【OpenGL ES】是嵌入式系统,特别是移动设备如Android平台上的核心图形库接口,用于高效绘制2D和3D图形。它简化了硬件层的复杂性,为开发者提供了统一的编程模型。OpenGL ES有两种主要版本,1.x针对固定管线硬件,而...
OpenGL ES 是一种基于 OpenGL 的图形库,专为嵌入式设备如智能手机、平板电脑和游戏机设计,用于渲染2D和3D图形。在Android平台上,OpenGL ES 是开发者常用的技术来实现高性能的图形处理。本篇文章将深入探讨如何...
总之,实现Android上的OpenGL ES地球仪绘制涉及了3D图形的基本原理、纹理映射技术以及用户交互的处理。理解并掌握这些知识点,对于开发具有3D图形界面的应用程序至关重要。通过阅读和分析提供的源码,可以更深入地...
总的来说,这个项目涉及了Android开发中的3D图形编程,通过OpenGL ES绘制不同类型的几何形状,每个形状作为一个独立的类实现,而renderer类则负责把这些形状渲染到屏幕上,创造出丰富的3D视觉效果。理解并掌握这些...
在本主题“opengles绘制纹理”中,我们将深入探讨如何在OpenGL ES环境中加载和绘制纹理,以增强图形渲染的质量和表现力。 1. **纹理的概念** 在计算机图形学中,纹理是指附加到几何形状上的二维图像数据,用于给...
在 Android 平台上,我们可以使用 OpenGL ES 进行3D图形编程,创建丰富的视觉效果。本资源主要讲解如何使用 OpenGL ES 绘制一个立方体,并通过触摸事件实现手动控制立方体的旋转,同时解决了立方体在旋转过程中可能...
### OpenGL入门学习之二——绘制几何图形:详细解析 #### 一、理解点、直线与多边形在OpenGL中的表现 在计算机图形学领域,尤其是OpenGL框架中,几何图形的基本构建块包括点、直线和多边形。这些概念在数学理论与...
OpenGL是一个跨语言、跨平台的编程接口,用于生成动态的2D和3D图形。在Android中,我们通常使用Android的OpenGL ES版本,它是针对嵌入式设备优化的OpenGL标准。要使用OpenGL ES,我们需要创建一个`GLSurfaceView`,...
OpenGL ES 是一种针对嵌入式系统的图形库,广泛...整个过程既需要理解3D图形学原理,也需要熟悉Android开发环境和OpenGL ES的API。完成这个项目不仅可以提升你的图形编程技能,还能增强对移动平台3D图形处理的理解。
采用最新的图形管线理论,将OpenGL ES的3D图形管线绘制过程划分为七个管线绘制部分(这七个部分归属于三个绘制阶段),分析每个绘制部分的主要工作,在此基础上针对各个阶段提出了相应的优化方法。