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