uniform代表opengl中用到的全局数据,是客户端向opengl传送数据的重要方式,该类数据不属于某个具体的shader。每一个uniform数据都属于一个uniform block,而uniform block分为两类,第一类是default block,第二类是uniform block,第一类block是每个program对象默认分配的,每一个program对象都有唯一的default block,通过glUseProgram切换程序对象时,对应的default block也会相应变化。第二类uniform block则可以在各个程序间共享,不随着program对象的变化而变化,下面就介绍下两种block对象及其使用。

Default Block及其使用

首先介绍default block,其变量定义在shader中,通过客户端赋值,shader程序不能对uniform变了赋值,shader中的定义如下:

uniform float fTime;

uniform vec4 testColor;

如上定义,uniform变量的定义只需在一般变量定义的最前面加上uniform关键字即可,这些变量都会分配在default block中,default block中的每个uniform变量都有一个唯一的位置用于标识,shader程序不需要显示指定其位置,系统会自动为变量分配位置,如果有需要,使用者也可以显示指定位置,方法如下

layout (location = 15) uniform vec4 myUniform

对于系统自动分配的uniform变量,可以使用如下方法查询其位置,如下:

GLint glGetUniformLocation(GLuint program,const GLchar * name)

例如上面定义的变量,可通过GLint  location = glGetuniformLocation(myProgram,"myUniform")查询其位置,返回值location为15。

接下来,需要为我们定义的uniform变量赋值,注意,shader程序不允许直接赋值,但可以在定义的时候赋予一个初始值,要想改变变量的值,需要通过glUniform*函数族,这类函数都需要知道uniform变量的位置,根据uniform数据类型的不同,函数名称也不同,一些常用的类型和使用方法如下

glUniform1f(0,45.2f) glUniform1i(1,42)  glUniform4f(2,1.0f,1.0f,1.0f,1.0f)  glUniform1i(3,GL_FALSE)

需要注意的是,bool型uniform变量和int型变量的赋值方法一样。上面各方法都是直接在参数中指定uniform变量需要的值,一来参数较多书写不方便,二来如果uniform变量是一个数组,参数无法指定,所以opengl又提供了以向量为参数的函数族,与上面的函数族相比,每一个函数后面都有一个“v”作为标识,如下:

GLfloat vColors[4][2] = {{1.0f,1.0f,1.0f,1.0f},{1.0f,0.0f,1.0f,1.0f}};

glUniform4fv(iColorLocation,2,vColors);  //中间的参数代表数组元素个数

Uniform Block及其使用

接下来介绍uniform block,这种类型的block适合保存一些不随程序变化的数据,比如变换矩阵等等,定义如下

uniform TransformBlock

{

float scale;

vec3 translation;

mat4 projection_matrix;

}transform;

如上所示,定义和之前介绍的interface block非常相似,唯一的区别是关键字由in或out换成了uniform,TransformBlock是uniform block的名字,transform是实例名称,有点类似c++中的类和对象的关系。每一个uniform block都有一个唯一的block index,block中的每一个成员变量都有一个唯一的index,这个index是跨block的,也就是说,系统是把所有的uniform block中的所有成员变量统一布局和划分index,通过idnex可以查询成员变量的大小,位置,类型,名字等各种详细信息。

uniform block都是用户自定义的结构体,opengl没有函数可以直接进行赋值,唯一的方法是绑定一个自定义的vbo对象,用户自己按照uniform block的实际布局在vbo对象中相应的位置对各个分量进行赋值,shader则直接从vbo对象中获得正确的值。这就涉及到结构体的布局问题,也就是常说的aligment对其方式,常用的有standard layout和share layout两种布局方法。stdlayout是一种约定好的标准,只要按照这个标准进行声明,在对应的vbo对象中也按照这个标准进行布局和赋值即可。share layout是在满足standard layout 的基础上,用户可以显示指定更为详细的布局方法。

标准布局的声明如下:

layout (std140) uniform TransformBlock

{

float scale;

... ...//

}

std140的具体规则是:

1 float bool int等基本类型必须放在4N的地址 ,如0,4,8等

2 vec2,ivec2,dvec2等两维向量必须放在8N的地址,如0,8,16等,vec3,vec4等高阶向量必须放在16N的地址

3 数组中的每一个成员变量都必须放在16N的地址,矩阵或者矩阵数组都可以认为是由相应列向量组成的数组

4 结构体成员变量必须放在16N 的地址

举个简单的例子,如下

share layout 的定义如下,在std140基础上,可以在成员变量定义前面通过offset修饰符指定具体位置,align代表每一个成员变量都必须满足的对其倍数,这两个值共同决定成员变量最后的位置。

前面提到,每一个uniform block的成员变量都有一个全局index,获取index方法如下:

void glGetUniformIndices(GUuint program,GLsizei uniformCount, const GLchar ** uniformNmaes,GUuint *uniformIndices);

使用方法如下:

static const GLchar * uniformNames[2] =

{

"TransformBlock.scale",

"TransformBlock.translation"

}

GLuint uniformIndices[2];

glGetUniformIndices(programe,2,uniformNames,uniformIndices);

有了成员变量的index,我们可以通过void glGetActiveUniformsiv(GUuint program, GLsizei uniformCount,const GUuint *uniformIndices, Glenum pname,GLint *params)来查询成员变量的详细信息,比较重要的是pname参数,这个参数代表要查询的属性,可取值范围如下:

GL_UNIFORM_TYPE //数据类型

GL_UNIFORM_SIZE  //数组长度,非数组类型返回1

GL_UNIFORM_NAME_LENGTH//名字长度

GL_UNIFORM_BLOCK_INDEX //block index

GL_UNIFORM_OFFSET //成员变量在uniform block中的偏移量

