The book is mainly focused on "real OpenGL development", something surely more suitable for tough C/C++ developers rather than Web Monkeys like me but since the book includes an OpenGL ES 2.0 related part, and since latter spec is basically what we can find in WebGL, it's always better start learning what's next knowing history and background of the used technology ... and here I am :-)
Something Already Wrong
I am not completely sure about "who started this techniques", John Resig with his micro template inside script nodes with a type text/html may be the indirect responsible for a sort of growing "monster" we can see in almost every WebGL related example ...HTML Embedded Shaders, the Web 3.0 NO-GO
Let me pass the therm, but 3D websites are not that far away from reality. Minefield, Chrome, WebKit, and probably others, are working hard with Khronos and WebGL and I do believe official support will come later this year with next browsers releases ( ... hoping IE9 final won't "block the world" avoiding WebGL support ... )Back in the topic, the common examples technique is a step backward in 1999 where runtime loading did not exists (aka: Ajax or scripts injection) and an HTML page was a trash bin for any kind of rubbish.
A Better Technique
We are in 2010 and we want use latest technologies, so why should we use old and deprecated one? Let me show this simple getShader function alternative:
// our shaders base path
loadShaders.base = "shader/";
// our shaders loader
function loadShaders(gl, shaders, callback) {
// (C) WebReflection - Mit Style License
function onreadystatechange() {
var
xhr = this,
i = xhr.i
;
if (xhr.readyState == 4) {
shaders[i] = gl.createShader(
shaders[i].slice(0, 2) == "fs" ?
gl.FRAGMENT_SHADER :
gl.VERTEX_SHADER
);
gl.shaderSource(shaders[i], xhr.responseText);
gl.compileShader(shaders[i]);
if (!gl.getShaderParameter(shaders[i], gl.COMPILE_STATUS))
throw gl.getShaderInfoLog(shaders[i])
;
!--length && typeof callback == "function" && callback(shaders);
}
}
for (var
shaders = [].concat(shaders),
asynchronous = !!callback,
i = shaders.length,
length = i,
xhr;
i--;
) {
(xhr = new XMLHttpRequest).i = i;
xhr.open("get", loadShaders.base + shaders[i] + ".c", asynchronous);
if (asynchronous) {
xhr.onreadystatechange = onreadystatechange;
}
xhr.send(null);
onreadystatechange.call(xhr);
}
return shaders;
}
With above minifier friendly function we can avoid shaders on the page. The natural advantage is that we can properly organize shaders in a structure like this one:
root
shader
vs // vertex shaders
ShaderName.c
fs // fragment shaders
FragmentName.c
Having a proper extension means that we can edit these files with highlighted syntax and we can edit these files a part, without looking for id or scripts inside an HTML page. Fragment and Vertex Shaders are our "application templates", so why on earth should we include them in the layout? Via loadShaders we can use cached shaders, share shaders, etc etc, and here some usage example.
vra gl = canvas.getContext("experimental-webgl");
// synchronous order, one shader
var myFragmentShader = loadShaders(gl, "fs/myFragment");
// synch, more shaders
var shaders = loadShaders(gl, [
"vs/what",
"vs/ever"
]);
// [whatShader, everShader]
// asynchronous loading
loadShaders(gl, ["fs/what", "vs/ever"], function (shaders) {
var
fragmentWhatShader = shaders[0],
vertexEverShader = shaders[1];
;
});
// asynch in "don't care mode, just cache them"
loadShaders(gl, ["fs/what", "vs/ever"], true);
Features
- Synchronous or Asynchronous loading
- Multiple Loads (unordered compilation for each result)
- Ordered Results, (order respected accordingly with paths)
Cheers :)
No comments:
Post a Comment