(第五章)OpenGL超级宝典学习:统一变量(uniform variable)
| 本篇在讲什么 本篇记录对glsl中的变量uniform的认知和学习 本篇适合什么 适合初学Open的小白 适合想要学习OpenGL中uniform的人 本篇需要什么 对C++语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上手 提供全流程的源码内容 |
★提高阅读体验★ 👉 ♠ 一级标题 👈👉 ♥ 二级标题 👈👉 ♣ 三级标题 👈👉 ♦ 四级标题 👈 |
目录
- ♠ uniform
- ♥ 什么是uniform
- ♥ uniform的作用
- ♥ 简单理解
- ♥ 定义
- ♣ 方式1
- ♣ 方式2
- ♣ 定义演示
- ♥ 赋值
- ♣ 获取位置赋值
- ♣ 直接赋值
- ♥ 实战演示
- ♠ 一致区块
- ♥ 定义
- ♥ 数据布局
- ♣ 标准布局
- ♥ 数据缓冲
- ♥ 完整示例
- ♠ 推送
- ♠ 结语
♠ uniform
♥ 什么是uniform
uniform在glsl是一种特殊变量的限定符,这种变量被称为统一变量
♥ uniform的作用
能够直接将数据从应有程序传递到着色器阶段
♥ 简单理解
简单理解,用uniform定义在着色器中的变量,类似代码中的静态变量
♥ 定义
♣ 方式1
uniform vec4 out_color;
可以直接通过uniform+类型+字段的方式定义在着色器内
♣ 方式2
layout(location = 0) uniform vec4 out_color;
可以在方式1的基础上加上layout位置限定符
♣ 定义演示
"#version 450 core \n"
" \n"
"uniform vec4 out_color1; \n"
" \n"
"layout(location = 0) uniform vec4 out_color2; \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = out_color1; \n"
"} \n"
以上是一个片段着色器的代码,我们在其中按照方式1和方式2定义了两个统一变量out_color1和out_color2
♥ 赋值
定义uniform后,我们需要在外部给其赋值,根据不同的定义方式,赋值的方式也略有不同
♣ 获取位置赋值
第一种赋值方式针对根据方式1定义的变量,我们首先需要获取变量在程序中的位置,才可以通过接口赋值,看下述代码
int location = glGetUniformLocation(program, "out_color1");
glUniform4f(location, 1.0f, 1.0f, 1.0f, 1.0f)
要点1:glGetUniformLocation
该接口可以根据定义的变量名,来获取
统一变量在程序中的位置,参数1是创建好的程序,参数2是自定义的变量名,out_color1是我们在上边定义代码中写的变量
要点2:glUniform4f
我们在获取到变量位置后,可以通过
glUniform**类似的接口给不同类型的统一变量赋值,参数1是位置,后边是需要赋的值
♣ 直接赋值
在上述定义2的形式中,我们直接通过限定符layout给变量设定了位置,如此一来我们就不需要再获取位置了,可以直接赋值
glUniform4f(0, 1.0f, 1.0f, 1.0f, 1.0f)
类似的形式还有很多,比如直接定义数组的赋值方式
GLfloat outColor[4] = {1.0f, 1.0f, 1.0f, 1.0f };glUniform4fv(0, 1, outColor);
♥ 实战演示
我们已经知道了如何定义变量,还有如何赋值,下面我们就写一个简单的例子,画一个三角形,通过uniform变量给三角形上色
注:该例子直接修改OpenGl超级宝典官方示例singletri.cpp,只需修改片段着色器和render方法
- 片段着色器
static const char * fs_source[] =
{"#version 450 core \n"" \n""uniform vec4 out_color1; \n"" \n""layout(location = 0) uniform vec4 out_color2; \n"" \n""out vec4 color; \n"" \n""void main(void) \n""{ \n"" color = out_color2; \n""} \n"
};
- render
virtual void render(double currentTime)
{static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };glClearBufferfv(GL_COLOR, 0, green);// 赋值方式1//int location = glGetUniformLocation(program, "out_color1");//glUniform4f(location, 1.0f, 1.0f, 1.0f, 1.0f);// 赋值方式2//glUniform4f(0, 1.0f, 1.0f, 1.0f, 1.0f);// 赋值数组GLfloat outColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };glUniform4fv(0, 1, outColor);glUseProgram(program);glDrawArrays(GL_TRIANGLES, 0, 3);
}

很简单的一个例子,我们通过glUniform4f或glUniform4fv方法,给outColor赋值,得以给三角形绘制指定颜色
♠ 一致区块
我们已经了解到统一变量的定义、赋值和使用,但是仅仅是单一变量,还有种高级点的用法,可以将很多的统一变量组合成一个区块,称之为一致区块
♥ 定义
以下声明了一个名为TransformBlock的一致区块
uniform TransformBlock{float scale;vec3 translation;float rotation[3];mat4 projection_matrix;
};
♥ 数据布局
命名好的区块会被写入到缓冲当中,在缓冲中,区块的数据布局可能不同,有两种数据布局
- 标准的、共识的数据布局(标准布局)
由于区块中的数据不同,占用的空间不同,该布局会根据每个统一变量的空间占用去存储
- OpenGL自己决定数据的布局方式(shared布局)
OpenGL自己决定存储方式,用之前并不知道各个数据位置,运行的时候需要先查询数据布局格式
♣ 标准布局
推荐使用标准布局,以下是标准布局的声明方式,需要用到限定符std140去声明一致区块
layout uniform (std140) TransformBlock{ float scale;vec4 color;
};
使用标准布局最重要的一点是我们需要知道区块内的统一变量,在缓存中的数据位置,我们简单理解一下数据的分布规则
- 每个类型都有固定长度
- 数据的起始点必须是其固定长度的倍数
我们以上边声明的TransformBlock为例来简单介绍一下
- 类型
float的长度是4,起始点是0,scale需要四个字节,所以结束位置4 - 类型
vec4的长度是16,因为前4位已被占用,并且4不是16的倍数,所以translation在缓冲的起始点只能是16,需要16个字节,在32结束
♥ 数据缓冲
区块的缓冲和我们之前学习的缓冲类似,结构基本一致,分为以下几个步骤
- 创建和绑定缓冲
unsigned int ubo;
glGenBuffers(1, &ubo);
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
- 分配内存
glBufferData(GL_UNIFORM_BUFFER, 4*8, NULL, GL_STATIC_DRAW);
- 将缓冲区对象内的范围绑定到索引的缓冲区目标
glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, 4 * 8);
- 更新数据
glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * 4, sColor);
♥ 完整示例
我们来看一个完整的演示示例吧,很简单,我们只通过区块内的统一变量去给三角形上色
注:该例子直接修改OpenGl超级宝典官方示例singletri.cpp,只需修改startup方法即可
virtual void startup()
{static const char * vs_source[] ={"#version 450 core \n"" \n"" \n""void main(void) \n""{ \n"" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"" vec4(-0.25, -0.25, 0.5, 1.0), \n"" vec4( 0.25, 0.25, 0.5, 1.0)); \n"" \n"" gl_Position = vertices[gl_VertexID]; \n""} \n"};static const char * fs_source[] ={"#version 450 core \n"" \n""layout (std140) uniform color_block \n""{ \n"" vec4 out_color; \n""}; \n"" \n""out vec4 color; \n"" \n""void main(void) \n""{ \n"" color = out_color; \n""} \n"};program = glCreateProgram();GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fs, 1, fs_source, NULL);glCompileShader(fs);GLuint vs = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vs, 1, vs_source, NULL);glCompileShader(vs);glAttachShader(program, vs);glAttachShader(program, fs);glLinkProgram(program);glGenVertexArrays(1, &vao);glBindVertexArray(vao);GLfloat sColor[] = { 1.0f, 0.5f, 0.0f, 1.0f };unsigned int ubo;glGenBuffers(1, &ubo);glBindBuffer(GL_UNIFORM_BUFFER, ubo);glBufferData(GL_UNIFORM_BUFFER, 4*8, NULL, GL_STATIC_DRAW);glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, 4 * 8);glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * 4, sColor);
}
要点1:在该片段着色器中我们声明了一个标准区块color_block,其存有唯一变量out_color,该变量会作为三角形颜色被赋值
要点2:自定义颜色sColor,作为数值通过glBufferSubData接口更新到了区块内,以下是最终显示效果

