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

举报
天元浪子 发表于 2021/11/25 15:56:12 2021/11/25
【摘要】 在OpenGL的渲染管线上,顶点数据不是批量处理的,而是一个顶点一个顶点逐一处理的。也就是说,顶点着色器程序每次只处理一个顶点。同样的,后续的着色器也是逐面片、逐图元、逐片元处理的。

1 存储限定符

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

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

对于一个模型的一次渲染,在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)数据块的布局,这需要另外几个布局限定符,见下表。

布局限定符 说明
shared 多程序共享uniform数据块(默认布局方式)
packed uniform数据块占用最小内存空间,同时禁止多程序共享
std140 使用标准布局方式设置uniform数据块和buffer块
std430 使用标准布局方式设置buffer块
row_major 以行主序方式存储uniform数据块中的矩阵
column_major 以列主序方式存储uniform数据块中的矩阵

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

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

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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。