您的位置:首页 > 运维架构

[置顶] OpenGL ES总结(一)OpenGL 初识

2017-03-12 13:55 756 查看
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/61615215

OpenGL是在图形图像中,非常优秀的渲染库,文中Demo下载地址:https://github.com/hejunlin2013/OpenGL31,看下今天的Agenda:

OpenGL是什么?

OpenGL主要功能是什么?

OpenGL ES是什么?

Android中如何描述OpenGL ES版本

映射坐标绘制对象

坐标列表转化为逆时针绘制顺序

小总结

OpenGL ES 3.1 Demo实践

OpenGL是什么?

OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。

OpenGL™ 是行业领域中最为广泛接纳的 2D/3D 图形 API,其自诞生至今已催生了各种计算机平台及设备上的数千优秀应用程序。OpenGL™ 是独立于视窗操作系统或其它操作系统的,亦是网络透明的。在包含CAD、内容创作、能源、娱乐、游戏开发、制造业、制药业及虚拟现实等行业领域中,OpenGL™ 帮助程序员实现在 PC、工作站、超级计算机等硬件设备上的高性能、极具冲击力的高视觉表现力图形处理软件的开发。

OpenGL主要功能是什么?

OpenGL是一个开放的三维图形软件包,它独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植;OpenGL可以与Visual C++紧密接口,便于实现机械手的有关计算和图形算法,可保证算法的正确性和可靠性;OpenGL使用简便,效率高。它具有七大功能:

1、建模:OpenGL图形库除了提供基本的点、线、多边形的绘制函数外,还提供了复杂的三维物体(球、锥、多面体、茶壶等)以及复杂曲线和曲面绘制函数。

2、变换:OpenGL图形库的变换包括基本变换和投影变换。基本变换有平移、旋转、缩放、镜像四种变换,投影变换有平行投影(又称正射投影)和透视投 影两种变换。其变换方法有利于减少算法的运行时间,提高三维图形的显示速度。

3、颜色模式设置:OpenGL颜色模式有两种,即RGBA模式和颜色索引(Color Index)。

4、光照和材质设置:OpenGL光有自发光(Emitted Light)、环境光(Ambient Light)、漫反射光(Diffuse Light)和高光(Specular Light)。材质是用光反射率来表示。场景(Scene)中物体最终反映到人眼的颜色是光的红绿蓝分量与材质红绿蓝分量的反射率相乘后形成的颜色。

5、纹理映射(Texture Mapping)。利用OpenGL纹理映射功能可以十分逼真地表达物体表面细节。

6、位图显示和图象增强图象功能除了基本的拷贝和像素读写外,还提供融合(Blending)、抗锯齿(反走样)(Antialiasing)和雾(fog)的特殊图象效果处理。以上三条可使被仿真物更具真实感,增强图形显示的效果。

7、双缓存动画(Double Buffering)双缓存即前台缓存和后台缓存,简言之,后台缓存计算场景、生成画面,前台缓存显示后台缓存已画好的画面。

OpenGL ES是什么?

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

Android包括支持高性能2d和3d图形与开放图形库(OpenGL®),具体来说,OpenGL ES API。OpenGL是一个跨平台图形API,用于指定一个标准为3 d图形处理硬件的软件接口。OpenGL ES的味道OpenGL规范用于嵌入式设备。Android支持OpenGL ES API的几个版本:

OpenGL ES 1.0和1.1 -这个API规范支持Android 1.0和更高版本。

OpenGL ES 2.0 -这个API规范支持Android 2.2(API级别8)和更高。

OpenGL ES 3.0 -这个API规范支持Android 4.3(API级别18)和更高。

OpenGL ES 3.1 -这个API规范支持Android 5.0(API级别21)和更高。

Android支持OpenGL通过其框架API和本地开发工具包(NDK)。

在Android框架有两个基本类,让你创建和操作图形与OpenGL ES API:GLSurfaceView GLSurfaceView.Renderer。

GLSurfaceView

这是一个视图类,我们可以使用OpenGL绘制和操作对象API调用和SurfaceView是相似的函数。您可以使用这个类创建一个实例GLSurfaceView并add到你的Renderer(渲染器)。

