着色器:存储它们的最佳实践 [英] Shaders : Best practice to store them
问题描述
我正在通过本网站的课程学习 webgl.
为了存储着色器,作者在 标签中声明它们:
To store the shaders, the author declares them in a <script>
tag :
<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代码来检索它们:
Then uses some javascript code to retrieve them:
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;
}
我发现检索着色器很复杂,所以问题很简单:
I find it quite complex to retrieve the shader, so the question is quite simple :
检索和编译着色器的最佳做法是什么?这是标准方法吗?如果能够将着色器存储在其他文件中,我将不胜感激.
What is the best practice to retrieve and compile shaders? Is this the standard way? I would appreciate to be able to store shaders in other files.
推荐答案
我不太擅长 webGL,但我做了一些事情.我也在问自己这个问题.我知道有 3 种常用方法.第一个是您在此处介绍的基本内容.是的,它很乱,很复杂,但它有一些优点.着色器代码易于维护.
Im not very good in webGL, but I did some stuff. I was asking myself that question too. There are 3 common ways, that I know. First one is the basic one that you presented here. Yeah, it is messy, it is complicated, but it have some advantages. Shader code is easy to maintain.
我发现的第二种方法是将着色器代码放入数组,然后立即加入数组,使其成为字符串.之后,您可以将字符串传递给 gl.createShader
函数.
Second way that I found is put shader code into array, then join the array immediately, so it become a string. After that, you can pass string to gl.createShader
function.
这种技术在three.js javascript库中很常见,那里有大量的着色器代码.它使着色器保持人类可读性,不像第一个那样凌乱,但维护着色器代码有点困难,正如您可能看到的.主要的一点是,它将允许您将所有内容保存在一个单一的 javascript 文件中,这是每个优秀库都希望拥有的行为.
This technique is pretty common in three.js javascript library, where is plenty of shader code. It keeps shader human readable and not that messy as the first one, but maintaining shader code is a little bit harder, as you probably see. The main point is, that it will allows you to keep everything in one single javascript file, which is desired behavior of every good library.
小例子,这是我们的顶点着色器:
Small example, this is our vertex shader:
var vertexShader = [
"attribute vec3 aVertexPosition;",
"uniform mat4 uMVMatrix;",
"uniform mat4 uPMatrix;",
"void main(void) {",
"gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);",
"}"
].join( "\n" );
编辑
有人找到了更好的方法!
Someone has found a much better way of doing this!
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 是不错的选择.
But you are probably looking for something different. So the best option for you is to make file like "myvertexshader" and then call ajax to load that file into variable. Jquery is good option.
jQuery.get('myvertexshader', callback);
function callback(source) {
var shader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(shader, source);
gl.compileShader(shader);
...
}
然后您的着色器代码与 javascript 分离.您还可以设置您自己的文件扩展名,并在您的 IDE 中为着色器开发制定不同的规则,这对于丰富的着色器来说是个好主意.
Then your shader code is separated from javascript. You can also setup your own file extension and make different rules in your IDE for shader development, which is good idea for rich shaders.
PS:我听到一些传言说 blob 文件将能够编译着色器(也许它们已经是了,我不确定).
PS: I heard some rummors that blob files will be able to compile shaders (maybe they already are, Im not sure).
这篇关于着色器:存储它们的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!