2017-06-29 262 views
0

我嘗試使平滑的高斯模糊,但我沒有任何想法如何正確地做到這一點。OpenGL es 2.0中的平滑模糊高斯

我試過這樣幾件事情:

#version 100 

precision mediump float; 

varying vec3 vColor; 
varying vec2 TexCoords; 

uniform sampler2D texture0; 
uniform float radius; 
uniform vec2 dir; 
uniform resolution; 

void main() { 

    vec4 sum = vec4(0.0); 

    vec2 tc = TexCoords; 

    float blur = radius/resolution; 

    float hstep = dir.x; 
    float vstep = dir.y; 


    sum += texture2D(texture0, vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)) * 0.0162162162; 
    sum += texture2D(texture0, vec2(tc.x - 3.0*blur*hstep, tc.y - 3.0*blur*vstep)) * 0.0540540541; 
    sum += texture2D(texture0, vec2(tc.x - 2.0*blur*hstep, tc.y - 2.0*blur*vstep)) * 0.1216216216; 
    sum += texture2D(texture0, vec2(tc.x - 1.0*blur*hstep, tc.y - 1.0*blur*vstep)) * 0.1945945946; 

    sum += texture2D(texture0, vec2(tc.x, tc.y)) * 0.2270270270; 

    sum += texture2D(texture0, vec2(tc.x + 1.0*blur*hstep, tc.y + 1.0*blur*vstep)) * 0.1945945946; 
    sum += texture2D(texture0, vec2(tc.x + 2.0*blur*hstep, tc.y + 2.0*blur*vstep)) * 0.1216216216; 
    sum += texture2D(texture0, vec2(tc.x + 3.0*blur*hstep, tc.y + 3.0*blur*vstep)) * 0.0540540541; 
    sum += texture2D(texture0, vec2(tc.x + 4.0*blur*hstep, tc.y + 4.0*blur*vstep)) * 0.0162162162; 

    gl_FragColor = vec4(vColor, 1.0) * vec4(sum.rgb, 1.0); 
} 

但結果是類似的東西: http://i.imgur.com/N6ks3Pw.png

我怎樣才能獲得更好的效果?

回答

0

您似乎是在一個正確的方式,但您的vstephstep似乎太大。應該設計一個步驟,以便只需要下一個像素,這意味着它應該是1/size,其大小等於您的情況下的紋理大小。

你只需要幾個像素周圍不會產生太多的模糊。通常你至少需要一個7x7或9x9的矩陣。你所採取的是有點奇怪,因爲這看起來像你只使用當前像素周圍的一些對角線值。

在概念的結果應該是這樣的

for(horizontalOffset = -radius; horizontalOffset<radius; horizontalOffset += step) { 
    for(verticalOffset = -radius; verticalOffset<radius; verticalOffset += step) { 
     sum += texture2D(texture, textureCoordinate+vec2(horizontalOffset, verticalOffset))*gaussFactorForOffset(sqrt(horizontalOffset*horizontalOffset + verticalOffset*verticalOffset)/radius); 
    } 
} 

這是有點慢,但因爲對於具有7個步驟的實例將產生49訪問其使得O2質地。您可以通過將其分成2個繪製調用進行優化,其中一個是創建垂直模糊,另一個是水平模糊。這意味着你需要2個着色器,其中一個只有一個垂直循環,另一個只有水平循環。結果是你有14次調用紋理的7個步驟,這樣就可以花費20多次繪製調用並在內存中擁有另一個紋理(除非你可以重複使用原始紋理進行第二次繪製調用)。

此外,您還可以在頁面上找到大量着色器,例如this one。他們通常沒有優化,但他們至少可以讓你有一個地方開始。

+0

Hello @Matic對於遲到的回覆感到抱歉,我不明白你所說的「你正在服用雖然有點奇怪,因爲這看起來像你只使用當前像素周圍的一些對角線值」,如果vstep和hstep設置爲1,它會做一個對角線(vstep和hstep是模糊高斯的方向)。 對於你的例子,我嘗試避免循環,因爲我使用GLSL 1.00,它不需要統一(條件表達式的右邊必須是常量),但如果你知道解決這個我真的想知道的其他問題。 謝謝 – KeurKeur

+0

你不需要循環,但你需要NxN調用,而不是N.偏移量必須像(-4,-4),(-3,-4)...(+4,-4) ,(-4,-3),(-3,-3)...(+4,+4)。你必須通過一些偏移量訪問當前周圍的所有像素,在你的情況下是4,這樣就可以進行9x9的調用。 –

+0

嗨,謝謝你的工作。它有點慢,但它的工作原理再次感謝:) – KeurKeur