Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

glsl

webgl

The popular way of using GLSL shaders in WebGL seems to be to embed them in the main html file. The vertex and fragments shaders are embedded in tags like:

<script id="shader-fs" type="x-shader/x-fragment">

This is the same convention I see in the WebGL samples in the Mozilla Developer Network page.

This works fine for simple apps, but when you have a complex app with a number of shaders, the html file gets cluttered. (I keep editing the wrong shader!) Also if you want to reuse your shaders, this scheme is inconvenient.

So I was thinking about putting these shaders in a separate XML files and loading them using XMLHttpRequest(). Then I saw that someone else had the same idea:

http://webreflection.blogspot.com/2010/09/fragment-and-vertex-shaders-my-way-to.html

I like the suggestion to use .c files, since that gives you syntax highlighting and other editor conveniences for GLSL.

But the issue with the above approach is that (as far as I understand) XMLHttpRequest() cannot load a local .c file - ie, on the client side - while you are developing and testing the WebGL app. But it is cumbersome to keep uploading it to the server during this process.

So if I want to keep the shaders out of the html file, is the only option to embed them as strings in the code? But that would make it hard to write as well as debug...

I'd appreciate any suggestions on managing multiple GLSL shaders in WebGL apps.

Regards

Edit (May 05 2011)

Since I use a Mac for development, I decided to enable Apache server, and put my webgl code under http://localhost/~username/. This sidesteps the issue of file: protocol being disabled during development. Now the javascript file loading code works locally since http: is used, rather than file:. Just thought I'd put this up here in case anyone finds it useful.

like image 796
M-V Avatar asked May 04 '11 04:05

M-V


People also ask

Does WebGL use shaders?

As mentioned in how it works WebGL requires 2 shaders every time you draw something. A vertex shader and a fragment shader. Each shader is a function.

What shader language does WebGL use?

Shaders are the programs that run on GPU. Shaders are written in OpenGL ES Shader Language (known as ES SL). ES SL has variables of its own, data types, qualifiers, built-in inputs and outputs.

How do I use WebGL multiple shaders?

So, if you want to render two objects with two different shaders, you should bind one object (it's buffers actually), use first material ( gl. useProgram(shaderProgramA) ) and dispatch draw. Then bind second object, set second material ( gl. useProgram(shaderProgramB) ) and dispatch another call.


2 Answers

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;   } `; 
like image 186
Giles Thomas Avatar answered Nov 12 '22 00:11

Giles Thomas


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.

like image 41
Valer Avatar answered Nov 12 '22 00:11

Valer