public void setRenderer(GLSurfaceView.Renderer renderer)


起到连接OpenGL ES与Android 的View层次结构之间的桥梁作用。

使得Open GL ES库适应于Anndroid系统的Activity生命周期。

使得选择合适的Frame buffer像素格式变得容易。

创建和管理单独绘图线程以达到平滑动画效果。

提供了方便使用的调试工具来跟踪OpenGL ES函数调用以帮助检查错误。

GLSurfaceView.Renderer

这个接口定义了在GLSurfaceView绘制图形时所需的方法。既然是接口,那么就必须有一个实现该接口的类。然后使用GLSurfaceView.setRenderer(这里接收那个具体实类)方法,把这个实现类set到GLSurfaceView上。

GLSurfaceView.Renderer接口需要实现以下方法:

onSurfaceCreated():创建GLSurfaceView时回调。使用这个方法来执行操作,只需要发生一次,如设置OpenGL环境参数或初始化OpenGL图形对象。设置一些绘制时不常变化的参数,比如:背景色,是否打开 z-buffer等。

onDrawFrame():每绘制一帧的时回调。

onSurfaceChanged():GLSurfaceView几何变化时回调,包括GLSurfaceView大小的变化或设备的屏幕变换。

Android中如何描述OpenGL ES版本?

AndroidManifest.xml中加入:

For OpenGL ES 2.0:

<!-- Tell the system this app requires OpenGL ES 2.0. -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />


For OpenGL ES 3.0:

<!-- Tell the system this app requires OpenGL ES 3.0. -->
<uses-feature android:glEsVersion="0x00030000" android:required="true" />


For OpenGL ES 3.1:

<!-- Tell the system this app requires OpenGL ES 3.1. -->
<uses-feature android:glEsVersion="0x00030001" android:required="true" />


映射坐标绘制对象

OpenGL是假定一个正方形,统一系统坐标,默认情况下,它是将这些看起来在非正方形的屏幕上,看起来像正方形。



默认的OpenGL坐标系(左)映射到一个典型的Android设备屏幕(右)。

上面的图显示了(左边)一个OpenGL的统一坐标系统,和如何将这些坐标映射到(右边)一个典型的横向设备屏幕。为了解决这个问题,我们可以应用OpenGL正确的比例下通过投影模式和相机视图坐标转换你的图形对象。

为了应用投影和相机视图,我们创建一个投影矩阵和一个相机视图矩阵并将它们应用于OpenGL渲染管道中。投影矩阵重新计算你的图形的坐标,使他们正确地映射到Android设备的屏幕。相机视图矩阵创建一个转换,它将从一个特定的位置显示对象。

投影(Projection)和OpenGL ES 1.0相机视图( Camera View )

投影矩阵——创建一个投影矩阵使用设备屏幕以重新计算对象的几何坐标所以他们用正确的比例。下面的示例代码演示了如何修改onSurfaceChanged GLSurfaceView()方法。渲染器实现来创建一个基于屏幕的长宽比和投影矩阵应用于OpenGL渲染环境。

public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);

// make adjustments for screen ratio
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);        // set matrix to projection mode
gl.glLoadIdentity();                        // reset the matrix to its default state
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);  // apply the projection matrix
}


相机变换矩阵——一旦你使用投影矩阵调整坐标系统,我们还必须添加一个相机视图。下面的示例代码显示了如何修改onDrawFrame GLSurfaceView()方法。渲染器实现应用模型视图,并使用GLU.gluLookAt()实用程序来创建一个模拟摄像机观察变换位置。

public void onDrawFrame(GL10 gl) {
...
// Set GL_MODELVIEW transformation mode
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();                      // reset the matrix to its default state

// When using GL_MODELVIEW, you must set the camera view
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
...
}


投影和OpenGL ES 2.0和更高版本的相机视图

ES 2.0和3.0 api,应用投影和相机视图首先要添加一个矩阵图形的顶点着色器(Shader)对象成员。添加了这个矩阵成员,我们可以生成和应用投影和相机观察矩阵对象。