GL_UNIFORM_ARRAY_STRIDE //数组中两个连续成员的偏移量,非数组成员返回0

GL_UNIFORM_MATRIX_STRIDE //连续两个行向量或列向量的偏移量,非矩阵成员变量返回0

GL_UNIFORM_IS_ROW_MAJOR //矩阵成员变量并且是行向量形式存储则返回1,其他返回0

该函数对于shader源码不可见的情况有较大用处,在对uniform block进行赋值的时候,通过查询可得知其内部布局,从而对vbo对象进行赋值操作,然后将vbo对象和uniform block进行绑定即可完成赋值操作,绑定相关方法如下:

1 通过GLuint glGetUniformBlockIndex(GUuint program ,const GLchar *uniformBlockName)获取block index;

2 通过void glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex,Gluint uniformBlockBinding)绑定block和uniform buffer的binding point

3 通过glBindBufferBase(GL_UNIFORM_BUFFER,index,buffer)将特定buffer 绑定在unifrom buffer对应的binding point

以上步骤即可完成对unifromBlock的赋值操作,但有一种更为简单的绑定方法,即在shader中指定绑定即可,如下:

layout (std140,binding = 2)uniform TransformBlock

{

....

} transfrom;

以上就是uniform block的基本使用方法,希望对大家有所帮助。

uniform对象及其使用相关推荐

  1. OpenGL基础40:Uniform缓冲

    前置:OpenGL基础39:GLSL内建变量与接口块 想想之前代码,glUniform()和glGetUniformLocation()的使用数量是不是过于频繁了,对于每个着色器的每一个uniform ...

  2. python中uniform函数_python scipy stats.uniform用法及代码示例

    均匀连续随机变量. 在标准形式下,分布均匀[0, 1].使用参数loc和scale,在上获得均匀分布[loc, loc + scale]. 作为一个实例rv_continuous类,uniform对象 ...

  3. osgEarth目标选择

    osgEarth目标拾取 本文展示了一种目标选择的方法.通过将osg::Node注册到osgEarth的对象管理器中,利用osgEarth的RTTPicker类以及重写的RTTPicker::Call ...

  4. 06-初始OpenGL ES -用GLSL实现画板的功能

    效果图 准备资料 1.下载案例中需要用的资源,地址:https://download.csdn.net/download/lyz0925/12351912: 2.将所需要的资源拖入项目中.如下图: 代 ...

  5. 使用three.js渲染瓦片地球-第一篇

    近期有个需求是想使用自己的3d引擎去渲染地球逻辑,如果从头实现一遍会比较耗费时间,而且后续还要实现倾斜摄影等等,所以打算使用cesium来帮我们做调度然后用自己的3d引擎渲染. 在github上找到了 ...

  6. 概率统计Python计算:总体未知参数的矩估计

    设样本(X1,X2,⋯,Xn)(X_1,X_2,\cdots,X_n)(X1​,X2​,⋯,Xn​)来自XXX,XXX的分布中含有mmm个未知参数θ1,θ2,⋯,θm\theta_1,\theta_2 ...

  7. java_B站_面试题

    Java面向对象有哪些特征,如何应用 ​ 面向对象编程是利用类和对象编程的一种思想.万物可归类,类是对于世界事物的高度抽象 ,不同的事物之间有不同的关系 ,一个类自身与外界的封装关系,一个父类和子类的 ...

  8. 史上最详细的23中设计模式解析,一个不落,理论搭配简单案例,更好理解哦

    目录 一.软件设计模式的产生背景 二.软件设计模式的概念与意义 1. 软件设计模式的概念 2. 学习设计模式的意义 三.23 种设计模式的分类和功能 1. 根据目的来分 2. 根据作用范围来分 3. ...

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

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

最新文章

  1. js base64 解码
  2. 13 种在 Linux 系统上检测 CPU 信息的工具
  3. 编程是一种对你的身体健康十分有害的工作
  4. python简单代码运行_python代码如何运行
  5. tf.clip_by_value
  6. haskell,lisp,erlang你们更喜欢哪个?
  7. Linux例行工作crontab
  8. linux 远程 i o 错误,故意在Linux中导致I / O错误?
  9. RT-Thread uart串口设备驱动代码结构剖析
  10. Tensorflow 2.1 迁移学习 基于VGG
  11. AWS 人工智能黑客马拉松正式开启!用实力演绎科技向善!
  12. MS SQL SERVER 读取数据库中每个表的描述/注释以及表中字段/列的字段名,字段类型,字段描述/注释/说明等信息...
  13. 【JY】No.7.2力学架构迈达斯使用教程
  14. 车架号校验 php代码,VIN车辆识别代码查询(精准版)
  15. HTML和CSS (前端)
  16. java求亲密数,怎么写更好更快?
  17. Window 7和 server 2003系统下载
  18. 【新番尝鲜】续 夏目友人帐——再续祖传的本子
  19. CHIL-SQL-NULL 函数
  20. 中国服装行业柔性供应链

热门文章

  1. 学编程和乐高机器人的区别
  2. 微信小程序爱江山更爱美人忘记服务器,爱江山更爱美人微信小程序
  3. [数据讨论][解包相关]下江小春也能轻松掌握的碧蓝档案提取工具
  4. 定时器0 定时器2波特率发生器 AD转换
  5. security基于数据库的认证
  6. hbuilderx代码自动补全_HBuilderX代码提示系统说明
  7. C++中的 RTTI
  8. C++保存中间结果到文件
  9. 2021年制冷与空调设备运行操作考试总结及制冷与空调设备运行操作实操考试视频
  10. 不用电线使灯泡 特斯拉_特斯拉方式如何使其领先