GLSL隔行扫描。

| 我想使用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代码中具有自定义混合功能。     
已邀请:
        (根据要求回答评论) 隔行扫描的问题是GPU在2x2群集中运行着色器,这意味着隔行扫描不会带来任何好处(好的软件实现可能只执行所需的实际像素,除非您要求偏导数)。 最佳情况下,隔行扫描以相同的速度运行,最坏的情况下,由于隔行扫描需要额外的工作,因此运行速度较慢。几年前,ShaderX4中有一篇文章建议隔行渲染。我在六块图形卡(每个“两个大”制造商的3代硬件)上尝试了该方法,但在每种情况下,它的运行速度都较慢(有时会略有降低,有时会高达50%)。 您可以做的是以垂直分辨率的1/2进行所有昂贵的渲染,这将使像素着色器的工作(和纹理带宽)减少1/2。然后可以放大纹理(GL_NEAREST),并丢弃其他所有行。 模版测试可用于在执行像素着色器之前丢弃像素。当然,硬件仍按2x2组运行着色器,因此在此过程中您不会获得任何好处。但是,这是否仅仅是最后一步,这是一个琐碎的着色器,可以写出单个提取的纹理像素,这无关紧要。成本更高的构图着色器(重要!)以一半的分辨率运行。 您可以在此处找到包含代码的详细描述:伪动态分支。该演示通过使用模板丢弃那些不在灯光范围内的像素来避免点亮像素。 不需要模板缓冲区的另一种方法是使用“显式Z剔除”。实际上,这甚至可能更容易,更快。 为此,清除Z,禁用颜色写入(
glColorMask
),并绘制一个全屏四边形,其顶点具有一些\“ close \” Z坐标,并使着色器杀死每条奇数行中的片段(或者,如果需要,可以使用不建议使用的alpha测试) , 管他呢)。
gl_FragCoord.y
是知道杀死哪条线的一种非常简单的方法,使用环绕的小纹理是另一种方法(如果必须使用GLSL 1.0)。 现在绘制另一个全屏四边形,其顶点具有“远” Z值(当然,还要进行深度测试)。只需获取半分辨率纹理(GL_NEAREST过滤),然后将其写出即可。由于深度缓冲区的每隔一行的值为\“ closer \”,它将丢弃这些像素。
glPolygonStipple
与此相比如何?多边形点画法已被弃用,因为硬件不直接支持点画法,而驱动程序必须通过“秘密地”重写着色器以包括额外的逻辑或通过退回软件来对其进行仿真。     
        这可能不是正确的隔行扫描方式。如果确实需要实现此效果,请不要在片段着色器中这样做。相反,您可以执行以下操作: 初始化一个全屏的1位模板缓冲区,其中每个位存储其对应行的奇偶校验。 像往常一样将场景渲染到具有垂直分辨率1/2的临时FBO。 打开模板测试,然后根据要绘制的扫描线集切换模板功能。 将上述fbo的重新缩放版本(包含框架的内容)对齐到模板缓冲区中。 请注意,您可以跳过屏幕外FBO步骤并直接使用模板缓冲区进行绘制,但这会浪费一些填充率来测试那些无论如何都会被裁剪的像素。如果您的程序着色器繁重,那么我刚才提到的解决方案将是最佳选择。如果不是这样,直接绘制到屏幕上可能会稍微好一些。     

要回复问题请先登录注册