OpenGL 分层渲染干扰第 0 层

OpenGL layered rendering interferes with layer 0

我在几何着色器中使用 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 );
}

EmitVertex 使它 returns 之后的所有每个顶点 输出 无效。此着色器中最明显的逐顶点输出是:

  1. raster_color
  2. gl_Position

但是,你可能没有意识到gl_Layer也是per-vertex或者需要为哪个顶点设置。


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,这是你应该假设的情况)。

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