我想使用GLSL在交错模式下高效地渲染。
我也可以这样做:
vec4 background = texture2D(plane[5], gl_TexCoord[1].st);
if(is_even_row(gl_TexCoord[1].t))
{
vec4 foreground = get_my_color();
gl_FragColor = vec4(fore.rgb * foreground .a + background .rgb * (1.0-foreground .a), background .a + fore.a);
}
else
gl_FragColor = background;然而,据我所知,GLSL中分支的本质是两个分支实际上都将被执行,因为"even_row“被认为是运行时值。
有什么技巧可以在这里使用,以避免不必要地调用相当繁重的函数"get_color"?is_even_row的行为是非常静态的。
或者有其他方法可以做到这一点?
注意: glPolygonStipple将不会工作,因为我在我的GLSL代码中有自定义的混合函数。
发布于 2011-06-26 22:06:47
(如有要求,请回复备注)
隔行扫描的问题是GPU在2x2簇中运行着色器,这意味着您不会从隔行扫描中获得任何好处(一个好的软件实现可能只执行所需的实际像素,除非您要求偏导数)。
在最好的情况下,隔行扫描以相同的速度运行,在最坏的情况下,由于隔行扫描的额外工作,它运行得更慢。几年前,ShaderX4上有一篇文章建议交错渲染。我在六块显卡(“两大”制造商各有3代硬件)上尝试了这种方法,但每种情况下运行速度都较慢(有时稍慢,有时高达50%)。
你可以做的是在1/2的垂直分辨率下完成所有昂贵的渲染,这将减少1/2的像素着色器工作(和纹理带宽)。然后你可以放大纹理(GL_NEAREST),并丢弃每隔一行。
模具测试可用于在执行像素着色器之前丢弃像素。当然,硬件仍然以2x2组的形式运行着色器,因此在此过程中不会获得任何结果。但是,如果这只是最后一次传递,这并不重要,这只是一个简单的着色器写出单个获取的纹理元素。更昂贵的合成着色器(重要的着色器!)以一半分辨率运行。
您可以在以下位置找到包含代码的详细描述:fake dynamic branching。此演示通过使用模板丢弃超出光线范围的像素来避免照亮像素。
另一种不需要模板缓冲区的方法是使用“显式Z剔除”。事实上,这可能会更容易、更快。
为此,请清除Z,禁用颜色写入(glColorMask),并绘制一个全屏四边形,其顶点具有一些“接近”的Z坐标,并让着色器在每个奇数行中删除碎片(如果需要,也可以使用不推荐使用的alpha测试,或其他任何方法)。gl_FragCoord.y是一种非常简单的知道删除哪一行的方法,使用环绕的小纹理将是另一种方法(如果你必须使用GLSL1.0)。
现在绘制另一个全屏四边形,顶点中有“远方”的Z值(当然还有深度测试)。只需获取您的半分辨率纹理(GL_NEAREST过滤),并将其写出来。由于深度缓冲区在每隔一行中有一个“更接近”的值,因此它将丢弃这些像素。
与此相比,glPolygonStipple又如何呢?多边形点绘是一项已弃用的功能,因为它不受硬件直接支持,必须由驱动程序通过“秘密”重写着色器以包含额外的逻辑或回退到软件来模拟。
发布于 2011-06-26 11:16:33
这可能不是做交错的正确方式。如果您确实需要实现此效果,请不要在片段着色器中执行此操作。相反,下面是你可以做的:
请注意,您可以跳过屏幕外的FBO步骤,直接使用模板缓冲区绘制,但这将浪费一些填充率测试那些即将裁剪的像素。如果你的程序是着色器密集型的,我刚才提到的解决方案将是最优的。如果不是这样,那么直接在屏幕上绘图可能会稍微好一点。
https://stackoverflow.com/questions/6478342
复制相似问题