2

Android OpenGL ES 渲染模式

 2 years ago
source link: http://www.rousetime.com/2022/02/25/Android-OpenGL-ES-%E6%B8%B2%E6%9F%93%E6%A8%A1%E5%BC%8F/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Android OpenGL ES 渲染模式

2022.02.25

Rouse

android

 热度 3℃

OpenGL ES 系列

Android OpenGL ES 基础原理

在说渲染模式之前,我们来简单了解下动态色值的填充方式。

OpenGL ES 基础原理中,我们只是对顶点做了简单的填充设置,现在我们继续对片段着色器中的颜色做自定义。

effect.jpeg

这是现有的样式,色值在片段着色器中是一个写死的值,现在我们需要将它变为动态设置的值,将这个两个三角形的颜色值设置为红、绿、蓝的混合色。也就是三角形的三个顶点,分别设置红绿蓝,颜色再从顶点向中间扩散。

下面是实际操作

修改着色器源码

要动态设置颜色值,需要定义颜色变量

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)

再走一遍这些流程,理解起来相信简单了许多。

渲染部分就不多说了,这个没什么不同。

下面来看下运行的效果

g_effect.jpeg

达到预期,大功告成。

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)

简单的来看,就是它会复用之前的两个顶点,但需要注意的是它的绘制顺序,并不是简单的直接按照直接的顺序进行复用。

这里的顺序逻辑是:

  1. 如果当前顶点是偶数,则为(n-2,n-1,n)
  2. 如果当前顶点是奇数,则为(n-1,n-2,n)

这种方式是为了保证绘制的每个三角形的顺序是一致的。

2560px-Triangles_Strip_In_OpenGL.svg.png

那么这种渲染模式的好处是什么呢?你会发现相同的顶点数,通过这种方式绘制出来的三角形个数比GL_TRIANGLES要多。

对应的我们就能发现,如果绘制相同的图形GL_TRIANGLE_STRIP所要加载的顶点数会更少,这样在OpenGL绘制的过程中占用的内存也就越低,所以也就更有效。

原理明白了,下面我们将例子中的绘制方式修改成GL_TRIANGLE_STRIP,看下效果是怎么样的。

m_effect.jpeg

GL_TRIANGLE_FAN

以扇形的方式进行,它会共用一个顶点,围绕它进行扇形绘制,(v0,v1,v2)、(v3,v0,v2)、(v4,v0,v3)、(v5,v0,v4)

这种方式很适合用来绘制多边形,以任意一个顶点为中心进行扇形绘制。

Trianglefan.png

我们再将例子中的绘制方式改成GL_TRIANGLE_FAN,看下效果如何。

f_effect.jpeg

如果不太明白的可以自己动手画一画,原理并不难。

后面我会继续聊聊对纹理方面的理解,敬请期待。

源码地址:OpenGL ES


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK