'How to include shaders as external files
Is there a way to include this shader code as an external vertexShader.js without quotes and include between "script" tags?
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'gl_PointSize = 10.0;'+
'}';
Solution 1:[1]
You asked how to include shaders as external files
There are several ways but first off it's important to note that using backticks for strings which are called multiline template literals let you have multiline strings
const str = `
this
string
is
on
multiple lines
`;
So there's no need to use 'this' + 'that' as you were doing.
If you really want to put them in separate files though then here's at least 3 of the many ways you could do it
put them in separate script files, assign to some global. Example
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;' } `;
in your html
<script src="vertexShader.js"></script> <script> // use shader as window.shaders.someVertexShader ... </script>
Note that your final JavaScript script could also be in a separate file just as long as it comes after the shader files.
Put them in a separate JavaScript module
Modern browsers support ES6 modules
vertexShader.js
export default ` attribute vec3 coordinates; void main(void) { gl_Position = vec4(coordinates, 1.0); gl_PointSize = 10.0;' } `;
In this case your JavaScript script must be in an external file so your HTML might look something like this
<script src="main.js" type="module"></script>
and main.js would look something like this
import someVertexShader from './vertexShader.js'; // use someVertexShader
There's an example here
Load them with
fetch
In this case there's no JavaScript in the shader file
vertexShader.shader
attribute vec3 coordinates; void main(void) { gl_Position = vec4(coordinates, 1.0); gl_PointSize = 10.0;' }
Then in your script
fetch('./vertexShader.shader') .then(response => response.text()) .then((shaderSource) => { // use shadeSource });
The biggest problem with this method is the scripts are downloaded asynchronously so you have to manually wait for them to download. Using async/await that's pretty easy though.
Imagine you wanted to download 6 shaders files and then use them. This code would wait for all 6 files to download before starting
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();
If it was me and I really wanted to put my shaders in external files I'd probably use import
and then either only target modern browsers or else use some program like webpack or rollup to package them into a single file for shipping. This is what THREE.js currently does.
Solution 2:[2]
You can add the shader code to a <script>
tag of type "x-shader/x-vertex"
for the vertex shader and "x-shader/x-fragment"
for the fragment shader.
See also 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>
The shader code can be "loaded" with ease:
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? may be of interest, too.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | gman |
Solution 2 |