♠ 推送
- Github
https://github.com/KingSun5
♠ 结语
若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。
相关文章:
(第五章)OpenGL超级宝典学习:统一变量(uniform variable)
统一变量 前言 本篇在讲什么 本篇记录对glsl中的变量uniform的认知和学习 本篇适合什么 适合初学Open的小白 适合想要学习OpenGL中uniform的人 本篇需要什么 对C语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 …...
数据存储技术复习(四)未完
1.什么是NAS。一般用途服务器与NAS设备之间有何不同。NAS是一个基于IP的专用高性能文件共享和存储设备。—般用途服务器可用于托管任何应用程序,因为它运行的是一般用途操作系统NAS设备专用于文件服务。它具有专门的操作系统,专用于通过使用行业标准协议…...
Rust编码的信息窃取恶意软件源代码公布,专家警告已被利用
黑客论坛上发布了一个 用Rust编码的信息窃取恶意软件源代码 ,安全分析师警告,该恶意软件已被积极用于攻击。 该恶意软件的开发者称,仅用6个小时就开发完成,相当隐蔽, VirusTotal的检测率约为22% 。 恶意软件开发者在…...
diffusers编写自己的推理管道
英文文献:Stable Diffusion with 🧨 Diffusers 编写自己的推理管道 最后,我们展示了如何使用diffusers. 编写自定义推理管道是对diffusers库的高级使用,可用于切换某些组件,例如上面解释的 VAE 或调度程序。 例如&a…...
计算机操作系统 左万利 第二章课后习题答案
计算机操作系统 左万利 第二章课后习题答案 1、为何引进多道程序设计,在多道程序设计中,内存中作业的道数是否越多越好?说明原因。 引入多道程序设计技术是为了提高计算机系统资源的利用率。在多道程序系统中,内存中作业的道数并…...
CODESYS开发教程10-文件读写(SysFile库)
今天继续我们的小白教程,老鸟就不要在这浪费时间了😊。 前面一期我们介绍了CODESYS的文件操作库CAA File。这一期主要介绍CODESYS的SysFile库所包含的文件读写功能块,主要包括文件路径、名称、大小的获取以及文件的创建、打开、读、写、拷贝…...
Linux安装redis
Linux安装redis一.下载二.解压配置1.创建文件夹2.上传文件3.解压4.编译配置三.启动测试1.启动2.防火墙配置3.测试四.设置开机自启1.配置脚本2.添加服务3.测试一.下载 redis官网:https://redis.io/ redis官方下载地址:http://download.redis.io/releases…...
计算机组成与体系结构 性能设计 William Stallings 第2章 性能问题
2.1 优化性能设计例如,当前需要微处理器强大功能的桌面应用程序包括:图像处理、三维渲染、语音识别、视频会议、多媒体创作、文件的声音和视频注释、仿真建模从计算机组成与体系结构的角度来看,一方面,现代计算机的基本组成与50多…...
anaconda详细介绍、安装及使用(python)
anaconda详细介绍、安装及使用1 介绍1.1 简介1.2 特点1.3 版本下载2 Anaconda管理Python包命令3 安装3.1 windows安装4 操作4.1 Conda 操作4.2 Anaconda Navigator 操作4.3 Spyder 操作4.4 Jupyter Notebook 操作5 示例参考1 介绍 1.1 简介 Anaconda是用于科学计算(…...
雅思经验(6)
反正我是希望遇到的雅思听力section 4.里面填空的地方多一些,之后单选的部分少一些。练了一下剑9 test3 的section 4,感觉还是不难的,都是在复现,而且绕的弯子也不是很多。本次考试的目标就是先弄一个六分,也就是说&am…...
CentOS9源码编译libvirtd工具
卸载原有版本libvirt [rootcentos9 ~]# yum remove libvirt Centos9配置网络源 [rootcentos9 ~]# dnf config-manager --set-enabled crb [rootcentos9 ~]# dnf install epel-release epel-next-release 安装依赖包 [rootcentos9 ~]# yum install -y libtirpc-devel libxml2-de…...
搭建内网穿透
文章目录摘要npsfrp服务提供商摘要 内网穿透是一种方便的技术,可以让用户随时随地访问内网设备。有两种方式可以使用内网穿透:自己搭建,使用nps/frps软件;购买服务,快速享受内网穿透带来的便利。 nps 内网穿透。参考…...
vue3组件库项目学习笔记(八):Git 使用总结
目前组件库的开发已经接近尾声,因为这次是使用 git 进行协作的开发模式,在团队协作的时候遇到很多的问题,开发过程中发现小伙伴们对于 git 的使用还不是很熟练,这里就简单总结一下常用的 git 的操作,大致有:…...
ISO7320FCQDRQ1数字隔离器LMG1025QDEETQ1半桥GaN驱动器
1、数字隔离器 DGTL ISO 3000VRMS 2CH 8SOIC型号:ISO7320FCQDRQ1批次:新技术:容性耦合类型:通用隔离式电源:无通道数:2输入 - 侧 1/侧 2:2/0通道类型:单向电压 - 隔离:30…...
openmmlab 语义分割算法基础
本文是openmmlab AI实战营的第六次课程的笔记,以下是我比较关注的部分。简要介绍语义分割:如下图,左边原图,右边语义分割图,对每个像数进行分类应用语义分割在个各种场景下都非常重要,特别是在自动驾驶和医…...
2023年深圳/东莞/惠州CPDA数据分析师认证报名入口
CPDA数据分析师认证是中国大数据领域有一定权威度的中高端人才认证,它不仅是中国较早大数据专业技术人才认证、更是中国大数据时代先行者,具有广泛的社会认知度和权威性。 无论是地方政府引进人才、公务员报考、各大企业选聘人才,还是招投标加…...
RabbitMQ-客户端源码之AMQChannel
AMQChannel是一个抽象类,是ChannelN的父类。其中包含唯一的抽象方法: /*** Protected API - called by nextCommand to check possibly handle an incoming Command before it is returned to the caller of nextCommand. If this method* returns true…...
注意力机制(SE,ECA,CBAM) Pytorch代码
注意力机制1 SENet2 ECANet3 CBAM3.1 通道注意力3.2 空间注意力3.3 CBAM4 展示网络层具体信息1 SENet SE注意力机制(Squeeze-and-Excitation Networks):是一种通道类型的注意力机制,就是在通道维度上增加注意力机制,主要内容是是…...
Vue2笔记03 脚手架(项目结构),常用属性配置,ToDoList(本地存储,组件通信)
Vue脚手架 vue-cli 向下兼容可以选择较高版本 初始化 全局安装脚手架 npm install -g vue/cli 创建项目:切换到项目所在目录 vue create xxx 按照指引选择vue版本 创建成功 根据指引依次输入上面指令即可运行项目 也可使用vue ui在界面上完成创建&…...
Java程序的执行顺序、简述对线程池的理解
点个关注,必回关 文章目录一、Java程序是如何执行的二、合理利用线程池能够带来三个好处一、Java程序是如何执行的 我们日常的工作中都使用开发工具(IntelliJ IDEA 或 Eclipse 等)可以很方便的调试程序,或者是通 过打包工具把项目…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
