Tu 11/12     Texture Mapping

Th 11/14     Medical Visualization / Volume Rendering

Tu 11/19     NeRFs + glTF

Th 11/21     Final Project Fast Forward!

Tu 11/26     Fieldtrip / Outside Lecture

Th 11/28     No Class

Tu 12/3       Skybox

Tu 12/10     Final Project Presentations

Th 12/12      Final Project Presentations II

Th 12/5      Recap Lecture

+

3D model

Assignment 5

Bonus

Assignment 5

Final Project!

counts as 40% of your grade!

#finalproject

Final Project Presentation

Final Submission

Tu 12/10

Th 12/19

Th 12/12

Lecture 1

GPU Access!

<canvas></canvas>

var c = document.createElement("canvas");

document.body.appendChild(c);

*.html

*.js

Lecture 2

Lecture 3

Lecture 4

Z-Fighting

Lecture 5

Assignment 2

X

Y

Z

XTK

How can we know this?

we can try it out!

Lecture 6

Wireframe

12 Triangles

Lecture 7

Lecture 8

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

Lecture 9

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

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

Rendering Primitives

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

Lecture 10

Uniforms

createRectangle()

Rendering Loop

And, they move!

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 =

objects = [];

objects.push( a );
objects.push( b );

createRectangle()

b =

return [ v_buffer, i_buffer, color, offset ];

[ a, b ]

Lecture 11

<html>
<head>
  <title>WebGPU!</title>
  <style>
    html, body {
      background-color: #000;
      margin: 0;
      padding: 0;
      height: 100%;
      overflow: hidden !important;
    }
    #c {
      width: 100%;
      height: 100%;
    }
  </style>
  <script id="vertexshader" type="wgsl">
    struct VertexInput {
        @location(0) position: vec3<f32>,
        @location(1) offset: vec3<f32>,
        @location(2) color: vec4<f32>, // Color for the instance
    };

    struct VertexOutput {
        @builtin(position) position: vec4<f32>,
        @location(0) color: vec4<f32>, // Pass color to fragment shader
    };

    @vertex
    fn main(input: VertexInput) -> VertexOutput {
        var output: VertexOutput;
        output.position = vec4(input.position + input.offset, 1.0); // Add offset
        output.color = input.color; // Pass color to fragment shader
        return output;
    }
  </script>
  <script id="fragmentshader" type="wgsl">
    @fragment
    fn main(@location(0) color: vec4<f32>) -> @location(0) vec4<f32> {
        return color; // Use the color passed from the vertex shader
    }
  </script>
  <script>
    window.onload = async function() {
      //************************************************************//
      //
      // INITIALIZE WEBGPU
      //
      const canvas = document.getElementById('c');
      const adapter = await navigator.gpu.requestAdapter();
      const device = await adapter.requestDevice();
      const context = canvas.getContext('webgpu');

      const format = navigator.gpu.getPreferredCanvasFormat();
      context.configure({
        device: device,
        format: format,
        alphaMode: 'opaque'
      });

      //************************************************************//
      //
      // SHADERS
      //
      const v_shader = device.createShaderModule({
        code: document.getElementById('vertexshader').innerText
      });
      const f_shader = device.createShaderModule({
        code: document.getElementById('fragmentshader').innerText
      });

      //************************************************************//
      //
      // CREATE GEOMETRY
      //
      // Define a single rectangle using triangles
      const 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
      ]);

      const v_buffer = device.createBuffer({
        size: vertices.byteLength,
        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
        mappedAtCreation: true
      });
      new Float32Array(v_buffer.getMappedRange()).set(vertices);
      v_buffer.unmap();

      //************************************************************//
      //
      // INSTANCE DATA
      //
      // Define the initial offsets for 3 rectangles
      const instanceOffsets = new Float32Array([
        -0.4,  -0.4, 0.0,  // Rectangle 1
        0.0,   0.0, 0.0,  // Rectangle 2
        0.4,   0.4, 0.0,  // Rectangle 3
      ]);

      const i_buffer = device.createBuffer({
        size: instanceOffsets.byteLength,
        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
        mappedAtCreation: true
      });
      new Float32Array(i_buffer.getMappedRange()).set(instanceOffsets);
      i_buffer.unmap();


      // Define colors for 3 rectangles
      const instanceColors = new Float32Array([
        1.0, 0.0, 0.0, 1.0, // Red for Rectangle 1
        0.0, 1.0, 0.0, 1.0, // Green for Rectangle 2
        0.0, 0.0, 1.0, 1.0, // Blue for Rectangle 3
      ]);

      const c_buffer = device.createBuffer({
        size: instanceColors.byteLength,
        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
        mappedAtCreation: true
      });
      new Float32Array(c_buffer.getMappedRange()).set(instanceColors);
      c_buffer.unmap();

      //************************************************************//
      //
      // SETUP RENDERING PIPELINE
      //
      const pipeline = device.createRenderPipeline({
        layout: 'auto',
        vertex: {
          module: v_shader,
          buffers: [
            {
              arrayStride: 3 * 4, // Vertex size
              attributes: [{
                shaderLocation: 0,
                offset: 0,
                format: 'float32x3'
              }]
            },
            {
              arrayStride: 3 * 4, // Instance size
              attributes: [{
                shaderLocation: 1,
                offset: 0,
                format: 'float32x3'
              }],
              stepMode: 'instance' // Instance data
            },
            {
              arrayStride: 4 * 4, // Color size
              attributes: [{
                shaderLocation: 2,
                offset: 0,
                format: 'float32x4'
              }],
              stepMode: 'instance' // Color data for each instance
            }
          ]
        },
        fragment: {
          module: f_shader,
          targets: [{
            format: format
          }]
        },
        primitive: {
          topology: 'triangle-list'
        }
      });

      //************************************************************//
      //
      // ANIMATION VARIABLES
      //
      let offsetSpeed = 0.005; // Speed of movement
      let offsetDirection = 1; // 1 for right, -1 for left

      //************************************************************//
      //
      // ANIMATION LOOP
      //

      console.log(instanceOffsets.length);
      function animate() {
        // Update instance offsets
        for (let i = 0; i < instanceOffsets.length / 3; i++) {
          instanceOffsets[i * 3] += offsetSpeed * offsetDirection;// Move in x direction
          // Reverse direction when reaching bounds
          if (instanceOffsets[i * 3]  > 1.0 || instanceOffsets[i * 3] < -1.0) {
            offsetDirection *= -1;
          }
        }

        // Update the instance buffer with new offsets
        device.queue.writeBuffer(i_buffer, 0, instanceOffsets);

        // Draw!
        const commandEncoder = device.createCommandEncoder();
        const textureView = context.getCurrentTexture().createView();

        const renderPassDescriptor = {
          colorAttachments: [{
            view: textureView,
            clearValue: [0, 0, 0, 0],
            loadOp: 'clear',
            storeOp: 'store'
          }]
        };

        const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
        passEncoder.setPipeline(pipeline);
        passEncoder.setVertexBuffer(0, v_buffer); // Set vertex buffer
        passEncoder.setVertexBuffer(1, i_buffer); // Set instance buffer for offsets
        passEncoder.setVertexBuffer(2, c_buffer); // Set instance buffer for colors
        passEncoder.draw(6, 3); // Draw 6 vertices (2 triangles) for 3 instances
        passEncoder.end();

        device.queue.submit([commandEncoder.finish()]);

        requestAnimationFrame(animate); // Continue the animation
      }

      animate(); // Start the animation loop
    }
  </script>
