OpenGL分层渲染会干扰第0层

时间:2015-08-15 23:35:50

标签: opengl graphics 3d glsl geometry-shader

我在几何着色器中使用<button> <svg version="1.1" fill="#fff" class="icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 96.828 96.827" xml:space="preserve"> <path d="M62.617,0H39.525c-10.29,0-17.413,2.256-23.824,7.552c-5.042,4.35-8.051,10.672-8.051,16.912c0,9.614,7.33,19.831,20.913,19.831c1.306,0,2.752-0.134,4.028-0.253l-0.188,0.457c-0.546,1.308-1.063,2.542-1.063,4.468c0,3.75,1.809,6.063,3.558,8.298l0.22,0.283l-0.391,0.027c-5.609,0.384-16.049,1.1-23.675,5.787c-9.007,5.355-9.707,13.145-9.707,15.404c0,8.988,8.376,18.06,27.09,18.06c21.76,0,33.146-12.005,33.146-23.863c0.002-8.771-5.141-13.101-10.6-17.698l-4.605-3.582c-1.423-1.179-3.195-2.646-3.195-5.364c0-2.672,1.772-4.436,3.336-5.992l0.163-0.165c4.973-3.917,10.609-8.358,10.609-17.964c0-9.658-6.035-14.649-8.937-17.048h7.663c0.094,0,0.188-0.026,0.266-0.077l6.601-4.15c0.188-0.119,0.276-0.348,0.214-0.562C63.037,0.147,62.839,0,62.617,0z M34.614,91.535c-13.264,0-22.176-6.195-22.176-15.416c0-6.021,3.645-10.396,10.824-12.997c5.749-1.935,13.17-2.031,13.244-2.031c1.257,0,1.889,0,2.893,0.126c9.281,6.605,13.743,10.073,13.743,16.678C53.141,86.309,46.041,91.535,34.614,91.535z M34.489,40.756c-11.132,0-15.752-14.633-15.752-22.468c0-3.984,0.906-7.042,2.77-9.351c2.023-2.531,5.487-4.166,8.825-4.166c10.221,0,15.873,13.738,15.873,23.233c0,1.498,0,6.055-3.148,9.22C40.94,39.337,37.497,40.756,34.489,40.756z" /> <path d="M94.982,45.223H82.814V33.098c0-0.276-0.225-0.5-0.5-0.5H77.08c-0.276,0-0.5,0.224-0.5,0.5v12.125H64.473c-0.276,0-0.5,0.224-0.5,0.5v5.304c0,0.275,0.224,0.5,0.5,0.5H76.58V63.73c0,0.275,0.224,0.5,0.5,0.5h5.234c0.275,0,0.5-0.225,0.5-0.5V51.525h12.168c0.276,0,0.5-0.223,0.5-0.5v-5.302C95.482,45.446,95.259,45.223,94.982,45.223z" /> </svg>Sign In with Google</button>渲染到附加了3D纹理的帧缓冲区。

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

我该如何避免这种情况?设置帧缓冲区时,我是否缺少一些重要的东西?也许是gl_Layer = gl_InvocationID;

几何着色器

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();
}

1 个答案:

答案 0 :(得分:3)

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

  1. raster_color
  2. gl_Position
  3. 但是,你可能没有意识到gl_Layer也是每个顶点或者需要设置哪个顶点。

    对于此着色器中第一个之后的每个顶点,

    gl_Layer都将是未定义的。有些司机会保持不变,只是工作,其他人会随心所欲地做任何事情,你不能在gl_Layer之后对EmitVertex (...)作出任何假设。 你正在玩火,因为它可能不是定义图元层的第一个顶点(稍后将详细介绍)。

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

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