OpenGL ES->GLSurfaceView绘制图形的流程
自定义View代码
class MyGLSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs), GLSurfaceView.Renderer {var mProgrem = 0init {// 设置 OpenGL ES 3.0 版本setEGLContextClientVersion(3)// 设置当前类为渲染器, 注册回调接口的实现类setRenderer(this)// 设置渲染模式, 仅在需要重新绘制时才进行渲染,以节省资源renderMode = RENDERMODE_WHEN_DIRTY}override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {// 当 Surface 创建时调用, 进行 OpenGL ES 环境的初始化操作, 设置清屏颜色为黑色 (Red=0, Green=0, Blue=0, Alpha=1)GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)// 初始化缓冲区initializeBuffers()// 顶点着色器代码val vertexShaderCode = """#version 300 eslayout (location = 0) in vec4 aPosition;void main() {gl_Position = aPosition;}""".trimIndent()// 片段着色器代码val fragmentShaderCode = """#version 300 esprecision mediump float;uniform vec4 vColor;out vec4 fragColor;void main() {fragColor = vColor;}""".trimIndent()// 初始化着色器mProgrem = initializeShaders(vertexShaderCode, fragmentShaderCode)}override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {// 当 Surface 尺寸发生变化时调用,例如设备的屏幕方向发生改变, 设置视口为新的尺寸,视口是指渲染区域的大小GLES30.glViewport(0, 0, width, height)}override fun onDrawFrame(gl: GL10?) {// 每一帧绘制时调用, 清除颜色缓冲区和深度缓冲区GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT or GLES30.GL_DEPTH_BUFFER_BIT)// 绘制图形drawSomething(mProgrem)}fun initializeBuffers(){// 1. 准备菱形的顶点数据val vertices = floatArrayOf(0.0f, 0.5f, 0.0f, // 顶点 1 (顶部)-0.5f, 0.0f, 0.0f, // 顶点 2 (左侧)0.5f, 0.0f, 0.0f, // 顶点 4 (右侧)0.0f, -0.5f, 0.0f // 顶点 3 (底部))// 2. 分配顶点数据的直接字节缓冲区val vertexBuffer = ByteBuffer.allocateDirect(vertices.size * 4) // 每个 float 占 4 个字节, 指定缓冲区所需要的字节数.order(ByteOrder.nativeOrder()) // 指定字节顺序(确定是大端还是小端), 默认情况下为小端, 即低地址存放低位数据, 高地址存放高位数据.asFloatBuffer() // 转换为FloatBuffer, 因为顶点数据是float类型vertexBuffer.put(vertices) // 将顶点数据放入 FloatBuffervertexBuffer.position(0) // 在将数据放入缓冲区后,位置指针会指向缓冲区的末尾。重置位置指针为 0,使得在后续操作中可以从缓冲区的开始位置读取数据// 3. 创建顶点缓冲区对象(Vertex Buffer Object, VBO)val vbo = IntArray(1)GLES30.glGenBuffers(1, vbo, 0) // 生成一个缓冲区对象ID,并存储在数组 vbo 中,存放位置为0GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]) // 绑定生成的顶点缓冲区对象,使其成为当前缓冲区操作的目标// 4. 将顶点数据复制到缓冲区中GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertices.size * 4, FloatBuffer.wrap(vertices), GLES30.GL_STATIC_DRAW)}fun drawSomething(program : Int){// 8. 获取顶点数据的位置, 并使用该位置的数据val positionHandle = GLES30.glGetAttribLocation(program, "aPosition")GLES30.glEnableVertexAttribArray(positionHandle)GLES30.glVertexAttribPointer(positionHandle, 3, GLES30.GL_FLOAT, false, 0, 0)// 9. 设置片段着色器的颜色val colorHandle = GLES30.glGetUniformLocation(program, "vColor")GLES30.glUniform4f(colorHandle, 1.0f, 0.0f, 0.0f, 1.0f) // 红色// 10. 绘制菱形GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4)// 11. 禁用顶点数据GLES30.glDisableVertexAttribArray(positionHandle)}fun initializeShaders(vertexShaderCode: String, fragmentShaderCode: String) : Int {// 5. 创建和编译顶点着色器程序val vertexShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)GLES30.glShaderSource(vertexShader, vertexShaderCode)GLES30.glCompileShader(vertexShader)// 6. 创建和编译片段着色器程序val fragmentShader = GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)GLES30.glShaderSource(fragmentShader, fragmentShaderCode)GLES30.glCompileShader(fragmentShader)// 7. 创建着色器程序, 将顶点着色器和片段着色器链接到一起val program = GLES30.glCreateProgram()GLES30.glAttachShader(program, vertexShader)GLES30.glAttachShader(program, fragmentShader)GLES30.glLinkProgram(program)GLES30.glUseProgram(program)return program}
}
总结
-
- 准备菱形的顶点数据:需要绘制的顶点数据存放在
Float的数组中
- 准备菱形的顶点数据:需要绘制的顶点数据存放在
-
- 分配顶点数据的直接字节缓冲区,使用
ByteBuffer直接与底层硬件进行数据传输,避免了不必要的内存拷贝,从而提高性能
- 常见内存拷贝图
+--------------+ +--------------+ +--------------+ | float[] | ----> | FloatBuffer | ----> | GPU | | (Java Heap) | | (Java Heap) | | (Native) | +--------------+ +--------------+ +--------------+ - 使用
ByteBuffer+--------------+ +--------------+ +--------------+ | float[] | ----> | ByteBuffer | ----> | GPU | | (Java Heap) | | (Direct) | | (Native) | +--------------+ +--------------+ +--------------+
- 分配顶点数据的直接字节缓冲区,使用
-
- 创建顶点缓冲区对象
(Vertex Buffer Object, VBO)
- 创建顶点缓冲区对象
-
- 将顶点数据复制到缓冲区中
-
- 创建和编译顶点着色器程序
// 定义顶点着色器代码的多行字符串 val vertexShaderCode = """#version 300 es // 指定使用 OpenGL ES 3.0 版本layout (location = 0) in vec4 aPosition; // 定义输入变量 aPosition,并指定其位置为 0void main() { // 主函数gl_Position = aPosition; // 将输入的顶点位置赋值给 gl_Position,进行顶点变换} """.trimIndent() // 去除多行字符串的公共缩进
- 创建和编译顶点着色器程序
-
- 创建和编译片段着色器程序
// 定义片段着色器代码的多行字符串 val fragmentShaderCode = """#version 300 es // 指定使用 OpenGL ES 3.0 版本precision mediump float; // 设置默认的浮点数精度为中等精度uniform vec4 vColor; // 定义一个 uniform 变量 vColor,用于传递颜色out vec4 fragColor; // 定义一个输出变量 fragColor,用于存储片段的颜色void main() { // 主函数fragColor = vColor; // 将 uniform 变量 vColor 的值赋给输出变量 fragColor} """.trimIndent() // 去除多行字符串的公共缩进
- 创建和编译片段着色器程序
-
- 创建着色器程序, 将顶点着色器和片段着色器链接到一起
-
- 获取顶点数据的位置, 并使用该位置的数据
-
- 设置片段着色器的颜色
-
- 绘制菱形
-
- 禁用顶点数据
+---------------------+ +-------------------+ +------------------+
| Application (Java) | ----> | OpenGL Driver | ----> | GPU |
+---------------------+ +-------------------+ +------------------+
| float[] vertices | | Bind VBO | | Process VBO |
| | | Upload Data | | Use Data |
+---------------------+ +-------------------+ +------------------+
相关文章:
OpenGL ES->GLSurfaceView绘制图形的流程
自定义View代码 class MyGLSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs), GLSurfaceView.Renderer {var mProgrem 0init {// 设置 OpenGL ES 3.0 版本setEGLContextClientVersion(3)// 设置当前类为渲染器, 注册回调接口的实现类set…...
Linux OOM Killer详解
Linux OOM Killer详解 一、概述二、OOM Killer的技术原理1. 内存区域划分2. 内存耗尽与OOM Killer触发3. 选择被杀进程的策略4. 内存回收机制5. 内存分配策略 三、OOM Killer的工作机制1. 内存压力监测2. 触发条件3. 选择被杀进程4. 终止进程 四、实际场景举例场景一࿱…...
2024rk(案例二)
试题二(25分) 阅读以下关于数据库缓存的叙述,在答题纸上回答问题1至问题3。 【说明】 某大型电商平台建立了一个在线 B2B 商店系统,并在全国多地建设了货物仓储中心,通过提前备货的方式来提高货物的运送效率。但是在运营过程中,发现会出现很多跨仓储中心调货从而延误货物…...
小红书爆文秘籍:ChatGPT助你从0到1创造热门内容!
在小红书打造爆款文案的策略中,以下是一些调整和同义词替换的建议,以便达到文章去重的要求: 了解目标受众: 在撰写文案前,先深入分析目标读者的属性,如年龄层次、性别、爱好和购买行为。通过ChatGPT, 你能迅…...
django快速实现个人博客(附源码)
文章目录 一、工程目录组织结构二、模型及管理实现1、模型2、admin管理 三、博客展现实现1、视图实现2、模板实现 四、部署及效果五、源代码 Django作为一款成熟的Python Web开发框架提供了丰富的内置功能,如ORM(对象关系映射)、Admin管理界面…...
K8s部署篇之手动部署二进制高可用集群架构
一、系统环境初始化 一)架构设计 所有节点都操作:3个master(etcd集群三个节点)和2个node 1、K8s服务调用如图 2、各组件说明 1、API Server 供Kubernetes API接口,主要处理 REST操作以及更新ETCD中的对象所有资源增删…...
【Unity/XLua】xlua自带教程示例分析(6)—— lua协程
文章目录 工具准备协程测试 工具准备 首先是工具脚本,一个Coroutine_Runner.cs和一个cs_coroutine.lua 前者定义了一个继承自Monobehavior的脚本组件,后者则使用lua去在Unity中实例化一个挂载该组件的GameObject,并将其设置为DontDestroyOn…...
CV目标检测概述
文章目录 目标检测概述目标检测图像分割目标检测和图像分割的区别 目标检测概述 目标检测和图像分割是计算机视觉中的两个重要任务,它们有着不同的目的和应用。以下是它们的简要介绍和区别: 目标检测 目标检测(Object Detection࿰…...
如何在notebook中运行nodejs
在 Python 生态系统的推动下,机器学习和人工智能日益流行,这带来了计算笔记本的概念。这些交互式计算平台主要是为以 Python 为中心的数据科学应用而开发的,它们将代码、计算输出、解释性文本和多媒体合并成一个有内聚力的文档。 作为 JavaS…...
Mybatis学习-day19
Mybatis学习-day19 1. resultMap resultMap 是 MyBatis 中最复杂的元素,主要用于解决实体类属性名与数据库表中字段名不一致的情况,可以将查询结果映射成实体对象。 <resultMap id"staffAndDep" type"com.easy.bean.Staff">…...
IDEA构建SpringBoot多模块项目
前言 最近一直在思考一个问题,springboot的多模块项目到底是怎么运行和运作的? 一般我们大部分的springboot项目都是单模块的项目,但是如果后续有要求开发多模块的项目应该怎么处理?于是基于这点进行了研究。 本次文章将会带大…...
【前端】NodeJS:nvm
文章目录 1 介绍2 使用2.1 下载安装2.2 常用命令 1 介绍 nvm全称:Node Version Manager,顾名思义它是用来管理node版本的工具,方便切换不同版本的Node.js。 2 使用 nvm的使用非常的简单,跟npm的使用方法类似。 2.1 下载安装 …...
Docker网络模式及通信
一、Docker默认的网络通信 1.1 Docker安装后默认的网络设置 Docker服务器安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡,其IP地址都是172.17.0.1/16 [rootubuntu1804 ~]#apt -y install bridge-utils [rootubuntu1804 ~]#brctl show 另…...
类模板实现实现Qt click/hover自定义操作
一、场景 常常会需要实现点击/hover时修改图片,可能是一个QPushButton、QLabel、QToolButton…… 由于Qt bug,QIcon/QSS只能实现常规态、按下态的图标切换,hover态的图片设置无效。 解决思路无非是安装事件过滤器、自定义类并重实现事件。 …...
Arco Design:引领未来的Vue 3创意先锋,一键开启高效与美感并重的Web开发之旅!
Arco Design 是一个基于 Vue 3 的 UI 框架,它提供了丰富的组件和样式,可以帮助开发者快速构建高质量的 Web 应用程序。以下是 Arco Design 的一些详细特点: 完整的设计系统:Arco Design 提供了一套完整的设计系统,包括…...
【MySQL】Linux下用C/C++链接MySQL数据库
文章目录 一、准备工作二、验证库和接口的使用三、链接数据库四、对数据库进行增删查改增删改查 五、结尾 一、准备工作 要使用C链接数据库, 首先要去MySQL官网下载官网提供的库, MySQL 社区下载. 如图所示: 接着选择: 按需选择版本: 如果用的是云服务器, 那么在安装mysql时…...
Python金融量化专栏简介
量化分析实战 - 专栏大纲 👉👉👉 《玩转Python金融量化专栏》👈👈👈 订阅本专栏的可以下载对应的代码和数据集 专栏目标 本专栏旨在帮助读者全面掌握使用Python进行金融技术指标的计算与应用,从基础到高级,涵盖各种技术指标的实现、策略开发与回测等内容。通过…...
出行365:依托分布式数据库,让出行无忧 | OceanBase案例
*本文首发自“新华社环球”杂志,作者张海鑫 每年的暑期旅游旺季,都会触发一轮轮的文旅消费的热潮,对于互联网出行服务行业而言,这既是一场盛大的狂欢,也是对其综合实力的严峻考验。 然而,自去年暑假起&…...
【C语言】位段详解
🦄个人主页:小米里的大麦-CSDN博客 🎏所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html 🎁代码托管:黄灿灿 (huang-cancan-xbc) - Gitee.com ⚙️操作环境:Visual Studio 2022 目录 一、什么是位段? 二、…...
LVS集群实验
NAT模式 本质是多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和PORT实现转发RIP和DIP应在同一个IP网络,且应使用私网地址:RS的网关要指向DIP请求报文和响应报文都必须经由Direclor转发,Direclor易于成为系统瓶…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
