使用 OpenGL ES 在 iOS 上渲染一个四边形:从基础到实现
使用 OpenGL ES 在 iOS 上渲染一个四边形:从基础到实现
在 iOS 开发中,OpenGL ES 是一个强大的工具,用于实现高性能的 2D 和 3D 图形渲染。本文将详细分析一段完整的代码,展示如何使用 OpenGL ES 在 iOS 上渲染一个简单的四边形。我们将从代码的结构、关键模块、着色器的实现以及渲染流程等方面进行深入解析,帮助你理解 OpenGL ES 的工作原理和实现细节。
1. 项目概述
这段代码的目标是使用 OpenGL ES 渲染一个带有颜色的四边形。主要实现步骤包括:
- 设置渲染环境(
CAEAGLLayer和 OpenGL ES 上下文)。 - 配置帧缓冲区和渲染缓冲区。
- 编写和加载顶点着色器和片段着色器。
- 配置顶点数据(位置和颜色)。
- 使用 OpenGL ES 的绘制命令渲染四边形。
2. 渲染流程解析
2.1 设置渲染显示区域
func setupLayer() {eaglLayer = CAEAGLLayer()eaglLayer.frame = view.frameeaglLayer.isOpaque = trueview.layer.addSublayer(eaglLayer)
}
- 作用:创建一个
CAEAGLLayer,作为 OpenGL ES 渲染的目标。 - 关键点:
CAEAGLLayer是 iOS 上 OpenGL ES 渲染的专用图层,支持硬件加速。isOpaque = true:设置图层为不透明,避免透明度计算,提高性能。view.layer.addSublayer(eaglLayer):将CAEAGLLayer添加到视图的层次结构中。
2.2 初始化 OpenGL ES 上下文
func setupContext() {if let context = EAGLContext(api: .openGLES3) {EAGLContext.setCurrent(context)myContext = contextprint("Create context success")} else {print("Create context failed!")}
}
- 作用:创建 OpenGL ES 上下文,并将其设置为当前上下文。
- 关键点:
EAGLContext(api: .openGLES3):创建一个 OpenGL ES 3.0 的上下文。如果设备不支持 OpenGL ES 3.0,可以降级为.openGLES2。EAGLContext.setCurrent(context):将上下文设置为当前线程的活动上下文,后续的 OpenGL ES 操作都会基于这个上下文。
2.3 配置渲染缓冲区和帧缓冲区
渲染缓冲区
func setupRenderBuffers() {glGenRenderbuffers(1, &renderBuffer)glBindRenderbuffer(GLenum(GL_RENDERBUFFER), renderBuffer)
}
- 作用:创建并绑定一个渲染缓冲区,用于存储渲染结果。
- 关键点:
glGenRenderbuffers:生成一个渲染缓冲区对象,并将其 ID 存储在renderBuffer中。glBindRenderbuffer:将生成的渲染缓冲区绑定到当前上下文。
帧缓冲区
func setupFrameBuffer() {glGenFramebuffers(1, &frameBuffer)glBindFramebuffer(GLenum(GL_FRAMEBUFFER), frameBuffer)glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), renderBuffer)myContext.renderbufferStorage(Int(GL_RENDERBUFFER), from: eaglLayer)
}
- 作用:创建并绑定一个帧缓冲区,将渲染缓冲区附加到帧缓冲区的颜色附件点。
- 关键点:
glGenFramebuffers:生成一个帧缓冲区对象。glBindFramebuffer:将帧缓冲区绑定到当前上下文。glFramebufferRenderbuffer:将渲染缓冲区附加到帧缓冲区的颜色附件点(GL_COLOR_ATTACHMENT0)。myContext.renderbufferStorage:为渲染缓冲区分配存储空间,并将其与CAEAGLLayer关联。
2.4 编写和加载着色器
顶点着色器
#version 300 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec4 aColors;
out vec4 vertexColor;void main() {gl_Position = vec4(aPos, 1.0);vertexColor = aColors;
}
- 作用:将顶点位置传递给 OpenGL 的渲染管线,并将顶点颜色传递给片段着色器。
- 关键点:
layout (location = 0):指定顶点属性的位置索引。gl_Position:设置顶点的最终位置。vertexColor:将顶点颜色传递给片段着色器。
片段着色器
#version 300 es
precision mediump float;in vec4 vertexColor;
out vec4 FragColor;void main() {FragColor = vertexColor;
}
- 作用:接收顶点着色器传递的颜色,并将其作为片段的最终颜色输出。
- 关键点:
FragColor:输出到帧缓冲区的颜色。
加载和编译着色器
func compileShader(vert: String, frag: String) {// 加载着色器源代码guard let vertexSource = loadShaderSource(from: vert),let fragmentSource = loadShaderSource(from: frag) else {return}// 创建和编译顶点着色器let vertexShader = glCreateShader(GLenum(GL_VERTEX_SHADER))vertexSource.withCString { ptr invar p: UnsafePointer<GLchar>? = UnsafePointer<GLchar>(ptr)glShaderSource(vertexShader, 1, &p, nil)}glCompileShader(vertexShader)// 创建和编译片段着色器let fragmentShader = glCreateShader(GLenum(GL_FRAGMENT_SHADER))fragmentSource.withCString { ptr invar p: UnsafePointer<GLchar>? = UnsafePointer<GLchar>(ptr)glShaderSource(fragmentShader, 1, &p, nil)}glCompileShader(fragmentShader)// 链接着色器程序shaderProgram = glCreateProgram()glAttachShader(shaderProgram, vertexShader)glAttachShader(shaderProgram, fragmentShader)glLinkProgram(shaderProgram)
}
- 作用:加载、编译和链接顶点着色器和片段着色器。
- 关键点:
glCreateShader:创建着色器对象。glShaderSource:将着色器源代码附加到着色器对象。glCompileShader:编译着色器。glCreateProgram:创建着色器程序。glAttachShader和glLinkProgram:将着色器链接到程序中。
2.5 配置顶点数据
func prepareVAOAndVBO() {let positions: [GLfloat] = [-0.5, -0.5, 0.0,0.5, -0.5, 0.0,-0.5, 0.5, 0.0,0.5, 0.5, 0.0]let colors: [GLfloat] = [1.0, 0.2, 0.2, 1.0,0.5, 1.0, 0.2, 1.0,0.5, 0.5, 1.0, 1.0]let indices: [GLubyte] = [0, 1, 2, 3]// 创建 VBO 和 VAOvar positionVBO = GLuint()glGenBuffers(1, &positionVBO)glBindBuffer(GLenum(GL_ARRAY_BUFFER), positionVBO)glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout<GLfloat>.size * positions.count, positions, GLenum(GL_STATIC_DRAW))var colorVBO = GLuint()glGenBuffers(1, &colorVBO)glBindBuffer(GLenum(GL_ARRAY_BUFFER), colorVBO)glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout<GLfloat>.size * colors.count, colors, GLenum(GL_STATIC_DRAW))var ebo = GLuint()glGenBuffers(1, &ebo)glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), ebo)glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), MemoryLayout<GLubyte>.size * indices.count, indices, GLenum(GL_STATIC_DRAW))glGenVertexArrays(1, &vao)glBindVertexArray(vao)glBindBuffer(GLenum(GL_ARRAY_BUFFER), positionVBO)glVertexAttribPointer(0, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 3), nil)glEnableVertexAttribArray(0)glBindBuffer(GLenum(GL_ARRAY_BUFFER), colorVBO)glVertexAttribPointer(1, 4, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 4), nil)glEnableVertexAttribArray(1)glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), ebo)glBindVertexArray(0)
}
- 作用:配置顶点数据(位置和颜色)以及索引数据。
- 关键点:
glGenBuffers和glBindBuffer:创建并绑定缓冲对象。glBufferData:将顶点数据传递到缓冲区。glVertexAttribPointer和glEnableVertexAttribArray:配置顶点属性。
2.6 渲染四边形
func renderLayer() {glClearColor(0.0, 0.0, 0.0, 1.0)glClear(GLbitfield(GL_COLOR_BUFFER_BIT))glViewport(GLint(0), GLint(0), GLsizei(view.frame.size.width), GLsizei(view.frame.size.height))shader.begin()glBindVertexArray(vao)glDrawElements(GLenum(GL_TRIANGLE_STRIP), 4, GLenum(GL_UNSIGNED_BYTE), nil)glBindVertexArray(0)myContext.presentRenderbuffer(Int(GL_RENDERBUFFER))
}
- 作用:清屏、设置视口、绑定 VAO,并绘制四边形。
- 关键点:
glClearColor和glClear:清除屏幕。glViewport:设置视口大小。glDrawElements:使用索引绘制四边形。myContext.presentRenderbuffer:将渲染结果显示到屏幕上。
3. 总结
这段代码展示了如何使用 OpenGL ES 在 iOS 上渲染一个简单的四边形。通过设置渲染环境、加载着色器、配置顶点数据和执行绘制命令,我们可以清晰地了解 OpenGL ES 的渲染流程。这种基础的实现方式为更复杂的图形渲染任务(如 3D 模型、纹理映射等)打下了坚实的基础。
如果你是 OpenGL ES 的初学者,这段代码是一个很好的起点。通过修改顶点数据、着色器代码或添加纹理,你可以进一步探索 OpenGL ES 的强大功能。
相关文章:
使用 OpenGL ES 在 iOS 上渲染一个四边形:从基础到实现
使用 OpenGL ES 在 iOS 上渲染一个四边形:从基础到实现 在 iOS 开发中,OpenGL ES 是一个强大的工具,用于实现高性能的 2D 和 3D 图形渲染。本文将详细分析一段完整的代码,展示如何使用 OpenGL ES 在 iOS 上渲染一个简单的四边形。…...
98.2 AI量化开发:基于DeepSeek打造个人专属金融消息面-AI量化分析师(理论+全套Python代码)
目录 0. 承前1. 金融工程结构图2. Why is DeepSeek3. 项目实现代码3.1 导入python库3.2 参数设置3.3 获取数据3.4 数据处理3.5 AI人设提示词3.6 Messages构建3.7 AI Agent3.8 response格式处理3.9 汇总函数3.10 运行案例 4. 总结4.1 系统优点4.2 系统缺点4.3 可提升方向 0. 承前…...
复制粘贴小工具——Ditto
在日常工作中,复制粘贴是常见的操作,但Windows系统自带的剪贴板功能较为有限,只能保存最近一次的复制记录,这对于需要频繁复制粘贴的用户来说不太方便。今天,我们介绍一款开源、免费且功能强大的剪贴板增强工具——Dit…...
中国人名汉语拼音字母拼写规则
中国人名汉语拼音字母拼写规则 1. Lv and Lyu2. 中国人名汉语拼音字母拼写规则References 1. Lv and Lyu LongBench: A Bilingual, Multitask Benchmark for Long Context Understanding https://arxiv.org/abs/2308.14508 2. 中国人名汉语拼音字母拼写规则 http://www.moe.g…...
MAC OS安装Homebrew
文章目录 1.下载Homebrew2.完成安装3.验证安装4.更新 Homebrew作为一个包管理器,提供了一种简便的方式来安装、更新和卸载各种命令行工具和应用程序。相比于手动下载和编译源代码,或者从不同的网站下载安装包,使用Homebrew可以显著减少这些操…...
计算机组成原理——存储系统(四)
当晨曦的第一缕光线划破夜空,那是宇宙给奋斗者的信号——光明属于那些在黑暗中依旧寻找希望的人。在这条通往梦想的道路上,每一步都充满挑战,但正是这些挑战定义了你的坚韧与不屈。不要满足于现状,因为你的潜力远超想象࿱…...
飞算JavaAI:开辟 AI + 行业趋势的编程新范式
在当今数字化浪潮汹涌澎湃的时代,科技的快速发展正以前所未有的速度重塑着各个行业的面貌。人工智能(AI)作为其中最具变革性的力量之一,已经深入渗透到众多领域,从金融、医疗到制造业、教育等,无一不在经历…...
Axure PR 9 动效 设计交互
大家好,我是大明同学。 这期内容,我们来用Axure制作一组动效。 动效 创建动效元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.选中画布,将画布填充颜色设置为蓝色(#0052D9)。 3.在元件库中拖出一个圆形元件,选中矩形元件&…...
DeepSeek 本地部署
DeepSeek 本地部署 一、引言二、为什么选择本地部署 DeepSeek?三、具体步骤1.下载Ollama并安装(Ollama 提供 API 支持)2. 部署 deepseek-r12.下载Chatbox并配置为本地DeepSeek (Chatbox 提供 UI 界面) 一、引言 近期&…...
langchain教程-3.OutputParser/输出解析
前言 该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial 我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容 这是教程清单 1.初试langchain2.prompt3.OutputParser/输出解析4.model/vllm模型部署和langchain调用5.DocumentLoader/多种文档…...
JavaScript系列(62)--实时通信系统实现详解
JavaScript实时通信系统实现详解 🔄 今天,让我们深入探讨JavaScript的实时通信系统实现。实时通信是现代Web应用中不可或缺的一部分,它能够提供即时的数据交互和更好的用户体验。 WebSocket通信基础 🌟 💡 小知识&am…...
网络工程师 (20)计算机网络的概念
一、定义 计算机网络是指将地理位置不同、具有独立功能的多台计算机及其外部设备,通过通信线路及通信设备连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现信息传递和资源共享的计算机通信系统。 二、组成 资源子网&…...
Unity UI Default Shader分析
文章目录 UI默认材质和Default ShaderShader的属性定义Mask组件支持RectMask2D组件支持其他支持使用Unity UGUI时经常有自定义shader的需求,虽然我们可以直接按照shader lab的规范写出shader,使用也没问题,但如果能让自定义shader符合UI shader的规范,支持Mask,Rect2DMask…...
IEEE 802.3/802.2 | LLC / SNAP
注:本文为 “IEEE 802.3/802.2 | LLC / SNAP” 相关文章合辑。 未整理去重。 第三篇部分内容出自第二篇。 802.2 协议 haoay321 2010-01-28 20:52:02 LLC 协议 LLC(Logic Link Control,逻辑链路控制)是 IEEE 802.2 协议中规定…...
【Linux】24.进程间通信(3)
文章目录 3.6 systemv共享内存3.6.1 共享内存函数3.6.3 一个简单的共享内存代码实现3.6.4 一个复杂的共享内存代码实现3.6.4 key和shmid的主要区别: 3.7 systemv消息队列(了解)3.8 systemv信号量(了解)进程互斥四个问题理解信号量…...
【自然语言处理】TextRank 算法提取关键词(Python实现)
文章目录 前言PageRank 实现TextRank 简单版源码实现jieba工具包实现TextRank 前言 TextRank 算法是一种基于图的排序算法,主要用于文本处理中的关键词提取和文本摘要。它基于图中节点之间的关系来评估节点的重要性,类似于 Google 的 PageRank 算法。Tex…...
Java-128陷阱、抽象类和接口的区别、为什么 hashCode()需要和equals()一起重写、封装继承多态
128陷阱 Integer a 100; Integer b 100; System.out.println(ab); //true Integer c 1000; Integer d 1000; System.out.println(cd);//false int e 1000; System.out.println(ce);//true 分析以上代码运行的结果 源码: Integer a128; 编译器执行的是&…...
使用 Python 编程语言来实现机器学习小项目教程案例
以下是一个简单的机器学习小项目教程案例,使用 Python 编程语言和 Scikit-learn 库来实现一个分类任务。我们将使用经典的鸢尾花(Iris)数据集来训练一个分类器,预测鸢尾花的种类。 项目目标 使用机器学习算法对鸢尾花数据集进行分类,预测鸢尾花的类别(Setosa、Versicolor…...
如何评价镜头的好坏?光学镜头的一种评价标准
1光学传递函数MTF MTF是什么? 光学传递函数(optical transfer function)是指以空间频率为变量,表征成像过程中调制度和横向相移的相对变化的函数。光学传递函数是光学系统对空间频谱的滤波变换。一个非相干照明的光学成像系统&a…...
openGauss 3.0 数据库在线实训课程1:学习数据库状态查看
openGauss数据库状态查看 前提 我正在参加21天养成好习惯| 第二届openGauss每日一练活动 课程详见:openGauss 3.0.0数据库在线实训课程 学习目标 学习从操作系统层面和使用openGauss工具查看数据库的状态、版本和数据文件目录。 课程作业 gs_ctl是openGauss提…...
Stable Diffusion的入门介绍和使用教程
Stable Diffusion是一个文本到图像的潜在扩散模型,由CompVis、StabilityAI和LAION的研究人员和工程师创建。它使用来自LAION-5B数据库子集的512x512图像进行训练。使用这个模型,可以生成包括人脸在内的任何图像,因为有开源的预训练模型&#…...
docker安装es及分词器ik
系统是macos,docker是docker-desktop 拉取镜像 docker pull bitnami/elasticsearch 启动docker镜像 docker create -e "discovery.typesingle-node" \ --name elasticsearch1 -p 9200:9200 -p 9300:9300 \ bitnami/elasticsearch:8.17.1 测试是否好…...
记一次框架利用接管学工系统
视频教程在我主页简介或专栏里 链接:观看更多 Springboot actuator (1)某学院学工管理系统存在Springboot actuator未授权,泄露了很多接口地址,其他接口就不过多介绍了,这里具体讲述这次利用到的httptrace和jolokia两…...
低代码提升交付效率的公式计算
低(无)代码平台(后统称“低代码”)能够提升数字化应用建设、交付效率,已经成为IT从业人员的共识。目前,大部分CIO/CDO都能清晰定位和认知低代码的特点和作用。但仍然有人认为,使用了低代码工具软…...
深入解析:如何利用 Python 爬虫获取商品 SKU 详细信息
在电商领域,SKU(Stock Keeping Unit,库存单位)详细信息是电商运营的核心数据之一。它不仅包含了商品的规格、价格、库存等关键信息,还直接影响到库存管理、价格策略和市场分析等多个方面。本文将详细介绍如何利用 Pyth…...
java后端开发面试常问
面试常问问题 1 spring相关 (1)Transactional失效的场景 <1> Transactional注解默认只会回滚运行时异常(RuntimeException),如果方法中抛出了其他异常,则事务不会回滚(数据库数据仍然插…...
第六期:开放银行突围战 - API经济下的跨域经营合规框架
一、监管沙盒中的API兵法 1.1 开放银行接口的军备等级 人行《商业银行应用程序接口管理规范》(2025修订版): 安全分级: L1(查询类):日均调用量≤10万次 (如余额查询) L2(交易类):必须双因素认证 (如转账) L3(决策类):需人工智能审计跟踪 (如授信评估) 实战接口设计…...
全程Kali linux---CTFshow misc入门(25-37)
第二十五题: 提示:flag在图片下面。 直接检查CRC,检测到错误,就直接暴力破解。 暴力破解CRC的python代码。 import binascii import struct def brute_force_ihdr_crc(filename): # 读取文件二进制数据 with open(filen…...
Axure大屏可视化动态交互设计:解锁数据魅力,引领决策新风尚
可视化组件/模板预览:https://8dge09.axshare.com 一、大屏可视化技术概览 在数据驱动决策的时代,大屏可视化技术凭借直观、动态的展示方式,已成为众多行业提升管理效率和优化决策过程的关键工具。它能够将复杂的数据转化为易于理解的图形和…...
《AI “造脸术”:生成对抗网络打造超真实虚拟人脸》
在科技飞速发展的当下,人工智能的浪潮席卷而来,其中生成对抗网络(GANs)技术以其独特的魅力,成为了生成高度真实感虚拟人脸的强大引擎。无论是影视制作中虚拟角色的塑造,还是游戏领域中多样化角色形象的构建…...
