
写在前面:最近在使用GLSL编程,还未掌握Uniform缓冲对象的相关知识,感觉处处碰壁,在这里对Uniform缓冲对象相关知识进行总结,同时本节案例是基于OpenGL ES 3.0实现的,案例程序均可在我github上下载。https://github.com/ModestBean/MySample如果大家发现错误以及不合理之处,还希望多多指出,我会虚心接受每一个建议。
本篇内容参考来自:
LearnOpenGL CN——高级GLSL一章
The fool的博客
感谢The fool的文章,他的文章中的部分内容非常有助于理解Uniform缓冲对象,我在此将两篇文章的重要内容进行了合并。
在没有掌握Uniform缓冲对象时,已经可以开发出很多高级特效了,但同时也遇到了一些繁琐的事情。比如说,当在一个项目(Project)中出现多个着色器,每一个着色器中大部分的Uniform变量都是相同的,例如:摄像机位置、光源位置此类所有物体都共同的属性等,每一次都需要我们重复的去设置它们,这便是一件繁琐的事情。在大型游戏中,多则上百个着色器,以前者的方式是很容易带来问题的。
OpenGL给我们提供了Uniform缓冲对象,该对象允许我们在多个着色器中定义全局的Uniform变量,在多个着色器中使用摄像机位置、光源位置时,不必多次重复设置,只需设置一次即可。这样做并不代表我们可以不用在着色器中定义Uniform变量了,这样只不过减少了宿主语言(C++、Java)的工作量。
Uniform块的内容是存储在缓冲对象中的,它实际上只是一块预留的内存,这块内存并不知道它具体保存的是什么类型的数据,我们还需要告诉OpenGL内存中哪一部分对应哪一个Uniform变量。
假设着色器有以下的Uniform块:
layout (std140) uniform ExampleBlock{
float value;
vec3 vector;
mat4 matrix;
float values[3];
bool boolean;
int integer;
};
这里的std140就代表着一种Uniform块的布局,Uniform块的布局常见的有如下三种。
shared(共享布局):默认情况下,GLSL都会使用这个布局,共享一但硬件定义了偏移量,它们在整个程序中都是共享的,使用shared布局时,允许GLSL对Uniform块中的变量的存储位置进行变动,共享布局可以节省很多空间的优化。
std140布局:std140布局中确定每个变量的偏移都是基于一系列的规则而决定的,这显示的声明了每个变量类型的内存布局,需要我们手动去计算每个变量的偏移量。
packed(紧凑布局):是不能保证这个布局在每个程序中保持不变的(即非共享),因为它允许编译器去将uniform变量从Uniform块中优化掉,这在每个着色器中都可能是不同的,所以这种布局是无法共享的,不满足Uniform Buffer的使用需求。

在使用Uniform缓冲时我们需要知道每个变量的字节和偏移量,每一个变量的大小都是确定的,我们在学习任何一门语言的初始都会学习变量的大小(字节),例如int类型的变量所占字节为4 Byte。但是Uniform块中变量的间距是无法确定的,这就允许硬件能够将变量放置在合适的位置,例如,一些硬件可能会将一个向量a放在float b之后,其他的硬件可能会将向量a放在float b之前。这个特性虽然合理的安排了变量的存储,但是却给我们使用Uniform缓冲带来了麻烦,因为有了这个特性,我们就无法知道整个Uniform块所占的字节,在初始分配Uniform缓冲时也无法合理的进行分配。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-61852-1.html
飞机偏离航道会不知道
获得更好的发展