Uniform块

当着色器程序变复杂时,用到的uniform变量数量也会上升。通常会在多个着色器程序中用到同一个uniform变量。由于uniform变量的位置是着色器链接的时候产生的(也就是glLinkProgram()的时候),因此它在应用程序中获得的索引可能会有变化,即使我们给uniform变量设置的值可能是完全相同的。而uniform缓存对象就是一种优化uniform变量访问,以及在不同的着色器程序之间共享uniform数据的方法。

访问一组uniform变量的方法是使用诸如glMapBuffer()的openGL函数,但是我们需要在着色器中对它们的声明方式略作修改。不再分别声明方式略作修改。不再分别声明每个uniform变量,而是直接将它们成组,形成一个类似架构提体的形式,也就是uniform块。一个uniform块要使用关键字uniform指定。然后及那个块中所有需要用到的变量包含在一堆花括号中。

例如:

uniform Matrices{
mat4 ModelView;
mat4 Projection;
mat4 Color;
};

着色器中的数据类型有两种:不透明的和透明的;其中不透明类型包括采样器、图像和原子计数器。一个uniform块中只可以包含透明类型的变量。此外,uniform块变量必须在全局作用域内声明。

uniform块中可以使用不同的限制符来设置变量的布局方式,这些限制符可以用来设置单个的uniform块,也可以用来设置所有后继uniform块的排列方式(需要使用布局声明)

uniform的布局限制符
布局限制符 描述
shared 设置uniform块是多个程序间共享的(这是默认的布局方式,与shared存储符不存在混淆)
packed 设置uniform共占用最小的内存空间,但是这样会禁止程序间共享这个块
std140 使用标准布局方式来设置uniform块或者着色器存储的buffer块
std430 使用标准布局方式来设置buffer块
row_major 使用行主序的方式来存储uniform块中的矩阵
column_major 使用列主序的方式来存储unifrom块中的矩阵

例如:如果需要共享一个uniform块,并且使用行主序的方式来存储数据,那么可以使用

layout(shared,row_major)uniform{...}

多个限制符可以通过圆括号中的逗号隔开。如果需要对所有后继的uniform块设置同一种布局,那么可以使用:

layout(packed,column_major)uniform;

注意:uniform块的名称并不能作为uniform变量的夫名称,因此在两个不同名称的uniform块中声明的同名变量会在编译时造成错误。

从应用程序中访问uniform块

uniform变量是着色器与应用程序之间共享数据的桥梁,因此如果着色器中的uniform变量是定义在命名uniform块中,那么就有必要找到不同变量的偏移值。如果获得了这个变量的具体位置,那么就可以使用数据对它们进行初始化,这一过程与处理缓存对象(使用glBufferData()等函数)是一致的。

假设应用程序的着色器中uniform块的名字已知。若要对uniform块中的uniform变量进行初始化,第一步就是找到块在着色器程序中的索引位置。可以使用glGenUniformBlockIndex()函数返回对应的信息,然后再应用程序的地质空间里完成uniform变量的映射。

GLuint glGetUnifromBlockIndex(GLuint progarm,const char* uniformBlockName);

返回program中名称为uniformBlockName的uniform块的索引值。如果uniformBlockName不是一个合法的uniform程序块,那么返回GL_INVALID_INDEX。

如果要初始化uniform块对应 的缓存对象,那么我们需要使用glBindBuffer()将缓存对象绑定到目标GL_UNIFORM_BUFFER之上。

当缓存对象进行初始化之后,需要判断命名的uniform块中的变量总供占据了多大的空间。可以使用glGetActiveUniformBlock()并且设置参数为GL_UNIFORM_BLOCK_DATA_SIZE,这样就可以返回编辑器分配的块的大小。GLActiveUniformBlockiv()函数还可以用来获取一个命名的uniform块的其他一些一些相关参数。

在获取unifrm块的索引之后,我们需要将一个缓存对象与这个块相关联。最常见的方法是调用glBindBufferRange(),或者如果uniform块是全部使用缓存来存储,那么可以使用glBindBufferBase()。

void glBindBufferRange(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size);
void glBindBufferBase(GLenum target,GLuint index,GLuint buffer);

将缓存对象buffer与索引为index的命名uniform块关联起来。target可以是GL_UNIFORM_BUFFER(对于uniform块)或者GL_TRANSFORM_FEEDBACK_BUFFER用于transform feedback)。index是uniform块的索引。offset和size分别指定了uniform缓存映射的起始索引和大小。

调用glBindBufferBase()等价于调用glBindBufferRange()并设置offset为0,size为缓存对象的大小。

在下列情况下调用这两个函数可能会产生OpenGL错误GL_INVALID_VALUE:size小于0;offset+size大于缓存大小;offset或size不是4的倍数;index小于0或者大于等于GL_UNIFORM_BUFFER_BINDINGS的返回值。

当建立了命名uniform块和缓存对象之间的关联之后,只要使用缓存相关的命令即可对数据块进行初始化或者修改。

如果多个着色器程序需要共享同一个uniform块,为了避免对于不同的着色器程序同一块有不同的索引号,可以直接设置某个命名uniform块和缓存对象之间的绑定关系。如果需要显式地控制一个uniform块的绑定方式,可以在调用glLinkProgram()之前调用glUniformBlockBinding()函数。

GLuint glUniformBlockBinding(GLuint program,GLuint uniformBlockIndex,GLuint uniformBlockBinding);

显式地将块uniformBlockIndex绑定到uniformBlockBinding.

在一个命名为uniform块中,uniform变量的布局是通过各种布局限制符在编译和链接时控制的。如果使用了默认的布局方式,那么需要判断每个变量在uniform块中的偏移量和数据存储大小。glGetUniformIndices()负责获取指定名称uniform变量的索引位置。

void glGetUniformIndices(GLuint program,Glsizei uniformCount,const char** uniformNames,GLuint* uniformIndices);

返回所有uniformCount个变量的索引位置,变量的名称通过字符串数组uniformNames来指定。

GLSL中Uniform块相关推荐

  1. opengl之高级GLSL(2)-接口块,Uniform缓冲对象,Uniform块布局等

    接口块 当程序变得更大时,你希望发送的可能就不只是几个变量了,它还可能包括数组和结构体. 为了帮助我们管理这些变量,GLSL为我们提供了一个叫做接口块(Interface Block)的东西,来方便我 ...

  2. Modern OpenGL - GLSL着色语言2:GLSL入口函数和GLSL中的变量

    文章目录 1 GLSL的入口函数和基本结构 2 GLSL中的变量声明 3 GLSL中变量的作用域 4 GLSL中变量的初始化 5 GLSL中变量的隐式转换 1 GLSL的入口函数和基本结构 对于很多编 ...

  3. 你真的懂switch吗?聊聊switch语句中的块级作用域

      最近在代码中不小心不规范的,在switch里面定义了块级变量,导致页面在某些浏览器中出错,本文讨论以下switch语句中的块级作用域. switch语句中的块级作用域 switch语句中的块级作用 ...

  4. ARC中block块作为属性的使用笔记

    ARC中block块作为属性的使用笔记 block较难理解,根据在内存中的分布情况就分为3种类型,根据使用的情形又分为很多很多种.虽然用起来容易,但使用不当会造成内存泄露,虽然都是这么说,但你真的研究 ...

  5. 浅析ios开发中Block块语法的妙用

    事实上,任何一个应用的开发都离不开多线程.而"块"block与GCD就是苹果OC语言中多线程的核心.      一.块的内部结构      在oc中,块语法以闭包的形式存在,每一个 ...

  6. Spring Batch中的块处理

    大数据集的处理是软件世界中最重要的问题之一. Spring Batch是一个轻量级且强大的批处理框架,用于处理数据集. Spring Batch Framework提供了"面向Tasklet ...

  7. CSS中的块元素,内联元素,内联块元素

    块元素,内联元素,内联块元素 元素就是标签,布局中常用的有三种标签,块元素.内联元素.内联块元素,了解这三种元素的特性,才能熟练的进行页面布局. 块元素 块元素,也可以称为行元素,布局中常用的标签如: ...

  8. Java 初始化 代码块_Java中初始化块详解及实例代码

    Java中初始化块详解 在Java中,有两种初始化块:静态初始化块和非静态初始化块. 静态初始化块:使用static定义,当类装载到系统时执行一次.若在静态初始化块中想初始化变量,那仅能初始化类变量, ...

  9. sdk版本过低怎么办_区块链中的“块”是什么?区块链网络拥堵怎么办?-Gemini双子新约...

    区块链中的"块"是什么? 比特币是基于区块链的,这一点大家都知道.但是这个区块链是什么呢?更准确地说,区块链的各个组成部分是什么呢? 区块链是一个数据块.每个块可以看作是分类帐中的 ...

最新文章

  1. TensorFlow之图结构与TensorBoard可视化
  2. SpringBoot下的模板技术Thymeleaf详解
  3. HTTP 错误 404.2 - Not Found 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面...
  4. 彻底删除 XP 自带的 Windows Messenger方法
  5. 三维向量变化为角度_物体的三维识别与6D位姿估计:PPF系列论文介绍(四)
  6. Python_多项式拟合
  7. 2048源码 linux,分享|2 的威力,Linux 的威力:终端中的 2048
  8. 拓端tecdat|用R语言模拟随机服务排队系统
  9. imageio.write页面怎么显示_微信吃喝玩乐怎么没有了?微信支付页面吃喝玩乐在哪里...
  10. Tableau系列软件概况
  11. 微信红包服务器卡死,东大跨年红包记--并发案例分析
  12. Java AQS的实现原理(大部分同步类都依赖AQS实现)
  13. 基于MATLAB对低照度图像进行直方图均衡化和同态滤波操作
  14. HTML 基础教程:HTML 编辑器
  15. SIP注册信令消息示范及解释
  16. win7锁定计算机快捷键6,win7锁定计算机快捷键_win10 锁定计算机
  17. hibernate mysql 时间比较_Hibernate中HQL函数汇总及获取当前时间进行比较举例
  18. 电磁信号检波方案:是否多此一举?
  19. c 语言英文参考文献,Humanized c-Myc Mouse 英文参考文献.doc
  20. 自适应 CSS 栅格布局

热门文章

  1. 2013年春晚刘谦李云迪魔术魔琴解密
  2. linuxdeployqt-linux下Qt打包工具
  3. NNDL 作业5:卷积
  4. 【高德地图API】从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自有数据检索
  5. 计算机电源原如何确定正常,电脑电源故障迅速准确判断方法
  6. SPT20 协议_夫妻财产分割协议书范本包括哪些内容?
  7. ubuntu安装pycuda软件
  8. 在html中有两种类型的标签 它们分别是,VB习题及题解答.doc
  9. 3,xilinx 7系列FPGA理论篇——7系列FPGA简介
  10. 迭代器与生成器原理及关系