OpenGL ES 01 渲染一个四边形

项目架构

着色器封装

vertex

#version 300 es
// 接收顶点数据
layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为0
layout (location = 1) in vec4 aColors; // 位置变量的属性位置值为1
out vec4 vertexColor; // 为片段着色器指定一个颜色输出void main() {gl_Position = vec4(aPos, 1.0); // 设置顶点位置vertexColor = aColors; // 设置顶点颜色为红色
}

fragment

#version 300 esprecision mediump float;in vec4 vertexColor; // 从顶点着色器传递过来的输入变量
out vec4 FragColor; // 输出到帧缓冲的颜色void main() {FragColor = vertexColor; // 设置片段颜色
}

着色器类封装

import UIKitclass Shader: NSObject {var shaderProgram: GLuint = 0private func loadShaderSource(from file: String) -> String? {guard let path = Bundle.main.path(forResource: file, ofType: "glsl") else {print("Failed to find shader file: \(file)")return nil}do {let source = try String(contentsOfFile: path, encoding: .utf8)return source} catch {print("Failed to load shader file: \(file), error: \(error)")return nil}}func begin() {glUseProgram(shaderProgram)}func compileShader(vert: String, frag: String) {// 读取着色器源代码guard let vertexSource = loadShaderSource(from: vert),let fragmentSource = loadShaderSource(from: frag) else {return}// 打印着色器源代码print("Vertex Shader Source:\n\(vertexSource)")print("Fragment Shader Source:\n\(fragmentSource)")// 创建着色器程序let vertexShader = glCreateShader(GLenum(GL_VERTEX_SHADER))let fragmentShader = glCreateShader(GLenum(GL_FRAGMENT_SHADER))// 将着色器源码附加到着色器对象上vertexSource.withCString { ptr invar p: UnsafePointer<GLchar>? = UnsafePointer<GLchar>(ptr)glShaderSource(vertexShader, 1, &p, nil)}fragmentSource.withCString { ptr invar p: UnsafePointer<GLchar>? = UnsafePointer<GLchar>(ptr)glShaderSource(fragmentShader, 1, &p, nil)}// 编译顶点着色器glCompileShader(vertexShader)// 检查编译错误var status: GLint = 0glGetShaderiv(vertexShader, GLenum(GL_COMPILE_STATUS), &status)if status == GL_FALSE {var logLength: GLint = 0glGetShaderiv(vertexShader, GLenum(GL_INFO_LOG_LENGTH), &logLength)// Allocate buffer with an extra byte for the null terminatorlet bufferLength = Int(logLength) + 1var log = [GLchar](repeating: 0, count: bufferLength)// Get the shader info logglGetShaderInfoLog(vertexShader, logLength, nil, &log)// Convert the buffer to a Swift stringif let logString = String(validatingUTF8: log) {print("编译 顶点着色器 error: \(logString)")} else {print("编译 顶点着色器 error: Failed to retrieve log.")}return}// 编译片元着色器glCompileShader(fragmentShader)// 检查编译错误glGetShaderiv(fragmentShader, GLenum(GL_COMPILE_STATUS), &status)if status == GL_FALSE {var logLength: GLint = 0glGetShaderiv(fragmentShader, GLenum(GL_INFO_LOG_LENGTH), &logLength)// Allocate buffer with an extra byte for the null terminatorlet bufferLength = Int(logLength) + 1var log = [GLchar](repeating: 0, count: bufferLength)// Get the shader info logglGetShaderInfoLog(fragmentShader, logLength, nil, &log)// Convert the buffer to a Swift stringif let logString = String(validatingUTF8: log) {print("编译 片元着色器 error: \(logString)")} else {print("编译 片元着色器 error: Failed to retrieve log.")}return}// 创建程序对象并链接着色器shaderProgram = glCreateProgram()glAttachShader(shaderProgram, vertexShader)glAttachShader(shaderProgram, fragmentShader)glLinkProgram(shaderProgram)var linkStatus: GLint = 0//获取链接状态glGetProgramiv(shaderProgram, GLenum(GL_LINK_STATUS), &linkStatus)if linkStatus == GL_FALSE {NSLog("link error")let message = UnsafeMutablePointer<GLchar>.allocate(capacity: 512)glGetProgramInfoLog(shaderProgram, GLsizei(MemoryLayout<GLchar>.size * 512), nil, message)let str = String(utf8String: message)print("error = \(str ?? "没获取到错误信息")")return} else {NSLog("link success")}// 删除着色器对象,因为它们已经链接到程序对象中glDeleteShader(vertexShader)glDeleteShader(fragmentShader)}
}

ViewController

import UIKit
import GLKit/**渲染一个四边形*/
class ViewController: UIViewController {var eaglLayer: CAEAGLLayer!var myContext: EAGLContext!var shader = Shader()var vao = GLuint()var renderBuffer = GLuint()var frameBuffer = GLuint()var fbo = GLuint()var fboTexture = GLuint()override func viewDidLoad() {super.viewDidLoad()// 设置渲染显示区域setupLayer()// 初始化上下文setupContext()// 设置帧缓冲区setupRenderBuffers()setupFrameBuffer()// 准备着色器prepareShader()prepareVAOAndVBO()renderLayer()}func setupLayer() {eaglLayer = CAEAGLLayer()eaglLayer.frame = view.frameeaglLayer.isOpaque = trueview.layer.addSublayer(eaglLayer)}func setupContext() {if let context = EAGLContext(api: .openGLES3) {EAGLContext.setCurrent(context)myContext = contextprint("Create context success")} else {print("Create context failed!")}}// 生成和绑定渲染缓冲区对象,为渲染缓冲区分配存储空间,生成和绑定帧缓冲区对象,并将渲染缓冲区附加到帧缓冲区的颜色附件点func setupRenderBuffers() {//生成一个渲染缓冲区对象,并将其ID存储在,colorRenderBuffer变量中。glGenRenderbuffers(1, &renderBuffer)//绑定生成的渲染缓冲区对象,使其成为当前的渲染缓冲区glBindRenderbuffer(GLenum(GL_RENDERBUFFER), renderBuffer)}func setupFrameBuffer() {// 生成一个帧缓冲区对象,并将其ID存储在frameBuffer变量中glGenFramebuffers(1, &frameBuffer)// 将frameBuffer绑定到GL_FRAMEBUFFER目标上glBindFramebuffer(GLenum(GL_FRAMEBUFFER), frameBuffer)// 将渲染缓冲区附加到帧缓冲区的颜色附件点。glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), renderBuffer)//方法为当前绑定的渲染缓冲区分配存储空间,并将其与 CAEAGLLayer 关联。myContext.renderbufferStorage(Int(GL_RENDERBUFFER), from: eaglLayer)}func prepareShader() {shader.compileShader(vert: "vertex", frag: "fragment")}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]var 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)glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)glBindVertexArray(0)}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()// 解绑FBOglBindFramebuffer(GLenum(GL_FRAMEBUFFER), 0)// 渲染FBO内容到屏幕glClearColor(0.0, 0.0, 0.0, 1.0)glClear(GLbitfield(GL_COLOR_BUFFER_BIT))// 绑定默认帧缓冲区glBindFramebuffer(GLenum(GL_FRAMEBUFFER), frameBuffer)// 使用FBO中的纹理进行后处理或直接绘制到屏幕// 这里你需要一个简单的着色器来绘制纹理到屏幕shader.begin()// 绑定FBO纹理glBindTexture(GLenum(GL_TEXTURE_2D), fboTexture)// 绘制一个全屏四边形,将FBO纹理渲染到屏幕上// 你需要设置适当的顶点和纹理坐标// 这里假设你已经有一个VAO和VBO来绘制全屏四边形glBindVertexArray(vao)glDrawElements(GLenum(GL_TRIANGLE_STRIP), 4, GLenum(GL_UNSIGNED_BYTE), nil)glBindVertexArray(0)myContext.presentRenderbuffer(Int(GL_RENDERBUFFER))}
}

最后效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/493396.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

游戏渠道假量解决方案

某推广公司在推广过程中被查出“短期内点击量激增”“存在同一地址多次访问”“已注册用户重复注册”等数据作弊行为&#xff0c;法院判罚退还服务费200余万元&#xff0c;并赔偿违约金约350万元。 某公司为提升其游戏在应用商店榜单排名&#xff0c;委托某网络公司进行下载、注…

物联网:全面概述、架构、应用、仿真工具、挑战和未来方向

中文论文标题&#xff1a;物联网&#xff1a;全面概述、架构、应用、仿真工具、挑战和未来方向 英文论文标题&#xff1a;Internet of Things: a comprehensive overview, architectures, applications, simulation tools, challenges and future directions 作者信息&#x…

29、基于springboot的网上购物商城系统研发

本课题是根据用户的需要以及网络的优势建立的一个基于Spring Boot的网上购物商城系统&#xff0c;来满足用户网络购物的需求。 本网上购物商城系统应用Java技术&#xff0c;MYSQL数据库存储数据&#xff0c;基于Spring Boot框架开发。在网站的整个开发过程中&#xff0c;首先对…

Spring Boot--06--整合Swagger

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Swagger一、简介官网&#xff1a;https://swagger.io/ Swagger 的优势 二、基本使用1. 导入相关依赖2. 编写配置文件2.1 配置基本信息2.2 配置接口信息2.3 配置分组…

写SQL太麻烦?免费搭建 Text2SQL 应用,智能写 SQL | OceanBase AI 实践

自OceanBase 4.3.3版本推出以来&#xff0c;向量检索的能力受到了很多客户的关注&#xff0c;也纷纷表达希望OB能拓展更多 多模数据库大模型 的AI应用实践。 在上篇文章 &#x1f449; OceanBase LLM&#xff0c;免费构建你的专属 AI 助手 &#xff0c;我们介绍了如何去搭建一…

题海拾贝:力扣 86.分隔链表

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞&#xff0c;关注&#xff01; 1、题…

sql server索引优化语句

第一步 建一个测试表 --create table TestUsers --( -- Id int primary key identity(1,1), -- Username varchar(30) not null, -- Password varchar(10) not null, -- CreateDateTime datetime not null --)第二步 插入100w数据 大概1分钟执行时间 ----插入数据…

多智能体/多机器人网络中的图论法

一、引言 1、网络科学至今受到广泛关注的原因&#xff1a; &#xff08;1&#xff09;大量的学科&#xff08;尤其生物及材料科学&#xff09;需要对元素间相互作用在多层级系统中所扮演的角色有更深层次的理解&#xff1b; &#xff08;2&#xff09;科技的发展促进了综合网…

VS Code Copilot 与 Cursor 对比

选手简介 VS Code Copilot&#xff1a;算是“老牌”编程助手了&#xff0c;虽然Copilot在别的编辑器上也有扩展&#xff0c;不过体验最好的还是VS Code&#xff0c;毕竟都是微软家的所以功能集成更好一些&#xff1b;主要提供的是Complete和Chat能力&#xff0c;也就是代码补全…

基于层次化设计方法,设计一个16位二进制全加器

设计思路&#xff1a;先一个半加器和一个或门&#xff0c;每两个半加器构成一个全加器&#xff0c;每四个全加器组成一个4位全加器&#xff0c;再将这4个4位全加器依次相连组成一个16位二进制全加器。 半加器的逻辑表达式&#xff1a;sumAB; coutAB; 半加器的真值表 全加器的逻…

ES搜索原理

ES搜索原理 bg: 搜索的时候&#xff0c;使用模糊查询经常出现搜索不到的情况&#xff0c;不如mysql的like有效。 https://www.bilibili.com/video/BV1yb421J7oX/?spm_id_from333.337.search-card.all.click&vd_source3f917722acc36b0fcca7cca2d21394e2 基础概念 索引&a…

轻松上手:使用 Vercel 部署 HTML 页面教程

&#x1f600; 在学习前端的过程中&#xff0c;部署项目往往是一个令人头疼的问题。然而&#xff0c;Vercel 为我们提供了一个便捷且免费的解决方案。 Vercel 是一个强大的云平台&#xff0c;专门用于前端项目的部署和托管。它不仅支持多种前端框架和静态网站生成器&#xff0…

STL 剖析

STL 六大组件 「STL 六大组件的交互关系」 Container 通过 Allocator 取得数据储存空间Algorithm 通过 Iterator 存取 Container 内容Functor 可以协助 Algorithm 完成不同的策略变化Adapter 可以修饰或套接 Functor、Iterator 配置器(allocator) 配置器&#xff1a;负责空间…

HTTP—03

触发 GET 请求 1&#xff09;直接在浏览器 地址栏 输入 URL&#xff0c;此时构成了一个GET请求 2&#xff09;HTML中的一些特殊标签可能会触发 例如 img,a,link,script... 3&#xff09;通过Form表单触发&#xff08;Form本质也是一个HTML标签&#xff09; 4&#xff0…

C 数组:索引魔杖点化的数据星图阵列

一、数组 1.数组的概念 数组是⼀组相同类型元素的集合&#xff1b;从这个概念中我们就可以发现2个有价值的信息&#xff1a; 数组中存放的是1个或者多个数据&#xff0c;但是数组元素个数不能为0。数组中存放的多个数据&#xff0c;类型是相同的。 2.数组的分类 数组主要分为一…

苹果手机怎么清理空间:拯救你的拥挤手机

在数字生活的海洋中&#xff0c;我们的苹果手机就像一艘小船&#xff0c;载满了照片、应用、视频和各种下载的“宝贝”。随着时间的推移&#xff0c;这艘小船开始变得拥挤&#xff0c;航行速度放缓&#xff0c;甚至有时候直接卡壳。苹果手机怎么清理空间&#xff1f;是时候学会…

Ubuntu上如何部署Nginx?

环境&#xff1a; Unbuntu 22.04 问题描述&#xff1a; Ubuntu上如何部署Nginx&#xff1f; 解决方案&#xff1a; 在Ubuntu上部署Nginx是一个相对简单的过程&#xff0c;以下是详细的步骤指南。我们将涵盖安装Nginx、启动服务、配置防火墙以及验证安装是否成功。 1. 更新…

javaScriptBOM

1.1、BOM概述 1.1.1、BOM简介 BOM&#xff08;browser Object&#xff09;即浏览器对象模型&#xff0c;它提供了独立于内容而与浏览器窗口进行交互的对象&#xff0c;其核心对象是window。 BOM由一系列的对象构成&#xff0c;并且每个对象都提供了很多方法与属性 BOM缺乏标准…

Unity3D仿星露谷物语开发7之事件创建动画

1、目标 掌握事件通知的Publisher - Subscriber设计模式&#xff0c;并通过事件通知触发动画。 2、发布者/订阅者模式 首先&#xff0c;定义事件Event 然后&#xff0c;Publisher触发事件 最后&#xff0c;Subscriber订阅事件并进行处理 &#xff08;1&#xff09;创建动作…

点击展示大图预览

原文链接在table表格里能够实现&#xff0c;点击里面的图片实现大图预览的效果&#xff1b; 一、先安装viewer — 使用npm安装 npm install v-viewer --save二、在main.js中引入 import Viewer from v-viewer //点击图片大图预览 import viewerjs/dist/viewer.css Vue.use(…