我的HTML页面(pipad.org/tmp/fourier02.html)包含两个着色器:
<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>
我希望我不会过于简单化,如果是的话,我可能需要修改。这些着色器以不同的方式使用(shaderB是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。没有比原来明显的优势。我们刚刚交换了ickyness的重复。
有更好的方法吗?
答案 0 :(得分: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);
&#13;
输出:
float plusToPlusMinus(float v) {
return v * 2.0 - 1.0;
}
...
void main() {
a = b * 3.14159;
}
答案 1 :(得分:1)
听起来你正在寻找的是template strings。它默认支持多行字符串。
如果兼容性是一个问题,shader = ["blah", "blah"].join('\n');
是IMO清洁而不是字符串连接。
答案 2 :(得分: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");