OpenGL学习脚印: uniform blocks在着色器中的使用

写在前面
目前,我们在着色器中要传递多个uniform变量时,总是使用多个uniform,然后在主程序中设置这些变量的值;同时如果要在多个shader之间共享变量,例如投影矩阵projection和视变换矩阵view的话,仍然需要为不同shader分别设置这些uniform变量。本节将为大家介绍interface block,以及基于此的uniform buffer object(UBO),这些技术将简化着色器中变量的传递和共享问题。本节示例程序均可以从我的github下载

本节内容参考自:
1.www.learningopengl.com Advanced GLSL
2.GLSL Tutorial – Uniform Blocks
3.《OpenGL 4.0 Shading Language Cookbook》-Using Uniform Blocks and Uniform Buffer Objects

interface block

interfac block是一组GLSL着色器里面的输入、输出、uniform等变量的集合,有一些类似于C语言中的struct,但是不像struct那样简单明了,还有一些其他的选项包含在里面。通过使用interface block,我们可以将着色器中的变量以组的形式来管理,这样书写更整洁。

interface block的声明形式为:

storage_qualifier block_name
{
  <define members here>
} instance_name;

其中storage_qualifier指明这个block的存储限定符,限定符可以使用in​, out​, uniform​, 或者buffer​(GLSL4.3支持)等,block_name则给定名称,而instance_name给定实例名称。

例如,我们之前在实现点光源的过程中,顶点着色器和片元着色器之间需要传递法向量、纹理坐标等变量,将他们封装到一个block中,代码显得更紧凑。顶点着色器中输出变量定义形式如下:

// 定义输出interface block
out VS_OUT
{
    vec3 FragPos;
    vec2 TextCoord;
    vec3 FragNormal;
}vs_out;

而在片元着色器中,要以相同的block_name接受,实例名称则可以不同,形式可以定义为:

// 定义输入interface block
in VS_OUT
{
    vec3 FragPos;
    vec2 TextCoord;
    vec3 FragNormal;
}fs_in;

如果指定了instance_name,则在片元着色器中引用这些变量时需要加上instance_name前缀,例如:

   // 环境光成分
    vec3    ambient = light.ambient * vec3(texture(material.diffuseMap, fs_in.TextCoord));

反之如果没有指定instance_name,则这个block中的变量将和uniform一样是全局的,可以直接使用。如果没有给定instance_name,则需要注意,interface block中给定的变量名不要和uniform给定的重复,否则造成重定义错误,例如下面的定义将造成重定义错误:

uniform MatrixBlock
{
  mat4 projection;
  mat4 modelview;
};

uniform vec3 modelview;  // 重定义错误 和MatrixBlock中冲突

相比于之前以分散形式书写这些变量,interface block能够让你更合理的组织变量为一组,逻辑更清晰。

主程序部分未变,实现的点光源效果相同,这里还是给出效果图如下:

这里写图片描述

从上面可以看出,interface block确实解决了我们一直想要合理组织着色器中变量的问题。这是我们提到的第一个问题。

UBO的概念

本节开始提到的第二个问题是,如何在

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值