Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Android OpenGL ES 基础原理

Android OpenGL ES 基础原理

作者头像
Rouse
发布于 2023-02-14 03:05:34
发布于 2023-02-14 03:05:34
1K00
代码可运行
举报
文章被收录于专栏:Android补给站Android补给站
运行总次数:0
代码可运行

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:

  1. 1.0&1.1 Android1.0及以上
  2. 2.0 Android2.2及以上
  3. 3.0 Android4.3及以上
  4. 3.1 Android5.0及以上

我们的内容主要是基于OpenGL ES 2.0来进行,也就是进行二维的图形渲染。

坐标

在Android中通过Canvas进行绘制的坐标原点是在屏幕的左上角,同时它的坐标范围都是以屏幕的宽高来定义。

OpenGL ES则不同,它是以绘制区域的中心为原点,同时它的坐标范围是-1.0 ~ 1.0。也就是说它的坐标都是基于可绘制区域进行比例换算。并不是真正的值。

形状与方向

在OpenGL ES中,绘制的形状都是以三角形为基础,也就是说它必须由3个或者以上的点来进行绘制。所以它是由多个三角形进行组合成特定的形状,经过不同程度的交叉与重叠来达到不同的形状。

例如以二维空间来定义

同时还存在绘制顺序,所谓的绘制顺序也是以三角形为基础,通过三角形的三个顶点进行环绕绘制。默认是以逆时针进行绘制。

对于二维图像可能绘制顺序没那么重要,但是对于三维图像就很重要了。三维图像是由于视角的问题,会存在正反面的关系。

例如一款3D游戏,游戏中有一辆汽车,正对我们的为正面,我们看不到的一面为反面,虽然反面看不到,但OpenGL ES还是会进行绘制。为了对反面不做无用的绘制,可以使用OpenGL的面剔除操作,该操作允许渲染管道忽略形状的反面,这样就可以节约时间与内存并缩短处理周期。

那么这里的正面就是沿逆时针绘制的面。

GL程序

OpenGL ES渲染需要借助GL程序,通过创建GL程序、顶点与片段着色器、加载着色器代码、编译代码、应用、数据填充,最终进行渲染。

在创建GL程序之前,我们先来了解顶点着色器与片段着色器。

着色器源码

GL程序渲染的过程中需要确认顶点位置与对应的颜色,而这两个部分分别借助于顶点与片段着色器来实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 顶点
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是变量修饰符,用的比较多的是以下三种。

  1. attribute:表示只读的顶点数据,应用在顶点着色器中。可修饰声明顶点、颜色等数据
  2. uniform:顶点着色器与片段着色器的共享数据,在程序中值的不变的,初始值由程序外部传入
  3. varying:顶点着色器输入,片段着色器输出;由顶点着色器传输给片段着色器中的插值数据

vec4是变量类型,变量主要有以下几种

除此之外还有数组与结构体,用来实现复杂的数据类型。

我们将定义的a_Position赋值给gl_Position,这样GL程序就会使用定义的顶点数据进行渲染。

同理gl_FragColor也是一样,代表对应渲染顶点位置时的颜色,这里直接写死了一个蓝色。

创建GL程序

首先我们要创建GL程序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建GL程序
val programId = GLES20.glCreateProgram()

拿到programId,为之后的程序操作做准备

添加顶点与片段着色器

首先创建顶点与片段着色器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 创建顶点与片段着色器
val vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER)
val fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER)

将之前定义的着色器源码加载到着色器中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 加载顶点与片段着色器代码
GLES20.glShaderSource(vertexShader, VERTEX_SHADER_SOURCE)
GLES20.glShaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE)

通过GL程序进行编译

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 编译顶点与片段着色器代码
GLES20.glCompileShader(vertexShader)
GLES20.glCompileShader(fragmentShader)

最后将编译完的顶点与片段着色器添加到指定的GL程序中,也就是我们第一步创建的GL程序

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 添加到GL程序中
GLES20.glAttachShader(programId, vertexShader)
GLES20.glAttachShader(programId, fragmentShader)

链接与应用

着色器装载完毕之后,剩下的就是将我们创建的GL程序进行链接与应用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 链接GL程序
GLES20.glLinkProgram(programId)
// 应用GL程序
GLES20.glUseProgram(programId)

这样我们的GL程序才算真正的完成了,下面就是数据的填充与渲染操作。

数据填充

在顶点着色器源码定义中,我们定义了a_Position变量,需要我们从外部将数据添加到a_Position,这样才能真正应用到gl_Position中。

下面我们来进行数据的填充

首先我们定义一个填充的顶点数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 加载顶点数据
val vertexBuffer = ByteBuffer.allocateDirect(mVertexData.size * Float.SIZE_BYTES)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
vertexBuffer.put(mVertexData)
vertexBuffer.position(0)

