繁体   English   中英

是否可以使用具有或不具有几何着色器的相同顶点着色器和片段着色器?

[英]Is it possible to have the same vertex shader and fragment shader with or without a geometry shader?

所以我只是学习几何着色器,我有一个用例。

出于性能原因,我不想一直使用几何着色器,即使是通过,因为大多数时候大多数对象都不需要它。 但是当我想要它时,顶点和片段着色器应该做同样的事情。 我可以重用我的顶点和片段着色器。

IE浏览器。

顶点:

#version 330
in vec3 position;
out vec3 whatever;

void main()
{
    ...
}

几何:

#version 330
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
in whatever[];
out whatever;

void main()
{
    ...
}

分段:

#version 330
in whatever

void main()
{
    ...
}

因此,如果没有几何着色器,这将起作用,因为顶点可以out whatever与片段无关in whatever 然而,对于几何着色器,我最终会重新设置为in和out两者。

我读过你可以使用: layout (location = 0) out whatever然后你不需要相同的名字,但这对我不起作用,给出了编译错误: ERROR: -1:65535: '' : storage qualifier not valid with layout qualifier id 我认为这是因为我没有足够新的opengl版本来支持该语法。

我还读到你可以使用扩展名:arb_separate_shader_objects,但未能找到任何使用它的例子。

有什么建议?

事实上你可以做到这一点。 但是你需要接口块来完成它。 实际上,这是创建输入/输出接口块以解决的主要问题之一:

#version 330
in vec3 position;
out Data
{
  vec3 whatever;
};

void main()
{
    ...
    whatever = ...;
}

这是您的顶点着色器,使用接口块作为其输出。 顶点着色器输入无法聚合到接口块中。 请注意,顶点着色器调用接口块的成员whatever 这很快就会很重要。

在片段着色器中:

#version 330
in Data
{
    in vec3 whatever;
};

void main()
{
    ...
    ... = whatever;
}

片段着色器现在声明了一个补充输入块。 为了使其工作,块必须使用与前一阶段的相应输出块相同的名称。 它必须以相同的顺序声明与相应输出块相同的所有变量。

再次注意,片段着色器将变量称为whatever变量。 这在目前很重要。

如果您使用这两个着色器并将它们链接在一起(直接或间接与单独的程序 ),它们将正常工作。 现在,是时候看看Geometry Shader在它们之间看起来是什么样子了:

#version 330
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

in Data
{
    vec3 whatever;
} vertex_input[];

out Data
{
    vec3 whatever;
} vertex_output;

void main()
{
    ...
    vertex_output.whatever = vertex_input[0].whatever;
}

好吧, 很多东西刚刚发生。

你要注意的第一件事是我们似乎已经两次声明了相同的接口块。 不,我们没有; 输入和输出接口块位于不同的命名空间中。 因此,声明一个具有相同块名称的输入接口块作为输出接口块是完全正常的。

输入Data相匹配与所述输出Data从顶点着色器。 输出Data相匹配与输入Data的片段着色器。 所以接口匹配。

现在,您可能会注意到我们以不同方式声明了这些块。 输入块具有标记vertex_input[] ,而输出块具有vertex_output 这不像在C / C ++中的结构声明之后声明的结构变量。 这个名称就是所谓的接口块的实例名称 这是非常重要的。

为什么? 因为它允许我们对接口块成员的名称进行范围化。

声明没有实例名称的块全局范围成员。 这就是为什么我们可以用这个名称引用VS和FS中的whatever 然而,由于GS需要有两个独立的whatever变量,我们需要一些方法来区分它们。

这就是实例名称的用途。 通过为块提供实例名称,我们必须在该变量的所有引用前加上该实例名称。

请注意,跨接口的块名称匹配。 也就是说,GS的输入与VS的输出匹配,因为它们都被命名为Data 实例名称在着色器中用于名称范围成员。 它不会影响接口匹配。

最后,您会注意到GS的输入变量不是数组。 它是排列的接口块的实例名称 这就是接口块在GS(以及采用阵列输入/输出的曲面细分着色器)中的工作方式。

根据这个定义,你可以在VS和FS之间滑动这个GS,而不必改变它们中的任何一个。 因此,您根本不必修改VS或FS代码(显然除了使用接口块之外)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM