Last active
December 26, 2020 21:43
-
-
Save Carla-de-Beer/10ad7c7309fad48d94df to your computer and use it in GitHub Desktop.
WebGL files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var canvas; | |
var gl; | |
// Cube | |
var pointsC = []; | |
var colorsC = []; | |
// Tetra | |
var pointsT = []; | |
var colorsT = []; | |
// Octo | |
var pointsO = []; | |
var colorsO = []; | |
// Axes: 0 = x; 1 = y; 3 = z | |
var xAxis = 0; | |
var yAxis = 1; | |
var zAxis = 2; | |
var axis = 0; | |
// Array of angles: 0 = x; 1 = y; 3 = z | |
var theta = [ 0, 0, 0 ]; | |
var thetaLoc; | |
window.onload = function init() | |
{ | |
canvas = document.getElementById( "gl-canvas" ); | |
gl = WebGLUtils.setupWebGL( canvas ); | |
if ( !gl ) { alert( "WebGL is not available" ); } | |
// --------------- Cube -------------------------- | |
colorCube(); | |
// --------------- Tetrahedron ------------------- | |
colorTetra(); | |
// --------------- Octohedron -------------------- | |
colorOcto(); | |
// viewport = rectangular area of display window | |
gl.viewport( 0, 0, canvas.width, canvas.height ); | |
// clear area of display for rendering at each frame | |
gl.clearColor( 0.1, 0.1, 0.1, 1.0 ); | |
gl.enable(gl.DEPTH_TEST); | |
// --------------- Load shaders and initialize attribute buffers | |
// --------------- Cube -------------------------- | |
// Create a buffer object, initialise it, and associate it | |
// with the associated attribute variable in our vertex shader | |
var programCube = initShaders( gl, "vertex-shader", "fragment-shader" ); | |
gl.useProgram( programCube ); | |
// Buffer | |
var ccBuffer = gl.createBuffer(); | |
gl.bindBuffer( gl.ARRAY_BUFFER, ccBuffer ); | |
gl.bufferData( gl.ARRAY_BUFFER, transpose(colorsC), gl.STATIC_DRAW ); | |
// Cube colour; set attributes | |
var cvColor = gl.getAttribLocation( programCube, "vColor" ); | |
gl.vertexAttribPointer( cvColor, 4, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray( cvColor ); | |
// Cube create points buffer | |
var cvBuffer = gl.createBuffer(); | |
gl.bindBuffer( gl.ARRAY_BUFFER, cvBuffer ); | |
gl.bufferData( gl.ARRAY_BUFFER, transpose(pointsC), gl.STATIC_DRAW ); | |
// Cube create position | |
var cvPosition = gl.getAttribLocation( programCube, "vPosition" ); | |
gl.vertexAttribPointer( cvPosition, 3, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray( cvPosition ); | |
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
thetaLoc = gl.getUniformLocation(programCube, "theta"); | |
//gl.drawArrays( gl.TRIANGLES, 0, pointsC.length ); | |
gl.uniform3fv(thetaLoc, theta); | |
render(); | |
// --------------- Tetrahedron ------------------- | |
// Create a buffer object, initialise it, and associate it | |
// with the associated attribute variable in our vertex shader | |
var programTetra = initShaders( gl, "vertex-shader", "fragment-shader" ); | |
gl.useProgram( programTetra ); | |
var tcBuffer = gl.createBuffer(); | |
gl.bindBuffer( gl.ARRAY_BUFFER, tcBuffer ); | |
gl.bufferData( gl.ARRAY_BUFFER, transpose(colorsT), gl.STATIC_DRAW ); | |
var tvColor = gl.getAttribLocation( programTetra, "vColor" ); | |
gl.vertexAttribPointer( tvColor, 3, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray( tvColor ); | |
var tvBuffer = gl.createBuffer(); | |
gl.bindBuffer( gl.ARRAY_BUFFER, tvBuffer); | |
gl.bufferData( gl.ARRAY_BUFFER, transpose(pointsT), gl.STATIC_DRAW ); | |
var tvPosition = gl.getAttribLocation( programTetra, "vPosition" ); | |
gl.vertexAttribPointer( tvPosition, 3, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray( tvPosition ); | |
//thetaLoc = gl.getUniformLocation(programTetra, "theta"); | |
gl.drawArrays( gl.TRIANGLES, 0, pointsT.length ); | |
// --------------- Octohedron -------------------- | |
// Create a buffer object, initialise it, and associate it | |
// with the associated attribute variable in our vertex shader | |
var programOcto = initShaders( gl, "vertex-shader", "fragment-shader" ); | |
gl.useProgram( programOcto ); | |
var ocBuffer = gl.createBuffer(); | |
gl.bindBuffer( gl.ARRAY_BUFFER, ocBuffer ); | |
gl.bufferData( gl.ARRAY_BUFFER, transpose(colorsO), gl.STATIC_DRAW ); | |
var ovColor = gl.getAttribLocation( programOcto, "vColor" ); | |
gl.vertexAttribPointer( ovColor, 3, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray( ovColor ); | |
var ovBuffer = gl.createBuffer(); | |
gl.bindBuffer( gl.ARRAY_BUFFER, ovBuffer ); | |
gl.bufferData( gl.ARRAY_BUFFER, transpose(pointsO), gl.STATIC_DRAW ); | |
var ovPosition = gl.getAttribLocation( programOcto, "vPosition" ); | |
gl.vertexAttribPointer( ovPosition, 3, gl.FLOAT, false, 0, 0 ); | |
gl.enableVertexAttribArray( ovPosition ); | |
//thetaLoc = gl.getUniformLocation(programOcto, "theta"); | |
gl.drawArrays( gl.TRIANGLES, 0, pointsO.length ); | |
// ------------------------------------------------------------------ | |
// Event listeners for buttons | |
var isZ = false; | |
var isY = false; | |
var isX = false; | |
document.getElementById( "xRot" ).onclick = function() { | |
axis = xAxis; | |
isX = !isX; | |
document.getElementById('xRot').style.background='#bebfba'; | |
if(!isX){ | |
document.getElementById('xRot').style.background='#FFF'; | |
} | |
}; | |
document.getElementById( "yRot" ).onclick = function() { | |
axis = yAxis; | |
isY = !isY; | |
document.getElementById('yRot').style.background='#bebfba'; | |
if(!isY){ | |
document.getElementById('yRot').style.background='#FFF'; | |
} | |
}; | |
document.getElementById( "zRot" ).onclick = function() { | |
axis = zAxis; | |
isZ = !isZ; | |
document.getElementById('zRot').style.background='#bebfba'; | |
if(!isZ){ | |
document.getElementById('zRot').style.background='#FFF'; | |
} | |
}; | |
} | |
// ------------------------------------------------------------------- | |
function render() | |
{ | |
theta[axis] += 2.0; | |
gl.uniform3fv(thetaLoc, theta); | |
// Render cube | |
gl.drawArrays( gl.TRIANGLES, 0, pointsC.length ); | |
requestAnimationFrame( render ); | |
} | |
// DEFINE CUBE | |
function colorCube() | |
{ | |
square( 1, 0, 3, 2 ); | |
square( 2, 3, 7, 6 ); | |
square( 3, 0, 4, 7 ); | |
square( 6, 5, 1, 2 ); | |
square( 4, 5, 6, 7 ); | |
square( 5, 4, 0, 1 ); | |
} | |
function square(a, b, c, d) | |
{ | |
var verticesC = [ | |
vec3( -0.25, -0.25, 0.25 ), | |
vec3( -0.25, 0.25, 0.25 ), | |
vec3( 0.25, 0.25, 0.25 ), | |
vec3( 0.25, -0.25, 0.25 ), | |
vec3( -0.25, -0.25, -0.25 ), | |
vec3( -0.25, 0.25, -0.25 ), | |
vec3( 0.25, 0.25, -0.25 ), | |
vec3( 0.25, -0.25, -0.25 ) | |
]; | |
var vertexColors = [ | |
[ 0.9, 0.9, 0.2, 1.0 ], // orange | |
[ 0.0, 1.0, 1.0, 1.0 ], // cyan | |
[ 1.0, 0.0, 0.0, 1.0 ], // red | |
[ 1.0, 1.0, 0.0, 1.0 ], // yellow | |
[ 0.0, 1.0, 0.0, 1.0 ], // green | |
[ 1.0, 0.0, 1.0, 1.0 ], // magenta | |
[ 0.0, 0.0, 1.0, 1.0 ], // blue | |
[ 1.0, 1.0, 1.0, 1.0 ] // white | |
]; | |
// Partion the square into two triangles in order for | |
// WebGL to be able to render it. | |
// Vertex color assigned by the index of the vertex | |
var indices = [ a, b, c, a, c, d ]; | |
for ( var i = 0; i < indices.length; ++i ) { | |
pointsC.push( verticesC[indices[i]] ); | |
colorsC.push( vertexColors[indices[i]] ); | |
//for solid colored faces use | |
//colorsC.push(vertexColors[a]); | |
} | |
} | |
// DEFINE TETRAHEDRON | |
function colorTetra(){ | |
var verticesT = [ | |
vec3( 0.0000, 0.0000, -0.3500 ), | |
vec3( 0.0000, 0.3500, 0.1500 ), | |
vec3( -0.3500, -0.1500, 0.1500 ), | |
vec3( 0.3500, -0.1500, 0.1500 ) | |
]; | |
tetra(verticesT[0], verticesT[1], verticesT[2], verticesT[3]); | |
} | |
function makeTetra( a, b, c, color ) | |
{ | |
// add colors and vertices for one triangle | |
var baseColors = [ | |
vec3(0.7, 0.7, 0.9, 1.0), | |
vec3(0.6, 0.8, 0.9, 1.0), | |
vec3(0.5, 0.6, 0.9, 1.0), | |
vec3(1.0, 1.0, 0.2, 1.0) | |
]; | |
colorsT.push( baseColors[color] ); | |
pointsT.push( a ); | |
colorsT.push( baseColors[color] ); | |
pointsT.push( b ); | |
colorsT.push( baseColors[color] ); | |
pointsT.push( c ); | |
} | |
function tetra( p, q, r, s ) | |
{ | |
// tetrahedron with each side using | |
// a different color | |
makeTetra( p, r, q, 0 ); | |
makeTetra( p, r, s, 1 ); | |
makeTetra( p, q, s, 2 ); | |
makeTetra( q, r, s, 3 ); | |
} | |
// DEFINE OCTOHEDRON | |
function colorOcto(){ | |
var verticesO = [ | |
vec3( 0.4000, 0.0000, 0.0000 ), | |
vec3( 0.0000, 0.0000, 0.0000 ), | |
vec3( 0.0000, 0.4000, 0.0000 ), | |
vec3( 0.4000, 0.4000, 0.0000 ), | |
vec3( 0.2000, 0.2000, 0.3000 ), | |
vec3( 0.2000, 0.2000, -0.3000 ) | |
]; | |
octo(verticesO[0], verticesO[1], verticesO[2], verticesO[3], verticesO[4], verticesO[5]); | |
} | |
function makeOcto( a, b, c, color ) | |
{ | |
// add colors and vertices for one triangle | |
var baseColors = [ | |
vec3(0.6, 0.6, 0.6, 1.0), | |
vec3(0.3, 0.4, 0.9, 1.0), | |
vec3(0.9, 0.9, 0.9, 1.0), | |
]; | |
colorsO.push( baseColors[color] ); | |
pointsO.push( a ); | |
colorsO.push( baseColors[color] ); | |
pointsO.push( b ); | |
colorsO.push( baseColors[color] ); | |
pointsO.push( c ); | |
} | |
function octo( a, b, c, d , e, f) | |
{ | |
// tetrahedron with each side using | |
// a different color | |
makeOcto( a, d, e, 0 ); | |
makeOcto( a, b, e, 1 ); | |
makeOcto( b, c, e, 0 ); | |
makeOcto( c, d, e, 1 ); | |
makeOcto( a, d, f, 1 ); | |
makeOcto( a, b, f, 2 ); | |
makeOcto( b, c, f, 1 ); | |
makeOcto( c, d, f, 2 ); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<script id="vertex-shader" type="x-shader/x-vertex"> | |
attribute vec4 vPosition; | |
attribute vec4 vColor; | |
varying vec4 fColor; | |
uniform vec3 theta; | |
void main() | |
{ | |
// Compute the sines and cosines of theta for each of | |
// the three axes in one computation. | |
vec3 angles = radians( theta ); | |
vec3 c = cos( angles ); | |
vec3 s = sin( angles ); | |
// The matrices are column-major | |
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0, | |
0.0, c.x, s.x, 0.0, | |
0.0, -s.x, c.x, 0.0, | |
0.0, 0.0, 0.0, 1.0 ); | |
mat4 ry = mat4( c.y, 0.0, -s.y, 0.0, | |
0.0, 1.0, 0.0, 0.0, | |
s.y, 0.0, c.y, 0.0, | |
0.0, 0.0, 0.0, 1.0 ); | |
mat4 rz = mat4( c.z, -s.z, 0.0, 0.0, | |
s.z, c.z, 0.0, 0.0, | |
0.0, 0.0, 1.0, 0.0, | |
0.0, 0.0, 0.0, 1.0 ); | |
fColor = vColor; | |
gl_Position = rz * ry * rx * vPosition; | |
} | |
</script> | |
<script id="fragment-shader" type="x-shader/x-fragment"> | |
precision mediump float; | |
varying vec4 fColor; | |
void | |
main() | |
{ | |
gl_FragColor = fColor; | |
} | |
</script> | |
<script type="text/javascript" src="webgl-utils.js"></script> | |
<script type="text/javascript" src="initShaders.js"></script> | |
<script type="text/javascript" src="MV.js"></script> | |
<script type="text/javascript" src="cube.js"></script> | |
<body> | |
<canvas id="gl-canvas" width="725"" height="725"> | |
Oops ... your browser doesn't support the HTML5 canvas element | |
</canvas> | |
<br/> | |
<br> | |
<button id="xButton" style="background: #FFF">Rotate X</button> | |
<button id="yButton" style="background: #FFF">Rotate Y</button> | |
<button id="zButton" style="background: #FFF">Rotate Z</button> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function initShaders( gl, vertexShaderId, fragmentShaderId ) | |
{ | |
var vertShdr; | |
var fragShdr; | |
var vertElem = document.getElementById( vertexShaderId ); | |
if ( !vertElem ) { | |
alert( "Unable to load vertex shader " + vertexShaderId ); | |
return -1; | |
} | |
else { | |
vertShdr = gl.createShader( gl.VERTEX_SHADER ); | |
gl.shaderSource( vertShdr, vertElem.text ); | |
gl.compileShader( vertShdr ); | |
if ( !gl.getShaderParameter(vertShdr, gl.COMPILE_STATUS) ) { | |
var msg = "Vertex shader failed to compile. The error log is:" | |
+ "<pre>" + gl.getShaderInfoLog( vertShdr ) + "</pre>"; | |
alert( msg ); | |
return -1; | |
} | |
} | |
var fragElem = document.getElementById( fragmentShaderId ); | |
if ( !fragElem ) { | |
alert( "Unable to load vertex shader " + fragmentShaderId ); | |
return -1; | |
} | |
else { | |
fragShdr = gl.createShader( gl.FRAGMENT_SHADER ); | |
gl.shaderSource( fragShdr, fragElem.text ); | |
gl.compileShader( fragShdr ); | |
if ( !gl.getShaderParameter(fragShdr, gl.COMPILE_STATUS) ) { | |
var msg = "Fragment shader failed to compile. The error log is:" | |
+ "<pre>" + gl.getShaderInfoLog( fragShdr ) + "</pre>"; | |
alert( msg ); | |
return -1; | |
} | |
} | |
var program = gl.createProgram(); | |
gl.attachShader( program, vertShdr ); | |
gl.attachShader( program, fragShdr ); | |
gl.linkProgram( program ); | |
if ( !gl.getProgramParameter(program, gl.LINK_STATUS) ) { | |
var msg = "Shader program failed to link. The error log is:" | |
+ "<pre>" + gl.getProgramInfoLog( program ) + "</pre>"; | |
alert( msg ); | |
return -1; | |
} | |
return program; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//---------------------------------------------------------------------------- | |
// | |
// Helper functions | |
// | |
function _argumentsToArray( args ) | |
{ | |
return [].concat.apply( [], Array.prototype.slice.apply(args) ); | |
} | |
//---------------------------------------------------------------------------- | |
function radians( degrees ) { | |
return degrees * Math.PI / 180.0; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Vector Constructors | |
// | |
function vec2() | |
{ | |
var result = _argumentsToArray( arguments ); | |
switch ( result.length ) { | |
case 0: result.push( 0.0 ); | |
case 1: result.push( 0.0 ); | |
} | |
return result.splice( 0, 2 ); | |
} | |
function vec3() | |
{ | |
var result = _argumentsToArray( arguments ); | |
switch ( result.length ) { | |
case 0: result.push( 0.0 ); | |
case 1: result.push( 0.0 ); | |
case 2: result.push( 0.0 ); | |
} | |
return result.splice( 0, 3 ); | |
} | |
function vec4() | |
{ | |
var result = _argumentsToArray( arguments ); | |
switch ( result.length ) { | |
case 0: result.push( 0.0 ); | |
case 1: result.push( 0.0 ); | |
case 2: result.push( 0.0 ); | |
case 3: result.push( 1.0 ); | |
} | |
return result.splice( 0, 4 ); | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Matrix Constructors | |
// | |
function mat2() | |
{ | |
var v = _argumentsToArray( arguments ); | |
var m = []; | |
switch ( v.length ) { | |
case 0: | |
v[0] = 1; | |
case 1: | |
m = [ | |
vec2( v[0], 0.0 ), | |
vec2( 0.0, v[0] ) | |
]; | |
break; | |
default: | |
m.push( vec2(v) ); v.splice( 0, 2 ); | |
m.push( vec2(v) ); | |
break; | |
} | |
m.matrix = true; | |
return m; | |
} | |
//---------------------------------------------------------------------------- | |
function mat3() | |
{ | |
var v = _argumentsToArray( arguments ); | |
var m = []; | |
switch ( v.length ) { | |
case 0: | |
v[0] = 1; | |
case 1: | |
m = [ | |
vec3( v[0], 0.0, 0.0 ), | |
vec3( 0.0, v[0], 0.0 ), | |
vec3( 0.0, 0.0, v[0] ) | |
]; | |
break; | |
default: | |
m.push( vec3(v) ); v.splice( 0, 3 ); | |
m.push( vec3(v) ); v.splice( 0, 3 ); | |
m.push( vec3(v) ); | |
break; | |
} | |
m.matrix = true; | |
return m; | |
} | |
//---------------------------------------------------------------------------- | |
function mat4() | |
{ | |
var v = _argumentsToArray( arguments ); | |
var m = []; | |
switch ( v.length ) { | |
case 0: | |
v[0] = 1; | |
case 1: | |
m = [ | |
vec4( v[0], 0.0, 0.0, 0.0 ), | |
vec4( 0.0, v[0], 0.0, 0.0 ), | |
vec4( 0.0, 0.0, v[0], 0.0 ), | |
vec4( 0.0, 0.0, 0.0, v[0] ) | |
]; | |
break; | |
default: | |
m.push( vec4(v) ); v.splice( 0, 4 ); | |
m.push( vec4(v) ); v.splice( 0, 4 ); | |
m.push( vec4(v) ); v.splice( 0, 4 ); | |
m.push( vec4(v) ); | |
break; | |
} | |
m.matrix = true; | |
return m; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Generic Mathematical Operations for Vectors and Matrices | |
// | |
function equal( u, v ) | |
{ | |
if ( u.length != v.length ) { return false; } | |
if ( u.matrix && v.matrix ) { | |
for ( var i = 0; i < u.length; ++i ) { | |
if ( u[i].length != v[i].length ) { return false; } | |
for ( var j = 0; j < u[i].length; ++j ) { | |
if ( u[i][j] !== v[i][j] ) { return false; } | |
} | |
} | |
} | |
else if ( u.matrix && !v.matrix || !u.matrix && v.matrix ) { | |
return false; | |
} | |
else { | |
for ( var i = 0; i < u.length; ++i ) { | |
if ( u[i] !== v[i] ) { return false; } | |
} | |
} | |
return true; | |
} | |
//---------------------------------------------------------------------------- | |
function add( u, v ) | |
{ | |
var result = []; | |
if ( u.matrix && v.matrix ) { | |
if ( u.length != v.length ) { | |
throw "add(): trying to add matrices of different dimensions"; | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
if ( u[i].length != v[i].length ) { | |
throw "add(): trying to add matrices of different dimensions"; | |
} | |
result.push( [] ); | |
for ( var j = 0; j < u[i].length; ++j ) { | |
result[i].push( u[i][j] + v[i][j] ); | |
} | |
} | |
result.matrix = true; | |
return result; | |
} | |
else if ( u.matrix && !v.matrix || !u.matrix && v.matrix ) { | |
throw "add(): trying to add matrix and non-matrix variables"; | |
} | |
else { | |
if ( u.length != v.length ) { | |
throw "add(): vectors are not the same dimension"; | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
result.push( u[i] + v[i] ); | |
} | |
return result; | |
} | |
} | |
//---------------------------------------------------------------------------- | |
function subtract( u, v ) | |
{ | |
var result = []; | |
if ( u.matrix && v.matrix ) { | |
if ( u.length != v.length ) { | |
throw "subtract(): trying to subtract matrices" + | |
" of different dimensions"; | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
if ( u[i].length != v[i].length ) { | |
throw "subtract(): trying to subtact matrices" + | |
" of different dimensions"; | |
} | |
result.push( [] ); | |
for ( var j = 0; j < u[i].length; ++j ) { | |
result[i].push( u[i][j] - v[i][j] ); | |
} | |
} | |
result.matrix = true; | |
return result; | |
} | |
else if ( u.matrix && !v.matrix || !u.matrix && v.matrix ) { | |
throw "subtact(): trying to subtact matrix and non-matrix variables"; | |
} | |
else { | |
if ( u.length != v.length ) { | |
throw "subtract(): vectors are not the same length"; | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
result.push( u[i] - v[i] ); | |
} | |
return result; | |
} | |
} | |
//---------------------------------------------------------------------------- | |
function mult( u, v ) | |
{ | |
var result = []; | |
if ( u.matrix && v.matrix ) { | |
if ( u.length != v.length ) { | |
throw "mult(): trying to add matrices of different dimensions"; | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
if ( u[i].length != v[i].length ) { | |
throw "mult(): trying to add matrices of different dimensions"; | |
} | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
result.push( [] ); | |
for ( var j = 0; j < v.length; ++j ) { | |
var sum = 0.0; | |
for ( var k = 0; k < u.length; ++k ) { | |
sum += u[i][k] * v[k][j]; | |
} | |
result[i].push( sum ); | |
} | |
} | |
result.matrix = true; | |
return result; | |
} | |
else { | |
if ( u.length != v.length ) { | |
throw "mult(): vectors are not the same dimension"; | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
result.push( u[i] * v[i] ); | |
} | |
return result; | |
} | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Basic Transformation Matrix Generators | |
// | |
function translate( x, y, z ) | |
{ | |
if ( Array.isArray(x) && x.length == 3 ) { | |
z = x[2]; | |
y = x[1]; | |
x = x[0]; | |
} | |
var result = mat4(); | |
result[0][3] = x; | |
result[1][3] = y; | |
result[2][3] = z; | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
function rotate( angle, axis ) | |
{ | |
if ( !Array.isArray(axis) ) { | |
axis = [ arguments[1], arguments[2], arguments[3] ]; | |
} | |
var v = normalize( axis ); | |
var x = v[0]; | |
var y = v[1]; | |
var z = v[2]; | |
var c = Math.cos( radians(angle) ); | |
var omc = 1.0 - c; | |
var s = Math.sin( radians(angle) ); | |
var result = mat4( | |
vec4( x*x*omc + c, x*y*omc - z*s, x*z*omc + y*s, 0.0 ), | |
vec4( x*y*omc + z*s, y*y*omc + c, y*z*omc - x*s, 0.0 ), | |
vec4( x*z*omc - y*s, y*z*omc + x*s, z*z*omc + c, 0.0 ), | |
vec4() | |
); | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
function scale( x, y, z ) | |
{ | |
if ( Array.isArray(x) && x.length == 3 ) { | |
z = x[2]; | |
y = x[1]; | |
x = x[0]; | |
} | |
var result = mat4(); | |
result[0][0] = x; | |
result[1][1] = y; | |
result[2][2] = z; | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// ModelView Matrix Generators | |
// | |
function lookAt( eye, at, up ) | |
{ | |
if ( !Array.isArray(eye) || eye.length != 3) { | |
throw "lookAt(): first parameter [eye] must be an a vec3"; | |
} | |
if ( !Array.isArray(at) || at.length != 3) { | |
throw "lookAt(): first parameter [at] must be an a vec3"; | |
} | |
if ( !Array.isArray(up) || up.length != 3) { | |
throw "lookAt(): first parameter [up] must be an a vec3"; | |
} | |
if ( equal(eye, at) ) { | |
return mat4(); | |
} | |
var v = normalize( subtract(at, eye) ); // view direction vector | |
var n = normalize( cross(v, up) ); // perpendicular vector | |
var u = normalize( cross(n, v) ); // "new" up vector | |
v = negate( v ); | |
var result = mat4( | |
vec4( n, -dot(n, eye) ), | |
vec4( u, -dot(u, eye) ), | |
vec4( v, -dot(v, eye) ), | |
vec4() | |
); | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Projection Matrix Generators | |
// | |
function ortho( left, right, bottom, top, near, far ) | |
{ | |
if ( left == right ) { throw "ortho(): left and right are equal"; } | |
if ( bottom == top ) { throw "ortho(): bottom and top are equal"; } | |
if ( near == far ) { throw "ortho(): near and far are equal"; } | |
var w = right - left; | |
var h = top - bottom; | |
var d = far - near; | |
var result = mat4(); | |
result[0][0] = 2.0 / w; | |
result[1][1] = 2.0 / h; | |
result[2][2] = -2.0 / d; | |
result[0][3] = -(left + right) / w; | |
result[1][3] = -(top + bottom) / h; | |
result[2][3] = -(near + far) / d; | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
function perspective( fovy, aspect, near, far ) | |
{ | |
var f = 1.0 / Math.tan( radians(fovy) / 2 ); | |
var d = far - near; | |
var result = mat4(); | |
result[0][0] = f / aspect; | |
result[1][1] = f; | |
result[2][2] = -(near + far) / d; | |
result[2][3] = -2 * near * far / d; | |
result[3][2] = -1; | |
result[3][3] = 0.0; | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Matrix Functions | |
// | |
function transpose( m ) | |
{ | |
if ( !m.matrix ) { | |
return "transpose(): trying to transpose a non-matrix"; | |
} | |
var result = []; | |
for ( var i = 0; i < m.length; ++i ) { | |
result.push( [] ); | |
for ( var j = 0; j < m[i].length; ++j ) { | |
result[i].push( m[j][i] ); | |
} | |
} | |
result.matrix = true; | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Vector Functions | |
// | |
function dot( u, v ) | |
{ | |
if ( u.length != v.length ) { | |
throw "dot(): vectors are not the same dimension"; | |
} | |
var sum = 0.0; | |
for ( var i = 0; i < u.length; ++i ) { | |
sum += u[i] * v[i]; | |
} | |
return sum; | |
} | |
//---------------------------------------------------------------------------- | |
function negate( u ) | |
{ | |
result = []; | |
for ( var i = 0; i < u.length; ++i ) { | |
result.push( -u[i] ); | |
} | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
function cross( u, v ) | |
{ | |
if ( !Array.isArray(u) || u.length < 3 ) { | |
throw "cross(): first argument is not a vector of at least 3"; | |
} | |
if ( !Array.isArray(v) || v.length < 3 ) { | |
throw "cross(): second argument is not a vector of at least 3"; | |
} | |
var result = [ | |
u[1]*v[2] - u[2]*v[1], | |
u[2]*v[0] - u[0]*v[2], | |
u[0]*v[1] - u[1]*v[0] | |
]; | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
function length( u ) | |
{ | |
return Math.sqrt( dot(u, u) ); | |
} | |
//---------------------------------------------------------------------------- | |
function normalize( u, excludeLastComponent ) | |
{ | |
if ( excludeLastComponent ) { | |
var last = u.pop(); | |
} | |
var len = length( u ); | |
if ( !isFinite(len) ) { | |
throw "normalize: vector " + u + " has zero length"; | |
} | |
for ( var i = 0; i < u.length; ++i ) { | |
u[i] /= len; | |
} | |
if ( excludeLastComponent ) { | |
u.push( last ); | |
} | |
return u; | |
} | |
//---------------------------------------------------------------------------- | |
function mix( u, v, s ) | |
{ | |
if ( typeof s !== "number" ) { | |
throw "mix: the last paramter " + s + " must be a number"; | |
} | |
if ( u.length != v.length ) { | |
throw "vector dimension mismatch"; | |
} | |
var result = []; | |
for ( var i = 0; i < u.length; ++i ) { | |
result.push( s * u[i] + (1.0 - s) * v[i] ); | |
} | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// Vector and Matrix functions | |
// | |
function scale( s, u ) | |
{ | |
if ( !Array.isArray(u) ) { | |
throw "scale: second parameter " + u + " is not a vector"; | |
} | |
result = []; | |
for ( var i = 0; i < u.length; ++i ) { | |
result.push( s * u[i] ); | |
} | |
return result; | |
} | |
//---------------------------------------------------------------------------- | |
// | |
// | |
// | |
function flatten( v ) | |
{ | |
if ( v.matrix === true ) { | |
v = transpose( v ); | |
} | |
var n = v.length; | |
var elemsAreArrays = false; | |
if ( Array.isArray(v[0]) ) { | |
elemsAreArrays = true; | |
n *= v[0].length; | |
} | |
var floats = new Float32Array( n ); | |
if ( elemsAreArrays ) { | |
var idx = 0; | |
for ( var i = 0; i < v.length; ++i ) { | |
for ( var j = 0; j < v[i].length; ++j ) { | |
floats[idx++] = v[i][j]; | |
} | |
} | |
} | |
else { | |
for ( var i = 0; i < v.length; ++i ) { | |
floats[i] = v[i]; | |
} | |
} | |
return floats; | |
} | |
//---------------------------------------------------------------------------- | |
var sizeof = { | |
'vec2' : new Float32Array( flatten(vec2()) ).byteLength, | |
'vec3' : new Float32Array( flatten(vec3()) ).byteLength, | |
'vec4' : new Float32Array( flatten(vec4()) ).byteLength, | |
'mat2' : new Float32Array( flatten(mat2()) ).byteLength, | |
'mat3' : new Float32Array( flatten(mat3()) ).byteLength, | |
'mat4' : new Float32Array( flatten(mat4()) ).byteLength | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2010, Google Inc. | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are | |
* met: | |
* | |
* * Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* * Redistributions in binary form must reproduce the above | |
* copyright notice, this list of conditions and the following disclaimer | |
* in the documentation and/or other materials provided with the | |
* distribution. | |
* * Neither the name of Google Inc. nor the names of its | |
* contributors may be used to endorse or promote products derived from | |
* this software without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
/** | |
* @fileoverview This file contains functions every webgl program will need | |
* a version of one way or another. | |
* | |
* Instead of setting up a context manually it is recommended to | |
* use. This will check for success or failure. On failure it | |
* will attempt to present an approriate message to the user. | |
* | |
* gl = WebGLUtils.setupWebGL(canvas); | |
* | |
* For animated WebGL apps use of setTimeout or setInterval are | |
* discouraged. It is recommended you structure your rendering | |
* loop like this. | |
* | |
* function render() { | |
* window.requestAnimFrame(render, canvas); | |
* | |
* // do rendering | |
* ... | |
* } | |
* render(); | |
* | |
* This will call your rendering function up to the refresh rate | |
* of your display but will stop rendering if your app is not | |
* visible. | |
*/ | |
WebGLUtils = function() { | |
/** | |
* Creates the HTLM for a failure message | |
* @param {string} canvasContainerId id of container of th | |
* canvas. | |
* @return {string} The html. | |
*/ | |
var makeFailHTML = function(msg) { | |
return '' + | |
'<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>' + | |
'<td align="center">' + | |
'<div style="display: table-cell; vertical-align: middle;">' + | |
'<div style="">' + msg + '</div>' + | |
'</div>' + | |
'</td></tr></table>'; | |
}; | |
/** | |
* Mesasge for getting a webgl browser | |
* @type {string} | |
*/ | |
var GET_A_WEBGL_BROWSER = '' + | |
'This page requires a browser that supports WebGL.<br/>' + | |
'<a href="http://get.webgl.org">Click here to upgrade your browser.</a>'; | |
/** | |
* Mesasge for need better hardware | |
* @type {string} | |
*/ | |
var OTHER_PROBLEM = '' + | |
"It doesn't appear your computer can support WebGL.<br/>" + | |
'<a href="http://get.webgl.org/troubleshooting/">Click here for more information.</a>'; | |
/** | |
* Creates a webgl context. If creation fails it will | |
* change the contents of the container of the <canvas> | |
* tag to an error message with the correct links for WebGL. | |
* @param {Element} canvas. The canvas element to create a | |
* context from. | |
* @param {WebGLContextCreationAttirbutes} opt_attribs Any | |
* creation attributes you want to pass in. | |
* @return {WebGLRenderingContext} The created context. | |
*/ | |
var setupWebGL = function(canvas, opt_attribs) { | |
function showLink(str) { | |
var container = canvas.parentNode; | |
if (container) { | |
container.innerHTML = makeFailHTML(str); | |
} | |
}; | |
if (!window.WebGLRenderingContext) { | |
showLink(GET_A_WEBGL_BROWSER); | |
return null; | |
} | |
var context = create3DContext(canvas, opt_attribs); | |
if (!context) { | |
showLink(OTHER_PROBLEM); | |
} | |
return context; | |
}; | |
/** | |
* Creates a webgl context. | |
* @param {!Canvas} canvas The canvas tag to get context | |
* from. If one is not passed in one will be created. | |
* @return {!WebGLContext} The created context. | |
*/ | |
var create3DContext = function(canvas, opt_attribs) { | |
var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]; | |
var context = null; | |
for (var ii = 0; ii < names.length; ++ii) { | |
try { | |
context = canvas.getContext(names[ii], opt_attribs); | |
} catch(e) {} | |
if (context) { | |
break; | |
} | |
} | |
return context; | |
} | |
return { | |
create3DContext: create3DContext, | |
setupWebGL: setupWebGL | |
}; | |
}(); | |
/** | |
* Provides requestAnimationFrame in a cross browser way. | |
*/ | |
window.requestAnimFrame = (function() { | |
return window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
window.oRequestAnimationFrame || | |
window.msRequestAnimationFrame || | |
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { | |
window.setTimeout(callback, 1000/60); | |
}; | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment