Skip to content
Browse files

Minor refactor to allow single file version of webglu, also created s…

…imple python script to do the merge
  • Loading branch information...
1 parent cbba406 commit 34f918c3f40541359cf7eedb7adc500632f3727f Benjamin DeLillo committed
Showing with 8,340 additions and 3,487 deletions.
  1. +135 −135 src/Animation.js
  2. +151 −150 src/Constants.js
  3. +19 −23 src/DefaultUniformActions.js
  4. +99 −96 src/Framebuffer.js
  5. +552 −550 src/GLSL.js
  6. +187 −186 src/GLU.js
  7. +137 −136 src/Material.js
  8. +354 −346 src/Object.js
  9. +57 −55 src/Renderer.js
  10. +101 −99 src/Texture.js
  11. +746 −741 src/Util.js
  12. +777 −774 src/crazyglu.js
  13. +184 −182 src/gameglu.js
  14. +18 −0 src/mergeModules.py
  15. +4,810 −0 src/webglu.complete.js
  16. +13 −14 src/webglu.js
View
270 src/Animation.js
@@ -1,168 +1,168 @@
-/** @class A procedurally generated animation.
- * Starts updating immediately.
- */
-$W.ProceduralAnimation = function ProceduralAnimation() {
- $W.ObjectState.call(this); // subclass of ObjectState
+$W.initAnimation = function() {
+ /** @class A procedurally generated animation.
+ * Starts updating immediately.
+ */
+ $W.ProceduralAnimation = function ProceduralAnimation() {
+ $W.ObjectState.call(this); // subclass of ObjectState
- /** XXX The right way to do this? */
- var ptyp = $W.ProceduralAnimation.prototype;
+ /** XXX The right way to do this? */
+ var ptyp = $W.ProceduralAnimation.prototype;
- /** The time in milliseconds since this animation began */
- this.age = 0;
+ /** The time in milliseconds since this animation began */
+ this.age = 0;
- /** Call to advance the animation by `dt` milliseconds */
- this.update = function(dt){};
- this._update = function(dt){};
+ /** Call to advance the animation by `dt` milliseconds */
+ this.update = function(dt){};
+ this._update = function(dt){};
- /** Internal.
- * @return {Function} Update this animation.
- */
- this._play = function(dt) {
- this.preUpdate(dt);
+ /** Internal.
+ * @return {Function} Update this animation.
+ */
+ this._play = function(dt) {
+ this.preUpdate(dt);
- this.age += dt;
+ this.age += dt;
- this._update(dt);
+ this._update(dt);
- this.updatePosition(dt);
- this.updateRotation(dt);
- this.updateScale(dt);
+ this.updatePosition(dt);
+ this.updateRotation(dt);
+ this.updateScale(dt);
- this.postUpdate(dt);
- }
+ this.postUpdate(dt);
+ }
- /** Internal.
- * @return {Function} Do nothing.
- */
- this._pause = function() { }
+ /** Internal.
+ * @return {Function} Do nothing.
+ */
+ this._pause = function() { }
- /** This animation will advance on subsequent update()
- * calls.
- */
- this.play = function() {
- this.update = this._play;
- }
+ /** This animation will advance on subsequent update()
+ * calls.
+ */
+ this.play = function() {
+ this.update = this._play;
+ }
- /** This animation will not change on subsequent update()
- * calls.
- */
- this.pause = function() {
- this.update = this._pause;
- }
+ /** This animation will not change on subsequent update()
+ * calls.
+ */
+ this.pause = function() {
+ this.update = this._pause;
+ }
- /** Called before `dt` is added to this.age
- * Does nothing by default.
+ /** Called before `dt` is added to this.age
+ * Does nothing by default.
+ */
+ this.preUpdate = function(dt){}
+
+ /** Update the position. Does nothing by default. */
+ this.updatePosition = function(dt){}
+ /** Update the rotation. Does nothing by default. */
+ this.updateRotation = function(dt){}
+ /** Update the scale. Does nothing by default. */
+ this.updateScale = function(dt){}
+
+ /** Called after all other update calls.
+ * Does nothing by default.
+ */
+ this.postUpdate = function(dt){}
+
+ this.play();
+ };
+
+
+ /** @class A single frame of animation.
+ * A position, rotation, and scale at a particular point in time.
+ *
+ * @param {3 Array} pos Position.
+ * @param {3 Array} rot Rotation.
+ * @param {3 Array} scl Scale.
+ * @param {Number} atTime Time, in seconds, this keyframe occurs at.
*/
- this.preUpdate = function(dt){}
-
- /** Update the position. Does nothing by default. */
- this.updatePosition = function(dt){}
- /** Update the rotation. Does nothing by default. */
- this.updateRotation = function(dt){}
- /** Update the scale. Does nothing by default. */
- this.updateScale = function(dt){}
+ $W.Keyframe = function Keyframe(pos, rot, scl, atTime) {
+ if (arguments.length == 4) {
+ $W.ObjectState.call(this, pos, rot, scl); // Subclass ObjectState
+ this.atTime = atTime * 1000; // time, in seconds, this keyframe occurs at
+ }else {
+ $W.ObjectState.call(this);
+ this.atTime = 0;
+ }
+ };
- /** Called after all other update calls.
- * Does nothing by default.
+ /** @class A keyframe based animation
+ * Rotations interpolation uses quaternions.
*/
- this.postUpdate = function(dt){}
-
- this.play();
-};
+ $W.KeyFrameAnimation = function() {
+ $W.ProceduralAnimation.call(this); // Subclass ProceduralAnimation
+ this.keyframes = [];
+ /** Frame index to interpolate from. */
+ this.A = 0;
+ /** Frame index to interpolate to. */
+ this.B = 1;
-/** @class A single frame of animation.
- * A position, rotation, and scale at a particular point in time.
- *
- * @param {3 Array} pos Position.
- * @param {3 Array} rot Rotation.
- * @param {3 Array} scl Scale.
- * @param {Number} atTime Time, in seconds, this keyframe occurs at.
- */
-$W.Keyframe = function Keyframe(pos, rot, scl, atTime) {
- if (arguments.length == 4) {
- $W.ObjectState.call(this, pos, rot, scl); // Subclass ObjectState
- this.atTime = atTime * 1000; // time, in seconds, this keyframe occurs at
- }else {
- $W.ObjectState.call(this);
- this.atTime = 0;
- }
-};
+ /** Time scale multiplier */
+ this.timeScale = 1;
-/** @class A keyframe based animation
- * Rotations interpolation uses quaternions.
- */
-$W.KeyFrameAnimation = function() {
- $W.ProceduralAnimation.call(this); // Subclass ProceduralAnimation
- this.keyframes = [];
- /** Frame index to interpolate from. */
- this.A = 0;
- /** Frame index to interpolate to. */
- this.B = 1;
+ this.update = function(dt) {
+ this.age += dt * this.timeScale;
- /** Time scale multiplier */
- this.timeScale = 1;
+ // Time for next frame?
+ if (this.age >= (this.keyframes[this.B]).atTime) {
+ // Increment frame counters
+ this.A = ++this.A % this.keyframes.length;
+ this.B = ++this.B % this.keyframes.length;
- this.update = function(dt) {
- this.age += dt * this.timeScale;
-
- // Time for next frame?
- if (this.age >= (this.keyframes[this.B]).atTime) {
-
- // Increment frame counters
- this.A = ++this.A % this.keyframes.length;
- this.B = ++this.B % this.keyframes.length;
-
- // Account for slop (by throwing it out)
- this.age = (this.keyframes[this.A]).atTime;
- }
-
+ // Account for slop (by throwing it out)
+ this.age = (this.keyframes[this.A]).atTime;
+ }
- var progress = this.age - (this.keyframes[this.A]).atTime;
- var duration = (this.keyframes[this.B]).atTime - (this.keyframes[this.A]).atTime;
- var t = progress / duration;
+ var progress = this.age - (this.keyframes[this.A]).atTime;
+ var duration = (this.keyframes[this.B]).atTime - (this.keyframes[this.A]).atTime;
+ var t = progress / duration;
- // Interpolate position
- this.position.elements = $W.util.lerpTriple(t,
- this.keyframes[this.A].position.elements,
- this.keyframes[this.B].position.elements);
- // Interpolate quaternions for rotation
- this.q = $W.util.slerp(t,
- this.keyframes[this.A].q,
- this.keyframes[this.B].q);
+ // Interpolate position
+ this.position.elements = $W.util.lerpTriple(t,
+ this.keyframes[this.A].position.elements,
+ this.keyframes[this.B].position.elements);
- // Interpolate scale
- this.scale.elements = $W.util.lerpTriple(t,
- this.keyframes[this.A].scale.elements,
- this.keyframes[this.B].scale.elements);
- }
+ // Interpolate quaternions for rotation
+ this.q = $W.util.slerp(t,
+ this.keyframes[this.A].q,
+ this.keyframes[this.B].q);
- /** Add a new keyframe.
- * For now it needs to be added in time order as it
- * doesn't sort on its own.
- * @param {Keyframe} keyframe The keyframe to add.
- */
- this.addKeyframe = function(keyframe) {
- this.keyframes.push(keyframe);
- }
+ // Interpolate scale
+ this.scale.elements = $W.util.lerpTriple(t,
+ this.keyframes[this.A].scale.elements,
+ this.keyframes[this.B].scale.elements);
+ }
- /** Remove the keyframe at index from the list of keyframes.
- * @param {Integer} index The index of the keyframe to remove.
- */
- this.removeKeyframe = function(index) {
- var result = [];
+ /** Add a new keyframe.
+ * For now it needs to be added in time order as it
+ * doesn't sort on its own.
+ * @param {Keyframe} keyframe The keyframe to add.
+ */
+ this.addKeyframe = function(keyframe) {
+ this.keyframes.push(keyframe);
+ }
- // - 1 for frame -1
- for (var i = 0; i < this.keyframes.length - 1; i++) {
- if (i != index) {
- result.push(this.keyframes[i]);
+ /** Remove the keyframe at index from the list of keyframes.
+ * @param {Integer} index The index of the keyframe to remove.
+ */
+ this.removeKeyframe = function(index) {
+ var result = [];
+
+ // - 1 for frame -1
+ for (var i = 0; i < this.keyframes.length - 1; i++) {
+ if (i != index) {
+ result.push(this.keyframes[i]);
+ }
}
}
- }
+ };
};
-
-
View
301 src/Constants.js
@@ -1,162 +1,163 @@
+$W.initConstants = function() {
+ /** @namespace Contains (semi)constant values that generally shouldn't be
+ * changed.
+ */
+ $W.constants = {};
-/** @namespace Contains (semi)constant values that generally shouldn't be
- * changed.
- */
-$W.constants = {};
+ /** @namespace Color constants */
+ $W.constants.colors = {
+ RED :[1.0, 0.0, 0.0],
+ GREEN:[0.0, 1.0, 0.0],
+ BLUE :[0.0, 0.0, 1.0],
+ GREY :[0.5, 0.5, 0.5],
+ WHITE:[1.0, 1.0, 1.0],
+ BLACK:[0.0, 0.0, 0.0]
+ };
-/** @namespace Color constants */
-$W.constants.colors = {
- RED :[1.0, 0.0, 0.0],
- GREEN:[0.0, 1.0, 0.0],
- BLUE :[0.0, 0.0, 1.0],
- GREY :[0.5, 0.5, 0.5],
- WHITE:[1.0, 1.0, 1.0],
- BLACK:[0.0, 0.0, 0.0]
-};
+ /** The name that a uniform variable needs to have to be automatically
+ * identified as the Model-View Matrix.
+ */
+ $W.constants.ModelViewUniform = 'ModelViewMatrix',
-/** The name that a uniform variable needs to have to be automatically
- * identified as the Model-View Matrix.
- */
-$W.constants.ModelViewUniform = 'ModelViewMatrix',
+ /** The name that a uniform variable needs to have to be automatically
+ * identified as the Projection Matrix.
+ */
+ $W.constants.ProjectionUniform = 'ProjectionMatrix',
-/** The name that a uniform variable needs to have to be automatically
- * identified as the Projection Matrix.
- */
-$W.constants.ProjectionUniform = 'ProjectionMatrix',
+ /** The name that a uniform variable needs to have to be automatically
+ * identified as the Normal Matrix.
+ */
+ $W.constants.NormalMatrixUniform = 'NormalMatrix'
-/** The name that a uniform variable needs to have to be automatically
- * identified as the Normal Matrix.
- */
-$W.constants.NormalMatrixUniform = 'NormalMatrix'
+ /** Data for a unit cube.
+ * Intended to be used with setElements.
+ */
+ $W.constants.unitCube = {
+ /** Vertices on the unit cube. */
+ vertices : [
+ // Front face
+ -1.0, -1.0, 1.0,
+ 1.0, -1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ -1.0, 1.0, 1.0,
+
+ // Back face
+ -1.0, -1.0, -1.0,
+ -1.0, 1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, -1.0, -1.0,
+
+ // Top face
+ -1.0, 1.0, -1.0,
+ -1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, 1.0, -1.0,
+
+ // Bottom face
+ -1.0, -1.0, -1.0,
+ 1.0, -1.0, -1.0,
+ 1.0, -1.0, 1.0,
+ -1.0, -1.0, 1.0,
+
+ // Right face
+ 1.0, -1.0, -1.0,
+ 1.0, 1.0, -1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, -1.0, 1.0,
+
+ // Left face
+ -1.0, -1.0, -1.0,
+ -1.0, -1.0, 1.0,
+ -1.0, 1.0, 1.0,
+ -1.0, 1.0, -1.0
-/** Data for a unit cube.
- * Intended to be used with setElements.
- */
-$W.constants.unitCube = {
- /** Vertices on the unit cube. */
- vertices : [
- // Front face
- -1.0, -1.0, 1.0,
- 1.0, -1.0, 1.0,
- 1.0, 1.0, 1.0,
- -1.0, 1.0, 1.0,
-
- // Back face
- -1.0, -1.0, -1.0,
- -1.0, 1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, -1.0, -1.0,
-
- // Top face
- -1.0, 1.0, -1.0,
- -1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0,
- 1.0, 1.0, -1.0,
-
- // Bottom face
- -1.0, -1.0, -1.0,
- 1.0, -1.0, -1.0,
- 1.0, -1.0, 1.0,
- -1.0, -1.0, 1.0,
-
- // Right face
- 1.0, -1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, 1.0, 1.0,
- 1.0, -1.0, 1.0,
-
- // Left face
- -1.0, -1.0, -1.0,
- -1.0, -1.0, 1.0,
- -1.0, 1.0, 1.0,
- -1.0, 1.0, -1.0
+ ],
+
+ /** Normals on the unit cube. */
+ normals : [
+ // Front
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0,
+
+ // Back
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+ 0.0, 0.0, -1.0,
+
+ // Top
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+
+ // Bottom
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+ 0.0, -1.0, 0.0,
+
+ // Right
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+
+ // Left
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0,
+ -1.0, 0.0, 0.0
- ],
-
- /** Normals on the unit cube. */
- normals : [
- // Front
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
-
- // Back
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
-
- // Top
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
-
- // Bottom
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
-
- // Right
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
-
- // Left
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0
+ ],
+
+ /** Texture coordinates on the unit cube. */
+ texCoords : [
+ // Front
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Back
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Top
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Bottom
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Right
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0,
+ // Left
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 1.0
+ ],
- ],
-
- /** Texture coordinates on the unit cube. */
- texCoords : [
- // Front
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Back
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Top
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Bottom
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Right
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Left
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0
- ],
+ /** Per element indices for unit cube */
+ indices : [
+ 0, 1, 2, 0, 2, 3, // front
+ 4, 5, 6, 4, 6, 7, // back
+ 8, 9, 10, 8, 10, 11, // top
+ 12, 13, 14, 12, 14, 15, // bottom
+ 16, 17, 18, 16, 18, 19, // right
+ 20, 21, 22, 20, 22, 23 // left
+ ]
+ };
- /** Per element indices for unit cube */
- indices : [
- 0, 1, 2, 0, 2, 3, // front
- 4, 5, 6, 4, 6, 7, // back
- 8, 9, 10, 8, 10, 11, // top
- 12, 13, 14, 12, 14, 15, // bottom
- 16, 17, 18, 16, 18, 19, // right
- 20, 21, 22, 20, 22, 23 // left
- ]
};
-
View
42 src/DefaultUniformActions.js
@@ -1,13 +1,11 @@
-$W.uniformActions = [];
-$W.uniformNames = {};
-$W.uniformNames.ModelView = 'ModelViewMatrix';
-$W.uniformNames.Projection = 'ProjectionMatrix';
-$W.uniformNames.NormalMatrix = 'NormalMatrix';
-$W.uniformNames.SimpleTexture = 'sampler';
-$W.uniformNames.MaterialTexture = 'wglu_mat_texture';
-
-
-$W.setupUniformActions = function() {
+$W.initDefaultUniformActions = function() {
+ $W.uniformActions = [];
+ $W.uniformNames = {};
+ $W.uniformNames.ModelView = 'ModelViewMatrix';
+ $W.uniformNames.Projection = 'ProjectionMatrix';
+ $W.uniformNames.NormalMatrix = 'NormalMatrix';
+ $W.uniformNames.SimpleTexture = 'sampler';
+ $W.uniformNames.MaterialTexture = 'wglu_mat_texture';
ModelViewAction =
function DUA_ModelViewAction(_, object, material) {
$W.GL.uniformMatrix4fv(this.location, false,
@@ -76,26 +74,24 @@ $W.setupUniformActions = function() {
- $W.uniformActions = [];
$W.uniformActions[$W.constants.ModelViewUniform] = ModelViewAction;
$W.uniformActions[$W.constants.ProjectionUniform] = ProjectionAction;
$W.uniformActions[$W.constants.NormalUniform] = NormalMatrixAction;
$W.uniformActions[$W.constants.SimpleTextureUniform] = SimpleSamplerAction;
-};
-$W.util.getUniformAction = function(name) {
- var action = $W.uniformActions[name];
+ $W.util.getUniformAction = function(name) {
+ var action = $W.uniformActions[name];
- if (typeof(action) === 'undefined') {
- action = function(){};
- $W.debug("\tno default action for uniform `" + name + "` found");
-
+ if (typeof(action) === 'undefined') {
+ action = function(){};
+ $W.debug("\tno default action for uniform `" + name + "` found");
+
- }else {
- $W.debug("\tfound `" + action.name + "` for uniform `" + name + "`");
- }
+ }else {
+ $W.debug("\tfound `" + action.name + "` for uniform `" + name + "`");
+ }
- return action;
+ return action;
+ };
};
-$W.setupUniformActions();
View
195 src/Framebuffer.js
@@ -1,113 +1,116 @@
-$W.framebuffers = {};
+$W.initFramebuffer = function() {
-$W.Framebuffer = function(name) {
- $W.info("Creating framebuffer");
- var GL = $W.GL;
- var RBUF = GL.RENDERBUFFER;
- var FBUF = GL.FRAMEBUFFER;
+ $W.framebuffers = {};
- this.name = name;
- $W.framebuffers[name] = this;
- this.glFramebuffer = GL.createFramebuffer();
- this.glRenderbuffers = [];
- this.textures = [];
+ $W.Framebuffer = function(name) {
+ $W.info("Creating framebuffer");
+ var GL = $W.GL;
+ var RBUF = GL.RENDERBUFFER;
+ var FBUF = GL.FRAMEBUFFER;
- this.isGood = function FBUF_isGood() {
- try {
- if (!GL.isFramebuffer(this.glFramebuffer)) {
- throw("Invalid framebuffer");
- }
- var status = GL.checkFramebufferStatus(this.glFramebuffer);
- switch (status) {
- case GL.FRAMEBUFFER_COMPLETE:
- break;
- default:
- throw("Incomplete framebuffer: " + status);
+ this.name = name;
+ $W.framebuffers[name] = this;
+ this.glFramebuffer = GL.createFramebuffer();
+ this.glRenderbuffers = [];
+ this.textures = [];
+
+ this.isGood = function FBUF_isGood() {
+ try {
+ if (!GL.isFramebuffer(this.glFramebuffer)) {
+ throw("Invalid framebuffer");
+ }
+ var status = GL.checkFramebufferStatus(this.glFramebuffer);
+ switch (status) {
+ case GL.FRAMEBUFFER_COMPLETE:
+ break;
+ default:
+ throw("Incomplete framebuffer: " + status);
+ }
+ }catch (e) {
+ console.error(e);
+ return false;
}
- }catch (e) {
- console.error(e);
- return false;
- }
- return true;
- };
+ return true;
+ };
- this.bind = function FBUF_bind(){
- GL.bindFramebuffer(FBUF, this.glFramebuffer);
- };
+ this.bind = function FBUF_bind(){
+ GL.bindFramebuffer(FBUF, this.glFramebuffer);
+ };
- this.unbind = function FBUF_unbind(){
- GL.bindFramebuffer(FBUF, null);
- };
+ this.unbind = function FBUF_unbind(){
+ GL.bindFramebuffer(FBUF, null);
+ };
- this.attachRenderbuffer = function FBUF_attachRenderbuffer(storageFormat, width, height, attachment) {
- var rBuffer = GL.createRenderbuffer();
- this.glRenderbuffers.push(rBuffer);
+ this.attachRenderbuffer = function FBUF_attachRenderbuffer(storageFormat, width, height, attachment) {
+ var rBuffer = GL.createRenderbuffer();
+ this.glRenderbuffers.push(rBuffer);
- this.bind();
- GL.bindRenderbuffer(RBUF, rBuffer);
- GL.renderbufferStorage(RBUF, storageFormat, width, height);
- GL.framebufferRenderbuffer(FBUF, attachment, RBUF, rBuffer);
- GL.bindRenderbuffer(RBUF, null);
- this.unbind();
- };
+ this.bind();
+ GL.bindRenderbuffer(RBUF, rBuffer);
+ GL.renderbufferStorage(RBUF, storageFormat, width, height);
+ GL.framebufferRenderbuffer(FBUF, attachment, RBUF, rBuffer);
+ GL.bindRenderbuffer(RBUF, null);
+ this.unbind();
+ };
- this.attachExistingTexture = function FBUF_attachExistingTexture(texture, attachment) {
- this.textures.push(texture);
- texture.bind();
- GL.framebufferTexture2D(GL.FRAMEBUFFER, attachment, GL.TEXTURE_2D, texture.glTexture, 0);
- texture.unbind();
- }
+ this.attachExistingTexture = function FBUF_attachExistingTexture(texture, attachment) {
+ this.textures.push(texture);
+ texture.bind();
+ GL.framebufferTexture2D(GL.FRAMEBUFFER, attachment, GL.TEXTURE_2D, texture.glTexture, 0);
+ texture.unbind();
+ }
- this.attachNewTexture = function FBUF_attachNewTexture(format, width, height, attachment) {
- var texture = new $W.Texture(this.name + 'Texture' + this.textures.length);
+ this.attachNewTexture = function FBUF_attachNewTexture(format, width, height, attachment) {
+ var texture = new $W.Texture(this.name + 'Texture' + this.textures.length);
- texture.bind();
- try{
- GL.texImage2D(GL.TEXTURE_2D, 0, format, width, height,
- 0, format, $W.GL.UNSIGNED_BYTE, null);
- } catch (e) {
- console.warn('Using empty texture fallback');
- var storage = new WebGLUnsignedByteArray(4 * width * height);
- GL.texImage2D(GL.TEXTURE_2D, 0, format, width, height,
- 0, format, $W.GL.UNSIGNED_BYTE, storage);
- }
- texture.unbind();
+ texture.bind();
+ try{
+ GL.texImage2D(GL.TEXTURE_2D, 0, format, width, height,
+ 0, format, $W.GL.UNSIGNED_BYTE, null);
+ } catch (e) {
+ console.warn('Using empty texture fallback');
+ var storage = new WebGLUnsignedByteArray(4 * width * height);
+ GL.texImage2D(GL.TEXTURE_2D, 0, format, width, height,
+ 0, format, $W.GL.UNSIGNED_BYTE, storage);
+ }
+ texture.unbind();
- this.attachExistingTexture(texture, attachment);
- }
+ this.attachExistingTexture(texture, attachment);
+ }
- this.attachTexture = function FBUF_attachTexture() {
- this.bind();
- if (arguments.length === 4) {
- this.attachNewTexture.apply(this, arguments);
- }else {
- this.attachExistingTexture.apply(this, arguments);
+ this.attachTexture = function FBUF_attachTexture() {
+ this.bind();
+ if (arguments.length === 4) {
+ this.attachNewTexture.apply(this, arguments);
+ }else {
+ this.attachExistingTexture.apply(this, arguments);
+ }
+ this.unbind();
}
- this.unbind();
- }
+ };
};
/** @author Benjamin DeLillo */
/*
- * Copyright (c) 2009-2010 Benjamin P. DeLillo
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
-*/
+ * Copyright (c) 2009-2010 Benjamin P. DeLillo
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
View
1,102 src/GLSL.js
@@ -1,650 +1,652 @@
-/**
- * @namespace Contains objects for working with GLSL shaders and
- * shader programs
- */
-$W.GLSL = {
- shaderVarLengths: {
- int:1,
- float:1,
- bool:1,
- vec2:2,
- vec3:3,
- vec4:4
- },
-
- uniformSetters: {
- int:function(value) {
- $W.GL.uniform1i(this.location, value);
- },
- float:function(value) {
- $W.GL.uniform1f(this.location, value);
- },
- vec2:function(value) {
- $W.GL.uniform2fv(this.location, value);
- },
- vec3:function(value) {
- $W.GL.uniform3fv(this.location, value);
- },
- vec4:function(value) {
- $W.GL.uniform4fv(this.location, value);
- },
- mat3:function(value) {
- $W.GL.uniformMatrix3fv(this.location, value);
- },
- mat4:function(value) {
- $W.GL.uniformMatrix4fv(this.location, value);
+$W.initGLSL = function() {
+ /**
+ * @namespace Contains objects for working with GLSL shaders and
+ * shader programs
+ */
+ $W.GLSL = {
+ shaderVarLengths: {
+ int:1,
+ float:1,
+ bool:1,
+ vec2:2,
+ vec3:3,
+ vec4:4
},
- sampler2D:function(value) {
- $W.GL.uniform1i(this.location, value);
+
+ uniformSetters: {
+ int:function(value) {
+ $W.GL.uniform1i(this.location, value);
+ },
+ float:function(value) {
+ $W.GL.uniform1f(this.location, value);
+ },
+ vec2:function(value) {
+ $W.GL.uniform2fv(this.location, value);
+ },
+ vec3:function(value) {
+ $W.GL.uniform3fv(this.location, value);
+ },
+ vec4:function(value) {
+ $W.GL.uniform4fv(this.location, value);
+ },
+ mat3:function(value) {
+ $W.GL.uniformMatrix3fv(this.location, value);
+ },
+ mat4:function(value) {
+ $W.GL.uniformMatrix4fv(this.location, value);
+ },
+ sampler2D:function(value) {
+ $W.GL.uniform1i(this.location, value);
+ }
}
- }
-};
+ };
-$W.GLSL.util = {
- getUniformSetter: function GLSL_getUniformSetter(type){
- setter = $W.GLSL.uniformSetters[type];
+ $W.GLSL.util = {
+ getUniformSetter: function GLSL_getUniformSetter(type){
+ setter = $W.GLSL.uniformSetters[type];
- if (typeof(setter) !== 'undefined') {
- return setter;
- }else {
- console.error("No setter for uniform of type `" + type + "`");
- return null;
- }
- },
-
- getShaderSourceById: function(id) {
- var source;
- var shaderScript = document.getElementById(id);
- if (!shaderScript) {
- console.error("No script with id '" + id + "'");
- return null;
- }
-
- source = "";
- var k = shaderScript.firstChild;
- while (k) {
- if (k.nodeType === 3) {
- source += k.textContent;
+ if (typeof(setter) !== 'undefined') {
+ return setter;
+ }else {
+ console.error("No setter for uniform of type `" + type + "`");
+ return null;
}
- k = k.nextSibling;
- }
-
- return source;
- },
-
- getShaderTypeById: function(id) {
- var type;
- var shaderScript = document.getElementById(id);
- if (!shaderScript) {
- console.error("No script with id '" + id + "'");
- return null;
+ },
+
+ getShaderSourceById: function(id) {
+ var source;
+ var shaderScript = document.getElementById(id);
+ if (!shaderScript) {
+ console.error("No script with id '" + id + "'");
+ return null;
+ }
+
+ source = "";
+ var k = shaderScript.firstChild;
+ while (k) {
+ if (k.nodeType === 3) {
+ source += k.textContent;
+ }
+ k = k.nextSibling;
+ }
+
+ return source;
+ },
+
+ getShaderTypeById: function(id) {
+ var type;
+ var shaderScript = document.getElementById(id);
+ if (!shaderScript) {
+ console.error("No script with id '" + id + "'");
+ return null;
+ }
+
+ if (shaderScript.type === "x-shader/x-fragment") {
+ type = $W.GL.FRAGMENT_SHADER;
+ } else if (shaderScript.type === "x-shader/x-vertex") {
+ type = $W.GL.VERTEX_SHADER;
+ } else {
+ console.warn('invalid shader type' + shaderScript.type);
+ }
+
+ return type;
}
-
- if (shaderScript.type === "x-shader/x-fragment") {
- type = $W.GL.FRAGMENT_SHADER;
- } else if (shaderScript.type === "x-shader/x-vertex") {
- type = $W.GL.VERTEX_SHADER;
- } else {
- console.warn('invalid shader type' + shaderScript.type);
+ };
+
+
+ /** @class Holds data for shader attribute variables.
+ * @param {String} name Attributes have the name they are given in
+ * the shader code.
+ */
+ $W.GLSL.Attribute = function (name, length, location) {
+ this.name = name;
+ this.length = length;
+ this.location = location;
+ this.clone = function() {
+ return new $W.GLSL.Attribute(this.name, this.length, this.location);
}
-
- return type;
- }
-};
+ };
-/** @class Holds data for shader attribute variables.
- * @param {String} name Attributes have the name they are given in
- * the shader code.
- */
-$W.GLSL.Attribute = function (name, length, location) {
- this.name = name;
- this.length = length;
- this.location = location;
- this.clone = function() {
- return new $W.GLSL.Attribute(this.name, this.length, this.location);
- }
-};
+
+ /** @class Holds data for shader uniform variables
+ * @param {String} name Uniforms have the name they are given in
+ * the shader code.
+ * @param {Function} action The function to update the data in the
+ * uniform each frame.
+ */
+ $W.GLSL.Uniform = function (name, action, type, location) {
+ this.name = name;
+ this.location = location; // only used by the shader program
+ this.action = action;
+ this.type = type;
+
+ this.set =$W.GLSL.util.getUniformSetter(type);
+
+ this.clone = function() {
+ return new $W.GLSL.Uniform(this.name, this.action, this.type, this.location);
+ }
+ };
+ /** @class Handles compilation, attributes, and uniforms of a GLSL
+ * shader.
+ * @param {String} name All shaders need a unique name
+ * @param {String} [src] The source code, if not included then
+ * name is assumed to be a DOM element Id to a script element
+ * containing the source code for a shader.
+ * @param [type] The type of shader, valid types are<br>
+ * $W.GL.VERTEX_SHADER<br>
+ * $W.GL.FRAGMENT_SHADER<br>
+ */
+ $W.GLSL.Shader = function(name, src, type) {
+ $W.log("creating shader '" + name + "'");
+ $W.indentLog();
+ $W.shaders[name] = this;
-/** @class Holds data for shader uniform variables
- * @param {String} name Uniforms have the name they are given in
- * the shader code.
- * @param {Function} action The function to update the data in the
- * uniform each frame.
- */
-$W.GLSL.Uniform = function (name, action, type, location) {
- this.name = name;
- this.location = location; // only used by the shader program
- this.action = action;
- this.type = type;
+ /** Name of the shader. */
+ this.name = name;
+ var name = this.name;
- this.set =$W.GLSL.util.getUniformSetter(type);
+ /** Source code of the shader. */
+ var source = src;
- this.clone = function() {
- return new $W.GLSL.Uniform(this.name, this.action, this.type, this.location);
- }
-};
+ /** Shader type $W.GL.VERTEX_SHADER or $W.GL.FRAGMENT_SHADER. */
+ this.type = -1;
+ // If the source wasn't passed in we assume name is an element
+ // ID in the page
+ if (source === undefined) {
+ source = getShaderSourceById(name);
+ this.type = getShaderTypeById(name);
-/** @class Handles compilation, attributes, and uniforms of a GLSL
- * shader.
- * @param {String} name All shaders need a unique name
- * @param {String} [src] The source code, if not included then
- * name is assumed to be a DOM element Id to a script element
- * containing the source code for a shader.
- * @param [type] The type of shader, valid types are<br>
- * $W.GL.VERTEX_SHADER<br>
- * $W.GL.FRAGMENT_SHADER<br>
- */
-$W.GLSL.Shader = function(name, src, type) {
- $W.log("creating shader '" + name + "'");
- $W.indentLog();
- $W.shaders[name] = this;
-
- /** Name of the shader. */
- this.name = name;
- var name = this.name;
-
- /** Source code of the shader. */
- var source = src;
-
- /** Shader type $W.GL.VERTEX_SHADER or $W.GL.FRAGMENT_SHADER. */
- this.type = -1;
-
- // If the source wasn't passed in we assume name is an element
- // ID in the page
- if (source === undefined) {
- source = getShaderSourceById(name);
- this.type = getShaderTypeById(name);
-
- // Else we just use the provided source and type
- }else {
- this.type = type;
- }
-
- /** The WebGL shader object. */
- var glShader = null;
-
- /** Attributes for this shader. */
- this.attributes = [];
- /** Uniforms for this shader. */
- this.uniforms = [];
-
- /** Names of programs which use this shader. */
- var programs = [];
-
- /** Tracks if this shader need to be (re)compiled. */
- var isDirty = true;
-
- // TODO Have _dirty and _clean update the dirty status of all
- // programs which use this shader.
- var dirty = function() {
- glShader = null;
- $W.log("Marking shader `" + name + "` as dirty", $W.LL.INFO);
- for (var i = 0; i < programs.length; i++) {
- $W.log('dirtying program `' + programs[i] + "`", $W.LL.INFO);
- $W.programs[programs[i]].dirty();
+ // Else we just use the provided source and type
+ }else {
+ this.type = type;
}
- isDirty = true;
- };
- var clean = function() {
- isDirty = false;
- };
- this.isDirty = function() {
- return isDirty;
- };
+ /** The WebGL shader object. */
+ var glShader = null;
+ /** Attributes for this shader. */
+ this.attributes = [];
+ /** Uniforms for this shader. */
+ this.uniforms = [];
- this.addProgram = function(name) {
- programs.push(name);
- };
- this.removeProgram = function(name) {
- programs = programs.remove(name);
- };
-
- /** Change the source for this shader
- * @param {String} src The source code.
- */
- this.setSource = function(src) {
- dirty();
- source = src;
- };
+ /** Names of programs which use this shader. */
+ var programs = [];
- this.source = function() {
- return source;
- };
+ /** Tracks if this shader need to be (re)compiled. */
+ var isDirty = true;
- /** @returns The raw WebGL shader object */
- this.getGLShader = function() {
- // Ensure the shader is valid before we return it
- if (isDirty) {
- $W.info("'" + this.name + "' is dirty");
- if (!this.compile()) {
- return false;
+ // TODO Have _dirty and _clean update the dirty status of all
+ // programs which use this shader.
+ var dirty = function() {
+ glShader = null;
+ $W.log("Marking shader `" + name + "` as dirty", $W.LL.INFO);
+ for (var i = 0; i < programs.length; i++) {
+ $W.log('dirtying program `' + programs[i] + "`", $W.LL.INFO);
+ $W.programs[programs[i]].dirty();
+ }
+ isDirty = true;
+ };
+
+ var clean = function() {
+ isDirty = false;
+ };
+ this.isDirty = function() {
+ return isDirty;
+ };
+
+
+ this.addProgram = function(name) {
+ programs.push(name);
+ };
+ this.removeProgram = function(name) {
+ programs = programs.remove(name);
+ };
+
+ /** Change the source for this shader
+ * @param {String} src The source code.
+ */
+ this.setSource = function(src) {
+ dirty();
+ source = src;
+ };
+
+ this.source = function() {
+ return source;
+ };
+
+ /** @returns The raw WebGL shader object */
+ this.getGLShader = function() {
+ // Ensure the shader is valid before we return it
+ if (isDirty) {
+ $W.info("'" + this.name + "' is dirty");
+ if (!this.compile()) {
+ return false;
+ }else {
+ clean();
+ }
}else {
- clean();
+ $W.info("'" + this.name + "' is clean, using");
}
- }else {
- $W.info("'" + this.name + "' is clean, using");
- }
- return glShader;
- }
-
- /** Store the information about this named uniform.
- * @param {String} name The uniform variable name as defined in
- * the shader source.
- * @param {Function} [action=function(){}] The function to call
- * each frame to prep/send this uniform to the shader.
- */
- this.addUniform = function(name, action, type) {
- $W.debug("\tadding uniform '" + name + "'");
- if (!action) {
- action = function(){}
+ return glShader;
}
- this.uniforms.push(new $W.GLSL.Uniform(name, action, type));
- }
- /** Store the information about this named attribute.
- * @param {String} name The attribute variable name as defined in
- * the shader source.
- * @param {Integer} [length=3] The length of the attribute.
- */
- this.addAttribute = function(name, length) {
- $W.debug("\tadding attribute '" + name + "'");
- if (!length) { length = 3; }
- this.attributes.push(new $W.GLSL.Attribute(name, length));
- }
-
- // Find and initialize all uniforms and attributes found in the source
- this.parseShaderVariables = function(str) {
- var tokens = str.split(/[\[\]\s\n;]+?/);
-
- for (var i = 0; i < tokens.length; i++) {
- if (tokens[i] === "attribute") {
- var type = tokens[i+1];
- var name = tokens[i+2];
- var length = $W.GLSL.shaderVarLengths[type];
- this.addAttribute(name, length);
- }
- if (tokens[i] === "uniform") {
- var type = tokens[i+1];
- var name = tokens[i+2];
-
- this.addUniform(name, $W.util.getUniformAction(name), type);
+ /** Store the information about this named uniform.
+ * @param {String} name The uniform variable name as defined in
+ * the shader source.
+ * @param {Function} [action=function(){}] The function to call
+ * each frame to prep/send this uniform to the shader.
+ */
+ this.addUniform = function(name, action, type) {
+ $W.debug("\tadding uniform '" + name + "'");
+ if (!action) {
+ action = function(){}
}
+ this.uniforms.push(new $W.GLSL.Uniform(name, action, type));
+ }
+
+ /** Store the information about this named attribute.
+ * @param {String} name The attribute variable name as defined in
+ * the shader source.
+ * @param {Integer} [length=3] The length of the attribute.
+ */
+ this.addAttribute = function(name, length) {
+ $W.debug("\tadding attribute '" + name + "'");
+ if (!length) { length = 3; }
+ this.attributes.push(new $W.GLSL.Attribute(name, length));
}
+
+ // Find and initialize all uniforms and attributes found in the source
+ this.parseShaderVariables = function(str) {
+ var tokens = str.split(/[\[\]\s\n;]+?/);
+
+ for (var i = 0; i < tokens.length; i++) {
+ if (tokens[i] === "attribute") {
+ var type = tokens[i+1];
+ var name = tokens[i+2];
+ var length = $W.GLSL.shaderVarLengths[type];
+ this.addAttribute(name, length);
+ }
+ if (tokens[i] === "uniform") {
+ var type = tokens[i+1];
+ var name = tokens[i+2];
+
+ this.addUniform(name, $W.util.getUniformAction(name), type);
+ }
+ }
+ };
+
+ /** Compile the shader if able.
+ * Lets any shader programs which use this shader know they need to
+ * relink
+ */
+ this.compile = function() {
+ if (this.type === $W.GL.VERTEX_SHADER) {
+ $W.debug("compiling '" + this.name + "' as vertex shader");
+ }else if (this.type === $W.GL.FRAGMENT_SHADER) {
+ $W.debug("compiling '" + this.name + "' as vertex shader");
+ }else {
+ console.error("compiling '" + this.name + "' as unknown type " + this.type);
+ }
+ if (glShader !== null) {
+ $W.GL.deleteShader(glShader);
+ glShader = null;
+ }
+
+ var shader = $W.GL.createShader(this.type);
+
+ $W.GL.shaderSource(shader, source);
+ $W.GL.compileShader(shader);
+
+ if (!$W.GL.getShaderParameter(shader, $W.GL.COMPILE_STATUS)) {
+ console.error("Compile error in `" + this.name + "`\n" +
+ $W.GL.getShaderInfoLog(shader));
+ glShader = null;
+ } else {
+ clean();
+ glShader = shader;
+ }
+
+ return (glShader !== null);
+ };
+
+ //source = $W.GLSL.util.handlePragmas(source);
+ this.parseShaderVariables(source);
+ this.compile();
+ $W.dedentLog();
};
- /** Compile the shader if able.
- * Lets any shader programs which use this shader know they need to
- * relink
+ /** @class Handles data and linking for a shader program.
+ * Also ensures all shaders which it uses are compiled and up
+ * to date.
+ * @param {String} name All shader programs need a unique name.
*/
- this.compile = function() {
- if (this.type === $W.GL.VERTEX_SHADER) {
- $W.debug("compiling '" + this.name + "' as vertex shader");
- }else if (this.type === $W.GL.FRAGMENT_SHADER) {
- $W.debug("compiling '" + this.name + "' as vertex shader");
- }else {
- console.error("compiling '" + this.name + "' as unknown type " + this.type);
- }
- if (glShader !== null) {
- $W.GL.deleteShader(glShader);
- glShader = null;
- }
+ $W.GLSL.ShaderProgram = function(name) {
+ $W.log("creating shader program '" + name + "'");
+ $W.indentLog();
- var shader = $W.GL.createShader(this.type);
-
- $W.GL.shaderSource(shader, source);
- $W.GL.compileShader(shader);
+ /** Global name of the shader program. */
+ this.name = name;
+ $W.programs[name] = this;
- if (!$W.GL.getShaderParameter(shader, $W.GL.COMPILE_STATUS)) {
- console.error("Compile error in `" + this.name + "`\n" +
- $W.GL.getShaderInfoLog(shader));
- glShader = null;
- } else {
- clean();
- glShader = shader;
+ /** WebGL shader program object. */
+ this.glProgram = null;
+
+ /** Tracks link state and compile state of all attached shaders. */
+ var isDirty = true;
+
+ var dirty = function() {
+ this.glProgram = null;
+ isDirty = true;
}
+ this.dirty = dirty;
- return (glShader !== null);
- };
+ var clean = function() {
+ isDirty = false;
+ }
- //source = $W.GLSL.util.handlePragmas(source);
- this.parseShaderVariables(source);
- this.compile();
- $W.dedentLog();
-};
+ this.isDirty = function() {
+ return isDirty;
+ }
+
+ /** Attached shaders */
+ this.shaders = [];
-/** @class Handles data and linking for a shader program.
- * Also ensures all shaders which it uses are compiled and up
- * to date.
- * @param {String} name All shader programs need a unique name.
- */
-$W.GLSL.ShaderProgram = function(name) {
- $W.log("creating shader program '" + name + "'");
- $W.indentLog();
-
- /** Global name of the shader program. */
- this.name = name;
- $W.programs[name] = this;
-
- /** WebGL shader program object. */
- this.glProgram = null;
-
- /** Tracks link state and compile state of all attached shaders. */
- var isDirty = true;
-
- var dirty = function() {
- this.glProgram = null;
- isDirty = true;
- }
- this.dirty = dirty;
-
- var clean = function() {
- isDirty = false;
- }
-
- this.isDirty = function() {
- return isDirty;
- }
-
- /** Attached shaders */
- this.shaders = [];
-
- /** Attributes from all attached shaders. */
- this.attributes = [];
-
- /** Uniforms from all attached shaders. */
- this.uniforms = [];
-
- this._setupAttributes = function() {
+ /** Attributes from all attached shaders. */
this.attributes = [];
- // Each shader keeps track of its attributes,
- for (var i = 0; i < this.shaders.length; i++) {
- var shader = $W.shaders[this.shaders[i]];
+ /** Uniforms from all attached shaders. */
+ this.uniforms = [];
- for (var j = 0; j < shader.attributes.length; j++) {
- var attribute = shader.attributes[j].clone();
+ this._setupAttributes = function() {
+ this.attributes = [];
+
+ // Each shader keeps track of its attributes,
+ for (var i = 0; i < this.shaders.length; i++) {
+ var shader = $W.shaders[this.shaders[i]];
+
+ for (var j = 0; j < shader.attributes.length; j++) {
+ var attribute = shader.attributes[j].clone();
- // but attribute locations are unique to each program
- attribute.location = $W.GL.getAttribLocation(this.glProgram, attribute.name);
+ // but attribute locations are unique to each program
+ attribute.location = $W.GL.getAttribLocation(this.glProgram, attribute.name);
- // buffers are unique to each object
- //attribute.buffer = $W.GL.createBuffer();
+ // buffers are unique to each object
+ //attribute.buffer = $W.GL.createBuffer();
- this.attributes.push(attribute);
+ this.attributes.push(attribute);
+ }
}
}
- }
- this._setupUniforms = function() {
+ this._setupUniforms = function() {
- // Each shader keeps track of its uniforms
- for (var i = 0; i < this.shaders.length; i++) {
- var shader = $W.shaders[this.shaders[i]];
+ // Each shader keeps track of its uniforms
+ for (var i = 0; i < this.shaders.length; i++) {
+ var shader = $W.shaders[this.shaders[i]];
- for (var j = 0; j < shader.uniforms.length; j++) {
- var uniform = shader.uniforms[j].clone();
+ for (var j = 0; j < shader.uniforms.length; j++) {
+ var uniform = shader.uniforms[j].clone();
- // locations are unique to each shader program (I think)
- uniform.location = $W.GL.getUniformLocation(this.glProgram, uniform.name);
- $W.debug(uniform.name + " " + uniform.location);
- this.uniforms.push(uniform);
+ // locations are unique to each shader program (I think)
+ uniform.location = $W.GL.getUniformLocation(this.glProgram, uniform.name);
+ $W.debug(uniform.name + " " + uniform.location);
+ this.uniforms.push(uniform);
+ }
}
}
- }
-
- /** Set the action to take per fram for a particular uniform.
- * Here instead of the shader because different programs can both
- * use the same shader, but treat it differently.
- * XXX What if two shaders have the same named variable
- * XXX Move to Object? If different objects could need to
- * different actions then we ought to store the uniform actions
- * on a per-object basis.
- * @param {String} name The name of the uniform.
- * @param {Function} action The function to call per frame.
- */
- this.setUniformAction = function(name, action) {
- this.use();
- var uniform = this.uniforms.findByAttributeValue('name', name);
+ /** Set the action to take per fram for a particular uniform.
+ * Here instead of the shader because different programs can both
+ * use the same shader, but treat it differently.
+ * XXX What if two shaders have the same named variable
+ * XXX Move to Object? If different objects could need to
+ * different actions then we ought to store the uniform actions
+ * on a per-object basis.
+ * @param {String} name The name of the uniform.
+ * @param {Function} action The function to call per frame.
+ */
+ this.setUniformAction = function(name, action) {
+ this.use();
+
+ var uniform = this.uniforms.findByAttributeValue('name', name);
+
+ if (uniform === undefined) {
+ console.error("Cannot set uniform `" + name + "` in shader program `" + this.name + "`, no uniform with that name exists");
+ return;
+ }else {
+ $W.info("Setting action for uniform `" + name + "` in shader program `" + this.name + "`");
+ }
- if (uniform === undefined) {
- console.error("Cannot set uniform `" + name + "` in shader program `" + this.name + "`, no uniform with that name exists");
- return;
- }else {
- $W.info("Setting action for uniform `" + name + "` in shader program `" + this.name + "`");
+ uniform.action = action;
}
- uniform.action = action;
- }
-
- /** Set the named uniform variable to a single value.
- * Overloaded to allow 1-4 values to be passed. This allows
- * this function to set the value of int, float, vec2, vec3, and
- * vec4 uniform variables in a shader.
- * @param {String} name The name of the uniform to set.
- * @param optional1 A value
- * @param optional2 A value
- * @param optional3 A value
- * @param optional4 A value
- */
- this.setUniform = function(name) {
- // Program must be active before we can do anything with it
- this.use();
-
- var uniform;
- for (var i = 0; i < this.uniforms.length; i++) {
- if (this.uniforms[i].name === name) {
- uniform = this.uniforms[i];
+ /** Set the named uniform variable to a single value.
+ * Overloaded to allow 1-4 values to be passed. This allows
+ * this function to set the value of int, float, vec2, vec3, and
+ * vec4 uniform variables in a shader.
+ * @param {String} name The name of the uniform to set.
+ * @param optional1 A value
+ * @param optional2 A value
+ * @param optional3 A value
+ * @param optional4 A value
+ */
+ this.setUniform = function(name) {
+ // Program must be active before we can do anything with it
+ this.use();
+
+ var uniform;
+ for (var i = 0; i < this.uniforms.length; i++) {
+ if (this.uniforms[i].name === name) {
+ uniform = this.uniforms[i];
+ }
}
- }
- if (uniform === undefined) {
- console.error("Cannot set uniform `" + name + "` in shader program `" + this.name + "`, no uniform with that name exists");
- return;
- }else {
- $W.log("Setting uniform `" + name + "` in shader program `" + this.name + "`", $W.LL.DEBUG);
- }
+ if (uniform === undefined) {
+ console.error("Cannot set uniform `" + name + "` in shader program `" + this.name + "`, no uniform with that name exists");
+ return;
+ }else {
+ $W.log("Setting uniform `" + name + "` in shader program `" + this.name + "`", $W.LL.DEBUG);
+ }
+
+ //XXX deal with other types too
+ if (arguments.length === 2) {
+ var val = arguments[1];
+ if (uniform.type === "int") {
+ uniform.action = function() {
+ $W.GL.uniform1i(this.location, val);
+ }
+ }else {
+ uniform.action = function() {
+ $W.GL.uniform1f(this.location, val);
+ }
+ }
- //XXX deal with other types too
- if (arguments.length === 2) {
- var val = arguments[1];
- if (uniform.type === "int") {
+ } else if (arguments.length === 3) {
uniform.action = function() {
- $W.GL.uniform1i(this.location, val);
+ $W.GL.uniform2f(this.location,
+ arguments[1], arguments[2]);
}
- }else {
+
+ } else if (arguments.length === 4) {
uniform.action = function() {
- $W.GL.uniform1f(this.location, val);
+ $W.GL.uniform3f(this.location,
+ arguments[1], arguments[2],
+ arguments[3]);
}
- }
- } else if (arguments.length === 3) {
- uniform.action = function() {
- $W.GL.uniform2f(this.location,
- arguments[1], arguments[2]);
- }
+ } else if (arguments.length === 5) {
+ uniform.action = function() {
+ $W.GL.uniform4f(this.location,
+ arguments[1], arguments[2],
+ arguments[3], arguments[4]);
+ }
- } else if (arguments.length === 4) {
- uniform.action = function() {
- $W.GL.uniform3f(this.location,
- arguments[1], arguments[2],
- arguments[3]);
}
+ }
- } else if (arguments.length === 5) {
- uniform.action = function() {
- $W.GL.uniform4f(this.location,
- arguments[1], arguments[2],
- arguments[3], arguments[4]);
+ /** Called once per frame to calculate and set uniforms. */
+ this.processUniforms = function(obj) {
+ for (var i = 0; i < this.uniforms.length; i++) {
+ this.uniforms[i].action(this.uniforms[i], obj);
}
-
}
- }
- /** Called once per frame to calculate and set uniforms. */
- this.processUniforms = function(obj) {
- for (var i = 0; i < this.uniforms.length; i++) {
- this.uniforms[i].action(this.uniforms[i], obj);
- }
- }
+ /** Link this shader program to make it useable.
+ * Will [re]compile all attached shaders if necessary.
+ */
+ this.link = function() {
+ $W.log("linking program `" + this.name + "`");
- /** Link this shader program to make it useable.
- * Will [re]compile all attached shaders if necessary.
- */
- this.link = function() {
- $W.log("linking program `" + this.name + "`");
+ // Only delete the program if one already exists
+ if (this.glProgram !== null) {
+ $W.log("already exists, deleting and relinking");
+ $W.GL.deleteProgram(this.glProgram);
+ this.attributes = [];
+ this.uniforms = [];
+ this.glProgram = null;
+ }
- // Only delete the program if one already exists
- if (this.glProgram !== null) {
- $W.log("already exists, deleting and relinking");
- $W.GL.deleteProgram(this.glProgram);
- this.attributes = [];
- this.uniforms = [];
- this.glProgram = null;
- }
+ this.glProgram = $W.GL.createProgram();
- this.glProgram = $W.GL.createProgram();
+ // Attach all the shaders
+ for (var i = 0; i < this.shaders.length; i++) {
+ var shader = $W.shaders[this.shaders[i]];
+ var glShader = shader.getGLShader();
- // Attach all the shaders
- for (var i = 0; i < this.shaders.length; i++) {
- var shader = $W.shaders[this.shaders[i]];
- var glShader = shader.getGLShader();
+ // if the shader is still dirty after calling get,
+ // which should have cleaned it, then the compile failed.
+ if (shader.isDirty()) {
+ $W.warn(this.shaders[i] + " failed to compile");
+ }else {
+ $W.GL.attachShader(this.glProgram, glShader);
+ }
+ }
- // if the shader is still dirty after calling get,
- // which should have cleaned it, then the compile failed.
- if (shader.isDirty()) {
- $W.warn(this.shaders[i] + " failed to compile");
- }else {
- $W.GL.attachShader(this.glProgram, glShader);
- }
- }
+ $W.GL.linkProgram(this.glProgram);
- $W.GL.linkProgram(this.glProgram);
+ // Check for errors
+ if (!$W.GL.getProgramParameter(this.glProgram, $W.GL.LINK_STATUS)) {
+ console.error("Link error in `" + this.name + "`\n" +
+ $W.GL.getProgramInfoLog(this.glProgram));
+ dirty();
+ }
+
+ clean();
+ this._setupAttributes();
+ this._setupUniforms();
- // Check for errors
- if (!$W.GL.getProgramParameter(this.glProgram, $W.GL.LINK_STATUS)) {
- console.error("Link error in `" + this.name + "`\n" +
- $W.GL.getProgramInfoLog(this.glProgram));
- dirty();
+ console.groupEnd();
+ return isDirty;
}
-
- clean();
- this._setupAttributes();
- this._setupUniforms();
-
- console.groupEnd();
- return isDirty;
- }
-
- /** XXX @Deprecated */
- this.detachShaderByName = function(name) {
- console.warn("detachShaderByName is deprecated, use detachShader instead");
- this.detachShader(name);
- }
-
- /** Remove the named shader from this program.
- * Can be used to alter a shader program on the fly.
- * @param {String} name
- */
- this.detachShader = function(name) {
- var tempShaders = [];
- for (var i = 0; i < this.shaders.length; i++) {
- if (this.shaders[i] != name) {
- tempShaders.push(this.shaders[i]);
- }
+ /** XXX @Deprecated */
+ this.detachShaderByName = function(name) {
+ console.warn("detachShaderByName is deprecated, use detachShader instead");
+ this.detachShader(name);
}
- isDirty = true;
- this.shaders = tempShaders;
- }
+ /** Remove the named shader from this program.
+ * Can be used to alter a shader program on the fly.
+ * @param {String} name
+ */
+ this.detachShader = function(name) {
+ var tempShaders = [];
- /** Attach a shader to this shader program.
- * Overloaded to work with as <br>
- * attachShader(GLSL.Shader shader)<br>
- * attachShader(String name, String source, type)<br>
- * attachShader(String name, String filePath)<br>
- * attachShader(String name, String source, type)<br>
- */
- this.attachShader = function(shader, path, type) {
- // Shader from node ID, filename, or source.
- // Otherwise we've been passed a shader object.
- if (typeof shader === 'string') {
- // Shader from ID
- if (arguments.length === 1) {
- shader = new $W.GLSL.Shader(shader);
-
- // Shader from file
- }else if (arguments.length === 2){
-
- // Try to infer type
- var ext = path.slice(path.length - 4);
- if (ext === 'vert' || ext.slice(2) === 'vp') {
- type = $W.GL.VERTEX_SHADER;
- }
- if (ext === 'frag' || ext.slice(2) === 'fp') {
- type = $W.GL.FRAGMENT_SHADER;
+ for (var i = 0; i < this.shaders.length; i++) {
+ if (this.shaders[i] != name) {
+ tempShaders.push(this.shaders[i]);
}
+ }
- try {
- shader = new $W.GLSL.Shader(shader, $W.util.loadFileAsText(path), type);
- }catch (e) {
- console.error(e);
- return;
- }
+ isDirty = true;
+ this.shaders = tempShaders;
+ }
- // Shader from source
- }else {
- shader = new $W.GLSL.Shader(shader, path, type);
+ /** Attach a shader to this shader program.
+ * Overloaded to work with as <br>
+ * attachShader(GLSL.Shader shader)<br>
+ * attachShader(String name, String source, type)<br>
+ * attachShader(String name, String filePath)<br>
+ * attachShader(String name, String source, type)<br>
+ */
+ this.attachShader = function(shader, path, type) {
+ // Shader from node ID, filename, or source.
+ // Otherwise we've been passed a shader object.
+ if (typeof shader === 'string') {
+ // Shader from ID
+ if (arguments.length === 1) {
+ shader = new $W.GLSL.Shader(shader);
+
+ // Shader from file
+ }else if (arguments.length === 2){
+
+ // Try to infer type
+ var ext = path.slice(path.length - 4);
+ if (ext === 'vert' || ext.slice(2) === 'vp') {
+ type = $W.GL.VERTEX_SHADER;
+ }
+ if (ext === 'frag' || ext.slice(2) === 'fp') {
+ type = $W.GL.FRAGMENT_SHADER;
+ }
+
+ try {
+ shader = new $W.GLSL.Shader(shader, $W.util.loadFileAsText(path), type);
+ }catch (e) {
+ console.error(e);
+ return;
+ }
+
+ // Shader from source
+ }else {
+ shader = new $W.GLSL.Shader(shader, path, type);
+ }
}
+
+ this._attachShader(shader);
}
- this._attachShader(shader);
- }
+ this._attachShader = function(shader) {
+ $W.log("\tattaching '" + shader.name + "' to '" + this.name + "'", $W.LL.INFO);
+ try{
+ shader.addProgram(this.name);
+ }catch(e) {
+ console.error(e);
+ }
+ isDirty = true;
+ this.shaders.push(shader.name);
+ }
- this._attachShader = function(shader) {
- $W.log("\tattaching '" + shader.name + "' to '" + this.name + "'", $W.LL.INFO);
- try{
- shader.addProgram(this.name);
- }catch(e) {
- console.error(e);
+ /** XXX @Deprecated */
+ this.attachShaderByID = function(name) {
+ console.warn("attachShaderByID is deprecated, use attachShader instead");
+ this.attachShader(new $W.GLSL.Shader(name));
}
- isDirty = true;
- this.shaders.push(shader.name);
- }
-
- /** XXX @Deprecated */
- this.attachShaderByID = function(name) {
- console.warn("attachShaderByID is deprecated, use attachShader instead");
- this.attachShader(new $W.GLSL.Shader(name));
- }
-
- /** Set this shader program to be the active program for
- * rendering.
- */
- this.use = function() {
- // Try to link if needed
- if (isDirty) {
- if (!this.link()) { return false; }
+
+ /** Set this shader program to be the active program for
+ * rendering.
+ */
+ this.use = function() {
+ // Try to link if needed
+ if (isDirty) {
+ if (!this.link()) { return false; }
+ }
+ $W.GL.useProgram(this.glProgram);
+ return true;
}
- $W.GL.useProgram(this.glProgram);
- return true;
- }
- $W.dedentLog();
+ $W.dedentLog();
+ };
};
/** @author Benjamin DeLillo */
/*
- * Copyright (c) 2009 Benjamin P. DeLillo
+ * Copyright (c) 2009-2010 Benjamin P. DeLillo
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
View
373 src/GLU.js
@@ -1,200 +1,201 @@
-
-/** @namespace Functions with similar functionaliy to the original GLU
- * libraries.
- */
-$W.GLU = {
- /** Given a point in screen-space, transform to an object-space point */
- unproject:function(winX, winY, winZ, model, proj, view) {
- if (model === undefined){model = $W.modelview.matrix;}
- if (proj === undefined) {proj = $W.projection.matrix;}
- if (view === undefined) {view = [0,0, $W.canvas.width, $W.canvas.height];}
-
- var pickMatrix = (model.multiply(proj)).inverse();
- },
-
- //----------------------------
- // these are like the OpenGL functions of the same name
-
- /** glLookAt
- * (c) 2009 Vladimir Vukicevic
- */
- lookAt : function (ex, ey, ez,
- tx, ty, tz,
- ux, uy, uz) {
- var eye = $V([ex, ey, ez]);
- var target = $V([tx, ty, tz]);
- var up = $V([ux, uy, uz]);
-
- var z = eye.subtract(target).toUnitVector();
- var x = up.cross(z).toUnitVector();
- var y = z.cross(x).toUnitVector();
-
- var m = $M([[x.e(1), x.e(2), x.e(3), 0],
- [y.e(1), y.e(2), y.e(3), 0],
- [z.e(1), z.e(2), z.e(3), 0],
- [0, 0, 0, 1]]);
-
- var t = $M([[1, 0, 0, -ex],
- [0, 1, 0, -ey],
- [0, 0, 1, -ez],
- [0, 0, 0, 1]]);
- return m.x(t);
- },
-
- /** glOrtho
- * (c) 2009 Vladimir Vukicevic
+$W.initGLU = function() {
+ /** @namespace Functions with similar functionaliy to the original GLU
+ * libraries.
*/
- ortho :
- function (left, right,
- bottom, top,
- znear, zfar)
- {
- var tx = -(right+left)/(right-left);
- var ty = -(top+bottom)/(top-bottom);
- var tz = -(zfar+znear)/(zfar-znear);
-
- return $M([[2/(right-left), 0, 0, tx],
- [0, 2/(top-bottom), 0, ty],
- [0, 0, -2/(zfar-znear), tz],
- [0, 0, 0, 1]]);
+ $W.GLU = {
+ /** Given a point in screen-space, transform to an object-space point */
+ unproject:function(winX, winY, winZ, model, proj, view) {
+ if (model === undefined){model = $W.modelview.matrix;}
+ if (proj === undefined) {proj = $W.projection.matrix;}
+ if (view === undefined) {view = [0,0, $W.canvas.width, $W.canvas.height];}
+
+ var pickMatrix = (model.multiply(proj)).inverse();
},
+
+ //----------------------------
+ // these are like the OpenGL functions of the same name
+
+ /** glLookAt
+ * (c) 2009 Vladimir Vukicevic
+ */
+ lookAt : function (ex, ey, ez,
+ tx, ty, tz,
+ ux, uy, uz) {
+ var eye = $V([ex, ey, ez]);
+ var target = $V([tx, ty, tz]);
+ var up = $V([ux, uy, uz]);
+
+ var z = eye.subtract(target).toUnitVector();
+ var x = up.cross(z).toUnitVector();
+ var y = z.cross(x).toUnitVector();
+
+ var m = $M([[x.e(1), x.e(2), x.e(3), 0],
+ [y.e(1), y.e(2), y.e(3), 0],
+ [z.e(1), z.e(2), z.e(3), 0],
+ [0, 0, 0, 1]]);
- /** glFrustrum
- * (c) 2009 Vladimir Vukicevic
- */
- frustrum :
- function (left, right,
- bottom, top,
- znear, zfar)
- {
- var X = 2*znear/(right-left);
- var Y = 2*znear/(top-bottom);
- var A = (right+left)/(right-left);
- var B = (top+bottom)/(top-bottom);
- var C = -(zfar+znear)/(zfar-znear);
- var D = -2*zfar*znear/(zfar-znear);
-
- return $M([[X, 0, A, 0],
- [0, Y, B, 0],
- [0, 0, C, D],
- [0, 0, -1, 0]]);
+ var t = $M([[1, 0, 0, -ex],
+ [0, 1, 0, -ey],
+ [0, 0, 1, -ez],
+ [0, 0, 0, 1]]);
+ return m.x(t);
},
- /** glPerpective
- * (c) 2009 Vladimir Vukicevic
- */
- perspective :
- function (fovy, aspect, znear, zfar)
- {
- var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
- var ymin = -ymax;
- var xmin = ymin * aspect;
- var xmax = ymax * aspect;
-
- return $W.GLU.frustrum(xmin, xmax, ymin, ymax, znear, zfar);
- }
-};
-
-
-
-
-
-/* @class Operates similarly to the standard OpenGL built in matricies.
-* However * it is not identical. Rather than calling glMatrixMode,
-* you specify the matrix you want to modify prior to the call.
-* e.g. if `myTranslationVector` is the vector to translate by then to
-* translate the ModelView matrix you would call
-* `$W.modelview.translate(myTranslationVector);`
-*/
-$W.GLU.MatrixStack = function() {
- this._matrixStack = [];
- this.matrix = Matrix.I(4);
-
- /** converts the matrix to the format we need when we send it to
- * a shader.
- * @returns {WebGLFloatArray} The matrix as a flattened array.
- */
- this.getForUniform = function() {
- return new WebGLFloatArray(this.matrix.flatten());
+ /** glOrtho
+ * (c) 2009 Vladimir Vukicevic
+ */
+ ortho :
+ function (left, right,
+ bottom, top,
+ znear, zfar)
+ {
+ var tx = -(right+left)/(right-left);
+ var ty = -(top+bottom)/(top-bottom);
+ var tz