是否可以在几何着色器阶段之前进行面部剔除?

时间:2014-02-06 05:30:06

标签: opengl

是否可以仅将前三角形发送到几何着色器?我相信默认情况下,只有在几何着色器之后才会发生剔除。

3 个答案:

答案 0 :(得分:3)

是的,回到Quake的古代,使用每个三角形的简单点积在CPU上完成面部剔除。任何未通过测试的三角形都不包括在绘制的索引列表中。

现在这在大多数硬件上都不是可行的优化,但您仍然会在专门的应用程序中看到它不时使用。我见过的一个这样的应用程序是使用PS3的Cell SPE在批处理期间剔除三角形以保存PS3的RSX GPU上的顶点变换工作负载 - 请记住,PS3仍然使用基本着色器架构,其中有固定数字专用顶点着色器单元和片段着色器单元。在该GPU上平衡着色器工作负载非常重要。

我可能会忽略你的问题;你期望/想要从早期剔除原语中获得什么好处?

<小时/>

更新

我想说的是,在现代硬件和软件上,顶点变换/原始组装通常不是瓶颈。片段处理现在要昂贵得多,因此在光栅化过程中剔除基元是通常你必须担心性能的程度。 PS3的RSX是一种特殊情况,它具有非常差的顶点性能和难以保持忙碌的CPU架构,因此将原始剔除卸载到CPU是有意义的。

您仍然可以在CPU上的顶点着色器/曲面细分/几何着色器之前剔除三角形,但是在某处存储每个三角形的法线并传输一组新的索引以绘制每个帧几乎不会使这成为明智的资源使用。你可能花费更多的时间和内存设置缩小的三角形列表,而不是在GPU上处理它们时让GL在光栅化过程中抛出向后的基元。

至少有一个用例会浮现在脑海中,这实际上仍然是一件有用的事情。我指的是细分补丁。如果您可以在曲面细分发生之前在CPU上确定整个补丁面向错误的方式,则可以跳过必须在GPU上对它们进行细分。通常这些天渲染不会是顶点约束,但曲面细分可能是一种情况。

答案 1 :(得分:0)

实际上是可能的。像提到的其他答案一样,您可以在软件方面进行操作。但是顶点着色器和几何着色器之间存在阶段。即,船体(可编程),基元生成器(固定)和域(可编程)。在外壳着色器中,您可以为面片指定镶嵌级别。

如果将这些级别中的任何一个设置为0.0,则补丁将被丢弃,并且不会进入几何着色器!

希望这会有所帮助:)

答案 2 :(得分:0)

尽管由于三角形到达了几何着色器,所以从技术上讲它并不能解决问题,但是您可以在几何着色器本身中剔除三角形。这可能是人们阅读此问题时正在寻找的解决方案,这是给我的。

我使用下面的着色器通过剔除来实现四边形的线框绘制,其中每个四边形是使用两个三角形绘制的。使用

的想法
glPolygonMode(GL_FRONT_AND_BACK, GL_LINES) 
带有剔除的

包括每个四边形的对角线,这是不希望的,因此我使用几何着色器将每个三角形仅转换为两条线。但是,现在无法进行剔除,因为几何着色器仅发射线。取而代之的是在几何体着色器的开始处包含剔除,只需将所需的统一 culling 设置为-1、0或1(请注意,此剔除测试假定每个坐标的w坐标为正顶点)。

#version 430 core

layout (triangles) in;
layout (line_strip, max_vertices=3) out;

uniform int culling;

void main()
{
    // Perform culling here with an early return
    mat3 M = mat3(gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_in[2].gl_Position.xyz);
    if(culling * determinant(M) < 0)
    {
        EndPrimitive();  // Necessary?
        return;
    }
    
    gl_Position = gl_in[0].gl_Position;
    EmitVertex();
    
    gl_Position = gl_in[1].gl_Position;
    EmitVertex();
    
    gl_Position = gl_in[2].gl_Position;
    EmitVertex();
    
    EndPrimitive();
}