一次更新多个着色器程序中的统一变量 [英] Update an uniform variable in several shader programs at once

查看:22
本文介绍了一次更新多个着色器程序中的统一变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个带有统一变量的着色器,它们在所有着色器中都具有相同的名称.在所有着色器中一次更新具有相同名称的制服的最佳方法是什么?我考虑了以下方法:

I have several shaders with uniform variables, which have the same names in all shaders. What is the best way to update uniforms with same names in all shaders at once? I consider the following approaches:

1) 只需为每个程序存储该制服的位置,并在程序被指定为已使用"程序 (glUseProgram) 后立即更新它.

1) Just store locations of that uniform for each program and update it just after the program is assigned as "used" program (glUseProgram).

缺点:每次glUseProgram 调用后,所有共享"统一变量都会更新.此外,如果某个程序在当前帧中不是第一次使用,则所有 glUniform* 调用都将是多余的.或者,应该有一组标志来判断程序是否第一次使用.未使用"标志应在每一帧中重置.

Disadvantages: All "shared" uniform variables will be updated after each glUseProgram call. Moreover, if a program is being used not for the first time during the current frame, all glUniform* calls will be redundant. Alternatively there should be a set of flags which will tell if the program is used for the first time or not. "Unused" flags should be reset every frame.

2) 使用统一缓冲区和 shared(甚至 std140)布局.在这种方法中,我们可以立即设置统一,然后在不更新缓冲区的情况下更改着色器程序.但是如果有一堆简单的着色器,其中唯一的共享变量是变换矩阵呢?对于这么小的内存使用统一缓冲区可以吗?在一些论坛讨论中,我读到了

2) Use uniform buffers and shared (or even std140) layout. In this approach we can set an uniform at once and then change shader programs without updating buffers. But what if there is a bunch of simple shaders, where the only shared variable is transformation matrix? Is it okay to use uniform buffers for such a small amount of memory? In some forum discussions I've read that

glBindBuffer(GL_UNIFORM_BUFFER,buf);
glBufferSubData(/*just 16 floats*/);
glBindBuffer(GL_UNIFORM_BUFFER,0);

glUniform* 调用慢得多.在这里我们可以注意到,在第一种和第二种方法之间的选择取决于以下条件:

is much slower than glUniform* call. Here we can notice, that the choice between first and second approach depends on the following conditions:

  • 每帧着色器多久更改一次?重复多久?
  • 有多少共享"制服?
  • 每帧应该传递多少数据给着色器程序?

是否有任何折衷的设计模式,无论这三个问题的答案如何,都会有良好的性能?

Is there any compromise design pattern which will have good performance regardless of answers for these three questions?

3) 使用超级着色器.在第二段中提到:GLSL 多着色器程序 VS 制服开关.我有两个问题:

3) Use ubershader. Mentioned here in the second paragraph: GLSL multiple shaderprogram VS uniforms switches. I have two questions about it:

什么有更好的性能:一个 glUseProgram 调用或几个统一的开关,这将改变 ubershader 的功能?

What has better performance: one glUseProgram call or several uniform switches, which will change ubershader's functionality?

提到的那个问题的作者

每帧必须多次更改制服

作为 ubershader 的缺点之一.但为什么不好呢?它的性能很差吗?如果是这样,是否可以将变换矩阵和其他一些小尺寸的东西作为统一变量传递并在每一帧更新它们?

as one of disadvantages of ubershader. But why is it bad? Does it have bad performance? If so, is it okay to pass transformation matrices and some other low-sized stuff as uniform variables and update them each frame?

以及总结以上所有内容的主要问题:您是否可以建议任何其他技术或设计模式来更新多个不同着色器程序中的同名统一变量?

And the main question to summarize all above: may you suggest any other techniques or design patterns for updating same-named uniform variables in several different shader programs?

UPD:答案已被接受,但是如果您可以提出一种重要的高级设计技术(在 C++ 或与语言无关的情况下),请将其留在此处.

UPD: the answer is accepted, nevertheless if you can suggest a nontrivial high-level design technique (in C++ or language-independent), plese leave it here.

推荐答案

在一些论坛讨论中,我读到 [...] 比 glUniform* 调用慢得多.

In some forum discussions I've read that [...] is much slower than glUniform* call.

那如果是(当然,假设有证据表明它是)呢?您每帧只执行一次,而 glUniform 调用是每个修改后的程序调用一次.

So what if it is (assuming that there is evidence that it even is, of course)? You only do that once per frame, while glUniform calls are one per modified program.

对于任何共享数据,我都会使用统一块(默认情况下始终使用 std140).更新它们的成本是固定的,而更新其他的则是可变成本.

I'd go with uniform blocks (always use std140 by default) for any shared data. There's a fixed cost to updating them, while there's a variable cost to updating the others.

这篇关于一次更新多个着色器程序中的统一变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