为了满足我们Uniform缓冲的需要,我们使用的Uniform块通常都为std140布局,这就需要我们手动去计算每个变量的偏移量,这里便涉及到字节对齐的概念。
字节对齐最经典的案例就是C/C++中结构体的使用。例如。结构体
struct MyByteStruct{
char c;
float a;
int b;
};
/*按照正常理解为 4+4+1=9*/
/*此处使用了字节对齐,使机器访问更快,真是为4+4+4=12 */
按照我们通常的思维,此结构体所占的字节的 4(float)+4(int)+1(char)=9,但是事实并非如此,真实的所占的字节为4(float)+4(int)+4(char)=12。为什么会这样?
该结构体的内存布局如下所示:
字节对齐重要的一个原因就是为了使机器访问的更加快速,例如在32字长的地址的机器中,每次读取4个字节数据,所以将字节对齐到上述地址 0x0000,0x0004和0x0008, 0x000C将使读取更加迅速。如果没有第一个padding,那么上面结构体中的int i将跨越两个字长(0x0000和0x0004),需要两次读取操作,影响效率。
上文介绍std140布局时已经提到每个变量的偏移都是基于一系列的规则而决定的,OpenGL中的Uniform缓冲的规范为,GLSL中的每个变量,比如说int、float和bool,都被定义为4字节量。每4个字节将会用一个N来表示。:
以上文的结构体为例,对当前的对齐偏移量进行计算得到如图的结果,第一幅图为LearnOpenGL中的相关教程,第二幅图为我自己绘制的,都可进行参考。
首先如何才能让OpenGL ES知道哪个Uniform缓冲对应的是哪个Uniform块呢?这里使用的便是绑定点的知识(Binding),可以参考LearnOpenGL中的教程,如下。
![]()
可以看出,每一个Uniform缓冲对象都是绑定到对应的绑定点的,不同的着色器在使用对应的Uniform缓冲时,只需对应到相应Uniform缓冲的绑定点即可。
我完成了一个非常简单的基于OpenGL ES 3.0的一个Uniform缓冲的案例,案例中有两套着色器,一套用于绘制红色三角形,一套用于绘制绿色三角形 。
首先给出案例中绘制红色三角形顶点着色器的代码。结构体
#version 300 es
uniform mat4 Modelview;//总变换矩阵
in vec3 Position;//顶点位置
out ve vColor1;//输出到片元着色器的颜色
layout (std140) uniform myColor{//输入的Uniform缓冲
ve color1;
ve color2;
};
void main(){
gl_Position = Modelview * ve(Position,1);//根据总变换矩阵计算此次绘制此顶点位置
vColor1=color1;
}
着色器中的两个颜色变量color1和color2均来自于Uniform缓冲,在母体语言(C++)中我只传入了一次颜色值,同时可以在两套着色器中使用,这完全符合Uniform缓冲的使用规则。接着详细介绍如何分配一个Uniform缓冲。
首先通过以下代码分配一个内容字节大小为32 byte的Uniform缓冲,并将缓冲绑定到绑定点0。
void MyGLThread::iniUniformBuffer(){
glGenBuffers(1, &uboExampleBlock);
glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock);
glBufferData(GL_UNIFORM_BUFFER, 32, NULL, GL_STATIC_DRAW); // 分配32字节的内存
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-61852-2.html
你牛
明白
实在不行拍拍屈股跑路
一省养一艘航母算啥