顶点着色器添加矩阵——为视图创建一个变量投影矩阵,包括乘数着色器的位置。在下面的例子中顶点着色器代码,包括uMVPMatrix成员允许您应用投影和相机观测矩阵的坐标对象。

private final String vertexShaderCode =

// This matrix member variable provides a hook to manipulate
// the coordinates of objects that use this vertex shader.
"uniform mat4 uMVPMatrix;   \n" +

"attribute vec4 vPosition;  \n" +
"void main(){               \n" +
// The matrix must be included as part of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition; \n" +

"}  \n";


访问着色矩阵之后,创建一个钩在你的顶点着色器应用投影和相机视图中,您可以访问该变量应用投影和相机观测矩阵。下面的代码演示如何修改onSurfaceCreated GLSurfaceView()方法。渲染器实现访问上面的顶点着色器中定义的矩阵变量。

public void onSurfaceCreated(GL10 unused, EGLConfig config) {
...
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
...
}


创建投影和相机观察矩阵——生成投影矩阵和查看应用的图形对象。下面的示例代码显示了如何修改onSurfaceCreated()和onSurfaceChanged GLSurfaceView()方法。渲染器实现创建相机视图矩阵和投影矩阵基于设备的屏幕宽高比。

public void onSurfaceCreated(GL10 unused, EGLConfig config) {
...
// Create a camera view matrix
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
}

public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);

float ratio = (float) width / height;

// create a projection matrix from device screen geometry
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}


应用投影和相机观察矩阵——应用投影和相机视图的转换,将矩阵的相乘,然后设置在顶点着色器中。下面的代码显示了如何修改onDrawFrame GLSurfaceView()方法。渲染器实现结合投影矩阵和相机视图中创建上面的代码,然后把它应用到由OpenGL渲染的图形对象。

public void onDrawFrame(GL10 unused) {
...
// Combine the projection and camera view matrices
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);

// Apply the combined projection and camera view transformations
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);

// Draw objects
...
}


在OpenGL,一个形状是一个表面由三个或更多的点在三维空间中定义的。一组三个或更多三维点(称为顶点在OpenGL)有正面和背面。你怎么知道哪面是正面和背面?答案是 winding,或者简单的说,你定义点的方向。



坐标列表转化为逆时针绘制顺序

在这个例子中,三角形的点是通过一定的顺序定义的,以致它们是通过逆时针方向绘制的。这些坐标定义的顺序就是环绕方向。默认情况下,在OpenGL中,我们正对的方向是逆时针画的方向。上图所示的三角形定义,我们看到就是正面,另一边是背面。

为什么我们要知道,我们面对的是不是正面?原因是:在处理OpenGL的常用特性时,有一个叫Face culling的环境因素,Face culling是OpenGL中一个可以参考的环境,它可以让你在渲染到pipeline的过程中忽略背面(不计算或绘制),节省时间,内存和处理周期。

// enable face culling feature
gl.glEnable(GL10.GL_CULL_FACE);
// specify which faces to not draw
gl.glCullFace(GL10.GL_BACK);


如果我们尝试使用Face culling特性,但又不知道它的形状是正面和背面,我们的OpenGL图形看起来有点怪,或者有时根本不显示。所以,总是定义我们的OpenGL图形的坐标逆时针顺序。

以上小总结:

OpenGL 绘制的都是图形,包括形状和填充,基本形状是三角形。

每个形状都有顶点,Vertix,顶点的序列就是一个图形。

图形有正反面,如果我们看向一个图形,它的顶点序列是逆时针方向,那我们看到的就是正面。

Shader,着色器,用来描述如何绘制(渲染),GLSL 是 OpenGL 的编程语言,全称就叫 OpenGL - -Shader Language。OpenGL 渲染需要两种 shader,vertex 和 fragment。

Vertex shader,控制顶点的绘制,指定坐标、变换等。

Fragment shader,控制形状内区域渲染,纹理填充内容。

OpenGL ES 3.1 Demo实践

效果图:





MyGLSurfaceView.java





Renderer







Square







Triangle







第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。


如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: