【OpenGL手册12】 统一变量Uniform

OpenGL基础 - 统一变量Uniform

目录

  • 一、说明
  • 二、 Uniform变量概念
    • 2.1 Uniform变量和特点
    • 2.2 Uniform变量定义方法
    • 2.3 Uniform变量赋值和传参
  • 三、如何在Shader中自定义Location
  • 四、赋值
  • 五、统一变量缓冲对象
  • 六、赋值函数

一、说明

   关于统一变量,也有一系列概念和方式,如果不加以梳理,迟早将陷入泥藻之中,本篇将梳理全套的有关Uniform的描述,汇集起来当作手册备用。

二、 Uniform变量概念

2.1 Uniform变量和特点

   OpenGL基础: Uniform变量 ,即统一变量。简单理解就是一个GLSL shader中的全局常量,特点是:

  •    可以随意在任意shader(vertex shader, geometry shader, or fragment shader)访问,不同的shader中uniform是一起链接的。
  •    初始化之后,不能修改其值,否则会引起编译错误。
  •    是CPU一侧直接赋值给GPU的变量。

2.2 Uniform变量定义方法

   1 定义以及使用Uniform变量的方法:
在着色器内定义接受变量

vertex shader#version 400
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
out vec3 outColor;
uniform mat4 wmat;
void main()
{Color = color;gl_Position = wmat * vec4(position, 1.f);
}

2.3 Uniform变量赋值和传参

1 ) 值传
   使用Uniform的定义一个向量,可以通过location设置Unfirom值,外部CPU程序代码中写:

glm::mat amat; // define a mat, and give it any value you need.
...
GLuint loc = glGetUniformLocation(program, "wmat");
if (loc >= 0) // if fail, loc == -1
{glUniformMatrix4fv(loc, 1, GL_FALSE, &amat[0][0]);
}
  • “wmat”:是着色器的对应变量。
  • glUniformMatrix4fv:此为执行赋值函数。

2)数组传递
   如果是Uniform数组(由vecx元素组成)也可以直接这样获取location:

GLSL中定义:

uniform vec3 Array[10];

C++客户端程序获取指针:

GLuint loc = glGetUniformLocation(program, "Array[1]");

3)结构传递
   如果是Uniform Struct,也可以类似地直接获取

GLSL中定义:

struct aStruct
{vec3 lightPos;vec4 lightColor;mat4x3 otherMat;
}myStruct;

   C++客户端程序获取(注意前缀名字是myStruct,不是aStruct):

   GLuint loc = glGetUniformLocation(program, “myStruct.lightPos”)
这个名字变量的获取风格类C了,对于C程序员十分友好。

   其实就是定义在GLSL中的一个结构体Struct

例子:

uniform MyBlock // 定义在shader中
{vec4 color1;vec4 color2;float r1;float r2;
}myBlock;

三、如何在Shader中自定义Location

   就是在Shader中自定义一个uniform的location:

layout(location = 2) uniform mat4 worldMat;

   这样在C++客户端程序中就可以直接赋值,无需要寻址了

glUniformMatrix4fv(2, 1, GL_FALSE, &worldMat[0][0]);
不过这种自定义location,需要十分小心,如果赋予两个uniform同样的location,那就会产生链接错误。

   尤其是同时赋予多个uniform location的时候要注意:

layout(location = 2) uniform vec4 aVec[8];

   那么aVec的uniform location值范围是[2, 10)

   所以如果这样定义:

layout(location = 2) uniform vec4 aVec[8];
layout(location = 5) uniform mat4 aMat[2];

   那么就是非法的,会引起链接错误。因为,aVec占用了【2-10】,aMat只能从11开始。

四、赋值

   可以给uniform赋予默认值,如果C++客户端没有给uniform值得时候,GLSL会预先给出默认值,当客户端赋值时,默认值被冲掉:

uniform vec4 greenColor = vec4(0.0, 1.0, 0.0, 1.0);
uniform vec3 vers[4] = vec3[](vec3(0.3, -0.8, 0.1),vec3(0.2, 1.0, 0.2),vec3(0.6, -1.0, 0.3),vec3(0.9, 0.7, 0.4));

五、统一变量缓冲对象

   这是高级用法:统一变量缓冲对象 – Uniform buffer object
   这个用法稍微有点难,坑比较多的,所以,建议初学者可以暂时跳过,因为一开始学OpenGL,应该暂时不需要使用,使用前面的方法操作Uniform应该就足够了。

   这里先抛砖引玉,简单举例应用一下,一些小坑,小知识点不详细展开,会后续教程中补全的,还会专门讲这个用法。当然,看完下面这一段也足够可以使用这个知识点了。

   这个是OpenGL客户端程序和GLSL中的Uniform变量对应的对象,也可以是和变量块Uniform block, 变量数组Uniform array对应。

   目的是为了方便在OpenGL客户端操作(修改值)GLSL的Uniform对象,尤其是一组uniform值得时候,更加方便修改。

   例如在GLSL中定义:

layout (std140, binding = 0) uniform MATS
{mat4 mvMat;vec3 aPos;
};
layout (std140, binding = 1) uniform MAT_BLOCK
{mat4 matPool[120];
};
在C++客户端程序中修改:// 第一个(binding = 0):
struct ABlock
{glm::mat4     aMatrix;glm::vec3     pos;
};
glGenBuffers(1, &aMapBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, aMapBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(ABlock), NULL, GL_DYNAMIC_DRAW);// Careful: The parameter 0: is correspondant to binding = 0; not location.
// 0 是对应 GLSL中的bingding = 0; 不是location = 0
glBindBufferBase(GL_UNIFORM_BUFFER, 0, aMapBuffer);ABlock* mapBlock = (ABlock*)glMapBufferRange(GL_UNIFORM_BUFFER,0,sizeof(ABlock),GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);mapBlock->aMatrix = glm::mat(1); // set any value you want here to GLSL
mapBlock->pos = glm::vec3(1); // set any value you want here to GLSL
glUnmapBuffer(GL_UNIFORM_BUFFER);// 第二个(binding = 1)
struct MatPool
{glm::mat4     viewMat;glm::mat4     worldMat;glm::mat4     modelMat
};glGenBuffers(1, &matBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, matBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(MatPool), NULL, GL_DYNAMIC_DRAW);// Careful: The parameter 1: is correspondant to binding = 1; not location.
// 1 是对应 GLSL中的bingding = 1; 不是location = 1
glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniforms_buffer);
MatPool* mBlock = (MatPool*)glMapBufferRange(GL_UNIFORM_BUFFER,0,sizeof(MatPool),GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
glm::mat4 modelMat = glm::mat(1);
glm::mat4 viewMat = glm::mat(1);
glm::mat4 worldMat = glm::mat(1);
mBlock->viewMat = viewMat;
mBlock->worldMat = worldMat;
mBlock->modelMat = modelMat;
glUnmapBuffer(GL_UNIFORM_BUFFER);

   第二个设置的时候,可以看到C++客户端的Struct结构和GLSL的结构体是不一样的,C++客户端是三个mat4的结构体,GLSL是一个结构体数组,我故意举这样的例子,是为了说明只要数据对应就行了,不一定要格式严格对应。

   GLSL中利用binding设置索引位置,可以使用多个Uniform block绑定到客户端使用,当然也可以使用下面函数取得这个索引位置,就可以不在GLSL中明显声明,即可以省略binding = 0;由GLSL自动分配索引位置。

GLuint glGetUniformBlockIndex( GLuint program, const char *uniformBlockName );

   还有其他各种用法,其实就没有那么实用了,这里就不贴出来,可以根据需要的时候,再进一步查阅。

六、赋值函数

   可以使用glUniform*这个函数来设置不同值类型的uniform,OpenGL的设计风格是使用不同类型的后缀变形函数来设置,参考All kinds of set up uniform value examples:

   GLAPI/glUniform - OpenGL Wiki
​www.khronos.org/opengl/wiki/GLAPI/glUniform
   这里摘录一些,摘录这些的原因是只要知道这些赋值方法,那么其他类值得赋值方法也能推演出来:

glUniform1i(loc, (int)value); // setup uniform one int value
void glUniform2f(GLint location, GLfloat v0, GLfloat v1);
void glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);

更多的函数形式

函数参数1参数2参数3参数4参数5
void glUniform1f( GLint location,GLfloat v0);
void glUniform2f( GLint location,GLfloat v0,GLfloat v1);
void glUniform3f( GLint location,GLfloat v0,GLfloat v1,GLfloat v2);
void glUniform4f( GLint location,GLfloat v0,GLfloat v1,GLfloat v2,GLfloat v3);
void glUniform1i( GLint location,GLint v0);
void glUniform2i( GLint location,GLint v0,GLint v1);
void glUniform3i( GLint location,GLint v0,GLint v1,GLint v2);
void glUniform4i( GLint location,GLint v0,GLint v1,GLint v2,GLint v3);
void glUniform1ui( GLint location,GLuint v0);
void glUniform2ui( GLint location,GLuint v0,GLuint v1);
void glUniform3ui( GLint location,GLuint v0,GLuint v1,GLuint v2);
void glUniform4ui( GLint location,GLuint v0,GLuint v1,GLuint v2,GLuint v3);
void glUniform1fv( GLint location,GLsizei count,const GLfloat *value);
void glUniform2fv( GLint location,GLsizei count,const GLfloat *value);
void glUniform3fv( GLint location,GLsizei count,const GLfloat *value);
void glUniform4fv( GLint location,GLsizei count,const GLfloat *value);
void glUniform1iv( GLint location,GLsizei count,const GLint *value);
void glUniform2iv( GLint location,GLsizei count,const GLint *value);
void glUniform3iv( GLint location,GLsizei count,const GLint *value);
void glUniform4iv( GLint location,GLsizei count,const GLint *value);
void glUniform1uiv( GLint location,GLsizei count,const GLuint *value);
void glUniform2uiv( GLint location,GLsizei count,const GLuint *value);
void glUniform3uiv( GLint location,GLsizei count,const GLuint *value);
void glUniform4uiv( GLint location,GLsizei count,const GLuint *value);
void glUniformMatrix2fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix3fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix4fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix2x3fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix3x2fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix2x4fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix4x2fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix3x4fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
void glUniformMatrix4x3fv( GLint location,GLsizei count,GLboolean transpose,const GLfloat *value);
  1. 参考:

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

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

相关文章

【嵌入式】字体极限瘦身术:Fontmin在嵌入式UI中的魔法应用(附3500常用汉字)

1. 概述 在嵌入式系统的用户界面(UI)设计中,字体的选择和优化至关重要。一个恰当的字体不仅能够提升用户体验,还能彰显产品特色。然而,由于嵌入式设备常常受限于存储空间和处理能力,大型字体文件可能成为性…

代码随想录算法训练营第五十五天丨583. 两个字符串的删除操作、72. 编辑距离

583. 两个字符串的删除操作 开窍了 class Solution:def minDistance(self, word1: str, word2: str) -> int:n1, n2 len(word1), len(word2)dp [[0] * (n2 1) for _ in range(n1 1)]for i in range(1, n1 1):dp[i][0] ifor j in range(1, n2 1):dp[0][j] jfor i i…

LeetCode的使用方法

LeetCode的使用方法 一、LeetCode是什么?1.LeetCode简介2.LeetCode官网 二、LeetCode的使用方法1.注册账号2.力扣社区力扣编辑器 2.1 讨论发起讨论参与讨论关注讨论 2.2 文章撰写文章关注文章 3.力扣面试官版测评面试招聘竞赛 4.力扣学习LeetBook 书架我的阅读猜您喜…

支付宝开放平台证书验签生成签名接入方式的操作流程之公钥证书,密钥证书的生成

#小李子9479# 调用支付宝接口的安全验证方式均使用sign_type为RSA2的方式,有两种 1。密钥模式:应用公钥、应用私钥、平台公钥生成签名和验签方式 2。证书模式:支付宝根证书、支付宝公钥证书、应用公钥证书、应用私钥,采用RSA20…

【2024.3.8练习】[2015 国 AC] 穿越雷区

题目描述 题目分析 最短步数问题&#xff0c;采用BFS算法即可。 我的代码 #include <iostream> #include <algorithm> #include <queue> #include <cmath> using namespace std; int n; int ans; int flag; const int max_n 102; char map[max_n][m…

Qt初识 - 编写Hello World的两种方式 | 对象树

目录 一、通过图形化方式&#xff0c;在界面上创建出一个控件 二、通过代码方式&#xff0c;创建Hello World 三、Qt 内存泄漏问题 (一) 对象树 一、通过图形化方式&#xff0c;在界面上创建出一个控件 创建项目后&#xff0c;打开双击forms文件夹中的ui文件&#xff0c;可…

【java基础】异常处理机制

目录 1、异常体系介绍 1.1、异常是什么? 1.2、运行时异常和编译时异常的区别? 2、异常的用法 2.1、捕获异常 2.2、异常中的常见方法 2.3、抛出异常 2.4、自定义异常 1、异常体系介绍 1.1、异常是什么? java异常是指在程序运行时可能出现的一些错误&#xff0c;如&am…

把flask 项目部署在windows上步骤

