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

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

问题描述

我有几个着色均匀变量,其在所有着色器相同的名称。什么是一次更新所有着色器有相同的名字制服的最好方法?我认为以下方法:

1)只是存储统一为每个程序的位置,并更新它的程序被指定为紧跟在拿来主义的程序( glUseProgram )。

缺点:
所有的共享统一变量将每个 glUseProgram 呼叫后更新。此外,如果一个节目被在当前帧中未使用的第一次中,所有 glUniform * 呼叫将是多余的。
另外应该有一组标志,如果使用首次与否的程序,它会告诉我们。 未使用的标志应该是复位每一帧。

2)使用统一的缓冲器和共享(甚至 std140 )的布局。在这种方法中,我们可以一次设置一个统一的,然后更改着色器程序,而无需更新缓冲区。但如果有一串简单着色器,其中唯一的共享变量是变换矩阵的?什么情况下可以使用统一的缓冲区的内存如此少量?在一些论坛讨论我读过

  glBindBuffer(GL_UNIFORM_BUFFER,BUF);
glBufferSubData(/ *只有16个花车* /);
glBindBuffer(GL_UNIFORM_BUFFER,0);

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


  • 多久着色器每帧改变,他们会重复的频率?

  • 共享的制服有多少?

  • 应在每一帧传递给着色器程序哪些数据量?

有没有这将有不错的表现,无论这三个问题的答案的任何妥协的设计模式?

3)使用ubershader。这里提到第二段:<一href=\"http://stackoverflow.com/questions/6539774/glsl-multiple-shaderprogram-vs-uniforms-switches\">GLSL多shaderprogram VS制服切换。我有两个问题吧:

什么都有较好的表现:有一个 glUseProgram 来电或几个统一的交换机,这将改变ubershader的功能

提到问题作者


  

制服已到每帧改变多次


作为ubershader的缺点之一。但为什么不好呢?是否有坏的表现?如果是这样,什么情况下可以通过变换矩阵和其他一些小规模的东西,统一的变量和更新他们的每一帧?

和主要问题的所有上述总结:你可以提出任何其他技术或设计模式在几个不同的着色器程序更新的同名变量均匀​​

UPD:答案是公认的,但如果你能提出一个平凡的高级设计技术(C ++或语言无关),普莱舍离开这里。


解决方案

  

在一些论坛讨论我读过[...]比glUniform *调用慢得多。


因此​​,如果它是什么(假设有证据表明,它甚至是,当然)?你只能做到每帧的一次,而 glUniform 通话按修改后的程序之一。

我要均匀块去(总是使用 std140 默认情况下)任何共享的数据。有一个固定的成本来更新它们,同时有一个可变成本,更新等。

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) Just store locations of that uniform for each program and update it just after the program is assigned as "used" program (glUseProgram).

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) 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);

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

  • How often will the shaders change per frame and how often will they repeat?
  • How many "shared" uniforms are there?
  • What amount of data should be passed to shader program in each frame?

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

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

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

Author of that question mentioned

Uniforms have to be changed many times per frame

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: the answer is accepted, nevertheless if you can suggest a nontrivial high-level design technique (in C++ or language-independent), plese leave it here.

解决方案

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

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.

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天全站免登陆