多重采样似乎不适用于片段着色器生成的片段。 在下面的示例中,片段着色器用于生成检查板程序纹理。 正方形的外边缘是正确的抗锯齿,但程序纹理的内边缘不是。
片段着色器是否仅针对每个像素进行评估? 或者给定像素的每个片段的纹理坐标是否相同?
下面是代码,image显示其输出(请注意,白色和灰色方块之间的程序边缘不是抗锯齿的,而黑色和白色/灰色之间的几何边缘是:)
#!/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()
答案 0 :(得分:6)
这是MSAA(多重采样抗锯齿)的基本思想。片段着色器仅对每个片段执行一次。然后使用样本掩码来控制将结果片段写入哪些样本。
假设你使用4x MSAA,其中每个片段由2x2个样本组成。如果三角形的边缘穿过片段,则仅使用新颜色更新边缘内侧的样本。因此,如果片段仅部分位于三角形内,则可以更新4个样本中的1,2或3个。但 更新的样本都使用相同颜色进行更新。因此,片段着色器只需要进行一次评估。
这种方法的最大优点是效率很高。与没有MSAA的渲染相比,它通常只会增加非常适度的开销。如已经建立的,着色器执行的数量保持不变。渲染目标理论上要大4倍,这可能会大大增加内存使用量。但是这种记忆通常可以有效地压缩,所以它并没有听起来那么糟糕。显然,在渲染帧结束时会有一个下采样步骤,这会增加开销。
缺点是MSAA只能帮助平滑三角形边界和交叉点。如果您在三角形内有明显的过渡,例如由于纹理内容,或由于程序纹理,它根本没有帮助。 Mipmapping可以减少纹理中的锯齿状边缘,并且程序纹理可以通过考虑梯度来减少锐利的过渡。但MSAA没有帮助。
如果你想要抗锯齿,从尖锐的过渡中解决所有混叠源,你可以全力以赴并使用超级采样。这意味着您以更高的分辨率渲染整个场景。例如,如果最终渲染目标的大小为w
次h
,则渲染到大小为2 * w
次2 * h
的曲面,并在最后进行缩减。这是基本更昂贵,因为您现在经常执行片段着色器4次,并且在较大表面上的压缩也不会像在MSAA表面上那样有效。
我没有使用您找到的ARB_sample_shading extension。但据我所知,它试图接近超级采样的视觉质量,同时至少保持MSAA的一些性能优势。
答案 1 :(得分:0)
需要sample_shading扩展名:&#34;在标准多重采样渲染中,允许实现为每个样本指定相同的颜色和纹理坐标值,然后允许仅在评估着色器的情况下进行优化一次,然后分发到已被确定为当前被栅格化的原语覆盖的样本。&#34;