F   11/17      Volume Rendering

M   11/27      Atacama.bio Guest Lecture

F    12/01      WebGPU II

F   11/24      No class (Thanksgiving Recess)

W   11/29      Final Project Fast Forward (60 seconds each!)

M   11/20     Field Trip / Outside Lecture

W  11/22      glTF / WebGPU I

M   12/04     Final Project Presentations I

W   12/06     Final Project Presentations II

F   12/08     Skybox

M   12/11       Final Project Presentations III

W   12/13       Final Recap and Last Lecture!

F   12/22       Final Project Submission

How do we start?

<html>
<head>
    <title>WebGPU Hello Triangle</title>
    <style>
        html, body { width: 100%; height: 100%; padding: 0; margin: 0; }
        #c { width: 100%; height: 100%; }
    </style>
</head>
<body>
    <canvas id="c" width="600" height="600"></canvas>
    <script>
        async function initWebGPU() {

            // Ensure WebGPU is supported
            if (!navigator.gpu) {
                console.error("WebGPU is not supported. Please use a compatible browser.");
                return;
            }

            // Initialization
            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
            });

            // Shaders
            const shaderCode = `
                @vertex
                fn vs_main(

                  @builtin(vertex_index) VertexIndex : u32

                ) -> @builtin(position) vec4<f32> {

                  var pos = array<vec2<f32>, 3>(
                    vec2(0.0, 0.5),
                    vec2(-0.5, -0.5),
                    vec2(0.5, -0.5)
                  );

                  return vec4<f32>(pos[VertexIndex], 0.0, 1.0);

                }

                @fragment
                fn fs_main() -> @location(0) vec4<f32> {

                  return vec4(1.0, 0.0, 0.0, 1.0);

                }
            `;

            const shaderModule = device.createShaderModule({ code: shaderCode });

            // Pipeline Configuration
            const pipeline = device.createRenderPipeline({
                vertex: {
                    module: shaderModule,
                    entryPoint: "vs_main"
                },
                fragment: {
                    module: shaderModule,
                    entryPoint: "fs_main",
                    targets: [{
                        format: format
                    }]
                },
                primitive: {
                    topology: "triangle-list"
                },
                layout: "auto"
            });

            // Drawing
            const commandEncoder = device.createCommandEncoder();
            const textureView = context.getCurrentTexture().createView();
            const renderPassDescriptor = {
                colorAttachments: [{
                    view: textureView,
                    loadValue: { r: 0, g: 0, b: 0, a: 1 },
                    storeOp: 'store',
                    loadOp: 'clear'
                }]
            };

            const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
            passEncoder.setPipeline(pipeline);
            passEncoder.draw(3, 1, 0, 0);
            passEncoder.end();

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

        window.onload = initWebGPU;
    </script>
</body>
</html>

How do we start?

<html>
<head>
    <title>Babylon.js</title>
    <style>
        html, body { width: 100%; height: 100%; padding: 0; margin: 0; }
        #c { width: 100%; height: 100%; }
    </style>

    <script src="https://cdn.babylonjs.com/babylon.js"></script>

    <script>

        window.onload = async function() {

            var canvas = document.getElementById('c');

            var engine = new BABYLON.WebGPUEngine(canvas);
            await engine.initAsync();


            var scene = new BABYLON.Scene(engine);
            scene.clearColor = new BABYLON.Color3(0., 0., 0.);



            var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, 10), scene);
            camera.setTarget(BABYLON.Vector3.Zero());
            camera.attachControl(canvas, false);

            var light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(1, 1, 0));



            var customMesh = new BABYLON.Mesh("custom");
            customMesh.color = new BABYLON.Color3(1., 0., 0.);

            // Set the vertices for the triangle
            var positions = [
                0, 1, 0,  // vertex 0: position (x, y, z)
                1, 0, 0,  // vertex 1
                -1, 0, 0  // vertex 2
            ];

            // Set the indices for the triangle
            var indices = [0, 1, 2];

            var colors = [1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1];

            // Create a vertexData object
            var vertexData = new BABYLON.VertexData();
            vertexData.positions = positions;
            vertexData.indices = indices;
            vertexData.colors = colors;
            vertexData.applyToMesh(customMesh);



            engine.runRenderLoop(function () {
                scene.render();
            });



            // Watch for browser/canvas resize events
            window.addEventListener("resize", function () {
                engine.resize();
            });


        };
    </script>

</head>

<body>
    <canvas id="c"></canvas>
</body>
</html>

How do we start?

