2016-04-28 78 views
1

我的HTML頁面(pipad.org/tmp/fourier02.html)之間共享包含兩個着色器:一個函數避免重複代碼2個GLSL着色器

<script type="application/glsl" id="shaderA"> 
    uniform vec4 a; 
    vec4 f(vec4 x, vec4 y){ ... } // DUP 
    vec4 main(vec4 u, vec4 v) { return f(a,u); } 
</script> 

<script type="application/glsl" id="shaderB"> 
    uniform vec4 a; 
    vec4 f(vec4 x, vec4 y){ ... } // DUP 
    vec4 main(vec4 u) { return f(a,u); } // notice main's sig is different 
</script> 

我希望我沒有簡單化,我可以有如果我是修改。這些着色器以不同的方式使用(着色器B是RTT)。

可以看出,f在兩種情況下都是相同的。

有沒有辦法避免兩次寫?

我能看到的唯一方法是保持着色器爲字符串,因爲語法高亮不再工作這是混亂的,你要做的:

: 
var 
f = 
    "vec4 f(vec4 x, vec4 y){\n" + 
    "...\n" + 
    "}\n", 

shaderA = f + 
    "uniform vec4 a;\n" + 
    "vec4 main(vec4 u, vec4 v) { return f(a,u); }\n", 

shaderB = f + 
    "uniform vec4 a;\n" + 
    "vec4 main(vec4 u) { return f(a,u); }\n" 
; 

這是... MEH。沒有明顯的優勢。我們剛剛交換了瑣碎的重複。

有沒有更好的方法?

回答

2

正如你已經發現,字符串處理是製作着色器的常用方法。幾乎所有大型引擎都使用大量字符串替換來在運行時構建着色器。 WaclawJasper指出了模板字符串。它們是JavaScript的一項新功能,但由於幾乎所有支持WebGL的瀏覽器都可以獲得定期更新,因此您可以非常安全地使用它,也可以使用polyfill。

var t = { 
 
    PI: '3.14159', 
 
    plusToPlusMinus: ` 
 
    float plusToPlusMinus(float v) { 
 
     return v * 2.0 - 1.0; 
 
    } 
 
    `, 
 
}; 
 

 
var shader = ` 
 
    ${t.plusToPlusMinus} 
 
    ... 
 
    void main() { 
 
    a = b * ${t.PI}; 
 
    } 
 
`; 
 

 
console.log(shader);

輸出:

float plusToPlusMinus(float v) { 
    return v * 2.0 - 1.0; 
    } 

... 
void main() { 
a = b * 3.14159; 
} 
1

聽起來像你要找的是template strings。它默認支持多行字符串。

如果兼容性問題,shader = ["blah", "blah"].join('\n');是比字符串串聯更清潔的IMO。

1

在我搬出我的常見功能到一個單獨的<script type="application/glsl" id="common">標籤,並沒有結束:

<script> 
    : 
    function joinElements(A,B) { 
     return document.getElementById(A).innerHTML 
      + document.getElementById(B).innerHTML; 
    } 
    : 

...然後代替"#shaderA"joinElements("#common", "shaderA");