Skip to content

Commit 3804167

Browse files
author
Evan Wallace
committed
initial commit
0 parents  commit 3804167

9 files changed

+539
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.DS_Store
2+
lightgl.js

LICENSE

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (C) 2011 by Evan Wallace
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

README.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# lightgl.js
2+
3+
This library makes it easier to quickly prototype WebGL applications. It's lower level than many other WebGL libraries and while it doesn't provide a scene graph, it re-implements OpenGL's modelview/projection matrix stack to provide similar functionality. It also re-introduces some built-in uniforms from GLSL, including `gl_Vertex` and `gl_ModelViewProjectionMatrix`.
4+
5+
## Building Library
6+
7+
* `python build.py`: build `lightgl.js` from the files in the `src` directory
8+
* `python build.py debug`: rebuild the library any time the contents of the `src` directory change
9+
* `python build.py release`: minify the library using Google Closure Compiler, which assumes there is a `closure` command in your path that runs `compiler.jar`
10+
11+
## Sample Code
12+
13+
<script src="lightgl.js"></script>
14+
<script>
15+
16+
var mesh;
17+
var shader;
18+
var angle = 0;
19+
20+
function setup() {
21+
document.body.appendChild(gl.canvas);
22+
gl.clearColor(0, 0, 0, 1);
23+
gl.matrixMode(gl.PROJECTION);
24+
gl.loadIdentity();
25+
gl.perspective(45, gl.canvas.width / gl.canvas.height, 0.01, 100);
26+
gl.matrixMode(gl.MODELVIEW);
27+
mesh = Mesh.plane(1, 1, 5, 5);
28+
shader = new Shader('\
29+
void main() {\
30+
gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex, 1.0);\
31+
}\
32+
', '\
33+
void main() {\
34+
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\
35+
}\
36+
');
37+
}
38+
39+
function update(seconds) {
40+
angle += 45 * seconds;
41+
}
42+
43+
function draw() {
44+
gl.clear(gl.COLOR_BUFFER_BIT);
45+
gl.loadIdentity();
46+
gl.translate(0, 0, -5);
47+
gl.rotate(30, 1, 0, 0);
48+
gl.rotate(angle, 0, 1, 0);
49+
50+
gl.pushMatrix();
51+
gl.rotate(-90, 1, 0, 0);
52+
shader.draw(mesh);
53+
gl.popMatrix();
54+
}
55+
56+
</script>

build.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/python
2+
3+
input_path = 'src/'
4+
output_path = 'lightgl.js'
5+
6+
import re, os, sys, time, tempfile
7+
8+
header = '''/*
9+
* lightgl.js
10+
* http://github.com/evanw/lightgl.js/
11+
*
12+
* Copyright 2011 Evan Wallace
13+
* Released under the MIT license
14+
*/
15+
'''
16+
17+
def sources():
18+
return [os.path.join(base, f) for base, folders, files in \
19+
os.walk(input_path) for f in files if f.endswith('.js')]
20+
21+
def compile(sources):
22+
return '\n'.join('// %s\n%s' % (path, open(path).read()) for path in sources)
23+
24+
def compress_glsl(text):
25+
def compress(match):
26+
text = match.group(0)
27+
if ' ' in text: # assume all strings with two consecutive spaces are glsl
28+
text = re.sub('/\*.*?\*/', '', text) # remove all comments
29+
text = re.sub(' +', ' ', text) # replace consecutive spaces with one space
30+
text = re.sub(r' ?(\+|\-|\*|/|,|=|{|}|;|\(|\)|<|>|!|\'|\") ?', r'\1', text) # tighten spaces around some tokens
31+
return text
32+
33+
text = re.sub(r"('([^'\\]|\\(.|\n))*'|\"([^\"\\]|\\(.|\n))*\")", compress, text) # replace all strings
34+
return text
35+
36+
def build():
37+
data = '(function() {\n\n%s\n})();\n' % compile(sources())
38+
if 'release' in sys.argv:
39+
f1, temp1_path = tempfile.mkstemp()
40+
f2, temp2_path = tempfile.mkstemp()
41+
os.write(f1, data)
42+
os.close(f1)
43+
os.close(f2)
44+
os.system('closure --js %s --js_output_file %s' % (temp1_path, temp2_path))
45+
os.remove(temp1_path)
46+
data = open(temp2_path).read()
47+
os.remove(temp2_path)
48+
data = compress_glsl(data)
49+
data = header + data
50+
open(output_path, 'w').write(data)
51+
print 'built %s (%u lines)' % (output_path, len(data.split('\n')))
52+
53+
def stat():
54+
return [os.stat(file).st_mtime for file in sources()]
55+
56+
def monitor():
57+
a = stat()
58+
while True:
59+
time.sleep(0.5)
60+
b = stat()
61+
if a != b:
62+
a = b
63+
build()
64+
65+
if __name__ == '__main__':
66+
build()
67+
if 'debug' in sys.argv:
68+
monitor()

