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!

Lecture 10

By Daniel Haehn

Lecture 10

Slides for CS460 Computer Graphics at UMass Boston. See https://cs460.org!

  • 209