继续获取a_Position在GL程序中的参数位置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 获取对应参数位置
val positionLocation = GLES20.glGetAttribLocation(programId, "a_Position")

这一点与我们平常的编程不同,在GL程序中,如果要获取其中的变量,我们并不是直接拿到这个变量的本身,而是通过拿到它在GL中对应的位置索引,然后通过位置索引进行变量操作。

获取之后还要进行启动激活

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 启动对应参数位置
GLES20.glEnableVertexAttribArray(positionLocation)

最后就是填充

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 填充顶点数据
GLES20.glVertexAttribPointer(positionLocation, VERTEX_DIMENSION_SIZE, GLES20.GL_FLOAT, false, 0, vertexBuffer)

VERTEX_DIMENSION_SIZE代表的是填充一个二维的顶点数据,类型为GLES20.GL_FLOAT。

渲染

GL程序与顶点数据都已经准备完毕,接下来是最后一步渲染。

在渲染之前我们需要对屏幕进行清屏操作,默认屏幕是黑色,我们可以指定需要的清屏后的颜色

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 设置清屏颜色
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
// 清屏处理
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)

这里指定清屏颜色为白色

在渲染之前设置渲染的视图位置与大小,最后再进行渲染。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 设置视图大小
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个位置开始,也就是第一个顶点位置。

最后我们再来看下运行后的效果

大功告成,与我们的预期完全一样。

