Daniel Haehn PRO
Hi, I am a biomedical imaging and visualization researcher who investigates how computational methods can accelerate biological and medical research.
Due Tonight!
Quiz 6!
Patrick Cozzi and Liz Dailey
Today: e-visit at 1245pm!
Patrick Cozzi and Liz Dailey
Welcome!
Updates coming!
Transformations
Translate
Rotate
Scale
Transformations
Translate
Rotate
Scale
Matrix
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
x, y, z
x, y, z
new
Identity
matrix multiplication
Matrix
1 0 0 t_x
0 1 0 t_y
0 0 1 t_z
0 0 0 1
x, y, z
x, y, z
new
Translation
Matrix
s_x 0 0 t_x
0 s_y 0 t_y
0 0 s_z t_z
0 0 0 1
x, y, z
x, y, z
new
Scaling
Matrix
r r r t_x
r r r t_y
r r r t_z
0 0 0 1
x, y, z
x, y, z
new
Rotation
Sheer!
matrix.set(..) uses row-major ordering!
Three.js
var m = new THREE.Matrix4();
m.set(
r, r, r, t_x,
r, r, r, t_y,
r, r, r, t_z,
0, 0, 0, 1
);
WebGL / GLSL
Matrix
1 0 0 t_x
0 1 0 t_y
0 0 1 t_z
0 0 0 1
x, y, z
x, y, z
new
Translation
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Default WebGL!</title>
<style>
html, body {
background-color:#000;
margin: 0;
padding: 0;
height: 100%;
overflow: hidden !important;
}
#c {
width: 100%;
height: 100%;
}
</style>
</head>
<script type="text/javascript" src="https://cs460.org/js/glmatrix.js"></script>
<script id="vertexshader" type="glsl">
attribute vec3 a_position;
uniform vec3 u_offset;
void main(void) {
vec3 final_position = a_position;
final_position.x += u_offset.x;
final_position.y += u_offset.y;
final_position.z += u_offset.z;
gl_Position = vec4( final_position, 1.);
}
</script>
<script id="fragmentshader" type="glsl">
precision mediump float;
uniform vec4 u_color;
void main(void) {
gl_FragColor = u_color;
}
</script>
<script>
var c, gl;
var v_shader, f_shader, shaderprogram;
var vertices, indices, v_buffer, i_buffer;
window.onload = function() {
//************************************************************//
//
// INITIALIZE WEBGL
//
c = document.getElementById( 'c' ); // setup canvas
c.width = window.innerWidth;
c.height = window.innerHeight;
gl = c.getContext( 'webgl' ); // setup GL context
gl.viewport(0, 0, c.width, c.height );
//************************************************************//
//
// SHADERS
//
v_shader = gl.createShader( gl.VERTEX_SHADER );
f_shader = gl.createShader( gl.FRAGMENT_SHADER );
// compile vertex shader
gl.shaderSource( v_shader, document.getElementById( 'vertexshader' ).innerText );
gl.compileShader( v_shader );
if (!gl.getShaderParameter( v_shader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog( v_shader ));
}
// compile fragment shader
gl.shaderSource( f_shader, document.getElementById( 'fragmentshader' ).innerText );
gl.compileShader( f_shader );
if (!gl.getShaderParameter( f_shader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog( f_shader ));
}
// attach and link the shaders
shaderprogram = gl.createProgram();
gl.attachShader( shaderprogram, v_shader );
gl.attachShader( shaderprogram, f_shader );
gl.linkProgram( shaderprogram );
gl.useProgram( shaderprogram );
// create multiple rectangles
rectangles = [];
rectangles.push( createRectangle( new Float32Array([-.2,-.2,0]), new Float32Array([1.,1.,1.,1.]) ) );
rectangles.push( createRectangle( new Float32Array([0,0,0]), new Float32Array([1.,0.,0.,1.]) ) );
animate();
};
function createRectangle(offset, color) {
//************************************************************//
//
// CREATE GEOMETRY
//
var vertices = new Float32Array( [
-0.5, 0.5, 0.0, // 0: V0
-0.5, -0.5, 0.0, // 1: V1, V4
0.5, 0.5, 0.0, // 2: V2, V3
0.5, -0.5, 0.0 // 3: V5
] ); // 2 * 4 == 8 bytes
// now use indices
var indices = new Uint8Array( [ 0, 1, 2, 2, 1, 3 ] ); // 6 bytes
var v_buffer = gl.createBuffer(); // create
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer ); // bind
gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); // put data in
gl.bindBuffer( gl.ARRAY_BUFFER, null ); // unbind
var i_buffer = gl.createBuffer(); // create
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, i_buffer ); // bind
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW ); // put data in
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null ); // unbind
return [v_buffer, i_buffer, offset, color];
};
var step_x = .01;
var step_y = .01;
var direction = -1;
function animate() {
requestAnimationFrame(animate);
gl.clearColor( 0., 0., 0., 0.)
gl.clear( gl.COLOR_BUFFER_BIT );
for( var r = 0; r < rectangles.length; r++ ) {
// current_buffers is a list of [v_buffer, i_buffer]-pairs
var current_buffers = rectangles[r];
var current_v_buffer = current_buffers[0];
var current_i_buffer = current_buffers[1];
var current_offset = current_buffers[2];
var current_color = current_buffers[3];
// update offsets
if ( current_offset[0] <= -1. ) {
// bumped into left end of screen
direction = 1;
} else if ( current_offset[0] >= 1. ) {
// bumped into right end of screen
direction = -1;
}
current_offset[0] += direction*step_x;
if ( current_offset[1] <= -1. ) {
// bumped into left end of screen
direction = 1;
} else if ( current_offset[1] >= 1. ) {
// bumped into right end of screen
direction = -1;
}
current_offset[1] += direction*step_y;
//************************************************************//
//
// CONNECT SHADER WITH GEOMETRY
//
gl.bindBuffer( gl.ARRAY_BUFFER, current_v_buffer );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, current_i_buffer );
// find the attribute in the shader source
var a_position = gl.getAttribLocation( shaderprogram, 'a_position' );
gl.vertexAttribPointer( a_position, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray ( a_position );
// find the uniform in the shader source
var u_offset = gl.getUniformLocation( shaderprogram, 'u_offset' );
gl.uniform3fv( u_offset, current_offset)
var u_color = gl.getUniformLocation( shaderprogram, 'u_color' );
gl.uniform4fv( u_color, current_color );
//************************************************************//
//
// DRAW!
//
// gl.drawArrays( gl.TRIANGLES, 0, 6 );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
}
};
</script>
<body>
<canvas id="c"></canvas>
</body>
</html>
<script id="vertexshader" type="glsl">
attribute vec3 position;
uniform mat4 transform;
void main(void) {
vec4 final_position = transform * vec4( position, 1.);
gl_Position = final_position;
}
</script>
// ANIMATE..
var u_transform = gl.getUniformLocation( shaderprogram, 'transform' );
current_transform = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
OFFSET[0], OFFSET[1], 0, 1
]);
gl.uniformMatrix4fv( u_transform, false, current_transform );
Operator Overloading!
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Vanilla WebGL!</title>
<style>
html, body {
background-color:#000;
margin: 0;
padding: 0;
height: 100%;
overflow: hidden !important;
}
#c {
width: 100%;
height: 100%;
}
</style>
</head>
<script type="text/javascript" src="https://cs460.org/js/glmatrix.js"></script>
<script id="vertexshader" type="glsl">
attribute vec3 position;
uniform mat4 transform;
void main(void) {
vec4 final_position = transform * vec4(position, 1.);
gl_Position = final_position;
gl_PointSize = 10.;
}
</script>
<script id="fragmentshader" type="glsl">
precision mediump float;
uniform vec4 color;
void main(void) {
gl_FragColor = color; //vec4(1., 1., 1., 1.);
}
</script>
<script>
// VARIABLE DECLARATIONS
var c, gl;
var v_shader, f_shader, shaderprogram;
// var vertices, v_buffer, indices, i_buffer;
var objects;
window.onload = function() {
//************************************************************//
//
// INITIALIZE WEBGL
//
c = document.getElementById( 'c' );
c.width = window.innerWidth;
c.height = window.innerHeight;
gl = c.getContext( 'webgl' );
gl.viewport(0, 0, c.width, c.height);
//************************************************************//
//
// SHADERS
//
v_shader = gl.createShader( gl.VERTEX_SHADER );
f_shader = gl.createShader( gl.FRAGMENT_SHADER );
// compile vertex shader
gl.shaderSource( v_shader, document.getElementById( 'vertexshader' ).innerText );
gl.compileShader( v_shader );
if (!gl.getShaderParameter( v_shader, gl.COMPILE_STATUS )) {
console.log(gl.getShaderInfoLog( v_shader ));
}
// compile fragment shader
gl.shaderSource( f_shader, document.getElementById( 'fragmentshader' ).innerText );
gl.compileShader( f_shader );
if (!gl.getShaderParameter( f_shader, gl.COMPILE_STATUS )) {
console.log(gl.getShaderInfoLog( f_shader ));
}
// attach and link the shaders
shaderprogram = gl.createProgram();
gl.attachShader( shaderprogram, v_shader );
gl.attachShader( shaderprogram, f_shader );
gl.linkProgram( shaderprogram );
gl.useProgram( shaderprogram );
// add objects
objects = [];
objects.push(createRectangle(new Float32Array( [1., 1., 0., 1.]),
new Float32Array( [-.3, -.2, 0 ] )));
objects.push(createRectangle(new Float32Array( [1., 0., 0., 1.]),
new Float32Array( [-.1, -.2, 0 ] )));
animate();
};
function createRectangle(color, offset) {
//************************************************************//
//
// CREATE GEOMETRY
//
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0. // 0
-0.5, -0.5, 0.0, // V1, V4. // 1
0.5, 0.5, 0.0, // V2, V3. // 2
0.5, -0.5, 0.0 // V5. // 3
] );
indices = new Uint8Array( [
0, 1, 2, 2, 1, 3
] );
var v_buffer = gl.createBuffer(); // create
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer ); // bind
gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); // put data in
gl.bindBuffer( gl.ARRAY_BUFFER, null ); // unbind
var i_buffer = gl.createBuffer(); // create
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, i_buffer ); // bind
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW ); // put data in
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null ); // unbind
return [v_buffer, i_buffer, color, offset];
};
function animate() {
gl.clearColor( 0., 0., 0., 0. );
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
// loop through all objects in the scene
for (var o=0; o<objects.length; o++) {
var current_object = objects[o];
var v_buffer = current_object[0];
var i_buffer = current_object[1];
var current_color = current_object[2];
var current_offset = current_object[3];
// console.log(current_object);
//************************************************************//
//
// CONNECT SHADER WITH GEOMETRY
//
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, i_buffer );
var a_position = gl.getAttribLocation( shaderprogram, 'position' );
gl.vertexAttribPointer( a_position, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( a_position );
var u_color = gl.getUniformLocation( shaderprogram, 'color' );
gl.uniform4fv( u_color, current_color );
current_offset[0] -= .01;
if (current_offset[0] < -1) {
current_offset[0] = 1;
}
var u_transform = gl.getUniformLocation( shaderprogram, 'transform' );
current_transform = new Float32Array([
.5, 0, 0, 0,
0, .5, 0, 0,
0, 0, .5, 0,
current_offset[0], current_offset[1], 0, 1
]);
gl.uniformMatrix4fv( u_transform, false, current_transform );
//************************************************************//
//
// DRAW!
//
// gl.drawArrays( gl.LINE_LOOP, 0, 6);
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
}
// THIS IS OUR LOOP
requestAnimationFrame(animate);
};
</script>
<body>
<canvas id="c"></canvas>
</body>
</html>
Operator Overloading!
Matrix Games
winner gets extra credit or candy
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
0, 0, 0
?
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
0, 0, 0
0, 0, 0
0.5 0 0 0
0 0.5 0 0
0 0 0.5 0
0 0 0 1
2, 2, 2
?
1, 1, 1
0.5 0 0 0
0 0.5 0 0
0 0 0.5 0
0 0 0 1
2, 2, 2
1 0 0 -1
0 1 0 -1
0 0 1 -1
0 0 0 1
2, 2, 2
?
1, 1, 1
2, 2, 2
1 0 0 -1
0 1 0 -1
0 0 1 -1
0 0 0 1
0.5 0 0 -1
0 0.5 0 -1
0 0 0.5 -1
0 0 0 1
2, 2, 2
?
0.5 0 0 -1
0 0.5 0 -1
0 0 0.5 -1
0 0 0 1
2, 2, 2
0, 0, 0
cos(T) -sin(T) 0 0
sin(T) cos(T) 0 0
0 0 1 0
0 0 0 1
2, 2, 2
?
with T = Pi/2
= 90°
X
Y
Z
cos(T) -sin(T) 0 0
sin(T) cos(T) 0 0
0 0 1 0
0 0 0 1
2, 2, 2
with T = Pi/2
= 90°
-2, 2, 2
Scene Graph
Scene
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Scene
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Scene
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
*
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Scene
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
*
*
*
Scene
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Scene Graph is a Tree-like Hierarchy!
*
*
*
Inverse Kinematics
submit your music
Quiz 6 and Assignment 4 Due Today!
By Daniel Haehn
Hi, I am a biomedical imaging and visualization researcher who investigates how computational methods can accelerate biological and medical research.