webgl-tools

view glass.js @ 4:06d05a65bd77

- added glass_resize and glass_reshape_func
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 18 Jun 2011 05:13:48 +0300
parents 56ae66e32998
children 7b3ed284e4bb
line source
1 /*
2 glass - (web)gl-assistant.
3 Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
19 /* public interface
21 bool glass_init(canvas-id, optional-console-textarea-id);
22 void glass_start(void);
24 void glass_display_func(callback);
25 void glass_reshape_func(callback);
26 void glass_mouse_func(callback);
27 void glass_motion_func(callback);
29 void glass_resize(x, y);
31 WebGLTexture load_texture(uri);
33 WebGLShader load_shader(uri, type);
34 WebGLShader create_shader(source, type, optional-sdrname);
35 WebGLProgram load_program(vertex-uri, fragment-uri);
36 WebGLProgram create_program(vertex-shader, fragment-shader);
38 void set_uniform1i(program, uniform-name, value);
39 void set_uniform1f(program, uniform-name, value);
40 void set_uniform2f(program, uniform-name, x, y);
41 void set_uniform3f(program, uniform-name, x, y, z);
42 void set_uniform4f(program, uniform-name, x, y, z, w);
43 void set_uniform_matrix4fv(program, uniform-name, matrix);
45 void request_redisplay(void);
47 void logmsg(string);
48 */
50 var gl;
51 var canvas, console;
52 var glass_data_loaded, glass_data_count;
53 var glass_progr_prog;
54 var glass_start_time = 0;
56 var glass_cb_disp = null;
57 var glass_cb_reshape = null;
58 var glass_cb_mouse = null;
59 var glass_cb_motion = null;
61 function glass_init(canv_id, cons_id)
62 {
63 if(cons_id && (console = document.getElementById(cons_id))) {
64 console.value = "";
65 }
67 if(!(canvas = document.getElementById(canv_id))) {
68 logmsg("canvas \"" + canv_id + "\" does not exist\n");
69 return false;
70 }
71 try {
72 gl = canvas.getContext("experimental-webgl");
73 }
74 catch(e) {
75 logmsg("can't get an OpenGL context\n");
76 return false;
77 }
79 var vs = create_shader(glass_progr_vs_src, gl.VERTEX_SHADER);
80 var ps = create_shader(glass_progr_ps_src, gl.FRAGMENT_SHADER);
81 if(!vs || !ps || !(glass_progr_prog = create_program(vs, ps))) {
82 logmsg("internal glass error\n");
83 return false;
84 }
86 glass_data_loaded = glass_data_count = 0;
87 return true;
88 }
90 function glass_start()
91 {
92 if(glass_cb_motion) {
93 canvas.onmousemove = function(ev) {
94 glass_cb_motion(ev.clientX, ev.clientY);
95 }
96 }
98 if(glass_cb_mouse) {
99 canvas.onmousedown = function(ev) {
100 glass_cb_mouse(ev.button, true, ev.clientX, ev.clientY);
101 }
102 canvas.onmouseup = function(ev) {
103 glass_cb_mouse(ev.button, false, ev.clientX, ev.clientY);
104 }
105 }
107 glass_start_time = get_msec();
109 if(glass_cb_reshape) {
110 glass_cb_reshape(canvas.width, canvas.height);
111 }
112 glass_redraw();
113 }
115 function glass_display_func(func)
116 {
117 glass_cb_disp = func;
118 }
120 function glass_reshape_func(func)
121 {
122 glass_cb_reshape = func;
123 }
125 function glass_mouse_func(func)
126 {
127 glass_cb_mouse = func;
128 }
130 function glass_motion_func(func)
131 {
132 glass_cb_motion = func;
133 }
135 function glass_resize(x, y)
136 {
137 canvas.width = x;
138 canvas.height = y;
140 if(glass_cb_reshape) {
141 glass_cb_reshape(x, y);
142 }
143 }
146 function glass_redraw()
147 {
148 var msec = get_msec();
150 if(glass_data_loaded < glass_data_count || !glass_cb_disp) {
151 glass_draw_progress(msec);
152 } else {
153 glass_cb_disp(msec);
154 }
155 request_redisplay(glass_redraw);
156 }
158 function get_msec()
159 {
160 return new Date().getTime() - glass_start_time;
161 }
163 /* ---- textures ---- */
164 function load_texture(name)
165 {
166 glass_data_count++;
168 var tex = gl.createTexture();
169 tex.image = new Image();
170 tex.image.onload = function() { glass_tex_load_done(tex); }
171 tex.image.onerror = glass_tex_load_failed;
172 tex.image.src = name;
173 return tex;
174 }
176 function glass_tex_load_done(tex)
177 {
178 gl.bindTexture(gl.TEXTURE_2D, tex);
179 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, tex.image);
180 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
181 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
182 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
183 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
184 gl.bindTexture(gl.TEXTURE_2D, null);
185 glass_data_loaded++;
186 logmsg("loaded image: " + tex.image.src +
187 " (" + glass_data_loaded + "/" + glass_data_count + ")\n");
188 }
190 function glass_tex_load_failed()
191 {
192 logmsg("failed to load texture: " + this.src + "\n");
193 }
196 /* ---- shaders ---- */
197 function load_shader(name, type)
198 {
199 var xhr = new XMLHttpRequest();
200 xhr.open("GET", name, false);
201 xhr.overrideMimeType("text/plain");
202 xhr.send(null);
204 var src = xhr.responseText;
205 return create_shader(src, type, name);
206 }
208 function create_shader(src, type, name)
209 {
210 var sdr = gl.createShader(type);
211 gl.shaderSource(sdr, src);
212 gl.compileShader(sdr);
214 if(!gl.getShaderParameter(sdr, gl.COMPILE_STATUS)) {
215 if(!name) {
216 name = "<unnamed>";
217 }
218 logmsg("failed to compile shader: " + name + ": " + gl.getShaderInfoLog(sdr));
219 return null;
220 }
221 return sdr;
222 }
224 function load_program(vsname, psname)
225 {
226 var vs, ps;
228 if(!(vs = load_shader(vsname, gl.VERTEX_SHADER))) {
229 return null;
230 }
231 if(!(ps = load_shader(psname, gl.FRAGMENT_SHADER))) {
232 return null;
233 }
234 return create_program(vs, ps);
235 }
237 function create_program(vs, ps)
238 {
239 var prog = gl.createProgram();
240 gl.attachShader(prog, vs);
241 gl.attachShader(prog, ps);
242 gl.linkProgram(prog);
244 if(!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
245 logmsg("Failed to link GLSL program (" + vsname + " - " + psname + ")\n");
246 return null;
247 }
248 return prog;
249 }
251 function set_uniform1i(p, name, v)
252 {
253 var loc = gl.getUniformLocation(p, name);
254 if(loc != -1) {
255 gl.useProgram(p);
256 gl.uniform1i(loc, v);
257 }
258 }
260 function set_uniform1f(p, name, v)
261 {
262 var loc = gl.getUniformLocation(p, name);
263 if(loc != -1) {
264 gl.useProgram(p);
265 gl.uniform1f(loc, v);
266 }
267 }
269 function set_uniform2f(p, name, x, y)
270 {
271 var loc = gl.getUniformLocation(p, name);
272 if(loc != -1) {
273 gl.useProgram(p);
274 gl.uniform2f(loc, x, y);
275 }
276 }
278 function set_uniform3f(p, name, x, y, z)
279 {
280 var loc = gl.getUniformLocation(p, name);
281 if(loc != -1) {
282 gl.useProgram(p);
283 gl.uniform3f(loc, x, y, z);
284 }
285 }
287 function set_uniform4f(p, name, x, y, z, w)
288 {
289 var loc = gl.getUniformLocation(p, name);
290 if(loc != -1) {
291 gl.useProgram(p);
292 gl.uniform4f(loc, x, y, z, w);
293 }
294 }
296 function set_uniform_matrix4fv(p, name, mat)
297 {
298 var loc = gl.getUniformLocation(p, name);
299 if(loc != -1) {
300 gl.useProgram(p);
301 gl.uniformMatrix4fv(loc, false, mat);
302 }
303 }
305 function logmsg(str)
306 {
307 if(console) {
308 console.value += str;
309 }
310 }
312 window.request_redisplay = (function() {
313 return window.requestAnimationFrame ||
314 window.webkitRequestAnimationFrame ||
315 window.mozRequestAnimationFrame ||
316 window.oRequestAnimationFrame ||
317 window.msRequestAnimationFrame ||
318 function(callback, element) { window.setTimeout(callback, 1000/60); };
319 })();
322 var glass_progr_vs_src =
323 "attribute vec4 attr_vertex, attr_color;\n" +
324 "uniform mat4 mvmat, projmat;\n" +
325 "varying vec4 color;\n" +
326 "void main()\n{\n" +
327 "\tmat4 mvp = projmat * mvmat;\n" +
328 "\tgl_Position = mvp * attr_vertex;\n" +
329 "\tcolor = attr_color;\n}\n";
331 var glass_progr_ps_src =
332 "precision highp float;\n" +
333 "varying vec4 color;\n" +
334 "void main()\n{\n" +
335 "\tgl_FragColor = color;\n}\n";
337 function glass_draw_progress(msec)
338 {
339 glMatrixMode(GL_PROJECTION);
340 glPushMatrix();
341 glLoadIdentity();
343 glMatrixMode(GL_MODELVIEW);
344 glPushMatrix();
345 glLoadIdentity();
347 gl.clearColor(0, 0, 0, 1);
348 gl.clear(gl.COLOR_BUFFER_BIT);
350 var progr = glass_data_loaded / glass_data_count;
352 gl.useProgram(glass_progr_prog);
354 glBegin(GL_QUADS);
355 glColor3f(0.3, 0.5, 0.8);
356 glVertex2f(-0.55, -0.1);
357 glVertex2f(0.55, -0.1);
358 glVertex2f(0.55, 0.1);
359 glVertex2f(-0.55, 0.1);
361 glColor3f(0, 0, 0);
362 glVertex2f(-0.525, -0.075);
363 glVertex2f(0.525, -0.075);
364 glVertex2f(0.525, 0.075);
365 glVertex2f(-0.525, 0.075);
367 glColor3f(1.0, 0.3, 0.2);
368 glVertex2f(-0.5, -0.05);
369 glVertex2f(progr - 0.5, -0.05);
370 glVertex2f(progr - 0.5, 0.05);
371 glVertex2f(-0.5, 0.05);
372 glEnd();
374 glMatrixMode(GL_PROJECTION);
375 glPopMatrix();
376 glMatrixMode(GL_MODELVIEW);
377 glPopMatrix();
378 }