后续会继续聊聊颜色的动态填充、渲染的三种方式与纹理的操作,敬请期待。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-12-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android补给站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
干货 | 移动应用中使用OpenGL生成转场特效
作者简介 jzg,携程资深前端开发工程师,专注Android开发; zcc,携程高级前端开发工程师,专注iOS开发。 一、前言 随着移动端短视频的火热,音视频编辑工具在做内容类APP上的地位举足轻重。丰富的转场方式可以给短视频带来更多炫酷的效果,从而更好地赢得用户青睐。本议题主要包含了对OpenGL的简单介绍及相关API使用,GLSL着色器语言的基本使用,以及如何通过编写自定义的着色器程序来实现图片的转场效果。 二、为什么使用OpenGL以及使用的难点 2.1 为什么使用OpenGL 视频的转场效果离不开图
携程技术
2022/09/26
1.8K0
干货 | 移动应用中使用OpenGL生成转场特效
OpenGL ES 3.0 | 围绕HelloTriangle实战案例 展开 渲染流程分析
案例运行(绘制一个三角形)的基本步骤 【可以先看看文末的代码,结合文章内容去看, 理解了整个流程之后再来看这个步骤,会容易很多】 用EGL创建屏幕上的渲染表面(Android直接用一个GLSurfaceView) 加载顶点、片段着色器 创建一个程序对象, 连接顶点、片段着色器, 并链接程序对象; 设置视口; 清除颜色缓冲区; 渲染简单图元 使颜色缓冲区的内容在EGL窗口表面(GLSurfaceView)中可见 着色器 在OpenGL ES 3.0中, 除非加载有效的顶点和片段着色器,否则不会绘
凌川江雪
2020/08/11
1.6K0
OpenGL ES 3.0 | 围绕HelloTriangle实战案例 展开 渲染流程分析
Android OpenGL ES 渲染模式
在OpenGL ES 基础原理中,我们只是对顶点做了简单的填充设置,现在我们继续对片段着色器中的颜色做自定义。
Rouse
2023/02/14
5410
Android OpenGL ES 渲染模式
SurfaceView简单理解,Android混淆,Android openGl开发详解简单图形的绘制,
在要求实时性比较高的游戏开发中,显然,view的ondraw是满足不了你的,这时候只能是用SurfaceView。
zhangjiqun
2024/12/16
970
SurfaceView简单理解,Android混淆,Android openGl开发详解简单图形的绘制,
【C++】OpenGL:着色器基础与GLFW创建三角形示例
另外,在图形渲染中,要记住2D坐标和像素也是不同的,2D坐标精确表示一个点在2D空间中的位置,而2D像素是这个点的近似值,2D像素受到你的屏幕/窗口分辨率的限制。
DevFrank
2024/07/24
2580
【C++】OpenGL:着色器基础与GLFW创建三角形示例
Android多媒体之GL-ES战记第一集--勇者集结
前言 1.本系列借花献佛,结合了很多前人的文章以及书籍,我尽可能去总结并用我的思想进行加工 2.OpenGL一直是我的心结,也是时候去解开了,本系列称不上原创,但每行代码都有着我思考的痕迹 3.本系列所有的图片都是[张风捷特烈]所画,如果有什么错误还请指出,定会最快改正 4.本系列文章允许转载、截取、公众号发布,请保留前言部分,希望广大读者悉心指教 ---- NPC:开场词 传说,在这片代码大陆上,存在一个古老的种族,它们拥有无尽的力量,却罕有人能够驾驭 多媒体王国中存在一个隐蔽的角落
张风捷特烈
2019/02/25
1.7K0
Android多媒体之GL-ES战记第一集--勇者集结
1.opengl绘制三角形
下面,你会看到一个图形渲染管线的每个阶段的抽象展示。要注意蓝色部分代表的是我们可以注入自定义的着色器的部分。
诺谦
2020/09/27
1.2K0
1.opengl绘制三角形
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】一、初步了解OpenGL ES
提到OpenGL,想必很多人都会说,我知道这个东西,可以用来渲染2D画面和3D模型,同时又会说,OpenGL很难、很高级,不知道怎么用。
开发的猫
2020/04/01
2K0
【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】一、初步了解OpenGL ES
OpenGL现代编程第二课——第一个多边形
https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/
用户5908113
2020/01/02
7360
OpenGL ES简介
概述 在聊Android的View渲染流程中,通常会有一个比较核心的步骤:通过OpeGL ES接口调用GPU接口通知GPU绘制图形。其完整的流程:UI对象—->CPU处理为多维图形,纹理 —–通过Op
xiangzhihong
2018/01/26
2K0
Android OpenGL ES 纹理
之前我们一直都是在绘制简单的图形与颜色,如果是一张图片该如何通过OpenGL ES进行渲染出来呢?
Rouse
2023/02/14
1.2K0
Android OpenGL ES 纹理
OpenGL 系列---基础绘制流程
OpenGL 是一种应用程序编程接口,它是一种可以对图形硬件设备特性进行访问的软件库。
音视频开发进阶
2019/07/26
1.9K0
NDK开发(十) :Hello OpenGLES3
创建一个新工程,在 Choose your project 时选择 native c++ 模板。
103style
2022/12/19
4470
NDK开发(十) :Hello OpenGLES3
Android OpenGL ES(三)-平面图形
前两章,其实我们已经明白了绘制平面图形的套路了。 接下来我们按照套路继续画其他的图形。
deep_sadness
2018/08/30
1.6K0
Android OpenGL ES(三)-平面图形
【OpenGL】Clion配置
GLM(OpenGL Mathematics)是专门为OpenGL量身定做的数学库,它是一个只有头文件的库,可以快速实现矩阵变换等各种图形学中常用的几何计算。
叶茂林
2023/12/01
6780
【OpenGL】Clion配置
RenderDemo(1):用 OpenGL 画一个三角形丨音视频工程示例
这个公众号会路线图式的遍历分享音视频技术:音视频基础 → 音视频工具 → 音视频工程示例 → 音视频工业实战。关注一下成本不高,错过干货损失不小 ↓↓↓
关键帧
2022/11/29
1.3K0
RenderDemo(1):用 OpenGL 画一个三角形丨音视频工程示例
FFmpeg4.3系列之52:Android OpenGL实现3D画图及抛骰子案例实战
OpenGL(Open Graphics Library)是一个跨平台的图形API,广泛用于3D和2D图形渲染。要使用OpenGL实现点、线、面的基本绘制,你需要了解几个关键概念和技术:设置OpenGL上下文、加载着色器程序、定义顶点数据以及调用绘制命令。下面我们将通过一个简单的例子来分析如何用OpenGL绘制点、线和面。
瘦瘦itazs和fun
2025/01/02
650
OpenGL ES——着色器
前言 在App开发中,为了追求给CPU减负,我们经常会使用GPU来渲染我们想要显示的图片。如何控制GPU为我们工作? 渲染管线 GPU的工作流程是固定的: image.png 上图就是OpenGL E
Oceanlong
2018/07/03
7630
[-综合篇-] 相机、OpenGL、视频、Flutter和SurfaceView
认识一个类,相当于结交一位朋友;看一篇源码,相当于一次顶级的会话; 读一个框架,相当于见证一段思想;做一个程序,相当于创造一个生命; 一次Git提交,相当于记录一次成长;生活也许并非那么美好,但一切可以这么崇高。----张风捷特烈
张风捷特烈
2020/04/30
3.2K0
[-综合篇-] 相机、OpenGL、视频、Flutter和SurfaceView
Android OpenGL ES(一)-开始描绘一个平面三角形
今天的目标是做一个OpenGL ES学习的开端。就是画一个简单的三角形。暂时不考虑坐标系的矩阵变换和纹理等。只需要用顶点着色器简单的来进行描述。 这一节需要使用和认识的关键类是 GLSurfaceView和GLSurfaceView.Render 一句话来描述就是,我们会在GLSurfaceView.Render上进行描绘,在GLSurfaceView中显示出来。
deep_sadness
2018/08/30
1.4K0
Android OpenGL ES(一)-开始描绘一个平面三角形
相关推荐
干货 | 移动应用中使用OpenGL生成转场特效
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文