<script type="text/javascript">
draw_vert =
"precision mediump float; \n" +
"attribute vec2 inPos; \n" +
"uniform mat4 u_projectionMat44;" +
"uniform mat4 u_modelViewMat44;" +
"void main()" +
"{" +
" vec4 viewPos = u_modelViewMat44 * vec4( inPos.xy, 0.0, 1.0 );" +
" gl_Position = u_projectionMat44 * viewPos;" +
"}";
draw_frag =
"precision mediump float; \n" +
"uniform vec3 u_color;" +
"void main()" +
"{" +
" gl_FragColor = vec4( u_color.xyz, 1.0 );" +
"}";
glArrayType = typeof Float32Array !="undefined" ? Float32Array : ( typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array );
function IdentityMat44() {
var m = new glArrayType(16);
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
return m;
};
function RotateAxis(matA, angRad, axis) {
var aMap = [ [1, 2], [2, 0], [0, 1] ];
var a0 = aMap[axis][0], a1 = aMap[axis][1];
var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);
var matB = new glArrayType(16);
for ( var i = 0; i < 16; ++ i ) matB[i] = matA[i];
for ( var i = 0; i < 3; ++ i ) {
matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng;
matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng;
}
return matB;
}
function Translate( matA, trans ) {
var matB = new glArrayType(16);
for ( var i = 0; i < 16; ++ i ) matB[i] = matA[i];
for ( var i = 0; i < 3; ++ i )
matB[12+i] = matA[i] * trans[0] + matA[4+i] * trans[1] + matA[8+i] * trans[2] + matA[12+i];
return matB;
}
function Scale( matA, scale ) {
var matB = new glArrayType(16);
for ( var i = 0; i < 16; ++ i ) matB[i] = matA[i];
for ( var a = 0; a < 4; ++ a )
for ( var i = 0; i < 3; ++ i )
matB[a*4+i] = matA[a*4+i] * scale[0];
return matB;
}
Ortho = function( l, r, t, b, n, f ) {
var fn = f + n;
var f_n = f - n;
var m = IdentityMat44();
m[0] = 2/(r-l); m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = 2/(t-b); m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = -2 / f_n; m[11] = -fn / f_n;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
return m;
}
vec4_add = function( a, b ) { return [ a[0]+b[0], a[1]+b[1], a[2]+b[2], a[3]+b[3] ]; }
vec4_sub = function( a, b ) { return [ a[0]-b[0], a[1]-b[1], a[2]-b[2], a[3]-b[3] ]; }
vec4_mul = function( a, b ) { return [ a[0]*b[0], a[1]*b[1], a[2]*b[2], a[3]*b[3] ]; }
vec4_scale = function( a, s ) { return [ a[0]*s, a[1]*s, a[2]*s, a[3]*s ]; }
mat44_inverse = function( m ) {
var Coef00 = m[2*4+2] * m[3*4+3] - m[3*4+2] * m[2*4+3];
var Coef02 = m[1*4+2] * m[3*4+3] - m[3*4+2] * m[1*4+3];
var Coef03 = m[1*4+2] * m[2*4+3] - m[2*4+2] * m[1*4+3];
var Coef04 = m[2*4+1] * m[3*4+3] - m[3*4+1] * m[2*4+3];
var Coef06 = m[1*4+1] * m[3*4+3] - m[3*4+1] * m[1*4+3];
var Coef07 = m[1*4+1] * m[2*4+3] - m[2*4+1] * m[1*4+3];
var Coef08 = m[2*4+1] * m[3*4+2] - m[3*4+1] * m[2*4+2];
var Coef10 = m[1*4+1] * m[3*4+2] - m[3*4+1] * m[1*4+2];
var Coef11 = m[1*4+1] * m[2*4+2] - m[2*4+1] * m[1*4+2];
var Coef12 = m[2*4+0] * m[3*4+3] - m[3*4+0] * m[2*4+3];
var Coef14 = m[1*4+0] * m[3*4+3] - m[3*4+0] * m[1*4+3];
var Coef15 = m[1*4+0] * m[2*4+3] - m[2*4+0] * m[1*4+3];
var Coef16 = m[2*4+0] * m[3*4+2] - m[3*4+0] * m[2*4+2];
var Coef18 = m[1*4+0] * m[3*4+2] - m[3*4+0] * m[1*4+2];
var Coef19 = m[1*4+0] * m[2*4+2] - m[2*4+0] * m[1*4+2];
var Coef20 = m[2*4+0] * m[3*4+1] - m[3*4+0] * m[2*4+1];
var Coef22 = m[1*4+0] * m[3*4+1] - m[3*4+0] * m[1*4+1];
var Coef23 = m[1*4+0] * m[2*4+1] - m[2*4+0] * m[1*4+1];
var Fac0 = [Coef00, Coef00, Coef02, Coef03];
var Fac1 = [Coef04, Coef04, Coef06, Coef07];
var Fac2 = [Coef08, Coef08, Coef10, Coef11];
var Fac3 = [Coef12, Coef12, Coef14, Coef15];
var Fac4 = [Coef16, Coef16, Coef18, Coef19];
var Fac5 = [Coef20, Coef20, Coef22, Coef23];
var Vec0 = [ m[1*4+0], m[0*4+0], m[0*4+0], m[0*4+0] ];
var Vec1 = [ m[1*4+1], m[0*4+1], m[0*4+1], m[0*4+1] ];
var Vec2 = [ m[1*4+2], m[0*4+2], m[0*4+2], m[0*4+2] ];
var Vec3 = [ m[1*4+3], m[0*4+3], m[0*4+3], m[0*4+3] ];
var Inv0 = vec4_add( vec4_sub( vec4_mul(Vec1, Fac0), vec4_mul(Vec2, Fac1) ), vec4_mul( Vec3, Fac2 ) );
var Inv1 = vec4_add( vec4_sub( vec4_mul(Vec0, Fac0), vec4_mul(Vec2, Fac3) ), vec4_mul( Vec3, Fac4 ) );
var Inv2 = vec4_add( vec4_sub( vec4_mul(Vec0, Fac1), vec4_mul(Vec1, Fac3) ), vec4_mul( Vec3, Fac5 ) );
var Inv3 = vec4_add( vec4_sub( vec4_mul(Vec0, Fac2), vec4_mul(Vec1, Fac4) ), vec4_mul( Vec2, Fac5 ) );
var SignA = [+1.0, -1.0, +1.0, -1.0];
var SignB = [-1.0, +1.0, -1.0, +1.0];
var Inverse = [ vec4_mul(Inv0, SignA), vec4_mul(Inv1, SignB), vec4_mul(Inv2, SignA), vec4_mul(Inv3, SignB) ];
var Row0 = [Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0] ];
var Dot0 = [Row0[0], Row0[1], Row0[2], Row0[3] ];
Dot0 = vec4_mul( Dot0, [ m[0], m[1], m[2], m[3] ] );
var Dot1 = (Dot0[0] + Dot0[1]) + (Dot0[2] + Dot0[3]);
var OneOverDeterminant = 1 / Dot1;
var res = IdentityMat44();
for ( var inx1 = 0; inx1 < 4; inx1 ++ ) {
for ( var inx2 = 0; inx2 < 4; inx2 ++ )
res[inx1*4+inx2] = Inverse[inx1][inx2] * OneOverDeterminant;
}
return res;
}
Transform = function(vec, mat) {
var h = [
vec[0] * mat[0*4+0] + vec[1] * mat[1*4+0] + vec[2] * mat[2*4+0] + mat[3*4+0],
vec[0] * mat[0*4+1] + vec[1] * mat[1*4+1] + vec[2] * mat[2*4+1] + mat[3*4+1],
vec[0] * mat[0*4+2] + vec[1] * mat[1*4+2] + vec[2] * mat[2*4+2] + mat[3*4+2],
vec[0] * mat[0*4+3] + vec[1] * mat[1*4+3] + vec[2] * mat[2*4+3] + mat[3*4+3] ]
if ( h[3] == 0.0 )
return [0, 0, 0]
return [ h[0]/h[3], h[1]/h[3], h[2]/h[3] ];
}
// shader program object
var ShaderProgram = {};
ShaderProgram.Create = function( shaderList, uniformNames ) {
var shaderObjs = [];
for ( var i_sh = 0; i_sh < shaderList.length; ++ i_sh ) {
var shderObj = this.CompileShader( shaderList[i_sh].source, shaderList[i_sh].stage );
if ( shderObj == 0 )
return 0;
shaderObjs.push( shderObj );
}
var progObj = this.LinkProgram( shaderObjs )
if ( progObj != 0 ) {
progObj.unifomLocation = {};
for ( var i_n = 0; i_n < uniformNames.length; ++ i_n ) {
var name = uniformNames[i_n];
progObj.unifomLocation[name] = gl.getUniformLocation( progObj, name );
}
}
return progObj;
}
ShaderProgram.Use = function( progObj ) { gl.useProgram( progObj ); }
ShaderProgram.SetUniformInt = function( progObj, name, val ) { gl.uniform1i( progObj.unifomLocation[name], val ); }
ShaderProgram.SetUniform2f = function( progObj, name, arr ) { gl.uniform2fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniform3f = function( progObj, name, arr ) { gl.uniform3fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniformMat44 = function( progObj, name, mat ) { gl.uniformMatrix4fv( progObj.unifomLocation[name], false, mat ); }
ShaderProgram.CompileShader = function( source, shaderStage ) {
var shaderObj = gl.createShader( shaderStage );
gl.shaderSource( shaderObj, source );
gl.compileShader( shaderObj );
var status = gl.getShaderParameter( shaderObj, gl.COMPILE_STATUS );
if ( !status ) alert(gl.getShaderInfoLog(shaderObj));
return status ? shaderObj : 0;
}
ShaderProgram.LinkProgram = function( shaderObjs ) {
var prog = gl.createProgram();
for ( var i_sh = 0; i_sh < shaderObjs.length; ++ i_sh )
gl.attachShader( prog, shaderObjs[i_sh] );
gl.linkProgram( prog );
status = gl.getProgramParameter( prog, gl.LINK_STATUS );
if ( !status ) alert("Could not initialise shaders");
gl.useProgram( null );
return status ? prog : 0;
}
function drawScene(){
var canvas = document.getElementById( "camera-canvas" );
var currentTime = Date.now();
var deltaMS = currentTime - startTime;
var aspect = canvas.width / canvas.height;
var matOrtho = Ortho( -aspect, aspect, 1, -1, -1, 1 );
var matOrthoInv = mat44_inverse( matOrtho )
gl.viewport( 0, 0, canvas.width, canvas.height );
gl.enable( gl.DEPTH_TEST );
gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
ShaderProgram.Use( progDraw );
gl.enableVertexAttribArray( progDraw.inPos );
gl.bindBuffer( gl.ARRAY_BUFFER, bufObj.pos );
gl.vertexAttribPointer( progDraw.inPos, 2, gl.FLOAT, false, 0, 0 );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufObj.inx );
ShaderProgram.SetUniformMat44( progDraw, "u_projectionMat44", matOrtho );
var col = [ [1.0,0.0,0.0], [1.0,1.0,0.0], [0.0,0.0,1.0] ];
var invMat = []
for ( var i = 0; i < 3; ++ i ) {
var modelMat = Scale( IdentityMat44(), [ 0.3, 0.3, 0.3] );
var angRad = CalcAng( currentTime, 20.0 ) + i * Math.PI * 2 / 3;
var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad);
modelMat[12] = cosAng * 0.6;
modelMat[13] = sinAng * 0.6;
invMat.push( mat44_inverse( modelMat ) );
ShaderProgram.SetUniformMat44( progDraw, "u_modelViewMat44", modelMat );
ShaderProgram.SetUniform3f( progDraw, "u_color", col[i] );
gl.drawElements( gl.TRIANGLES, bufObj.inx.len, gl.UNSIGNED_SHORT, 0 );
}
gl.disableVertexAttribArray( progDraw.pos );
var newColor = "#000000";
var colorMap = ["#ff0000", "#ffff00", "#0000ff" ];
var pos = [-1, -1];
if (mousePos[0] > 0 && mousePos[1] > 0 ) {
var pos = [2.0 * mousePos[0] / canvas.width - 1.0, 1.0 - 2.0 * mousePos[1] / canvas.height];
for ( var i = 0; i < 3; ++ i ) {
var testVec = [ pos[0], pos[1], 0 ];
testVec = Transform(testVec, matOrthoInv);
testVec = Transform(testVec, invMat[i]);
if (testVec[0] > -1.0 && testVec[0] < 1.0 && testVec[1] > -1.0 && testVec[1] < 1.0 ) {
newColor = colorMap[i];
}
}
}
document.getElementById( "color" ).value = newColor;
document.getElementById( "mouseX" ).innerHTML = pos[0];
document.getElementById( "mouseY" ).innerHTML = pos[1];
}
var startTime;
function Fract( val ) {
return val - Math.trunc( val );
}
function CalcAng( currentTime, intervall ) {
return Fract( (currentTime - startTime) / (1000*intervall) ) * 2.0 * Math.PI;
}
function CalcMove( currentTime, intervall, range ) {
var pos = self.Fract( (currentTime - startTime) / (1000*intervall) ) * 2.0
var pos = pos < 1.0 ? pos : (2.0-pos)
return range[0] + (range[1] - range[0]) * pos;
}
var mousePos = [-1, -1];
var gl;
var prog;
var bufObj = {};
function cameraStart() {
var canvas = document.getElementById( "camera-canvas");
gl = canvas.getContext( "experimental-webgl" );
if ( !gl )
return;
progDraw = ShaderProgram.Create(
[ { source : draw_vert, stage : gl.VERTEX_SHADER },
{ source : draw_frag, stage : gl.FRAGMENT_SHADER }
],
[ "u_projectionMat44", "u_modelViewMat44", "u_color"] );
progDraw.inPos = gl.getAttribLocation( progDraw, "inPos" );
if ( prog == 0 )
return;
var pos = [ -1, -1, 1, -1, 1, 1, -1, 1 ];
var inx = [ 0, 1, 2, 0, 2, 3 ];
bufObj.pos = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, bufObj.pos );
gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( pos ), gl.STATIC_DRAW );
bufObj.inx = gl.createBuffer();
bufObj.inx.len = inx.length;
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, bufObj.inx );
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( inx ), gl.STATIC_DRAW );
startTime = Date.now();
setInterval(drawScene, 50);
}
(function() {
document.onmousemove = handleMouseMove;
function handleMouseMove(event) {
var dot, eventDoc, doc, body, pageX, pageY;
event = event || window.event; // IE-ism
if (event.pageX == null && event.clientX != null) {
eventDoc = (event.target && event.target.ownerDocument) || document;
doc = eventDoc.documentElement;
body = eventDoc.body;
event.pageX = event.clientX +
(doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY +
(doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
}
var canvas = document.getElementById( "camera-canvas");
var x = event.pageX - canvas.offsetLeft;
var y = event.pageY - canvas.offsetTop;
mousePos = [-1, -1];
if ( x >= 0 && x < canvas.width && y >= 0 && y < canvas.height ) {
mousePos = [x, y];
}
}
})();
</script>
<body onload="cameraStart();">
<div style="margin-left: 260px;">
<div style="float: right; width: 100%; background-color: #CCF;">
<form name="inputs">
<table>
<tr> <td> <input type="color" value="#000000" id="color" disabled></td> </tr>
<tr> <td> <span id="mouseX">0</span> </td> </tr>
<tr> <td> <span id="mouseY">0</span> </td> </tr>
</table>
</form>
</div>
<div style="float: right; width: 260px; margin-left: -260px;">
<canvas id="camera-canvas" style="border: none;" width="256" height="256"></canvas>
</div>
<div style="clear: both;"></div>
</div>
</body>