如何将着色器包含为外部文件
How to include shaders as external files
有没有办法将此着色器代码作为外部 vertexShader.js 不带引号包含在 "script" 标记之间?
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'gl_PointSize = 10.0;'+
'}';
您可以将着色器代码添加到 <script>
标记中,顶点着色器类型为 "x-shader/x-vertex"
,片段着色器类型为 "x-shader/x-fragment"
。
另见 WebGL and HTML shader-type
<script id="my_vertex_shader" type="x-shader/x-vertex">
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;
}
</script>
<script id="my_fragment_shader" type="x-shader/x-fragment">
// fragment shader code
</script>
着色器代码可以轻松“加载”:
var vertCode = document.getElementById("my_vertex_shader").text;
var fragCode = document.getElementById("my_fragment_shader").text;
WebGL - is there an alternative to embedding shaders in HTML? 可能也很有趣。
您询问了如何将着色器包含为外部文件
有几种方法,但首先要注意的是,对称为 multiline template literals 的字符串使用反引号可以让您拥有多行字符串
const str = `
this
string
is
on
multiple lines
`;
所以没有必要像你一样使用 'this' + 'that'。
如果您真的想将它们放在单独的文件中,那么至少有 3 种方法可以做到这一点
将它们放在单独的脚本文件中,分配给一些全局的。例子
vertexShader.js
window.shaders = window.shaders || {};
window.shaders.someVertexShader = `
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;'
}
`;
在你的 html
<script src="vertexShader.js"></script>
<script>
// use shader as window.shaders.someVertexShader
...
</script>
请注意,您的最终 JavaScript 脚本也可以位于单独的文件中,只要它位于着色器文件之后即可。
将它们放在单独的 JavaScript 模块中
现代浏览器支持 ES6 modules
vertexShader.js
export default `
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;'
}
`;
在这种情况下,您的 JavaScript 脚本 必须 位于外部文件中,以便您
HTML 可能看起来像这样
<script src="main.js" type="module"></script>
和main.js看起来像这样
import someVertexShader from './vertexShader.js';
// use someVertexShader
有个例子here
- 加载它们
在这种情况下,着色器文件中没有 JavaScript
vertexShader.shader
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;'
}
然后在你的脚本中
fetch('./vertexShader.shader')
.then(response => response.text())
.then((shaderSource) => {
// use shadeSource
});
这种方法最大的问题是脚本是异步下载的,所以你必须手动等待它们下载。不过使用 async/await 非常简单。
假设您想下载 6 个着色器文件然后使用它们。此代码将等待所有 6 个文件在开始之前下载
function loadTextFile(url) {
return fetch(url).then(response => response.text());
}
const urls = [
'./someShader1.shader',
'./someShader2.shader',
'./someShader3.shader',
'./someShader4.shader',
'./someShader5.shader',
'./someShader6.shader',
});
async function main() {
const files = await Promise.all(urls.map(loadTextFile));
// use files[0] thru files[5]
}
main();
如果是我,我真的想把我的着色器放在外部文件中,我可能会使用 import
,然后要么只针对现代浏览器,要么使用像 webpack or rollup to package them into a single file for shipping. This is what THREE.js 这样的程序.
有没有办法将此着色器代码作为外部 vertexShader.js 不带引号包含在 "script" 标记之间?
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'gl_PointSize = 10.0;'+
'}';
您可以将着色器代码添加到 <script>
标记中,顶点着色器类型为 "x-shader/x-vertex"
,片段着色器类型为 "x-shader/x-fragment"
。
另见 WebGL and HTML shader-type
<script id="my_vertex_shader" type="x-shader/x-vertex">
attribute vec3 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 1.0);
gl_PointSize = 10.0;
}
</script>
<script id="my_fragment_shader" type="x-shader/x-fragment">
// fragment shader code
</script>
着色器代码可以轻松“加载”:
var vertCode = document.getElementById("my_vertex_shader").text;
var fragCode = document.getElementById("my_fragment_shader").text;
WebGL - is there an alternative to embedding shaders in HTML? 可能也很有趣。
您询问了如何将着色器包含为外部文件
有几种方法,但首先要注意的是,对称为 multiline template literals 的字符串使用反引号可以让您拥有多行字符串
const str = `
this
string
is
on
multiple lines
`;
所以没有必要像你一样使用 'this' + 'that'。
如果您真的想将它们放在单独的文件中,那么至少有 3 种方法可以做到这一点
将它们放在单独的脚本文件中,分配给一些全局的。例子
vertexShader.js
window.shaders = window.shaders || {}; window.shaders.someVertexShader = ` attribute vec3 coordinates; void main(void) { gl_Position = vec4(coordinates, 1.0); gl_PointSize = 10.0;' } `;
在你的 html
<script src="vertexShader.js"></script> <script> // use shader as window.shaders.someVertexShader ... </script>
请注意,您的最终 JavaScript 脚本也可以位于单独的文件中,只要它位于着色器文件之后即可。
将它们放在单独的 JavaScript 模块中
现代浏览器支持 ES6 modules
vertexShader.js
export default ` attribute vec3 coordinates; void main(void) { gl_Position = vec4(coordinates, 1.0); gl_PointSize = 10.0;' } `;
在这种情况下,您的 JavaScript 脚本 必须 位于外部文件中,以便您 HTML 可能看起来像这样
<script src="main.js" type="module"></script>
和main.js看起来像这样
import someVertexShader from './vertexShader.js'; // use someVertexShader
有个例子here
- 加载它们
在这种情况下,着色器文件中没有 JavaScript
vertexShader.shader
attribute vec3 coordinates; void main(void) { gl_Position = vec4(coordinates, 1.0); gl_PointSize = 10.0;' }
然后在你的脚本中
fetch('./vertexShader.shader') .then(response => response.text()) .then((shaderSource) => { // use shadeSource });
这种方法最大的问题是脚本是异步下载的,所以你必须手动等待它们下载。不过使用 async/await 非常简单。
假设您想下载 6 个着色器文件然后使用它们。此代码将等待所有 6 个文件在开始之前下载
function loadTextFile(url) { return fetch(url).then(response => response.text()); } const urls = [ './someShader1.shader', './someShader2.shader', './someShader3.shader', './someShader4.shader', './someShader5.shader', './someShader6.shader', }); async function main() { const files = await Promise.all(urls.map(loadTextFile)); // use files[0] thru files[5] } main();
如果是我,我真的想把我的着色器放在外部文件中,我可能会使用 import
,然后要么只针对现代浏览器,要么使用像 webpack or rollup to package them into a single file for shipping. This is what THREE.js 这样的程序.