GLSL存储限定符和布局限定符

网友投稿 1031 2022-05-29

1 存储限定符

在OpenGL的渲染管线上,顶点数据不是批量处理的,而是一个顶点一个顶点逐一处理的。也就是说,顶点着色器程序每次只处理一个顶点。同样的,后续的着色器也是逐面片、逐图元、逐片元处理的。

假如一个模型有1万个顶点,则顶点着色器程序需要运行1万次,每次输入的顶点数据(包括法向量、纹理坐标等)是各不相同的。但是也有在这1万运行中保持不变的数据,比如在该模型的此次渲染期间,投影矩阵、视点矩阵不会改变,大多数情况下,灯光参数也不会改变。

GLSL的存储限定符和布局限定符

对于一个模型的一次渲染,在GLSL140版本之前,将顶点着色器程序每次运行时都会改变的数据称之为attribute,将每次运行保持不变的数据称之为uniform,将着色器之间顺序传递的数据称之为varying——这就是所谓的存储限定符。

我们可以向着色器程序传入attribute类型的数据和uniform类型的数据,但不能传入varying类型的数据。下图描述了attribute、uniform和varying的作用和用法。

也许是为了强化渲染管线数据的数据输入输出概念,自GLSL140版本开始,存储限定符attribute和varying不再被推荐使用,取而代之的是in和out。显然,in和out与attribute和varying并不是一一对应的关系。

除了一直不变的uniform,以及后来增补的in和out之外,还有一个存储限定符const,用来向着色器传递只读变量。

2 布局限定符

从GLSL330版本开始,GLSL增加了一个新的概念:布局管理。布局管理使用一个新的限定符layout,用来设置着色器输入/输出变量接口布局。下面的例子使用layout为in变量设置了接口位置,可以在渲染时直接使用这些接口而无需通过访问着色器程序获取它们。

#version 330 core layout(location=0) in vec4 a_Position; layout(location=1) in vec4 a_Normal; layout(location=3) in vec4 a_TexCoord;

如果变量是一个数组,则数组的每一个元素都会占据一个location的编号位置。下面的代码中,u_Matrix是一个长度为3的数组,所以它将占据5、6、7三个位置。

layout(location=5) uniform mat4 u_Matrix[3];

对于out变量,layout同样有效,且location的编号独立于in变量。

layout(location=0) out v_color; layout(location=1) out v_TexCoord;

限定符layout的另一个用途是控制UBO(Uniform Buffer Object)数据块的布局,这需要另外几个布局限定符,见下表。

下面的代码,共享了一个uniform数据块,以行主序方式存储数据,多个限定符之间以逗号分隔。

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

需要特别说明的是,尽管在声明uniform数据块时已经提供了数据块的名字,但不能将数据块名视为uniform变量的父名称。这意味着不同的uniform数据块中如果存在相同的uniform变量名,就会造成编译错误。

OpenGL 渲染

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《MXNet深度学习实战》—1.4 MXNet开发需要具备的知识
下一篇:【OBS对象存储服务】桶内对象数量减少或是突然无法找到处理流程
相关文章