Android OpenGL ES 渲染模式
Rouse
读完需要
8
分钟
速读仅需 3 分钟
动态色值
在说渲染模式之前,我们来简单了解下动态色值的填充方式。
在OpenGL ES 基础原理中,我们只是对顶点做了简单的填充设置,现在我们继续对片段着色器中的颜色做自定义。
这是现有的样式,色值在片段着色器中是一个写死的值,现在我们需要将它变为动态设置的值,将这个两个三角形的颜色值设置为红、绿、蓝的混合色。也就是三角形的三个顶点,分别设置红绿蓝,颜色再从顶点向中间扩散。
下面是实际操作
修改着色器源码
要动态设置颜色值,需要定义颜色变量
private const val VERTEX_SHADER_SOURCE =
"attribute vec4 a_Position;\n" +
"attribute vec4 a_Color;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
" v_Color = a_Color;\n" +
" gl_Position = a_Position;\n" +
"}"
private const val FRAGMENT_SHADER_SOURCE =
"precision mediump float;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
" gl_FragColor = v_Color;\n" +
"}"
之前的a_Position不动,新增a_Color与v_Color变量,注意v_Color被varying声明,所以它能够传递到片段着色器中,最后再将它赋值给gl_FragColor
定义颜色数据源
private val mColorData = floatArrayOf(
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f
)
private const val COLOR_DIMENSION_SIZE = 4
分别为两个三角形的六个顶点设置红绿蓝设置,颜色维度为4,不要忘了还有透明度。
加载颜色数据
这一点与顶点数据的加载方式一样,对于GL程序来说他们只是不同的变量,而变量的数据填充方式都是一致的。明白这一点就简单多了,按照顶点数据填充的方式来。
将颜色数据填充到Buffer中,并将索引位置移动到0位置。
// 加载颜色数据
val colorBuffer = ByteBuffer.allocateDirect(mColorData.size * Float.SIZE_BYTES)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
colorBuffer.put(mColorData)
colorBuffer.position(0)
继续获取a_Color在GL程序中的参数位置索引
// 获取对应color参数位置
val colorLocation = GLES20.glGetAttribLocation(programId, "a_Color")
随后激活
// 启动对应color参数位置
GLES20.glEnableVertexAttribArray(colorLocation)
最后填充
// 填充对应顶点处color数据
GLES20.glVertexAttribPointer(colorLocation, COLOR_DIMENSION_SIZE, GLES20.GL_FLOAT, false, 0, colorBuffer)
再走一遍这些流程,理解起来相信简单了许多。
渲染部分就不多说了,这个没什么不同。
下面来看下运行的效果
达到预期,大功告成。
渲染模式
// 渲染
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertexData.size / VERTEX_DIMENSION_SIZE)
GL_TRIANGLES是三角形渲染的一种方式,一共有三种。
GL_TRIANGLES
以每三个顶点为三角形的方式进行渲染,顶点不重复,即(v0,v1,v2)、(v3,v4,v5)等。
我们目前用到的渲染方式都是这种,所以我们定义6个顶点,按照这种方式我们就会绘制出两个完全不交叉的三角形,因为它们的顶点并没有交集。
GL_TRIANGLE_STRIP
选择绘制三角形的顶点不同,顶点会重复使用,即(v0,v1,v2)、(v2,v1,v3)、(v2,v3,v4)、(v4,v3,v5)
简单的来看,就是它会复用之前的两个顶点,但需要注意的是它的绘制顺序,并不是简单的直接按照直接的顺序进行复用。
这里的顺序逻辑是:
- 如果当前顶点是偶数,则为(n-2,n-1,n)
- 如果当前顶点是奇数,则为(n-1,n-2,n)
这种方式是为了保证绘制的每个三角形的顺序是一致的。
那么这种渲染模式的好处是什么呢?你会发现相同的顶点数,通过这种方式绘制出来的三角形个数比GL_TRIANGLES要多。
对应的我们就能发现,如果绘制相同的图形GL_TRIANGLE_STRIP所要加载的顶点数会更少,这样在OpenGL绘制的过程中占用的内存也就越低,所以也就更有效。
原理明白了,下面我们将例子中的绘制方式修改成GL_TRIANGLE_STRIP,看下效果是怎么样的。
GL_TRIANGLE_FAN
以扇形的方式进行,它会共用一个顶点,围绕它进行扇形绘制,(v0,v1,v2)、(v3,v0,v2)、(v4,v0,v3)、(v5,v0,v4)
这种方式很适合用来绘制多边形,以任意一个顶点为中心进行扇形绘制。
我们再将例子中的绘制方式改成GL_TRIANGLE_FAN,看下效果如何。
如果不太明白的可以自己动手画一画,原理并不难。
后面我会继续聊聊对纹理方面的理解,敬请期待。
OpenGL ES 系列
相关文章
- android 置灰不可点击,Android Studio 运行按钮灰色的完美解决方法
- Android Automotive OTA概念
- Android常用加密库集合
- android 的hook技术,Android Native Hook技术(一)
- Android集成lrzsz[通俗易懂]
- android activity singletask,Android Activity启动模式之singleTask实例详解
- Android–SQLite数据库实现增删改查
- android 定时器重置,Android定时器延迟和重置[通俗易懂]
- Android 数据库加密 android-database-sqlcipher 开源版本编译过程
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( You must define ANDROID_NDK before starting. | 下载指定版本 NDK )
- 【ijkplayer】编译 Android 版本的 ijkplayer ⑥ ( 进入 ijkplayer-android/android 目录 | 执行 compile-ijk.sh 脚本完成编译 )
- 【Android Gradle 插件】BuildType 编译类型配置 ① ( BuildType 编译类型简介 | BuildType#applicationIdSuffix 包名后缀配置 )
- 【错误记录】Android Studio 编译时 lint 检查报错 ( WARNING: DSL element ‘android.dataBinding.enabled‘ is obsolet )
- 【Android NDK 开发】CMake 中查找链接 Android 自带动态库位置说明 ( ndk-bundleplatformsandroid-29arch-armusrlib )
- Android开发中遇到的问题(二)——新建android工程的时候eclipse没有生成MainActivity和layout布局详解手机开发
- Android中android:visibility的3中属性的剖析详解手机开发
- Village for Android v4.5.1
- Android系统与Linux之间的联系(android和linux)
- 使用Android实现连接MySQL数据库:实现快速数据交互与管理(android连接mysql数据库)
- 深入比较ES数据库与Oracle数据库(es数据库和oracle)
- 使用ES数据导入Oracle让数据更加有序(es数据导入oracle)
- 抉择存储数据的最佳选择 ES 还是 Redis(存es还是redis)
- Android中的android:layout_weight使用详解
- Android中生成、使用Json数据实例