Assignment 3
Tuesday lecture by Vidhya!
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3(-10, 10, 0),
new THREE.Vector3(-10, -10, 0),
new THREE.Vector3(10, -10, 0)
);
geometry.faces.push( new THREE.Face3(0, 1, 2));
GPU
Vertex Shader
Fragment Shader
Viewport
From 3D..
..to 2D
vertex coordinates X Y Z
screenspace coordinates X Y
Vertices
Face
Rasterization
The Rendering Pipeline
XTK
X.renderer3D
X.cube
Three.js
THREE.WebGLRenderer
THREE.Scene
THREE.TrackballControls
THREE.PerspectiveCamera
THREE.AmbientLight
THREE.DirectionalLight
WebGL
gl.viewport
gl.createShader
gl.shaderSource
gl.compileShader
gl.getShaderInfoLog
gl.createProgram
gl.attachShader
gl.linkProgram
gl.useProgram
gl.createBuffer
gl.bindBuffer
gl.BufferData
gl.getAttribLocation
gl.vertexAttribPointer
gl.enableVertexAttribArray
gl.clearColor
gl.clear
gl.drawArrays
THREE.Geometry
THREE.Material
THREE.Mesh
Play it here:
Due 10/10!
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
setup Canvas
setup GL Context
compile vertex shader
compile fragment shader
attach and link shaders
create vertices
create and bind buffer
put data in
unbind buffer
bind buffer
find vertex attribute in shader source
configure vertex attribute
enable vertex attribute array
clear viewport
clear color buffer
draw vertex arrays
V0
V1
V2
V3
V4
V5
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
gl.TRIANGLES
V0
V1
V2
V3
V4
V5
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
gl.POINTS
gl_PointSize
V0
V1
V2
V3
V4
V5
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
gl.LINES
Rendering Primitives
V0
V1
V2
V3
V4
V5
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1, V4
0.5, 0.5, 0.0, // V2, V3
0.5, -0.5, 0.0 // V5
] );
V0
V1
V2
V3
V4
V5
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
] );
var indices = new Uint8Array( [ 0, 1, 2, // Triangle 1
2, 1, 3 ] ); // Triangle 2
0
1
2
3
Indexed Geometry
Before: 6 x 32 bits, Now: 4 x 32 bits
6 x 8 bits == 48 bits
We still save 16 bits.
We save 2 x 32 bits.
gl.ARRAY_BUFFER
gl.ELEMENT_ARRAY_BUFFER
Indexed Geometry
//************************************************************//
//
// CREATE GEOMETRY
//
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
] );
// now use indices
var indices = new Uint8Array( [ 0, 1, 2, // Triangle 1
2, 1, 3 ] ); // Triangle 2
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
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
important for assignment 4!
Indexed Geometry
important for assignment 4!
//************************************************************//
//
// CONNECT SHADER WITH GEOMETRY
//
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, i_buffer );
//************************************************************//
//
// DRAW!
//
gl.clearColor( 0., 0., 0., 0.)
gl.clear( gl.COLOR_BUFFER_BIT );
// gl.drawArrays( gl.TRIANGLES, 0, 6 );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
Let's code!
<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 id="vertexshader" type="glsl">
attribute vec3 position;
void main(void) {
gl_Position = vec4( position, 1.);
}
</script>
<script id="fragmentshader" type="glsl">
precision mediump float;
void main(void) {
gl_FragColor = vec4(1., 1., 1., 1.);
}
</script>
<script>
var c, gl;
var v_shader, f_shader, shaderprogram;
var vertices, v_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 GEOMETRY
//
vertices = new Float32Array( [
-0.5, 0.5, 0.0, // V0
-0.5, -0.5, 0.0, // V1
0.5, 0.5, 0.0, // V2
0.5, 0.5, 0.0, // V3
-0.5, -0.5, 0.0, // V4
0.5, -0.5, 0.0 // V5
] );
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
//************************************************************//
//
// CONNECT SHADER WITH GEOMETRY
//
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer );
// find the attribute in the shader source
var a_position = gl.getAttribLocation( shaderprogram, 'position' );
gl.vertexAttribPointer( a_position, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray ( a_position );
//************************************************************//
//
// DRAW!
//
gl.clearColor( 0., 0., 0., 0.)
gl.clear( gl.COLOR_BUFFER_BIT );
gl.drawArrays( gl.TRIANGLES, 0, 6 );
};
</script>
<body>
<canvas id="c"></canvas>
</body>
</html>
<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 position;
void main(void) {
gl_Position = vec4( position, 1.);
}
</script>
<script id="fragmentshader" type="glsl">
precision mediump float;
void main(void) {
gl_FragColor = vec4(1., 1., 1., 1.);
}
</script>
<script>
var c, gl;
var v_shader, f_shader, shaderprogram;
var vertices, v_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 GEOMETRY
//
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
] );
// now use indices
var indices = new Uint8Array( [ 0, 1, 2, // Triangle 1
2, 1, 3 ] ); // Triangle 2
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
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
//************************************************************//
//
// CONNECT SHADER WITH GEOMETRY
//
gl.bindBuffer( gl.ARRAY_BUFFER, v_buffer );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, i_buffer );
// find the attribute in the shader source
var a_position = gl.getAttribLocation( shaderprogram, 'position' );
gl.vertexAttribPointer( a_position, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray ( a_position );
//************************************************************//
//
// DRAW!
//
gl.clearColor( 0., 0., 0., 0.)
gl.clear( gl.COLOR_BUFFER_BIT );
// gl.drawArrays( gl.TRIANGLES, 0, 6 );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
};
</script>
<body>
<canvas id="c"></canvas>
</body>
</html>
Indexed Geometry
Uniforms
createRectangle()
Rendering Loop
And, they move!
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
setup Canvas
setup GL Context
compile vertex shader
compile fragment shader
attach and link shaders
create vertices
create and bind buffer
put data in
unbind buffer
bind buffer
find vertex attribute in shader source
configure vertex attribute
enable vertex attribute array
clear viewport
clear color buffer
draw vertex arrays
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
1 Frame
multiple Frames
animate()
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
1 Frame
multiple Frames
animate()
1 Rectangle
multiple Rectangles
createRectangle()
createRectangle()
1. Initialize WebGL
2. Shaders
3. Create Geometry
4. Connect Shader with Geometry
5. Draw!
1 Frame
multiple Frames
animate()
1 Rectangle
multiple Rectangles
createRectangle()
createRectangle()
change Offsets!
Fragment Shader
Vertex Shader
attribute vec3 position;
different data for each vertex
uniform vec3 offset;
different data for each gl.drawArray or gl.drawElements call
uniform vec4 color;
Shaderprogram
createRectangle()
return [ v_buffer, i_buffer, color, offset ];
a =
var current_v_buffer = a[0];
var current_i_buffer = a[1];
var current_color = a[2];
var current_offset = a[3];
createRectangle()
return [ v_buffer, i_buffer, color, offset ];
a =
objects = [];
objects.push( a );
objects.push( b );
createRectangle()
b =
return [ v_buffer, i_buffer, color, offset ];
[ a, b ]
[ a, b ]
[ [ v_buffer, i_buffer, color, offset ], [ v_buffer, i_buffer, color, offset ] ]
objects =
objects =
function animate() {
//
// all kinds of stuff
//
requestAnimationFrame( animate );
}
[ a, b ]
[ [ v_buffer, i_buffer, color, offset ], [ v_buffer, i_buffer, color, offset ] ]
objects =
objects =
function animate() {
for(var o = 0; o < objects.length; o++) {
var current_object = objects[o];
}
requestAnimationFrame( animate );
}
[ [ v_buffer, i_buffer, color, offset ], [ v_buffer, i_buffer, color, offset ] ]
objects =
function animate() {
for(var o = 0; o < objects.length; o++) {
var current_object = objects[o];
var current_v_buffer = current_object[0];
var current_i_buffer = current_object[1];
var current_color = current_object[2];
var current_offset = current_object[3];
// pass data to shader
gl.drawElements( gl.TRIANGLES ... )
}
requestAnimationFrame( animate );
}
Transformation
Transformations
Translate
Rotate
Scale
<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>
5-minute Bonus Opportunity!
createFish ( color, offset )
5-minute Bonus Opportunity!
createFish ( color, offset )
0,0
-.1, 0
.2, 0
0, .1
0, -.1
?, ?
?, ?
submit your music
Quiz 5 due tonight!