<html>
<head>
    <title>Taichi.js</title>
    <style>
        html, body { width: 100%; height: 100%; padding: 0; margin: 0; }
        #c { width: 100%; height: 100%; }
    </style>

    <script src="https://unpkg.com/taichi.js/dist/taichi.umd.js"></script>

    <script>



    </script>

</head>

<body>
    <canvas id="c"></canvas>
</body>
</html>
<html>
<head>
    <title>Taichi.js</title>
    <style>
        html, body { width: 100%; height: 100%; padding: 0; margin: 0; }
        #c { width: 100%; height: 100%; }
    </style>

    <script src="https://unpkg.com/taichi.js/dist/taichi.umd.js"></script>

    <script>

        window.onload = async function() {

          await ti.init();

          let htmlCanvas = document.getElementById('c');
          htmlCanvas.width = 720;
          htmlCanvas.height = 360;

          let VBO = ti.field(ti.types.vector(ti.f32, 3), 3);
          let IBO = ti.field(ti.i32, 3);

          let aspectRatio = htmlCanvas.width / htmlCanvas.height;
          let target = ti.canvasTexture(htmlCanvas);
          let depth = ti.depthTexture([htmlCanvas.width, htmlCanvas.height]);

          ti.addToKernelScope({ VBO, target, IBO, aspectRatio, depth });

          await VBO.fromArray([
            [-1, 0, 0],
            [1, 0, 0],
            [0, 1, 0]
          ]);
          await IBO.fromArray([
            0, 1, 2
          ]);

          let render = ti.kernel(() => {
            
            let center = [0., 0., 0.];
            let eye = [0, 0, 3];
            let view = ti.lookAt(eye, center, [0.0, 1.0, 0.0]);
            let proj = ti.perspective(70.0, aspectRatio, 0.1, 100);
            let mvp = proj.matmul(view);

            ti.clearColor(target, [0., 0., 0., 1]);
            ti.useDepth(depth);

            for (let v of ti.inputVertices(VBO, IBO)) {
              let pos = mvp.matmul([v.x, v.y, v.z, 1.0]);
              ti.outputPosition(pos);
              ti.outputVertex(v);
            }
            for (let f of ti.inputFragments()) {
              ti.outputColor(target, [1.,0.,0.,1.]);
            }
          });

          async function frame() {

            render();
            requestAnimationFrame(frame);
          }
          requestAnimationFrame(frame);
        };


    </script>

</head>

<body>
    <canvas id="c"></canvas>
</body>
</html>

Sky Box

Sky Sphere

// ...
var geometry = new THREE.SphereGeometry( 500, 60, 40 );
// invert the geometry on the x-axis so that all of the faces point inward
geometry.scale( - 1, 1, 1 );

var texture = new THREE.TextureLoader().load( 'photo.jpg' );
var material = new THREE.MeshBasicMaterial( { map: texture } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// ...
// ...
// ...
var geometry = new THREE.SphereGeometry( 500, 60, 40 );

var texture = new THREE.TextureLoader().load( 'photo.jpg' );
var material = new THREE.MeshBasicMaterial( { map: texture,
                                              side: THREE.BackSide } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// ...

Field Trip Footage

Let's code!

cs460student/360/

<html>
  <head>
    <style>
      html, body { 
        background-color:#000;
        margin: 0;
        padding: 0;
        height: 100%;
        overflow: hidden !important;  
      }
    </style>
    
    <script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

    <script type="importmap">
    {
      "imports": {
        "three": "https://unpkg.com/three@latest/build/three.module.js",
        "three/addons/": "https://unpkg.com/three@latest/examples/jsm/"
      }
    }
    </script>

    <script type="module">

      import * as THREE from 'three';
      import { OrbitControls } from 'three/addons/controls/OrbitControls.js';    


      var scene, camera, renderer, ambientLight, light, controls, sphere;

      window.onload = function() {

        scene = new THREE.Scene();

        camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.set( 0, 0, 500);

        renderer = new THREE.WebGLRenderer({ });
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );
        
        ambientLight = new THREE.AmbientLight(0x000000);
        scene.add( ambientLight );

        light = new THREE.DirectionalLight( 0xffffff, 5.0 );
        light.position.set( 10, 100, 10 );
        scene.add( light );





        // TODO




        controls = new OrbitControls( camera, renderer.domElement );


        animate();


      };

      function animate() {

        requestAnimationFrame( animate );

        controls.update();
        renderer.render( scene, camera );

      };


    </script>
  </head>
  <body>
  </body>
</html>

Course Evaluations

Quiz 14 coming soon!

MEGAQUIZ too..

submit your music