src/main.js

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
window.onload = function() {
2+
// Set up WebGL
3+
var canvas = document.createElement('canvas');
4+
canvas.width = 800;
5+
canvas.height = 600;
6+
try { gl = canvas.getContext('webgl'); } catch (e) {}
7+
try { gl = gl || canvas.getContext('experimental-webgl'); } catch (e) {}
8+
if (!gl) throw 'WebGL not supported';
9+
10+
// Add custom enums
11+
var ENUM = 0x12340000;
12+
gl.MODELVIEW = ENUM | 1;
13+
gl.PROJECTION = ENUM | 2;
14+
15+
// Add matrix funcitons
16+
gl.modelviewMatrix = new Matrix();
17+
gl.projectionMatrix = new Matrix();
18+
var modelviewStack = [];
19+
var projectionStack = [];
20+
var matrix, stack;
21+
gl.matrixMode = function(mode) {
22+
switch (mode) {
23+
case gl.MODELVIEW:
24+
matrix = gl.modelviewMatrix;
25+
stack = modelviewStack;
26+
break;
27+
case gl.PROJECTION:
28+
matrix = gl.projectionMatrix;
29+
stack = projectionStack;
30+
break;
31+
default:
32+
throw 'invalid matrix mode ' + mode;
33+
}
34+
};
35+
gl.loadIdentity = function() {
36+
matrix.m = new Matrix().m;
37+
};
38+
gl.perspective = function(fov, aspect, near, far) {
39+
var y = Math.tan(fov * Math.PI / 360) * near;
40+
var x = y * aspect;
41+
gl.frustum(-x, x, -y, y, near, far);
42+
};
43+
gl.frustum = function(l, r, b, t, n, f) {
44+
matrix.concat(
45+
2*n/(r-l), 0, (r+l)/(r-l), 0,
46+
0, 2*n/(t-b), (t+b)/(t-b), 0,
47+
0, 0, -(f+n)/(f-n), -2*f*n/(f-n),
48+
0, 0, -1, 0
49+
);
50+
};
51+
gl.ortho = function(l, r, b, t, n, f) {
52+
matrix.concat(
53+
2/(r-l), 0, 0, (r+l)/(r-l),
54+
0, 2/(t-b), 0, (t+b)/(t-b),
55+
0, 0, -2/(f-n), (f+n)/(f-n),
56+
0, 0, 0, 1
57+
);
58+
};
59+
gl.scale = function(x, y, z) {
60+
matrix.concat(
61+
x, 0, 0, 0,
62+
0, y, 0, 0,
63+
0, 0, z, 0,
64+
0, 0, 0, 1
65+
);
66+
};
67+
gl.translate = function(x, y, z) {
68+
matrix.concat(
69+
1, 0, 0, x,
70+
0, 1, 0, y,
71+
0, 0, 1, z,
72+
0, 0, 0, 1
73+
);
74+
};
75+
gl.rotate = function(a, x, y, z) {
76+
if (a && (x || y || z)) {
77+
var d = Math.sqrt(x*x + y*y + z*z);
78+
a *= Math.PI / 180; x /= d; y /= d; z /= d;
79+
var c = Math.cos(a), s = Math.sin(a), t = 1 - c;
80+
matrix.concat(
81+
x*x*t+c, x*y*t-z*s, x*z*t+y*s, 0,
82+
y*x*t+z*s, y*y*t+c, y*z*t-x*s, 0,
83+
z*x*t-y*s, z*y*t+x*s, z*z*t+c, 0,
84+
0, 0, 0, 1
85+
);
86+
}
87+
};
88+
gl.lookAt = function(ex, ey, ez, cx, cy, cz, ux, uy, uz) {
89+
var e = new Vector(ex, ey, ez);
90+
var c = new Vector(cx, cy, cz);
91+
var u = new Vector(ux, uy, uz);
92+
var f = e.subtract(c).unit();
93+
var s = u.cross(f).unit();
94+
var t = f.cross(s).unit();
95+
matrix.concat(
96+
s.x, s.y, s.z, -s.dot(e),
97+
t.x, t.y, t.z, -t.dot(e),
98+
f.x, f.y, f.z, -f.dot(e),
99+
0, 0, 0, 1
100+
);
101+
};
102+
gl.pushMatrix = function() {
103+
stack.push(Array.prototype.slice.call(matrix.m));
104+
};
105+
gl.popMatrix = function() {
106+
matrix.m = stack.pop();
107+
};
108+
gl.matrixMode(gl.MODELVIEW);
109+
110+
// Set up the animation loop
111+
var post =
112+
window.webkitRequestAnimationFrame ||
113+
window.mozRequestAnimationFrame ||
114+
function(callback) { setTimeout(callback, 1000 / 60); };
115+
var time = new Date();
116+
function frame() {
117+
var now = new Date();
118+
if (window.update) window.update((now - time) / 1000);
119+
time = now;
120+
if (window.draw) window.draw();
121+
post(frame);
122+
}
123+
124+
// Draw the initial frame and start the animation loop
125+
if (window.setup) window.setup();
126+
frame();
127+
};

src/matrix.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
Matrix = function() {
2+
this.m = Array.prototype.concat.apply([], arguments);
3+
if (!this.m.length) {
4+
this.m = [
5+
1, 0, 0, 0,
6+
0, 1, 0, 0,
7+
0, 0, 1, 0,
8+
0, 0, 0, 1
9+
];
10+
}
11+
};
12+
13+
Matrix.prototype.multiply = function(matrix) {
14+
var a = this.m, b = matrix.m;
15+
return new Matrix(
16+
a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12],
17+
a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13],
18+
a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14],
19+
a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15],
20+
21+
a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12],
22+
a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13],
23+
a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14],
24+
a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15],
25+
26+
a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12],
27+
a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13],
28+
a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14],
29+
a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15],
30+
31+
a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12],
32+
a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13],
33+
a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14],
34+
a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15]
35+
);
36+
};
37+
38+
Matrix.prototype.concat = function() {
39+
var m = {};
40+
Matrix.apply(m, arguments);
41+
this.m = this.multiply(m).m;
42+
};

0 commit comments

Comments
 (0)