1.激活虚拟环境 # 激活到系统Python环境&#xff08;如果当前已经在venv中&#xff0c;需要先退出&#xff09; C:\xxx>deactivate # 删除现有的虚拟环境文件夹 C:\xxx>rmdir /s /q venv # 创建新的虚拟环境 C:\xxx>python -m venv venv # 激活新的虚拟环…

责任链模式(Chain of Responsibility Pattern)

责任链模式 说明 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;属于行为型模式&#xff0c;它是指使多个对象都有机会处理请求&#xff0c;将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。从而避免请求…

IntelliJ IDEA自定义关闭当前文件的快捷方式

前言 idea中关闭当前标签页的默认快捷键是CtrlF4,这个组合键在键盘上操作起来很是不方便&#xff0c;我们可以在设置中自定义自己习惯的快捷方式。 自定义步骤 要在 IntelliJ IDEA 中将关闭当前文件的快捷方式设置为 Alt Q&#xff0c;请按照以下步骤操作&#xff1a;打开 …

Vue+Element页面生成快照截图

页面部分: <template><div ref"homePage" class"home-container rel"><div class"snap-box abs"><div title"页面快照" class"z-pointer" click"newSnapShot()"><img :src"snap…

ES分布式搜索-索引库操作

索引库操作 1、mapping映射属性 可以查看官方文档学习&#xff1a;ES官方手册 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; type&#xff1a;字段数据类型&#xff0c;常见的简单类型有&#xff1a; 字符串&#xff1a;text&#xff08;可…

github Commits must have verified signatures

1.首先确认是否有权限&#xff0c;如有权限的情况下那就是配置有问题了 我的情况是&#xff0c;能拉取代码&#xff0c;提交的时候出现这种情况&#xff1a;Commits must have verified signatures 这里是生成证书&#xff0c;如果已经生成过的&#xff0c;就不用生成了 ssh…

ARM/Linux嵌入式面经(一):海康威视

海康威视 1.函数指针和指针函数区别 1.定义的差异 函数指针&#xff1a;函数指针的定义涉及到函数的地址。例如&#xff0c;定义一个指向函数的指针 int (*fp)(int)&#xff0c;这里 fp 是一个指针&#xff0c;它指向一个接受一个整数参数并返回整数的函数。 指针函数&#…

99 centos 7 服务器上面 增加了 2181 的防火墙配置, 但是客户端连接不上

呵呵 最近部署 zookeeper 的时候出现这样的一个问题 centos 7 服务器上面 增加了 2181 的防火墙配置, 但是客户端连接不上 # 但是再 另外的一个虚拟机环境, ubuntu 16 的环境, docker 启动 2181 的服务, 然后 安装 firewalld, 配置 开放 2181 的 tcp 服务, 客户端能够正常连接…

《C缺陷和陷阱》-笔记(2)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、理解函数声明 1.(*(void(*)( ))0)( ); 2.signal 函数接受两个参数&#xff1a; 3.使用typedef 简化函数声明&#xff1a; 二、运算符的优先级…

代码随想录刷题第54天

倒计时day6。第一题是判断子序列https://leetcode.cn/problems/is-subsequence/description/&#xff0c;动规五步曲分析如下&#xff1a;dp[i][j]表示以下标为i - 1的字符串1与下标为j - 1的字符串2的相同子序列长度。当发现str1[i - 1] str2[j - 1]时&#xff0c;相同子序列…

【项目】Boost 搜索引擎

文章目录 1.背景2.宏观原理3.相关技术与开发环境4. 实现原理1.下载2.加载与解析文件2.1获取指定目录下的所有网页文件2.2. 获取网页文件中的关键信息2.3. 对读取文件进行保存 3.索引3.1正排与倒排3.2获取正排和倒排索引3.3建立索引3.3.1正排索引3.3.2倒排索引 4.搜索4.1 初始化…

UNIAPP微信小程序中使用Base64编解码原理分析和算法实现

为何要加上UNIAPP及微信小程序&#xff0c;可能是想让检索的翻围更广把。&#x1f607; Base64的JS原生编解码在uni的JS引擎中并不能直接使用&#xff0c;因此需要手写一个原生的Base64编解码器。正好项目中遇到此问题&#xff0c;需要通过URLLink进行小程序跳转并携带Base64参…

Linux第73步_学习Linux设备树和“OF函数”

掌握设备树是 Linux驱动开发人员必备的技能&#xff01; 1、了解设备树文件 在3.x版本以前的Linux内核源码中&#xff0c;存在大量的“arc/arm/mach-xxx”和“arc/arm/plat-xxx”文件夹&#xff0c;里面很多个“.c”和“.h”文件&#xff0c;它们用来描述设备信息。而现在的A…