我正在使用this site.
的课程学习webgl要存储着色器,作者会在<script>
标记中声明它们:
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}
</script>
然后使用一些javascript代码来检索它们:
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3)
str += k.textContent;
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
我发现检索着色器非常复杂,所以问题很简单:
检索和编译着色器的最佳做法是什么?这是标准方法吗?我很高兴能够将着色器存储在其他文件中。
答案 0 :(得分:2)
我对webGL不是很好,但我做了一些事情。我也问自己这个问题。 我知道有三种常见的方法。第一个是你在这里提出的基本一个。 是的,它很乱,很复杂,但它有一些优点。着色器代码易于维护。
我找到的第二种方法是将着色器代码放入数组中,然后立即加入数组,使其成为一个字符串。之后,您可以将字符串传递给gl.createShader
函数。
这种技术在three.js javascript库中很常见,其中有很多着色器代码。它保持着色器的可读性,而不是像第一个那样凌乱,但维护着色器代码有点难,正如您可能看到的那样。重点是,它将允许您将所有内容保存在一个单独的javascript文件中,这是每个好库的理想行为。
小例子,这是我们的顶点着色器:
var vertexShader = [
"attribute vec3 aVertexPosition;",
"uniform mat4 uMVMatrix;",
"uniform mat4 uPMatrix;",
"void main(void) {",
"gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);",
"}"
].join( "\n" );
修改强>
有人发现了更好的方法!
var vertexShader = `attribute vec3 aVertexPosition;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}`;
编辑结束
可以处理着色器的函数
function getShader(gl, source, type) {
var shader;
if (type == "fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (type == "vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
简单的函数调用
// var fragmentShader = getShader(gl, fragmentShader, "fragment");
var vertexShader = getShader(gl, vertexShader, "vertex");
但你可能正在寻找不同的东西。因此,最好的选择是将文件设置为“myvertexshader”,然后调用ajax将该文件加载到变量中。 Jquery是不错的选择。
jQuery.get('myvertexshader', callback);
function callback(source) {
var shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, source);
gl.compileShader(shader);
...
}
然后您的着色器代码与javascript分开。您还可以设置自己的文件扩展名,并在IDE中制作不同的规则以进行着色器开发,这对于富着色器很有用。
PS:我听到一些谣言说blob文件能够编译着色器(也许它们已经是,我不确定)。