2014-01-14 72 views
0

多重採樣似乎不適用於由片段着色器生成的片段。 在下面的示例中,片段着色器用於生成檢查板程序紋理。 正方形的外邊緣適當反鋸齒,但程序紋理的內邊緣不是。多重採樣和片段着色器

片段着色器僅對每個像素進行評估嗎? 或者給定像素的每個片段的紋理座標是否相同?

下面是代碼和image示出它的輸出(注意-between白色和灰色正方形程序邊緣不抗鋸齒,而幾何邊緣-between黑白/格雷是):

#!/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

這是哪一種語言? – Vallentin

+0

python/python3與pyopengl,但問題是不依賴於語言。如果有幫助,我可以添加一個C版本。 – rndblnch

+0

好吧,看起來像我需要[sample_shading](http://www.opengl.org/registry/specs/ARB/sample_shading.txt)擴展名: 「在標準多重採樣渲染中,允許實現分配相同的顏色和紋理座標值,然後允許進行優化,其中着色器只被評估一次,然後分佈到已確定被當前被柵格化的圖元覆蓋的樣本。「 – rndblnch

回答

0

需要擴展sample_shading:「在標準多重採樣渲染中,允許實現爲每個採樣分配相同的顏色和紋理座標值,然後允許優化,其中着色器僅評估一次,然後分配給樣本已被確定爲被當前被柵格化的原始圖像覆蓋「。

5

這是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的一些性能優勢。

+0

如果片段位於多個三角形中,該怎麼辦?例如,如果樣本1和2位於三角形A中,而樣本3和4位於三角形B中,是否意味着必須調用片段着色器兩次,每個三角形都有一個? –