Нет описания

trixl.html 6.9KB

    <!doctype html> <html> <head> <title>.trixl</title> <meta charset="utf-8" /> <style> #stage { position: absolute; top: 0; left: 0; } #debug { position: absolute; bottom: 0; right: 0; } </style> </head> <body> <canvas id="stage"> sorry. your browser is from the dark ages. please initiate temporal leap to a minimally brighter future where browsers can investigate the third dimension. </canvas> <span id="debug"></span> <script type="gl/vertex-shader"> attribute vec3 pos; varying vec3 world_pos; uniform mat4 transform; void main() { world_pos = pos; gl_Position = vec4(transform * vec4(pos, 1)); } </script> <script type="gl/fragment-shader"> precision mediump float; varying vec3 world_pos; void main() { gl_FragColor = vec4(world_pos.x, world_pos.y, world_pos.z, 1); } </script> <script> var createShader = function(src, type) { var shader = gl.createShader(type); gl.shaderSource(shader, src); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { throw gl.getShaderInfoLog(shader); } return shader; } var createProgram = function(vs, fs) { var program = gl.createProgram(); var vs = createShader(vs, gl.VERTEX_SHADER); var fs = createShader(fs, gl.FRAGMENT_SHADER); gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { throw gl.getProgramInfoLog(program); } return program; } var geometry = {}; geometry.cube = function() { return [ // front 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, // back 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, // left 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, // right 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, // top 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, // bottom 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0 ]; }; var matrix = {}; matrix.multiply = function(a, dim_a, b, dim_b) { if (dim_a[1] != dim_b[0]) { throw new Error("cols a != rows b"); } else { var c = []; var s = dim_a[1]; var n = dim_a[0], m = dim_b[1]; for (var i = 0; i < n; i++) { for (var j = 0; j < m; j++) { var sum = 0; for (var k = 0; k < s; k++) { sum += a[i * s + k] * b[k * m + j]; } c[i * m + j] = sum; } } return c; } }; matrix.multiplyMany4x4 = function() { var m = arguments[0]; for(var i = 1; i < arguments.length; i++) { m = matrix.multiply(m, [4, 4], arguments[i], [4, 4]); } return m; } matrix.identity = function(dim) { var m = []; for(var i = 0; i < dim; i++) { for(var j = 0; j < dim; j++) { m[i * dim + j] = i == j ? 1.0 : 0.0; } } return m; } matrix.transpose = function(m, dim) { var t = []; for(var i = 0; i < dim[0]; i++) { for(var j = 0; j < dim[1]; j++) { t[j * dim[0] + i] = m[i * dim[1] + j]; } } return t; } matrix.translate = function(tx, ty, tz) { var tx = tx || 0.0, ty = ty || 0.0, tz = tz || 0.0; return [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1 ]; } matrix.scale = function(sx, sy, sz) { var sx = sx || 1.0, sy = sy || 1.0, sz = sz || 1.0; return [ sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0, 0, 0, 0, 1 ]; } matrix.rotateX = function(angle) { var s = Math.sin(angle); var c = Math.cos(angle); return [ 1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1 ]; } matrix.rotateY = function(angle) { var s = Math.sin(angle); var c = Math.cos(angle); return [ c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1 ]; } matrix.rotateZ = function(angle) { var s = Math.sin(angle); var c = Math.cos(angle); return [ c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]; } </script> <script> window.trixl = {}; trixl.stage = document.querySelector("#stage"); trixl.window = {w: window.innerWidth, h: window.innerHeight}; trixl.stage.width = trixl.window.w; trixl.stage.height = trixl.window.h; trixl.debug = document.querySelector("#debug"); trixl.debug_pos = function(pos) { var coord_html = function(coord) { var s = (coord.toString() + " ").slice(0, 6); if (coord < -1.0 || coord > 1.0) { return '<span style="color: red">' + s + '</span>'; } else { return '<span>' + s + '</span>'; } return s; } trixl.debug.innerHTML = coord_html(pos[0]) + ", " + coord_html(pos[1]) + ", " + coord_html(pos[2]); } var gl = trixl.gl = trixl.stage.getContext("webgl"); //gl.enable(gl.CULL_FACE); gl.enable(gl.DEPTH_TEST); var vertexPosBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geometry.cube()), gl.STATIC_DRAW); var vs = document.querySelector("script[type='gl/vertex-shader']").textContent; var fs = document.querySelector("script[type='gl/fragment-shader']").textContent; var program = createProgram(vs, fs); gl.useProgram(program); program.vertexPosAttrib = gl.getAttribLocation(program, 'pos'); gl.enableVertexAttribArray(program.vertexPosAttrib); gl.vertexAttribPointer(program.vertexPosBuffer, 3, gl.FLOAT, false, 0, 0); var angle = {x: 0, y: 0, z: 0}; program.transform = gl.getUniformLocation(program, 'transform'); trixl.redraw = function() { var transform = matrix.multiplyMany4x4( //matrix.identity(4), matrix.identity(4) /* matrix.translate(-0.5, -0.5, -0.0), matrix.scale(0.5, 0.5, 0.5), matrix.rotateZ(angle.z / 4), //matrix.rotateY(angle.y / 10), matrix.rotateX(angle.x / 4), //matrix.translate(-0.5, -0.5, 0), //matrix.translate(-0.5, -0.5, -0.5), matrix.translate(-0.0, -0.0, -0.1) //matrix.perspective(Math.PI / 3, trixl.window.w / trixl.window.h, 0, 2000) //*/ ); trixl.debug_pos(matrix.multiply([1,1,1,1], [1, 4], transform, [4, 4])); gl.uniformMatrix4fv(program.transform, false, transform); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, 6 * 6); angle.x += Math.PI / 10; angle.y += Math.PI / 10; angle.z += Math.PI / 10; } trixl.step = function() { trixl.redraw(); trixl.step.reqId = requestAnimationFrame(trixl.step); } trixl.start = function() { trixl.step.reqId = requestAnimationFrame(trixl.step); } trixl.stop = function() { cancelAnimationFrame(trixl.step.reqId); trixl.step.reqId = null; } trixl.start(); document.addEventListener("keydown", function(ev) { if (ev.keyCode == 32) { if (trixl.step.reqId == null) { trixl.start(); } else { trixl.stop(); } } }); </script> </body> </html>