调用 EmitVertex 次数过多会导致编译失败,尽管低于 max_vertices 计数

问题描述 投票:0回答:1

在主程序中,查询几何着色器可以发射的最大顶点数:

GLint max_geo_out;
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &max_geo_out);
printf("max vertices from geometry shader: %d\n", max_geo_out);

这显示了 1024 个顶点。

一个简单的顶点着色器如下:

#version 450 core
layout(location = 0) in vec3 position;

void main() {
    gl_Position = vec4(0, 0, 0, 0); 
}

几何着色器:

#version 450 core

layout(points) in;

layout(triangle_strip, max_vertices = 1024) out;

out vec3 vertex_attribute;

void main() {
    for (int i = 0; i < 1024; i++) {    
        vertex_attribute = vec3(1, 1, 1);
        gl_Position = vec4(1, 1, 1, 1);
        EmitVertex();
    }
    EndPrimitive();
}

片段着色器:

#version 450 core

in vec3 vertex_attribute;

out vec4 final_color;

void main()
{   
    final_color = vec4(vertex_attribute[0], 1, 1, 1);
}

尽管调用

EmitVertex()
1024 次,这些着色器仍无法编译。这是为什么?

c++ opengl glsl
1个回答
0
投票

术语

max_vertices
实际上是指几何着色器可以输出的32位值的最大数量。这是有道理的,因为顶点可以具有任意数量的属性,例如位置、纹理坐标、法线等,而 GPU 的内存量是有限的。

这里有两个变量在起作用:几何着色器的“输出”数量和发出的顶点数量。即使没有“out”,你也会发现实际上只能发射256个顶点。这是因为

gl_Position
顶点属性已经使用了 4 个 32 位组件。 1024 除以 4 个分量最多可得到 256 个顶点。

如果不了解这一点,调试可能会很困难。一个常见的错误是为了简化而将片段着色器中的最终颜色设置为常量,但这样做时编译器会优化来自几何着色器的其他矢量属性。结果,它将进行编译,使其看起来能够发出比实际更多的顶点。

总体而言,您可以真正发出的最大顶点数定义为

max_vertices / (4 + outs)
。在本例中,
max_vertices
为 1024,并且 vec3 属性被发送到片段着色器,因此您可以发出的最大顶点数为 146。

© www.soinside.com 2019 - 2024. All rights reserved.