CS460 Computer Graphics - University of Massachusetts Boston

Assignment 3

coming soon!

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

The Rendering Pipeline

Rasterization

Vertices

Face

Let's resume Lecture 7

From 3D to 2D

From 2D to 3D?

Unprojecting...

0, 0

width, height

renderer.domElement.onclick = function(e) {
  
  pixel_coords = new THREE.Vector2(e.clientX, e.clientY);
  
};

400, 200

400     ,     200

Screen Space Coordinates

-1, -1

renderer.domElement.onclick = function(e) {
  
  pixel_coords = new THREE.Vector2( e.clientX, e.clientY );
  vp_coords = new THREE.Vector2( 
    ( pixel_coords.x / window.innerWidth ) * 2 - 1, // X
    - ( pixel_coords.y / window.innerHeight ) * 2 + 1 ); // Y
};

-0.2, 0.3

-0.2

Viewport Coordinates

1, 1

0, 0

0.3

zNear

zFar

Ray

2D Click can be mapped to any

point on the 3D Ray

zNear

zFar

Ray

2D Click can be mapped to any

point on the 3D Ray

But we know the exact

position on zNear!

renderer.domElement.onclick = function(e) {
  
  pixel_coords = new THREE.Vector2( e.clientX, e.clientY );
  vp_coords = new THREE.Vector2( 
    ( pixel_coords.x / window.innerWidth ) * 2 - 1, // X
    - ( pixel_coords.y / window.innerHeight ) * 2 + 1 ); // Y
  
  vp_coords_3d_near = new THREE.Vector3(vp_coords.x,
                                        vp_coords.y,
                                        0); // for zNear
  
};

Towards 3D Coordinates

This is not 3D yet!

THREE.Raycaster

zNear

zFar

Ray

Position (x,y,z)

needs 2 points to define Ray

raycaster = new THREE.Raycaster();
raycaster.setFromCamera(vp_coords_near, camera);

zNear

Ray

Position (x,y,z)

Invisible Plane

intersects = raycaster.intersectObject(           );

zNear

Ray

Position (x,y,z)

Invisible Plane

intersects = raycaster.intersectObject(           );
geometry = new THREE.PlaneBufferGeometry( 10000, 10000 );
material = new THREE.MeshBasicMaterial( {
  visible: false
});

invisible_plane = new THREE.Mesh( geometry, material );

scene.add( invisible_plane );
intersects = raycaster.intersectObject( invisible_plane );

( 0, 0, 0 )

<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 renderer, controls, scene, camera;

      window.onload = function() {

        // Three.js code goes here
        scene = new THREE.Scene();

        // setup the camera
        var fov = 75;
        var ratio = window.innerWidth / window.innerHeight;
        var zNear = 1;
        var zFar = 10000;
        camera = new THREE.PerspectiveCamera( fov, ratio, zNear, zFar );
        camera.position.set(0, 0, 100);

        // create renderer and setup the canvas
        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );



        renderer.domElement.onclick = function( e ){
          
            console.log('Yay! We clicked!');

            var pixel_coords = new THREE.Vector2( e.clientX, e.clientY );

            console.log('Pixel coords', pixel_coords);

            var vp_coords = new THREE.Vector2( 
                        ( pixel_coords.x / window.innerWidth ) * 2 - 1,  //X
                        -( pixel_coords.y / window.innerHeight ) * 2 + 1) // Y

            console.log('Viewport coords', vp_coords);

            var vp_coords_near = new THREE.Vector3( vp_coords.x, vp_coords.y, 0);

          };


        // setup lights
        var ambientLight = new THREE.AmbientLight();
        scene.add( ambientLight );

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

        // configure cube
        var geometry = new THREE.BoxGeometry( 20, 20, 20 );
        var material = new THREE.MeshStandardMaterial({ color: 0xffffff, wireframe: true });

        var cube = new THREE.Mesh( geometry, material );

        scene.add( cube );

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

        // call animation/rendering loop
        animate();
        
      };

      function animate() {

        requestAnimationFrame( animate );

        // and here..
        controls.update();
        renderer.render( scene, camera );
        
      };
    </script>
  </head>
  <body></body>
</html>
<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 renderer, controls, scene, camera;

      window.onload = function() {

        // Three.js code goes here
        scene = new THREE.Scene();

        // setup the camera
        var fov = 75;
        var ratio = window.innerWidth / window.innerHeight;
        var zNear = 1;
        var zFar = 10000;
        camera = new THREE.PerspectiveCamera( fov, ratio, zNear, zFar );
        camera.position.set(0, 0, 100);

        // create renderer and setup the canvas
        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );



        renderer.domElement.onclick = function( e ){
          
            console.log('Yay! We clicked!');

            var pixel_coords = new THREE.Vector2( e.clientX, e.clientY );

            console.log('Pixel coords', pixel_coords);

            var vp_coords = new THREE.Vector2( 
                        ( pixel_coords.x / window.innerWidth ) * 2 - 1,  //X
                        -( pixel_coords.y / window.innerHeight ) * 2 + 1) // Y

            console.log('Viewport coords', vp_coords);

            var vp_coords_near = new THREE.Vector3( vp_coords.x, vp_coords.y, 0);


            var raycaster = new THREE.Raycaster();
            raycaster.setFromCamera(vp_coords_near, camera);
            var intersects = raycaster.intersectObject(invisible_plane);

            console.log('Ray to Invisible Plane', intersects[0].point);

            // update cube position
            cube.position.set(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z);

          };


        // setup lights
        var ambientLight = new THREE.AmbientLight();
        scene.add( ambientLight );

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

        // configure cube
        var geometry = new THREE.BoxGeometry( 20, 20, 20 );
        var material = new THREE.MeshStandardMaterial({ color: 0xffffff, wireframe: true });

        var cube = new THREE.Mesh( geometry, material );

        scene.add( cube );



        //
        // The invisible plane
        //
        geometry = new THREE.PlaneGeometry( 10000, 10000 );
        material = new THREE.MeshBasicMaterial( {
          visible: false
        });

        var invisible_plane = new THREE.Mesh( geometry, material );

        scene.add( invisible_plane );
        //
        //
        //



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

        // call animation/rendering loop
        animate();
        
      };

      function animate() {

        requestAnimationFrame( animate );

        // and here..
        controls.update();
        renderer.render( scene, camera );
        
      };
    </script>
  </head>
  <body></body>
</html>

This will also be Assignment 03 starter code!

Shaders

GLSL

A rather complex example of shaders:

Vertex Shader

Fragment Shader

Vertex Shader

attribute vec4 a_position;

void main() {
  gl_Position = a_position;
}

This shader does nothing besides passing through positions.

Vertex Shader

attribute vec4 a_position;

void main() {
  gl_Position = a_position;
}

This shader does nothing besides passing through positions.

data is different for each vertex!

(x, y, z, w)

(x, y, z, 1.)

name

Vertex Shader

attribute vec4 a_position;

void main() {
  gl_Position = a_position;
}

This shader does nothing besides passing through positions.

gl_Position is the output of any vertex shader

Fragment Shader

precision mediump float;

void main() {
  gl_FragColor = vec4(1., 1., 1., 1.);
}

This shader colors every fragment (pixel) white.

Fragment Shader

precision mediump float;

void main() {
  gl_FragColor = vec4(1., 1., 1., 1.);
}

This shader colors every fragment (pixel) white.

defines the number of decimals for every value

Fragment Shader

precision mediump float;

void main() {
  gl_FragColor = vec4(1., 1., 1., 1.);
}

This shader colors every fragment (pixel) white.

every fragment shader outputs a color for

the current fragment / pixel.

Fragment Shader

Vertex Shader

gl_Position

gl_FragColor

for every vertex

for every pixel

Fragment Shader

Shader Art

Quiz 3 due today!!

submit your music!

Lecture 8

By Daniel Haehn

Lecture 8

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

  • 1,279