多重采样和片段着色器

rnd*_*nch 1 opengl glsl

多重采样似乎不适用于片段着色器生成的片段.在下面的示例中,片段着色器用于生成检查板程序纹理.正方形的外边缘是适当抗锯齿的,但程序纹理的内边缘不是.

片段着色器是否仅针对每个像素进行评估?或者给定像素的每个片段的纹理坐标是否相同?

下面是代码,图像显示其输出(请注意,白色和灰色方块之间的程序边缘不是抗锯齿的,而几何边缘 - 黑色和白色/灰色之间 - 是:)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


# imports ####################################################################

import sys

from OpenGL.GLUT import *
from OpenGL.GL import *


# display ####################################################################

def reshape(width, height):
    """window reshape callback."""
    glViewport(0, 0, width, height)

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    r = float(min(width, height))
    w, h = 2*width/r, 2*height/r
    glOrtho(-w, w, -h, h, -1, 1)

    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glRotate(45, 0, 0, 1)

def display():
    """window redisplay callback."""
    glClear(GL_COLOR_BUFFER_BIT)
    glBegin(GL_TRIANGLE_STRIP)
    for x in [-1, 1]:
        for y in [-1, 1]:
            glTexCoord(x, y)
            glVertex(x, y)
    glEnd()
    glutSwapBuffers()


# setup ######################################################################

glutInit(sys.argv)
glutInitDisplayString(b"rgba double samples=4")
glutInitWindowSize(100, 100)
glutCreateWindow(sys.argv[0].encode())

glutReshapeFunc(reshape)
glutDisplayFunc(display)

glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

shader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(shader, """
    void main() {
        vec2 c = gl_TexCoord[0].xy;
        vec4 color = gl_Color;
        if(c.x*c.y < 0.) color.a *= .5;
        gl_FragColor = color;
    }
""")
glCompileShader(shader)
program = glCreateProgram()
glAttachShader(program, shader)
glLinkProgram(program)
glUseProgram(program)

glutMainLoop()  
Run Code Online (Sandbox Code Playgroud)

Ret*_*adi 8

这是MSAA(多重采样抗锯齿)的基本思想.片段着色器每个片段只执行一次.然后使用样本掩码来控制将结果片段写入哪些样本.

假设您使用4x MSAA,其中每个片段由2x2样本组成.如果三角形的边缘穿过片段,则仅使用新颜色更新边缘内侧的样本.因此,如果片段仅部分位于三角形内,则可以更新4个样本中的1,2或3个.但更新的样本使用相同的颜色进行更新.因此,片段着色器只需要评估一次.

这种方法的最大优点是效率很高.与没有MSAA的渲染相比,它通常只会增加非常适度的开销.如已经建立的,着色器执行的数量保持不变.渲染目标理论上要大4倍,这可能会大大增加内存使用量.但是这种记忆通常可以有效地压缩,所以它并没有听起来那么糟糕.显然在渲染帧结束时有一个下采样步骤,这会增加开销.

缺点是MSAA只能帮助平滑三角形边界和交叉点.如果你在三角形内有明显的过渡,例如由于纹理内容,或者由于程序纹理,它根本没有帮助.Mipmapping可以减少纹理中的锯齿状边缘,并且程序纹理可以通过考虑梯度来减少锐利的过渡.但MSAA没有帮助.

如果你想要抗锯齿,从尖锐的过渡中解决所有混叠源,你可以全力以赴并使用超级采样.这意味着您以更高的分辨率渲染整个场景.例如,如果最终渲染目标的大小是w时间h,则渲染到具有大小2 * w时间的曲面,最后是2 * h下采样.这实际上更昂贵,因为您现在经常执行片段着色器4次,并且在较大表面上的压缩也不会像在MSAA表面上那样有效.

我没有使用您找到的ARB_sample_shading扩展名.但据我所知,它试图接近超级采样的视觉质量,同时至少保持MSAA的一些性能优势.