ron*_*nag 4 c++ opengl optimization glsl interlacing
我想使用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;
Run Code Online (Sandbox Code Playgroud)
但是,据我所知,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
),并绘制其顶点具有一些"接近"Z坐标的全屏四边形,并使着色器在每个奇数行中杀死碎片(或者如果需要,使用弃用的alpha测试,或者其他).gl_FragCoord.y
是一种非常简单的方法来知道要杀死哪一行,使用包裹的小纹理将是另一种(如果你必须使用GLSL 1.0).
现在绘制另一个全屏四边形,顶点中有"远处"的Z值(当然还有深度测试).只需获取半分区纹理(GL_NEAREST过滤),然后将其写出来.由于深度缓冲区具有在每隔一行中"更接近"的值,因此它将丢弃那些像素.
怎么glPolygonStipple
比较呢?多边形点画是一种不推荐使用的功能,因为硬件不直接支持它,并且必须通过"秘密"重写着色器以包含额外逻辑或通过回退到软件来模拟驱动程序.