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!