Rouse
读完需要
11
分钟
速读仅需 4 分钟
由于5G的发展,现在音视频越来越流行,我们的生活已经完全被抖音、视频号、B站等视频应用所包围。从这一点也能看到音视频的重要性。
而作为一名Android开发者,是时候来了解一下关于Android方面渲染方面的知识。音视频的应用都离不开OpenGL ES的处理。对于视频的高效渲染与融合操作是至关重要的。
上面的这种动画相信大家都很熟悉,类似的动画在各大直播间都会出现。那么这炫酷的原理实现内部都离不开OpenGL ES的高效渲染与更高级的融合处理。
多的就先不说了,现在我们就来认识一下OpenGL ES。
Android可以通过OpenGL来支持高效的2D和3D图形,同时OpenGL是一种跨平台的图形API。其中OpenGL ES是OpenGL规范的一种形式,适用于嵌入式设备。
Android支持多种版本的OpenGL ES API:
我们的内容主要是基于OpenGL ES 2.0来进行,也就是进行二维的图形渲染。
在Android中通过Canvas进行绘制的坐标原点是在屏幕的左上角,同时它的坐标范围都是以屏幕的宽高来定义。
OpenGL ES则不同,它是以绘制区域的中心为原点,同时它的坐标范围是-1.0 ~ 1.0。也就是说它的坐标都是基于可绘制区域进行比例换算。并不是真正的值。
在OpenGL ES中,绘制的形状都是以三角形为基础,也就是说它必须由3个或者以上的点来进行绘制。所以它是由多个三角形进行组合成特定的形状,经过不同程度的交叉与重叠来达到不同的形状。
例如以二维空间来定义
同时还存在绘制顺序,所谓的绘制顺序也是以三角形为基础,通过三角形的三个顶点进行环绕绘制。默认是以逆时针进行绘制。
对于二维图像可能绘制顺序没那么重要,但是对于三维图像就很重要了。三维图像是由于视角的问题,会存在正反面的关系。
例如一款3D游戏,游戏中有一辆汽车,正对我们的为正面,我们看不到的一面为反面,虽然反面看不到,但OpenGL ES还是会进行绘制。为了对反面不做无用的绘制,可以使用OpenGL的面剔除操作,该操作允许渲染管道忽略形状的反面,这样就可以节约时间与内存并缩短处理周期。
那么这里的正面就是沿逆时针绘制的面。
OpenGL ES渲染需要借助GL程序,通过创建GL程序、顶点与片段着色器、加载着色器代码、编译代码、应用、数据填充,最终进行渲染。
在创建GL程序之前,我们先来了解顶点着色器与片段着色器。
GL程序渲染的过程中需要确认顶点位置与对应的颜色,而这两个部分分别借助于顶点与片段着色器来实现。
// 顶点
private const val VERTEX_SHADER_SOURCE =
"attribute vec4 a_Position;\n" +
"void main() {\n" +
" gl_Position = a_Position;\n" +
"}"
// 片段
private const val FRAGMENT_SHADER_SOURCE =
"precision mediump float;\n" +
"void main() {\n" +
" gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" +
"}"
上面分别是顶点着色器与片段着色器的源码。attribute是变量修饰符,用的比较多的是以下三种。
vec4是变量类型,变量主要有以下几种
除此之外还有数组与结构体,用来实现复杂的数据类型。
我们将定义的a_Position赋值给gl_Position,这样GL程序就会使用定义的顶点数据进行渲染。
同理gl_FragColor也是一样,代表对应渲染顶点位置时的颜色,这里直接写死了一个蓝色。
首先我们要创建GL程序
// 创建GL程序
val programId = GLES20.glCreateProgram()
拿到programId,为之后的程序操作做准备
首先创建顶点与片段着色器
// 创建顶点与片段着色器
val vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER)
val fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER)
将之前定义的着色器源码加载到着色器中
// 加载顶点与片段着色器代码
GLES20.glShaderSource(vertexShader, VERTEX_SHADER_SOURCE)
GLES20.glShaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE)
通过GL程序进行编译
// 编译顶点与片段着色器代码
GLES20.glCompileShader(vertexShader)
GLES20.glCompileShader(fragmentShader)
最后将编译完的顶点与片段着色器添加到指定的GL程序中,也就是我们第一步创建的GL程序
// 添加到GL程序中
GLES20.glAttachShader(programId, vertexShader)
GLES20.glAttachShader(programId, fragmentShader)
着色器装载完毕之后,剩下的就是将我们创建的GL程序进行链接与应用
// 链接GL程序
GLES20.glLinkProgram(programId)
// 应用GL程序
GLES20.glUseProgram(programId)
这样我们的GL程序才算真正的完成了,下面就是数据的填充与渲染操作。
在顶点着色器源码定义中,我们定义了a_Position变量,需要我们从外部将数据添加到a_Position,这样才能真正应用到gl_Position中。
下面我们来进行数据的填充
首先我们定义一个填充的顶点数据
private val mVertexData = floatArrayOf(0.0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 1.0f, -1.0f, 0.5f, 0f, 0.5f)
private const val VERTEX_DIMENSION_SIZE = 2
顶点维度是二维,所以这里mVertexData中定义了6个顶点数据,也就是2个三角形的数据。第一个在左上角,第二个在中间。
我们将数据添加到Buffer中,并将索引位置定义到开始位置0
// 加载顶点数据
val vertexBuffer = ByteBuffer.allocateDirect(mVertexData.size * Float.SIZE_BYTES)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
vertexBuffer.put(mVertexData)
vertexBuffer.position(0)
继续获取a_Position在GL程序中的参数位置
// 获取对应参数位置
val positionLocation = GLES20.glGetAttribLocation(programId, "a_Position")
这一点与我们平常的编程不同,在GL程序中,如果要获取其中的变量,我们并不是直接拿到这个变量的本身,而是通过拿到它在GL中对应的位置索引,然后通过位置索引进行变量操作。
获取之后还要进行启动激活
// 启动对应参数位置
GLES20.glEnableVertexAttribArray(positionLocation)
最后就是填充
// 填充顶点数据
GLES20.glVertexAttribPointer(positionLocation, VERTEX_DIMENSION_SIZE, GLES20.GL_FLOAT, false, 0, vertexBuffer)
VERTEX_DIMENSION_SIZE代表的是填充一个二维的顶点数据,类型为GLES20.GL_FLOAT。
GL程序与顶点数据都已经准备完毕,接下来是最后一步渲染。
在渲染之前我们需要对屏幕进行清屏操作,默认屏幕是黑色,我们可以指定需要的清屏后的颜色
// 设置清屏颜色
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
// 清屏处理
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
这里指定清屏颜色为白色
在渲染之前设置渲染的视图位置与大小,最后再进行渲染。
// 设置视图大小
GLES20.glViewport(0, 0, mSurfaceViewWidth, mSurfaceViewHeight)
// 渲染
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertexData.size / VERTEX_DIMENSION_SIZE)
在渲染操作中使用了GLES20.GL_TRIANGLES,这是一种渲染方式,它代表会以每3个顶点为一组的方式进行三角形渲染,所以我们运行之后就能看到2个三角形。
参数0与mVertexData.size / VERTEX_DIMENSION_SIZE代表有6个顶点且从第0个位置开始,也就是第一个顶点位置。
最后我们再来看下运行后的效果
大功告成,与我们的预期完全一样。
后续会继续聊聊颜色的动态填充、渲染的三种方式与纹理的操作,敬请期待。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有