WebGL - is there an alternative to embedding shaders in HTML?

Following @droidballoon's hint I ended up using stack.gl which "is an open software ecosystem for WebGL, built on top of browserify and npm".

Its glslify provides a browserify transform which can be used in conjunction with gl-shader in order to load shaders. The Javascript would look something like this:

var glslify       = require('glslify');
var loadShader    = require('gl-shader');
var createContext = require('gl-context');

var canvas = document.createElement('canvas');
var gl = createContext(canvas);

var shader = loadShader(
    gl,
    glslify('./shader.vert'),
    glslify('./shader.frag')
);

EDIT 2021 this answer is antiquated. You should probably look for something else.


I've been using require.js's text plugin.

Here's a snippet:

define(
    /* Dependencies (I also loaded the gl-matrix library) */
    ["glmatrix", "text!shaders/fragment.shader", "text!shaders/vertex.shader"],
    
    /* Callback when all has been loaded */
    function(glmatrix, fragmentShaderCode, vertexShaderCode) {
        ....
        var vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, vertexShaderCode);
        gl.compileShader(vertexShader);
        ....
    }
);

The directory structure is as follows:

~require-gl-shaders/
 |~js/
 | |+lib/
 | |~shaders/
 | | |-fragment.shader
 | | `-vertex.shader
 | |-glmatrix.js - gl-matrix library
 | |-shader.js
 | |-text.js     - require.js's text plugin
 |-index.html
 |-main.js
 `-require.js    - the require.js library

Personally, I had a little bit of learning curve with require, but it really helped me keep cleaner code.


Yup, a local server's really the only way to go if you want to use XHR. I've written a bunch of WebGL lessons, and have often considered moving away from embedding the shaders in the HTML, but have been scared off by amount of explanation about web security I'd need to write...

Fortunately it's super easy to run a server. Just open a shell then

cd path-to-files
python -m SimpleHTTPServer

Then point your browser to

http://localhost:8000

That works for simple cases like textures and GLSL. For video and audio streaming see

What is a faster alternative to Python's http.server (or SimpleHTTPServer)?

On the other hand every browser that supports WebGL supports ES6 mutli-line template literals so if you don't care about old browsers you can just put you shaders in JavaScript using backticks like this

var vertexShaderSource = `
  attribute vec4 position;
  uniform mat4 u_matrix;

  void main() {
    gl_Position = u_matrix * position;
  }
`;

Tags:

Glsl

Webgl