5

I would like to efficiently render in an interlaced mode using GLSL.

I can alrdy do this like:

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;

However, as far as I have understood the nature of branching in GLSL is that both branches will actually be executed, since "even_row" is considered as run-time value.

Is there any trick I can use here in order to avoid unnecessarily calling the rather heavy function "get_color"? The behavior of is_even_row is quite static.

Or is there some other way to do this?

NOTE: glPolygonStipple will not work since I have custom blend functions in my GLSL code.

4

2 回答 2

6

(根据要求评论回答)

隔行扫描的问题在于 GPU 在 2x2 集群中运行着色器,这意味着您无法从隔行扫描中获得任何收益(一个好的软件实现可能只执行所需的实际像素,除非您要求偏导数)。

在最好的情况下,隔行扫描以相同的速度运行,在最坏的情况下它运行得更慢,因为隔行扫描需要额外的工作。几年前,ShaderX4有一篇文章,建议隔行渲染。我在六块显卡(“两大”制造商的各 3 代硬件)上尝试了这种方法,但在每种情况下运行速度都较慢(有时稍微慢一些,有时高达 50%)。

您可以做的是以 1/2 的垂直分辨率进行所有昂贵的渲染,这会将像素着色器工作(和纹理带宽)减少 1/2。然后,您可以放大纹理 (GL_NEAREST),并丢弃每隔一行。

模板测试可用于在执行像素着色器之前丢弃像素。当然,硬件仍然在 2x2 组中运行着色器,所以在这个过程中你什么也得不到。但是,如果它只是最后一遍,那就没关系了,这是一个简单的着色器,写出单个提取的纹素。更昂贵的合成着色器(重要的!)以半分辨率运行。
您可以在此处找到包含代码的详细描述:fake dynamic branching。此演示通过使用模板丢弃那些超出光照范围的像素来避免光照像素。

另一种不需要模板缓冲区的方法是使用“显式 Z 剔除”。这实际上可能更容易和更快。
为此,清除 Z,禁用颜色写入glColorMask( )。gl_FragCoord.y是一种非常简单的知道要杀死哪条线的方法,使用环绕的小纹理将是另一种方法(如果您必须使用 GLSL 1.0)。
现在绘制另一个全屏四边形,在顶点中具有“远处”的 Z 值(当然还有深度测试)。只需获取您的半分辨率纹理(GL_NEAREST 过滤),然后将其写出来。由于深度缓冲区的值每隔一行“更接近”,

与此相比如何glPolygonStipple?多边形点画是一个不推荐使用的功能,因为它不直接由硬件支持,并且必须由驱动程序通过“秘密”重写着色器以包含额外逻辑或回退到软件来模拟。

于 2011-06-26T14:06:46.920 回答
3

这可能不是进行隔行扫描的正确方法。如果你真的需要达到这个效果,就不要像这样在片段着色器中做。相反,您可以这样做:

  1. 初始化全屏 1 位模板缓冲区,其中每个位存储其对应行的奇偶校验。

  2. 像往常一样将您的场景渲染到具有 1/2 垂直分辨率的临时 FBO。

  3. 打开模板测试,根据您要绘制的扫描线组切换模板功能。

  4. 将上述 fbo(包含帧的内容)的重新缩放版本 Blit 到模板缓冲区。

请注意,您可以跳过屏幕外 FBO 步骤并直接使用模板缓冲区进行绘制,但这会浪费一些填充率来测试那些无论如何都会被剪裁的像素。如果你的程序着色器很重,我刚才提到的解决方案将是最佳的。如果不是这样,那么直接在屏幕上绘图可能会稍微好一些。

于 2011-06-26T03:16:33.327 回答