【问题标题】:OpenGL layered rendering interferes with layer 0OpenGL 分层渲染会干扰第 0 层
【发布时间】:2015-08-16 20:31:21
【问题描述】:

我在几何着色器中使用gl_Layer = gl_InvocationID; 渲染到附加了 3D 纹理的帧缓冲区。

这大部分都可以正常工作。除了每次调用着色器也会渲染到第 0 层,以及我指定的层。

我怎样才能避免这种情况?设置帧缓冲区时我缺少什么重要的东西吗?也许是glFramebufferTexture

几何着色器

#version 400

layout(invocations = 32) in;
layout(points) in;
layout(triangle_strip, max_vertices = 3) out;

out vec3 raster_color;

float blue;

void main()
{
  gl_Layer = gl_InvocationID;
  blue = float(gl_InvocationID) / 31.0;

  gl_Position  = vec4( -1.0, -1.0, 0.0, 1.0 );
  raster_color = vec3( 0.0, 0.0, blue );
  EmitVertex();

  gl_Position  = vec4( 1.0, -1.0, 0.0, 1.0 );
  raster_color = vec3( 1.0, 0.0, blue );
  EmitVertex();

  gl_Position  = vec4( 0.0, 1.0, 0.0, 1.0 );
  raster_color = vec3( 1.0, 1.0, blue );
  EmitVertex();

  EndPrimitive();
}

片段着色器

#version 400

in vec3 raster_color;
out vec4 fragment_color;

void main()
{
  fragment_color = vec4( raster_color, 1.0 );
}

【问题讨论】:

  • 你能包含有问题的几何着色器吗?我倾向于认为 it 应该为此负责,而不是您的 FBO 设置或片段着色器(不过,如果您也可以包含 fs,那会有所帮助)。
  • 当然,@Andon。我已将它们添加到问题中。

标签: opengl graphics 3d glsl geometry-shader


【解决方案1】:

EmitVertex 在返回后使所有每个顶点的输出 无效。这个着色器中最明显的逐顶点输出是:

  1. raster_color
  2. gl_Position

但是,您可能没有意识到 gl_Layer 也是逐顶点或需要为哪个顶点设置的。


gl_Layer 将在此着色器中的第一个顶点之后的每个顶点未定义。一些驱动程序会保持原样并简单地工作,其他驱动程序会用它做任何他们想做的事情,你不能在EmitVertex (...) 之后对gl_Layer 做出任何假设。 你在玩火,因为它可能不是定义图元层的第一个顶点(稍后会详细介绍)。

要解决此问题,请以这种方式重新编写几何着色器:

#version 400

layout(invocations = 32) in;
layout(points) in;
layout(triangle_strip, max_vertices = 3) out;

out vec3 raster_color;

float blue;

void main()
{
  blue = float(gl_InvocationID) / 31.0;

  gl_Position  = vec4( -1.0, -1.0, 0.0, 1.0 );
  raster_color = vec3( 0.0, 0.0, blue );
  gl_Layer = gl_InvocationID; // Handle case where First Vertex is Layer Provoking
  EmitVertex();

  gl_Position  = vec4( 1.0, -1.0, 0.0, 1.0 );
  raster_color = vec3( 1.0, 0.0, blue );
  gl_Layer = gl_InvocationID; // Handle case where Layer Provoking vertex is Undefined
  EmitVertex();

  gl_Position  = vec4( 0.0, 1.0, 0.0, 1.0 );
  raster_color = vec3( 1.0, 1.0, blue );
  gl_Layer = gl_InvocationID; // Handle case where Last Vertex is Layer Provoking
  EmitVertex();

  EndPrimitive();
}

我想借此机会指出,图元中只有 1 个顶点需要设置 gl_Layer;这个顶点称为Layer Provoking Vertex。您的着色器假定第一个顶点是层激发顶点,但这是特定于实现的。如有疑问,最好的解决方案是覆盖所有基(为所有顶点设置gl_Layer)。

您需要在运行时检查GL_LAYER_PROVOKING_VERTEX 以确定哪个顶点定义了您的层。如果你不想这样做,你可以按照我上面描述的方式编写你的着色器。引发顶点约定通常是第一个或最后一个,但几何着色器的工作方式留下了任何任意顶点都可以定义层的可能性(GL_UNDEFINED_VERTEX,这是您应该假设的情况)。

【讨论】:

  • 请参阅here 了解有关此情况的更多详细信息。它也适用于视口激发顶点。
  • 我尝试了您的代码修改无济于事,恐怕。但后来我一直在其他地方搜索,发现源头要平凡得多。我的纹理参数中的语法错误意味着它没有正确夹紧,并且顶层在采样时会回绕到底部。我现在更好地理解每个顶点的输出以供将来参考。所以谢谢你。
  • @Andy:啊,明白了。当我写这篇文章时,我怀疑它是否能完全解释你的问题,但它需要得到解决。理解这一点可能会为您节省很多挫败感;)如果您找到了解决方案,最好的做法是回答您自己的问题。即使它很简单,也要添加有问题的代码和对修复的解释,并将其标记为已接受。这就是 Stack Overflow 的工作方式。一个庞大的可搜索问答数据库,其中包含经过验证的问题解决方案。
【解决方案2】:

原来gl_Layer 没有问题。这只是glTexParameter 中的一个语法错误,导致我生成的 3D 纹理重复而不是固定到边缘。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多