</head>
<body>
<canvas id="c"></canvas>
</body>
</html>

Lecture 12

[ [ 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

5-minute Bonus Opportunity!

createFish ( color, offset )

0,0

-.1, 0

.2, 0

0, .1

0, -.1

.3, -.05

.3, .05

0

1

2

3

4

5

Transformation!

Lecture 13

Lecture 14

Manuel Sainsily

User eXperience (UX) + Human-Computer Interaction (HCI) + eXtended Reality (XR)

impressive!

Lecture 15

theta = Math.PI / 4;

current_transform = new Float32Array([
  Math.cos(theta), -Math.sin(theta), 0, 0,
  Math.sin(theta), Math.cos(theta), 0, 0,
  0, 0, 1, 0,
  current_offset[0], current_offset[1], 0., 1.
]);

gl.uniformMatrix4fv(u_transform, false, current_transform);
<script id="vertexshader" type="glsl">
    attribute vec3 a_position;

    uniform mat4 u_transform;


    void main(void) {

      vec4 final_position = u_transform * vec4( a_position, 1. );
    
      gl_Position = final_position;
    
    }
</script>

      function animate() {

        requestAnimationFrame( animate );

        for (var t in window.ALL_TORUSES) {


          t = ALL_TORUSES[t];

          var T = Math.PI / 2; // 180 degrees

          // around the y axis
          var x = Math.sin( T / 2 ) * 0; // = 0
          var y = Math.sin( T / 2 ) * 1;
          var z = Math.sin( T / 2 ) * 0; // = 0
          var w = Math.cos( T / 2 );

          var q = new THREE.Quaternion( x, y, z, w);

          t.quaternion.slerp( q, 0.01 );

        }


        // and here..
        controls.update();
        renderer.render( scene, camera );
        
      };

Arcball

Trackball

Controls

Natural Feeling

Spins twice as fast

Completely path independent

Both:

Map 2D to 3D Sphere

esay to implement with Quaternions

Lecture 16

Rigid Body Transformation

Quaternion

Translation Vector

w

x

y

z

x

y

z

0

Scaling

x, y, z

Lecture 17

Lecture 18

Lecture 19

Lecture 20

Lecture 21

Fragment Shader

Lecture 22

Lecture 23

Photogrammetry

High-resolution + Fast!

Lecture 24

1   Muhammad Moiz Amjad and Maxim Moskalenko
2   Rami Huu Nguyen
3   Gustavo Aguiar
4   Lorenzo Orio and Jongsoo Ha
5   Sachi Joshi and Edwin Juarbe
6   Kavin Raj Raveendran and Sai Kumar Agam and Disha Roopun
7   Devin DePina and Jonathan Pimentel and Darren Francisque
8   Charles Quigley and Liam Willis
9   Jason Luu
10  Michael Claude
11  David Martinez
12  Ivan Wu and Jeffrey Nguyen
13  William Mai
14  Minh Nguyen
15  Ayden Diel
16  Mohammad Masood and Alexander Troetsch
17  Sang Hyuk Kim
18  Elley Lavelle
19  Thong Hoang
20  Brandon Siscoe
21  Guy Blochstein

Lecture 25

Too rainy this time... :(

Sky Box

Lecture 26

Course Evaluations

...for a great semester!