Android OpenGLES2.0绘制三角形(二)

选择绘制三角形作为OpenGL ES 2.0的第一个实例,是因为前文中提到的,点、线、三角形是OpenGL ES世界的图形基础。无论多么复杂的几何物体,在OpenGL ES的世界里都可以用三角形拼成。关于Android OpenGL ES 三角形的绘制,在Android官方文档中有详细的说明和步骤,本文实例也是依照官方文档步骤绘制的三角形。

步骤

依照官方文档中的说明,Android中利用OpenGL ES 2.0绘制三角形的步骤为:

1. 在AndroidManifest.xml文件中设置使用的OpenGL ES的版本:

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

3.0的版本为0x00030000,3.1的版本为0x00030001。
需要注意的是前一篇博客中提到的Android各个版本对于OpenGL ES版本的支持,设置Android应用的minSDK不应该小于使用的支持OpenGL ES版本的最低Android SDK版本。

2. 毫无疑问的,显示三角形,需要一个载体。创建显示三角形的Activity,利用GLSurfaceView作为显示三角形的View,图形的具体渲染工作都是在Render中完成的。

3. 实现GLSurfaceView的Render,在Render中完成三角形的绘制,具体行为有:

  • 加载顶点和片元着色器
  • 确定需要绘制图形的坐标和颜色数据
  • 创建program对象,连接顶点和片元着色器,链接program对象。
  • 设置视图窗口(viewport)。
  • 将坐标数据颜色数据传入OpenGL ES程序中
  • 使颜色缓冲区的内容显示到屏幕上。

具体实现

我们设置好OpenGL ES版本、创建入口Activity并设置好GLSurfaceView做为显示载体后,就进入了我们最主要的工作了。

第一步

首先,我们需要编写一个简单的顶点着色器和一个简单的片元着色器:
顶点着色器:

 attribute vec4 vPosition;
 void main() {
  gl_Position = vPosition;
 }

片元着色器:

 precision mediump float;
 uniform vec4 vColor;
 void main() {
  gl_FragColor = vColor;
 }

gl_Position和gl_FragColor都是Shader的内置变量,分别为定点位置和片元颜色。

第二步

然后,我们确定我们要绘制的图形的顶点坐标和颜色:
我们现在需要绘制的是在一个三维空间中绘制一个三角形,三角形当然是三个顶点了。因为我们三角形只是一个平面图形,为了方便,我们现在不设置相机(相机在后面的博客中使用时在讲解)的情况下,三角形正对我们来呈现。所以我们把三个顶点的Z坐标都设定为0。
上篇博客中也有提到OpenGL ES坐标映射到屏幕上,从屏幕中心垂直到上下左右边缘距离都为1.0,所以(-1.0,0,0)和(0,1.0,0)到原点的距离在屏幕上呈现出来的结果是不一样的,图解如下(左边是理想状态,右边是实际状态):

所以,为了不超出屏幕,我们的坐标数据设置为:

float triangleCoords[] = {
   0.5f, 0.5f, 0.0f, // top
   -0.5f, -0.5f, 0.0f, // bottom left
   0.5f, -0.5f, 0.0f // bottom right
 };

颜色数据,我们设置为单一颜色:

float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; //白色

第三步

接着我们开始在Render中实现我们的三角形绘制了。Render接口有三个方法,分别为onSurfaceCreated、onSurfaceChanged和onDrawFrame。
在onSurfaceCreated方法中,我们来创建program对象,连接顶点和片元着色器,链接program对象。

 //将背景设置为灰色
 GLES20.glClearColor(0.5f,0.5f,0.5f,1.0f);
 //申请底层空间
 ByteBuffer bb = ByteBuffer.allocateDirect(
    triangleCoords.length * 4);
 bb.order(ByteOrder.nativeOrder());
 //将坐标数据转换为FloatBuffer,用以传入给OpenGL ES程序
 vertexBuffer = bb.asFloatBuffer();
 vertexBuffer.put(triangleCoords);
 vertexBuffer.position(0);
 int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
    vertexShaderCode);
 int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
    fragmentShaderCode);

 //创建一个空的OpenGLES程序
 mProgram = GLES20.glCreateProgram();
 //将顶点着色器加入到程序
 GLES20.glAttachShader(mProgram, vertexShader);
 //将片元着色器加入到程序中
 GLES20.glAttachShader(mProgram, fragmentShader);
 //连接到着色器程序
 GLES20.glLinkProgram(mProgram);

第四步

在onSurfaceChanged中设置设置视图窗口:

GLES20.glViewport(0,0,width,height);

第五步

最后在onDrawFrame中绘制:

 //将程序加入到OpenGLES2.0环境
 GLES20.glUseProgram(mProgram);

 //获取顶点着色器的vPosition成员句柄
 mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
 //启用三角形顶点的句柄
 GLES20.glEnableVertexAttribArray(mPositionHandle);
 //准备三角形的坐标数据
 GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
   GLES20.GL_FLOAT, false,
   vertexStride, vertexBuffer);
 //获取片元着色器的vColor成员的句柄
 mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
 //设置绘制三角形的颜色
 GLES20.glUniform4fv(mColorHandle, 1, color, 0);
 //绘制三角形
 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
 //禁止顶点数组的句柄
 GLES20.glDisableVertexAttribArray(mPositionHandle);

最终效果

源码地址

所有的代码全部在一个项目中,托管在Github上——Android OpenGLES 2.0系列博客的Demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2016-12-17

了解Android OpenGLES2.0(一)

什么是OpenGL ES? OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言.跨平台的编程接口规格的专业的图形程序接口.它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库. OpenGL在不同的平台上有不同的实现,但是它定义好了专业的程序接口,不同的平台都是遵照该接口来进行实现的,思想完全相同,方法名也是一致的,所以使用时也基本一致,只需要根据不同的语言环境稍有不同而已.OpenGL这套3D图形API从1992年发布的1.0版本到目前最新20

Android OpenGLES2.0等腰直角三角形和彩色的三角形(三)

上一篇博客中我们已经绘制出了一个直角三角形,虽然我们相对于坐标,我们设置的直角三角形的两腰是相等的,但是实际上展示出来的却并不是这样,虽然通过计算,我们可以把三角形的两腰计算一下比例,使它们在坐标上不等,但是现实出来相等,但是当绘制的图形比较复杂的话,这个工作量对我们来说实在太庞大了.那么我们怎么做呢?答案是,使用变换矩阵,把计算交给OpenGL. 矩阵 在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合 ,最早来自于方程组的系数及常数所构成的方阵.这一概念由19世纪英国数学家

详解升级Android Studio3.0时遇到的几个问题

今天收到了Android Studio3.0更新推送,在升级过程中遇到几个问题,在这里把问题和解决方法记录下,方便要升级的童鞋.如果还有童鞋遇到不同的问题,也可以评论下我做下记录 1.gradle打包,自定义apk名称代码报错(Cannot set the value of read-only property 'outputFile' ) 报错 Error:(56, 0) Cannot set the value of read-only property 'outputFile' for

Android 6.0指纹识别App开发案例

在android 6.0中google终于给android系统加上了指纹识别的支持,这个功能在iPhone上早就已经实现了,并且在很多厂商的定制的ROM中也都自己内部实现这个功能了,这个功能来的有点晚啊.在google全新发布的nexus设备:nexus 5x和nexus 6p中都携带了一颗指纹识别芯片在设备的背面,如下图(图片来自网络): 笔者手中的设备就是图上的那台黑色的nexus 5x,话说这台机器很是好看呢!手感超棒! 废话不多说,下面我出一个指纹识别的demo app,并且详细说明怎么

Android Studio3.0新特性及安装图文教程

Android Studio是Android的官方IDE.它是专为Android而打造,可以加快您的开发速度,帮助您为每款Android设备构建最优应用. 它提供专为Android开发者量身定制的工具,其中包括丰富的代码编辑.调试.测试和性能分析工具. 一.Android Studio3.0新特性 (1).核心IDE更改 我们将基础IDE从IntelliJ 2016.2升级到2017.1.2,在2016.3和 2017.1中增加了许多新功能, 包括参数提示,语义突出显示,搜索中的即时结果等等.

Android 6.0调用相机图册崩溃的完美解决方案

最近客户更新系统发现,以前的项目在调用相机的时候,闪退掉了,很奇怪,后来查阅后发现,Android 6.0以后需要程序授权相机权限,默认会给出提示,让用户授权,个人感觉这一特性很好,大概如下: 导入Android V4, V7包! Android Studio 导入很简单,右键项目后找到dependency就ok了. 继承AppCompatActivity public class MainActivity extends AppCompatActivity 引入需要的类库 import and

Android 7.0行为变更 FileUriExposedException解决方法

Android 7.0行为变更 FileUriExposedException解决方法 当我们开发关于[在应用间共享文件]相关功能的时候,在Android 7.0上经常会报出此运行时异常,那么Android 7.0以下没问题的代码,为什么跑到Android 7.0+的设备上运行就出问题了呢?,这主要来自于Android 7.0的一项[行为变更]! 对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI

Android 7.0中拍照和图片裁剪适配的问题详解

前言 Android 7.0系统发布后,拿到能升级的nexus 6P,就开始了7.0的适配.发现在Android 7.0以上,在相机拍照和图片裁剪上,可能会碰到以下一些错误: Process: com.yuyh.imgsel, PID: 22995 // 错误1 android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.yuyh.imgsel/cache/1486438962645.jpg ex

Android 7.0中新签名对多渠道打包的影响详解

老签名多渠道打包原理 前言 由于Android7.0发布了新的签名机制,加强了签名的加固,导致在新的签名机制下无法通过美团式的方式再继续打多渠道包了.不过在说新的签名机制对打包方案的 影响和为什么会影响我们原有的打包机制之前,需要先简单理解下打包原理和签名在整个打包过程中的作用. Android打包流程 Android打包过程大致如图所示,整个流程就是将Java代码,资源文件以及第三方库整合成一个Apk文件,并对整合后的文件进行签名和优化对齐.整个过程可以简 单分为以下几个步骤: 资源预编译 为