(第五章)OpenGL超级宝典学习:统一变量(uniform variable)

news2024/11/28 20:37:22
统一变量

前言
本篇在讲什么

本篇记录对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_color1out_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);
}

在这里插入图片描述

很简单的一个例子,我们通过glUniform4fglUniform4fv方法,给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

♠ 结语

若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。

👉 本文属于原创文章,转载请评论留言,并在转载文章头部著名作者出处👈

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式-组合模式和建筑者模式详解

一. 组合模式1. 背景在现实生活中,存在很多“部分-整体”的关系,例如,大学中的部门与学院、总公司中的部门与分公司、学习用品中的书与书包、生活用品中的衣月艮与衣柜以及厨房中的锅碗瓢盆等。在软件开发中也是这样,例如&#xf…

spring注解的开端(@Component替代bean标签的使用)

目录 一、介绍 1.什么是注解开发? 2.Spring注解的版本 3.基于spring注解的应用 4. Component的细分注解 5.相关注解 二、简单例子讲解 1.类打注解 2.扫描注解放入工厂 3.总工厂取注解调用 4.运行结果 总结: 一、介绍 1.什么是注解开发&…

人工智能聊天工具ChatGPT为Delphi写的诗歌

现在每个人似乎都在谈论 ChatGPT,所以这里有一首关于我们最喜欢的开发工具Delphi的好诗,来自 ChatGPT 生成的 Embarcadero 的 Delphi。 Delphi,哦,Delphi! 作者:ChatGPT Delphi,哦,…

java面试题(十九) Mybatis

4.1 谈谈MyBatis和JPA的区别 参考答案 ORM映射不同: MyBatis是半自动的ORM框架,提供数据库与结果集的映射; JPA(默认采用Hibernate实现)是全自动的ORM框架,提供对象与数据库的映射。 可移植性不同&…

166_技巧_Power BI 窗口函数处理连续发生业务问题

166_技巧_Power BI 窗口函数处理连续发生业务问题 一、背景 在生产经营的数据监控中,会有一类指标需要监控是否连续发生,从而根据其在设定区间中的连续频次来评价业务。 例如: 员工连续迟到天数。销售金额连续上升或者下降。用户连续登陆…

卧槽!一个小时不到就把ChatGPT接入了微信!被问疯了~

大家好,我是鸟哥。一个半路出家的程序员。 最近ChatGPT又火了,一时兴起就把它接入我的微信机器人中。从账号注册到接入微信机器人,全程不到1个小时就搞定了!当然不是我牛逼而是Github上的人才太多了。 大家聊的还是很嗨的&#…

Hadoop自动安装JDK

目录 1、使用xftp工具 在opt目录下创建install和soft文件 ​2、使用xftp工具 将压缩包上传到install文件 3、编写shell脚本 3.1、创建目录来放shell脚本 3.2、创建autoinsatll.sh文件并修改权限 3.3、编写autoinsatll.sh 文件 4、 运行 5、测试 1、使用xftp工具 在opt目…

SpringBoot整合(二)MyBatisPlus技术详解

MyBatisPlus详解 一、标准数据层开发 MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率 MyBatisPlus的官网为:https://mp.baomidou.com/ 1.1 标准CRUD 1.2 新增 int insert (T t)T:泛型&#xff0c…

SAP SD模块相关表的知识笔记

VBAK表 销售凭证(抬头数据) 主键为VBELN: 销售凭证 常用的有: kunnr : 售达方 erdat: 记录创建日期 vdatu: 请求交货日期 VBAP表 (销售凭证:项目数据) 主键为 vbeln销售凭证 和posnr 行号 常用的有&#x…

2年功能测试月薪9.5K,100多天自学自动化,跳槽涨薪4k后我的路还很长...

前言 其实最开始我并不是互联网从业者,是经历了一场六个月的培训才入的行,这个经历仿佛就是一个遮羞布,不能让任何人知道,就算有面试的时候被问到你是不是被培训的,我还是不能承认这段历史。我是为了生存,…

leaflet加载KML文件,显示图形(方法2)

第049个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中加载KML文件,将图形显示在地图上。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetMap无法加载,请加载其他来练习 文章目录 示例效果配置方式示例源代码(共66…

YOLOv5-Backbone模块实现

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍦 参考文章地址: 365天深度学习训练营-第P8周:YOLOv5-Backbone模块实现🍖 作者:K同学啊一、前期准备1.设置GPUimport torch from torch impor…

Node=>Express中间件分类 学习4

1.中间件分类 应用级别的中间件路由级别的中间件错误级别的中间件Express 内置的中间件第三方的中间件 通过app.use()或app.get()或app.post()绑定到app实力上的中间件,叫做应用级别的中间件 …

泼辣修图2023最新版本人像美白滤镜手机电脑修图工具

今天,小编分享的是泼辣修图2023最新版本,喜欢追新的朋友赶紧下载使用吧。新版本在图标设计和使用上都有了一些改变,简洁的操作是其一贯的风格。这是一款功能强大的手机及电脑修图app。具体包括了几十种滤镜、曲线调整、颜色调整、皮肤美白、脸…

Biotin-PEG-FITC 生物素聚乙二醇荧光素;FITC-PEG-Biotin 科研用生物试剂

结构式: ​Biotin-PEG-FITC 生物素聚乙二醇荧光素 英文名称:Biotin-PEG-Fluorescein 中文名称:生物素聚乙二醇荧光素 外观:黄色液体、半固体或固体,取决于分子量。 溶剂:溶于大部分有机溶剂,…

学弟学妹少走弯路,超完整算法刷题路线出炉

大家好,我是帅地。 本篇文章主要讲解下面三个事: 1、自己学习算法的一些经历 2、大家学习算法存在的一些普遍问题 3、给大家规划的算法刷题路线 一、算法学习往事 记得当初学了 C 语言就开始刷题了,刷题倒不是面试,而是为了…

图扑数字孪生智慧社区,助力社区数字化转型

前言 智慧社区是社区管理的一种新理念,是新形势下社会管理创新的一种新模式。智慧社区是指充分利用物联网、云计算、移动互联网等新一代信息技术的集成应用,为社区居民提供一个安全、舒适、便利的现代化、智慧化生活环境,从而形成基于信息化…

[Linux]-Ansible

[Linux]-Ansible 森格 | 2023年2月 介绍:本文旨在介绍ansible的基本使用,提高部署环境时的效率,避免重复操作带来的时间成本。 文章目录[Linux]-Ansible一、什么是Ansible1.1 基本介绍1.2 核心概念1.3 优点二、环境部署2.1 Ansible2.2 Docke…

帮中国人搞钱的ChatGPT,算不清自己的“经济账”

好消息,ChatGPT找到盈利模式了。坏消息,尽是“二道贩子”在赚钱。当OpenAI尝试着为红到发紫的ChatGPT推出20美元的Plus订阅服务时,大多数人已经忘记了这个“吞金兽”的成长耗费了多少财力物力。问答狂欢者的岁月静好靠的是OpenAI的负重前行&a…

可重构或可调谐微波滤波器技术

电子可重构,或者说电调微波滤波器由于其在改善现在及未来微波系统容量中不断提高的重要性而正吸引着人们越来越多的关注来对其进行研究和开发。例如,崭露头脚的超宽带(UWB)技术要求使用很宽的无线电频谱。然而,作为资源…