`
tangweiye
  • 浏览: 150866 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

android opengl es 总结

 
阅读更多

什么是OpenGL ES?

  • OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。
  • 为桌面版本OpenGL 的一个子集。
  • OpenGL ES 定义了一个在移动平台上能够支持OpenGL最基本功能的精简标准,以适应如手机,PDA或其它消费者移动终端的显示系统。
  • Khronos Group 定义和管理了OpenGL ES标准。

OpenGL 与 OpenGL ES的关系

OpenGL ES 是基于桌面版本OpenGL 的:
  • OpenGL ES 1.0  基于OpenGL 1.3 , 在2003年发布
  • OpenGL ES 1.1   基于OpenGL 1.5 ,  在2004年发布
  • OpenGL ES 2.0  基于OpenGL2.0,   在2007年发布
  • OpenGL 2.0 向下兼容OpenGL 1.5   而 OpenGL ES 2.0 和OpenGL ES 1.x 不兼容,是两种完全不同的实现。

OpenGL ES管道(Pipeline)

OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工的工序是固定的,但是可以通过打开或关闭开关来设置参数或者打开关闭某些功能。OpenGL ES 2.0 允许提供编程来控制一些重要的工序,一些“繁琐”的工序比如栅格化等仍然是固定的。(这些开关被就是state,注意应该尽量少的改变state,以免影响性能)
  • 管道“工序”大致可以分为 Transformation Stage 和 Rasterization Stage两大步。
  • OpenGL ES 支持的基本图形为 点Point, 线Line, 和三角形Triangle ,其它所有复制图形都是通过这几种基本几何图形组合而成。
  • 在发出绘图指令后,会对顶点(Vertices)数组进行指定的坐标变换或光照处理。
  • 顶点处理完成后,通过Rasterizer 来生成像素信息,称为”Fragments“ 。
  • 对于Fragment 在经过Texture Processing, Color Sum ,Fog 等处理并将最终处理结果存放在内存中(称为FrameBuffer)。
  • OpenGL 2.0可以通过编程来修改上述红色的部分的步骤,称为Programmable Shader.

OpenGL ES API 命名习惯

 
  • 定义的常量都以GL_为前缀。比如GL10.GL_COLOR_BUFFER_BIT
  • OpenGL ES 指令以gl开头 ,比如gl.glClearColor
  • 某些OpenGL指令以3f 或4f结尾,3和4代表参数的个数,f代表参数类型为浮点数,如gl.glColor4f ,i,x 代表 int如 gl.glColor4x
  • 对应以v结尾的OpenGL ES 指令,代表参数类型为一个矢量(Vector) ,如 glTexEnvfv
  • 所有8-bit整数对应到byte 类型,16-bit 对应到short类型,32-bit整数(包括GLFixed)对应到int类型,而所有32-bit 浮点数对应到float 类型。
  • GL_TRUE,GL_FALSE 对应到boolean类型
  • C字符串((char*)) 对应到Java 的 UTF-8 字符串。 
  •  

     

     
    创建简单的opengl es实例
     
     
     

    基本几何图形定义

    OpenGL ES 支持绘制的基本几何图形分为三类:点,线段,三角形。也就是说OpenGL ES 只能绘制这三种基本几何图形。任何复杂的2D或是3D图形都是通过这三种几何图形构造而成的。

    OpenGL ES提供了两类方法来绘制一个空间几何图形:

    • public abstract void glDrawArrays(int mode, int first, int count) 使用VetexBuffer 来绘制,顶点的顺序由vertexBuffer中的顺序指定。
    • public abstract void glDrawElements(int mode, int count, int type, Buffer indices) ,可以重新定义顶点的顺序,顶点的顺序由indices Buffer 指定。
    mode列表:GL_POINTS 绘制独立的点、GL_LINE_STRIP绘制一条线段、GL_LINE_LOOP绘制一条封闭线段(首位相连)、GL_LINES绘制多条线段、GL_TRIANGLES绘制多个三角形(两两不相邻)、GL_TRIANGLE_STRIP绘制多个三角形(两两相邻)、GL_TRIANGLE_FAN以一个点为顶点绘制多个相邻的三角形

    对应顶点除了可以为其定义坐标外,还可以指定颜色,材质,法线(用于光照处理)等。

    glEnableClientState 和 glDisableClientState 可以控制的pipeline开关可以有:GL_COLOR_ARRAY (颜色) ,GL_NORMAL_ARRAY (法线), GL_TEXTURE_COORD_ARRAY (材质), GL_VERTEX_ARRAY(顶点), GL_POINT_SIZE_ARRAY_OES等。

    对应的传入颜色,顶点,材质,法线的方法如下:

    glColorPointer(int size,int type,int stride,Buffer pointer)
    glVertexPointer(int size, int type, int stride, Buffer pointer)
    glTexCoordPointer(int size, int type, int stride, Buffer pointer)
    glNormalPointer(int type, int stride, Buffer pointer)

    OpenGL ES 内部存放图形数据的Buffer有COLOR ,DEPTH (深度信息)等,在绘制图形只前一般需要清空COLOR 和 DEPTH Buffer。


    三维坐标系及坐标变换初步

    OpenGL ES图形库最终的结果是在二维平面上显示3D物体,这个过程可以分成三个部分:
    • 坐标变换,坐标变换通过使用变换矩阵来描述,因此学习3D绘图需要了解一些空间几何,矩阵运算的知识。三维坐标通常使用齐次坐标来定义。变换矩阵操作可以分为视角(Viewing),模型(Modeling)和投影(Projection)操作,这些操作可以有选择,平移,缩放,正侧投影,透视投影等。
    • 由于最终的3D模型需要在一个矩形窗口中显示,因此在这个窗口之外的部分需要裁剪掉以提高绘图效率,对应3D图形,裁剪是将处在剪切面之外的部分扔掉。
    • 在最终绘制到显示器(2D屏幕),需要建立起变换后的坐标和屏幕像素之间的对应关系,这通常称为“视窗”坐标变换(Viewport) transformation.
    如果我们使用照相机拍照的过程做类比,可以更好的理解3D 坐标变换的过程。
    1. 拍照时第一步是架起三角架并把相机的镜头指向需要拍摄的场景,对应到3D 变换为viewing transformation (平移或是选择Camera )
    2. 然后摄影师可能需要调整被拍场景中某个物体的角度,位置,比如摄影师给架好三角架后给你拍照时,可以要让你调整站立姿势或是位置。对应到3D绘制就是Modeling transformation (调整所绘模型的位置,角度或是缩放比例)。
    3. 之后摄影师可以需要调整镜头取景(拉近或是拍摄远景),相机取景框所能拍摄的场景会随镜头的伸缩而变换,对应到3D绘图则为Projection transformation(裁剪投影场景)。
    4. 按下快门后,对于数码相机可以直接在屏幕上显示当前拍摄的照片,一般可以充满整个屏幕(相当于将坐标做规范化处理NDC),此时你可以使用缩放放大功能显示照片的部分。对应到3D绘图相当于viewport transformation (可以对最终的图像缩放显示等)
    对于Viewing transformation (平移,选择相机)和Modeling transformation(平移,选择模型)可以合并起来看,只是应为向左移动相机,和相机不同将模型右移的效果是等效的。

    在OpenGL ES 中,

    • 使用GL10.GL_MODELVIEW 来同时指定viewing matrix 和modeling matrix.
    • 使用GL10.GL_PROJECTION 指定投影变换,OpenGL 支持透视投影(3D)和正侧投影(2D)。
    • 使用glViewport 指定 Viewport 变换。
     
     

    通用的矩阵变换指令

     
    这里介绍对应指定的坐标系(比如viewmodel, projection或是viewport) Android OpenGL ES支持的一些矩阵运算及操作。
    矩阵本身可以支持加减乘除,对角线全为1的4X4 矩阵成为单位矩阵Identity Matrix 。
    • 将当前矩阵设为单位矩阵的指令 为glLoadIdentity().
    • 矩阵相乘的指令glMultMatrix*() 允许指定任意矩阵和当前矩阵相乘。
    • 选择当前矩阵种类glMatrixMode() OpenGL ES 可以运行指定GL_PROJECTION,GL_MODELVIEW等坐标系,后续的矩阵操作将针对选定的坐标。
    • 将当前矩阵设置成任意指定矩阵glLoadMatrix*()
    • 在栈中保存当前矩阵和从栈中恢复所存矩阵,可以使用glPushMatrix()glPopMatrix()
    • 特定的矩阵变换平移glTranslatef(),旋转glRotatef() 和缩放glScalef()
    方法public abstract void glTranslatef (float x, float y, float z) 用于坐标平移变换。
    方法public abstract void glRotatef(float angle, float x, float y, float z)用来实现选择坐标变换,单位为角度。 (x,y,z)定义旋转的参照矢量方向。多次旋转的顺序非常重要。
    方法public abstract void glScalef (float x, float y, float z)用于缩放变换。

    在进行平移,旋转,缩放变换时,所有的变换都是针对当前的矩阵(与当前矩阵相乘),如果需要将当前矩阵回复最初的无变换的矩阵,可以使用单位矩阵(无平移,缩放,旋转)。

    public abstract void glLoadIdentity()。

    在栈中保存当前矩阵和从栈中恢复所存矩阵,可以使用

    public abstract void glPushMatrix()

    public abstract void glPopMatrix()。

    在进行坐标变换的一个好习惯是在变换前使用glPushMatrix保存当前矩阵,完成坐标变换操作后,再调用glPopMatrix恢复原先的矩阵设置。
     
     

    Viewing和Modeling(MODELVIEW) 变换

     

    ndroid OpenGL ES 的GLU包有一个辅助函数gluLookAt提供一个更直观的方法来设置modelview 变换矩阵:

    void gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
    • eyex,eyey,eyez 指定观测点的空间坐标。
    • tarx,tary,tarz ,指定被观测物体的参考点的坐标。
    • upx,upy,upz 指定观测点方向为“上”的向量。(0,1,0)
     
     
     
    投影变换Projection
    投影变换则对应于调整相机镜头远近来取景。
    下面代码设置当前Matrix模式为Projection投影矩阵:
    gl.glMatrixMode(GL_PROJECTION);
    gl.glLoadIdentity();
    OpenGL ES可以使用两种不同的投影变换:透视投影(Perspective Projection)和正侧投影(Orthographic Projection)。
    Android OpenGL ES提供了一个辅助方法gluPerspective()可以更简单的来定义一个透视投影变换:

    GLU.gluPerspective(GL10 gl, float fovy, float aspect, float zNear, float zFar)

    • fovy: 定义视锥的view angle.
    • aspect:  定义视锥的宽高比。
    • zNear: 定义裁剪面的近距离。就是前面距离原点的距离
    • zFar: 定义创建面的远距离。就是后面距离原点的距离
    正侧投影(Orthographic Projection)
    正侧投影,它的视锥为一长方体,特点是物体的大小不随到观测点的距离而变化,投影后可以保持物体之间的距离和夹角。

     

     

    定义3D模型的前面和后面

    下面代码设置逆时针方法为面的“前面”:gl.glFrontFace(GL10.GL_CCW);

    打开 忽略“后面”设置:gl.glEnable(GL10.GL_CULL_FACE);然后明确指明“忽略“哪个面的代码如下:
    gl.glCullFace(GL10.GL_BACK);

    FrameBuffer、Depth Buffer

    OpenGL ES 中的FrameBuffer 指的是存储像素的内存空间。对应一个二维图像,如果屏幕分辨率为1280X1024 ,如果屏幕支持24位真彩色 (RGB),则存储这个屏幕区域的内存至少需要1024X1280X3个字节。此外如果需要支持透明度(Alpha),则一个像素需要4个字节。
    在最终OpenGL ES写入这些Buffer时,OpenGL ES提供一些Mask 函数可以控制Color Buffer 中RGBA通道,是否允许写入Depth Buffer 等,这些Mask 函数可以打开或是关闭某个通道,只有通道打开后,对应的分量才会写入指定Buffer,比如你可以关闭红色通道,这样最后写道Color Buffer中就不含有红色。

    OpenGL ES 中Depth Buffer 保存了像素与观测点之间的距离信息,在绘制3D图形时,将只绘制可见的面而不去绘制隐藏的面,这个过程叫”Hidden surface removal” ,采用的算法为”The depth buffer algorithm”。
    The depth buffer algorithm 在OpenGL ES 3D绘制的过程中这个算法是自动被采用的,但是了解这个算法有助于理解OpenGL ES 部分API的使用。

    下面给出了OpenGL ES中与Depth Buffer相关的几个方法:

    • gl.Clear(GL10.GL_DEPTH_BUFFER_BIT) 清空Depth Buffer (赋值为1.0)通常清空Depth Buffer和Color Buffer同时进行。
    • gl.glClearDepthf(float depth) 指定清空Depth Buffer是使用的值,缺省为1.0,通常无需改变这个值,
    • gl.glEnable(GL10.GL_DEPTH_TEST) 打开depth Test
    • gl.glDisable(GL10.GL_DEPTH_TEST) 关闭depth Test
     

    OpenGL光照模型

    为了能看出3D效果,给场景中添加光源。如果没有光照,绘出的球看上去和一个二维平面上圆没什么差别
    OpenGL 光照模型中最终的光照效果可以分为四个组成部分:Emitted(光源), ambient(环境光),diffuse(漫射光)和specular(镜面反射光),最终结果由这四种光叠加而成。

    Emitted : 一般只发光物体或者光源,这种光不受其它光源的影响。

    ambient: 环境光如果射到某个平面,其反射方向为所有方向。Ambient 没有位置方向,只有颜色。

    diffuse:当一束平行的入射光线射到粗糙的表面时,因面上凹凸不平,所以入射线虽然互相平行,由于各点的法线方向不一致,造成反射光线向不同的方向无规则地反射,这种反射称之为“漫反射”或“漫射”。这个反射的光则称为漫射光。漫射光射到某个平面时,其反射方向也为所有方向。diffuse 只依赖于光源的方向和法线的方向。

    specular : 一般指物体被光源直射的高亮区域,也可以成为镜面反射区,如金属。specular依赖于光源的方向,法线的方向和视角的方向。



    设置光照效果Set Lighting

    OpenGL ES API如何使用光照效果:
    • 设置光源
    • 定义法线
    • 设置物体材料光学属性

    光源

    OpenGL ES中可以最多同时使用八个光源,分别使用0到7表示。

    OpenGL ES光源可以分为

    • 平行光源(Parallel light source), 代表由位于无限远处均匀发光体,太阳可以近似控制平行光源。
    • 点光源(Spot light source)  如灯泡就是一个点光源,发出的光可以指向360度,可以为点光源设置光衰减属性(attenuation)或者让点光源只能射向某个方向(如射灯)。
    下面方法可以打开某个光源,使用光源首先要开光源的总开关:gl.glEnable(GL10.GL_LIGHTING);
    然后可以再打开某个光源如0号光源:gl.glEnable(GL10.GL_LIGHT0);
    设置光源方法如下:
    • public void glLightfv(int light,int pname, FloatBuffer params)
    • public void glLightfv(int light,int pname,float[] params,int offset)
    • public void glLightf(int light,int pname,float param)
    • light 指光源的序号,OpenGL ES可以设置从0到7共八个光源。
    • pname: 光源参数名称,可以有如下:GL_SPOT_EXPONENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION,  GL_LINEAR_ATTENUATION, GL_QUADRATIC_ATTENUATION, GL_AMBIENT, GL_DIFFUSE,GL_SPECULAR, GL_SPOT_DIRECTION, GL_POSITION
    • params 参数的值(数组或是Buffer类型)。
    其中为光源设置颜色的参数类型为上述蓝色值,可以分别指定R,G,B,A 的值。
    指定光源的位置的参数为GL_POSITION,值为(x,y,z,w):平行光将w 设为0.0,(x,y,z)为平行光的方向。

    法线
    在场景中设置好光源后,下一步要为所绘制的图形设置法线(Normal),只有设置了法线,光源才能在所会物体上出现光照效果。三维平面的法线是垂直于该平面的三维向量。曲面在某点P处的法线为垂直于该点切平面的向量

     

    打开法线数组gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); 


    和设置颜色类似,有两个方法可以为平面设置法线,一是public void glNormal3f(float nx,float ny,float nz)

    这个方法为后续所有平面设置同样的方向,直到重新设置新的法线为止。

    为某个顶点设置法线:public void glNormalPointer(int type,int stride, Buffer pointer)

    • type  为Buffer 的类型,可以为GL_BYTE, GL_SHORT, GL_FIXED,或 GL_FLOAT
    • stride: 每个参数之间的间隔。
    • pointer: 法线值。
    规范化法向量,比如使用坐标变换(缩放),如果三个方向缩放比例不同的话,顶点或是平面的法线可能就有变化,此时需要打开规范化法线设置:gl.glEnable(GL10.GL_NORMALIZE);
    经过规范化后法向量为单位向量(长度为1)。同时可以打开缩放法线设置gl.glEnable(GL10.GL_RESCALE_NORMAL);

    设置物体材料光学属性

    设置物体表面材料(Material)的反光属性(颜色和材质)的方法如下:

            gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, ambient, 0); 
            gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffuse, 0); 
            gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, specular, 0);  

     

            gl.glEnable(GL10.GL_COLOR_MATERIAL);  


    此外,方法glLightModleXX给出了光照模型的参数

    public void glLightModelf(int pname,float param)
    public void glLightModelfv(int pname,float[] params,int offset)
    public void glLightModelfv(int pname,FloatBuffer params)

    • pname: 参数类型,可以为GL_LIGHT_MODEL_AMBIENT和GL_LIGHT_MODEL_TWO_SIDE
    • params: 参数的值。

    最终顶点的颜色由这些参数(光源,材质光学属性,光照模型)综合决定(光照方程计算出)。

分享到:
评论

相关推荐

    Android OpenGL ES 简明开发教程

    ### Android OpenGL ES 开发教程详解 #### 概述与历史沿革 OpenGL ES(OpenGL for Embedded Systems)作为OpenGL API的子集,专为移动设备、PDA和游戏主机等嵌入式系统设计,旨在简化3D图形应用的开发流程。自2003...

    Android OpenGL ES 2.0学习书籍.rar

    最后,了解如何与硬件加速的OpenGLES API交互,以及熟悉GLSL语言(OpenGL Shading Language),是成为OpenGL ES 2.0专家的必经之路。通过编写高效、可读性强的着色器代码,可以创造出各种复杂的视觉效果,实现令人...

    Android OpenGl ES绘制圆点与优化圆点锯齿

    在Android平台上,OpenGL ES是一种广泛使用的图形库,用于在移动设备上实现高性能的2D和3D图形渲染。本文将深入探讨如何使用OpenGL ES来绘制圆点,并介绍一种方法来优化圆点边缘的锯齿问题,提升视觉效果。 首先,...

    Android OpenGL ES 绘制三维/空间坐标系透明

    OpenGL ES 是一种在嵌入式设备上广泛使用的图形库,特别是在Android系统中,它用于创建高性能的2D和3D图形。在这个主题中,我们主要关注如何在Android平台上使用OpenGL ES绘制一个透明的三维/空间坐标系。这个过程...

    Android平台使用OpenGLES2.0显示YUV数据

    总结起来,这个项目涉及到Android Camera API的使用,YUV到RGB的数据转换,OpenGLES2.0纹理处理,以及`GLSurfaceView`的使用。通过实践和学习这些知识点,开发者可以实现高效、流畅的摄像头预览效果,并为后续的视频...

    android openGl es2.0以画线的模式画成一个矩形 只有4条边中间透明

    android openGl es2.0以画线的模式画成一个矩形 只有4条边中间透明

    Android平台OpenGLES生成使用Mipmap纹理

    该案例代码为Android 平台OpenGL ES实现举例,有两个作用: ...2、使用 OpenGLES 生成与使用Mipmap纹理,构建远处模糊,近处清晰的效果。 具体案例文章讲解请见: https://xiaxl.blog.csdn.net/article/details/8873106

    Android OpenGL ES 绘制立方体 球体 圆柱 等几何形状

    OpenGL ES 是一种在嵌入式设备上广泛使用的图形库,特别是在Android系统中,它用于创建复杂的3D图形和动画。Android OpenGL ES 提供了一个接口,让开发者能够利用硬件加速的图形处理能力,来绘制出立方体、球体、...

    在Android中的jni里使用OpenGL ES和OpenCV渲染一幅图片

    总结起来,这个项目结合了Android的JNI、OpenGL ES和OpenCV,展示了如何在原生代码中处理图像并用OpenGL ES进行渲染,提供了一种高效且灵活的方式来显示和操作Android应用中的图像。这种技术对于需要高性能图形处理...

    Android OpenGL ES简明学习资料

    含有以下4个pdf,主要介绍基本概念和用法,对初学者非常有用。...Android OpenGL ES 简明开发教程.pdf Android_OpenGL_ES_book.pdf OpenGL ES 2 for Android.pdf Apress.Pro.OpenGL.ES.for.Android.Feb.2012.pdf

    Android中opengl es要实现Obj格式的3D导入

    OpenGL ES在Android平台上的应用是实现3D图形渲染的关键技术,而Obj文件格式是一种常见的3D模型数据交换格式。在Android开发中,如果想要将Obj格式的3D模型导入到应用中,就需要对OpenGL ES有深入的理解,并且掌握...

    android openGL ES使用小例子

    android openGL 里面提供了illegalArgumentException异常的解决方法

    Android openGL ES 画球

    Android openGL ES 画球

    android openGL ES 2.0画等边三角形,正方形

    android openGL ES 2.0画等边三角形,正方形

    Android平台 OpenGL ES3.0绘制点、线、三角形实现源码

    Android平台,OpenGL ES3.0 点、线、三角形绘制方式源码实现举例。 相关绘制方式文章讲解请参考: https://xiaxl.blog.csdn.net/article/details/8873002

    android opengl es 粒子,火焰

    OpenGL ES 是一种在嵌入式设备上广泛使用的图形库,特别是在Android平台上,它用于创建复杂的2D和3D图形效果。OpenGL ES(Embedded Systems)是OpenGL的轻量级版本,专为资源有限的移动设备设计。在Android系统中,...

    android opengles2.0 jni

    总结来说,Android上的OpenGL ES 2.0结合JNI,可以让我们实现复杂的图形特效,如水波纹。这个过程中涉及了顶点着色器和片段着色器的编写、纹理处理、OpenGL状态管理、性能优化等多个环节。通过深入理解这些概念和...

    Android平台 使用OpenGLES3.0实现纹理纹理、颜色混合

    在Android平台,使用OpenGLES3.0实现纹理纹理、颜色混合代码实现举例。 具体案例文章讲解请见: https://xiaxl.blog.csdn.net/article/details/121634894

    android OpenGL ES 中文 API

    `GL10`接口是`javax.microedition.khronos.opengles`包中的一个核心接口,它继承自`GL`接口,并且是`GL11`接口的父接口。`GL10`接口封装了OpenGL ES的基本功能,包括核心渲染命令和其他一些重要的扩展特性。此接口...

    Android开发之OpenGL ES教程

    Android平台上的OpenGL ES教程主要帮助开发者了解如何在Android应用程序中集成和使用这个库来创建交互式的图形界面。 在Android上设置OpenGL ES视图是开发过程中的第一步,而`GLSurfaceView`是实现这一目标的关键...

Global site tag (gtag.js) - Google Analytics