GLSL 问题:一个程序中存在多个着色器

发布于 2024-12-02 03:40:45 字数 202 浏览 1 评论 0原文

我一定对着色器有什么误解:

我认为,由于您可以将多个着色器附加到一个程序,因此您可以简单地附加多个片段着色器,例如:使用颜色调制渲染的板条箱纹理和折射。

但显然情况并非如此,因为每个程序只能有一个主函数。

  • 如何解决主函数限制并允许同一程序中并相互调用的多个片段着色器的任意动态组合?

I must have misunderstood something with shaders:

I thought that as you can attach multiple shaders to one program, you'd be able to simply attach more than one fragment shader, as an example: A crate texture rendered with a color modulation and refraction.

But apparently this is not the case, as you can have only one main function per program.

  • How can I work around the main function limit and allow for any dynamic combination of multiple fragment shaders which are in the same program and called after each other?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

南城旧梦 2024-12-09 03:40:45

您可以预先定义一组入口点。假设您的效果数量有限(漫反射、镜面反射、环境等)。它们最多不会应用一次,因此您只需要创建一个像这样的管理着色器:

void apply_diffuse();
void apply_specular();
void apply_environment();

void main(){ ...
     apply_diffuse();
     apply_specular();
     apply_environment();
...}

然后,当需要链接着色器程序时,您可以将相应的实现作为单独的 GLSL 对象附加。如果您不想要这种效果,某些实现可能是假的。这种方法不需要源文本解析,并且几乎没有性能损失。

You can have a set of entry points pre-defined. Suppose you have a limited number of effects (diffuse, specular, environment, etc). None of them is applied at most once, so you just need to create a managing shader like that one:

void apply_diffuse();
void apply_specular();
void apply_environment();

void main(){ ...
     apply_diffuse();
     apply_specular();
     apply_environment();
...}

Then, when it's time to link the shader program you attach the corresponding implementations as separate GLSL objects. Some implementations may be dummies if you don't want the effect. This approach doesn't require source text parsing and has next to no performance penalty.

陈甜 2024-12-09 03:40:45

你不能。这被称为着色器的组合爆炸。要么使用大量着色器(称为 Übershader 方法),要么我相信您可以通过扰乱预处理器并动态生成所需的着色器来实现它。

较新版本的 GLSL 应该支持虚拟函数,这允许您像在 CPU 代码中一样模块化地构建它们 - HLSL5 就是如此。

You can't. This is known as the combinatoric explosion of shaders. Either you use massive shaders- called the Übershader approach- or I believe you can achieve it by messing with the preprocessor and generating the shaders you need on the fly.

Newer versions of GLSL should support virtual functions, which allows you to modularly build them as you would in CPU code- HLSL5 does.

╰沐子 2024-12-09 03:40:45

问题在于您使用的术语。

让我打个比方:

  • 可执行文件由链接的对象组成,对象是从源代码编译的。
  • 着色器程序由链接的着色器对象组成,着色器对象是从源代码编译的。

如您所见,着色器程序是可执行文件。它链接多个着色器对象。每个着色器对象都是从源编译的。对于通常的可执行文件来说,只有一个主入口点,该入口点仅由一个着色器对象定义。就像使用任何编译工具链进行编译一样。

解决方案是着色器对象组合和着色器程序数量之间的良好平衡。当然,如果只有一个着色器程序用于渲染,那就太好了,但这太过分了:尝试考虑着色器功能,然后单独编译这些功能并根据需要进行链接。

你一定要看看OpenGL注册表,我想你可能会在扩展列表中发现一些有趣的东西。

The problem is the terms you are using.

Let me make a similitude:

  • An executable is composed by linked objects, objects are compiled from source.
  • A shader program is composed by linked shader objects, shader objects are compiled from source.

As you can see, a shader program is the executable. It links multiple shader objects. Each shader object is compiled from a source. As for usual executable, there is only one main entry point, which is defined by only one shader object. Just like compiling with any compilation tool-chain.

The solution is the good balance between shader objects combinations and the number of shader programs. Of course it would be beautyful to have only one shader program for rendering, but that's pretending too much: try to factor the shader functionalities, then compiled separately those functionalities and link as needed.

And you must have a look on OpenGL Registry, I think you may find something interesting in the extension list.

烟凡古楼 2024-12-09 03:40:45

您可以在一个着色器中拥有多个程序,但反之则不然。

要进行多种组合,最简单的方法是将每个主要块存储为具有命名入口点的片段,然后将它们包含在另一个程序中或在运行时将它们组合到单个程序中,并按您需要的顺序调用它们。然而,在处理输入和输出时,这可能会变得混乱。

您可以使用多个通道,每个通道具有不同的效果和程序。这会产生一些额外的开销,但更容易设置。

You can have multiple programs in a shader, but not the other way around.

To make multiple combinations, the easiest way is to store each major chunk as a fragment with a named entry point, then include them from another program or combine them at runtime into a single program, calling them in the order you need. That can get messy though, when handling input and outputs.

You can use multiple passes, with different effects and programs in each pass. That has some additional overhead, but can be easier to set up.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文