2014-05-20 46 views
0

我從網上找到了一個簡單而美麗的綻放着色器,但速度相對較慢。綻放着色器性能

從外觀上看,這裏的罪魁禍首是嵌套循環和紋理查找。

我該如何讓這個運行更快?

uniform sampler2D u_texture; 
varying vec2 v_texCoords; 
void main() { 
    vec4 sum = vec4(0); 
    vec2 texcoord = vec2(v_texCoords); 
    int j; 
    int i; 

    for (i = -2; i < 2; i++) { 
     for (j = -2; j < 2; j++) { 
      sum += texture2D(u_texture, texcoord + vec2(j, i)*0.004) * 0.25; 
     } 
    } 
    if (texture2D(u_texture, texcoord).r < 0.3) { 
     gl_FragColor = sum*sum*0.012 + texture2D(u_texture, texcoord); 
    } else { 
     if (texture2D(u_texture, texcoord).r < 0.5) { 
      gl_FragColor = sum*sum*0.009 + texture2D(u_texture, texcoord); 
     } else { 
      gl_FragColor = sum*sum*0.0075 + texture2D(u_texture, texcoord); 
     } 
    } 
} 
+0

時排除這些部分(所以着色器不會在這些像素上運行),這是bloom問題,因爲速度很慢它在該嵌套循環中查詢紋理25次 –

+0

這是一個可分離的過濾器,有時兩遍(水平和垂直)比1快 - 特別是當你開始使用更大的樣本窗口(這是一個5x5的內核)。您還可以利用硬件的內置功能快速對4個像素進行採樣和平均(線性濾波)。 –

+0

Err,現在我更仔細地看,這是一個4x4的內核。你爲什麼這麼做?我認爲你的循環應該包括*** I,j = 2而不是*結尾*。理想情況下,它將被分成兩個通道,所以每次通過我只有[-2,2] = 5次取回。 –

回答

0

我不能確定是否 '手動優化' GLSL使任何意義,但可嘗試:

  • UNROLL手動循環(對於(I = -2;我< 2;我++),對於(j = -2; j < 2; j ++)),它會給你16行而不是5,但'優化'代碼通常看起來'不夠優雅',通常這個操作應該由編譯器來完成...
  • 在向量中存儲texture2D(u_texture,texcoord)
  • 不要重複計算sum * su米
  • 結果應類似於: uniform sampler2D u_texture; varying vec2 v_texCoords; void main() { vec4 sum = vec4(0); vec4 col = vec4(0); vec2 texcoord = vec2(v_texCoords); sum += texture2D(u_texture, texcoord + vec2(-2, -2)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(-2, -1)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(-2, 0)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(-2, 1)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(-1, -2)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(-1, -1)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(-1, 0)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(-1, 1)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(0, -2)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(0, -1)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(0, 0)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(0, 1)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(1, -2)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(1, -1)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(1, 0)*0.004) * 0.25; sum += texture2D(u_texture, texcoord + vec2(1, 1)*0.004) * 0.25; sum *= sum; col = texture2D(u_texture, texcoord); if (col.r < 0.3) { gl_FragColor = 0.012 + col; } else { if (col.r < 0.5) { gl_FragColor = sum * 0.009 + col; } else { gl_FragColor = sum * 0.0075 + col; } } } 您也可以考慮尋找一些更具體的GLSL優化技巧(紋理拾取),優化工具等
+0

您也可以在總和結束時進行乘法運算 –

+0

手動展開循環似乎有問題。您不知道在所有架構上展開的版本是否會更快。編譯器應該能夠對展開是否有益作出更多的教育決定。正如@ratchetfreak指出的那樣,你可以消除一些操作。而中心點的紋理查找仍然是兩次。但我懷疑這些都是小小的改進。 25個紋理查找將很有可能控制其他所有內容。 –

+0

爲什麼25?它完成了我,j:{-2,-1,0,1}所以「只是」16,我錯了嗎? – jaroslawj

0

的事情,我在着色器看到一個是它不需要運行時col.r < 0.3這意味着,使用模板時,您可以在運行盛放着色器