Wk6 WebGL 2

42
9/28/2015 1 Shader Compiling/Linking Linking Shaders with Application Read shaders Compile shaders Create a program object Link everything together Link variables in application with variables in shaders Vertex attributes Uniform variables 2 Angel and Shreiner: Interactive Computer Graphics 7E © AddisonWesley 2015

Transcript of Wk6 WebGL 2

Page 1: Wk6 WebGL 2

9/28/2015

1

Shader Compiling/Linking

Linking Shaders with Application

• Read shaders

• Compile shaders

• Create a program object

• Link everything together

• Link variables in application with variables in shaders

– Vertex attributes

– Uniform variables

2Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 2: Wk6 WebGL 2

9/28/2015

2

Program Object

• Container for shaders 

– Can contain multiple shaders

– Other GLSL functions

var program = gl.createProgram();  

gl.attachShader( program, vertShdr );    gl.attachShader( program, fragShdr );    gl.linkProgram( program );

3Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Reading a Shader

• Shaders are added to the program object and compiled

• Usual method of passing a shader is as a null‐terminated string using the function

• gl.shaderSource( fragShdr, fragElem.text );

• If shader is in HTML file, we can get it into application by getElementById method

• If the shader is in a file, we can write a reader to convert the file to a string

4Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 3: Wk6 WebGL 2

9/28/2015

3

Adding a Vertex Shader

var vertShdr;var vertElem = document.getElementById( vertexShaderId );

vertShdr = gl.createShader( gl.VERTEX_SHADER );

gl.shaderSource( vertShdr, vertElem.text );gl.compileShader( vertShdr );

// after program object createdgl.attachShader( program, vertShdr );

5Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Shader Reader

• Following code may be a security issue with some browsers if you try to run it locally

– Cross Origin Request 

6

function getShader(gl, shaderName, type) {var shader = gl.createShader(type);shaderScript = loadFileAJAX(shaderName);if (!shaderScript) {alert("Could not find shader source:

"+shaderName);}

}

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 4: Wk6 WebGL 2

9/28/2015

4

Precision Declaration

• In GLSL for WebGL we must specify desired precision in fragment shaders– artifact inherited from OpenGL ES

– ES must run on very simple embedded devices that may not support 32‐bit floating point

– All implementations must support mediump

– No default for float in fragment shader

• Can use preprocessor directives (#ifdef) to check if highp supported and, if not, default to mediump

7Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Pass Through Fragment Shader

#ifdef GL_FRAGMENT_SHADER_PRECISION_HIGHprecision highp float;#elseprecision mediump float;#endif

varying vec4 fcolor;void main(void){

gl_FragColor = fcolor;}

8Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 5: Wk6 WebGL 2

9/28/2015

5

Execution in Browser

Event Loop

• Remember that the sample program specifies a render function which is a event listener orcallback function

– Every program should have a render callback

– For a static application we need only execute the render function once

– In a dynamic application, the render function can call itself recursively but each redrawing of the display must be triggered by an event

Page 6: Wk6 WebGL 2

9/28/2015

6

Lack of Object Orientation

• All versions of OpenGL are not object oriented so that there are multiple functions for a given logical function

• Example: sending values to shaders

– gl.uniform3f

– gl.uniform2i

– gl.uniform3dv

• Underlying storage mode is the same

WebGL function format

gl.uniform3f(x,y,z)

belongs to WebGL canvas

function name

x,y,z are variables

gl.uniform3fv(p)

p is an array

dimension

Page 7: Wk6 WebGL 2

9/28/2015

7

WebGL constants

• Most constants are defined in the canvas object 

– In desktop OpenGL, they were in #include files such as gl.h

• Examples– desktop OpenGL

• glEnable(GL_DEPTH_TEST);

– WebGL• gl.enable(gl.DEPTH_TEST)

– gl.clear(gl.COLOR_BUFFER_BIT)

WebGL and JS

Page 8: Wk6 WebGL 2

9/28/2015

8

Coding in WebGL

• Can run WebGL on any recent browser

– Chrome

– Firefox

– Safari

– IE

• Code written in JavaScript

• JS runs within browser

– Use local resources

WebGL

• Five steps

– Describe page (HTML file)

• request WebGL Canvas

• read in necessary files

– Define shaders (HTML file)

• could be done with a separate file (browser dependent)

– Compute or specify data (JS file)

– Send data to GPU (JS file)

– Render data (JS file)

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 9: Wk6 WebGL 2

9/28/2015

9

square.html

<!DOCTYPE html><html><head><script id="vertex‐shader" type="x‐shader/x‐vertex">

attribute vec4 vPosition;void main(){gl_Position = vPosition;

}</script>

<script id="fragment‐shader" type="x‐shader/x‐fragment">

precision mediump float;

void main(){gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );

}</script>

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Shaders

• We assign names to the shaders that we can use in the JS file

• These are trivial pass‐through (do nothing) shaders that which set the two required built‐in variables– gl_Position– gl_FragColor

• Note both shaders are full programs• Note vector type vec2• Must set precision in fragment shader

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 10: Wk6 WebGL 2

9/28/2015

10

square.html (cont)

<script type="text/javascript" src="../Common/webgl‐utils.js"></script><script type="text/javascript" src="../Common/initShaders.js"></script><script type="text/javascript" src="../Common/MV.js"></script><script type="text/javascript" src="square.js"></script></head>

<body><canvas id="gl‐canvas" width="512" height="512">Oops ... your browser doesn't support the HTML5 canvas element</canvas></body></html>

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Files

• ../Common/webgl-utils.js: Standard utilities for setting up WebGL context in Common directory on website

• ../Common/initShaders.js: contains JS and WebGL code for reading, compiling and linking the shaders 

• ../Common/MV.js: our matrix‐vector package

• square.js: the application file

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 11: Wk6 WebGL 2

9/28/2015

11

square.js

var gl;var points;

window.onload = function init(){var canvas = document.getElementById( "gl‐canvas" );

gl = WebGLUtils.setupWebGL( canvas );if ( !gl ) { alert( "WebGL isn't available" );

}// Four Vertices

var vertices = [vec2( ‐0.5, ‐0.5 ),vec2(  ‐0.5,  0.5 ),vec2(  0.5, 0.5 ),vec2( 0.5, ‐0.5)

];

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Notes

• onload: determines where to start execution when all code is loaded

• canvas gets WebGL context from HTML file

• vertices use vec2 type in MV.js

• JS array is not the same as a C or Java array

– object with methods

– vertices.length // 4

• Values in clip coordinates

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 12: Wk6 WebGL 2

9/28/2015

12

square.js (cont)

//  Configure WebGL

gl.viewport( 0, 0, canvas.width, canvas.height );gl.clearColor( 0.0, 0.0, 0.0, 1.0 );

//  Load shaders and initialize attribute buffers

var program = initShaders( gl, "vertex‐shader", "fragment‐shader" );gl.useProgram( program );

// Load the data into the GPU

var bufferId = gl.createBuffer();gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );

// Associate out shader variables with our data buffer

var vPosition = gl.getAttribLocation( program, "vPosition" );gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );gl.enableVertexAttribArray( vPosition );    

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Notes

• initShaders used to load, compile and link shaders to form a program object

• Load data onto GPU by creating a vertex buffer object on the GPU– Note use of flatten() to convert JS array to an array of float32’s

• Finally we must connect variable in program with variable in shader– need name, type, location in buffer

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 13: Wk6 WebGL 2

9/28/2015

13

square.js (cont)

render();};

function render() {gl.clear( gl.COLOR_BUFFER_BIT );gl.drawArrays( gl.TRIANGLE_FAN, 0, 4 );

}

0

1 2

3

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Triangles, Fans or Strips

gl.drawArrays( gl.TRIANGLES, 0, 6 ); // 0, 1, 2, 0, 2, 3 

0

1 2

3

gl.drawArrays( gl.TRIANGLE_STRIP, 0, 4 ); // 0, 1, 3, 2

gl.drawArrays( gl.TRIANGLE_FAN, 0, 4 ); // 0, 1 , 2, 3

0

1 2

3

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 14: Wk6 WebGL 2

9/28/2015

14

JavaScript Notes

• JavaScript (JS) is the language of the Web

– All browsers will execute JS code

– JavaScript is an interpreted object‐oriented language

• References

– Flanagan, JavaScript: The Definitive Guide, O’Reilly

– Crockford, JavaScript, The Good Parts, O’Reilly

–Many Web tutorials

JS Notes

• Is JS slow?– JS engines in browsers are getting much faster

– Not a key issues for graphics since once we get the data to the GPU it doesn’t matter how we got the data there

• JS is a (too) big language–We don’t need to use it all

– Choose parts we want to use

– Don’t try to make your code look like C or Java

Page 15: Wk6 WebGL 2

9/28/2015

15

JS Notes

• Very few native types:– numbers– strings– booleans

• Only one numerical type: 32 bit float– var x = 1;– var x = 1.0; // same– potential issue in loops– two operators for equality == and ===

• Dynamic typing

Scoping

• Different from other languages

• Function scope

• variables are hoisted within a function

– can use a variable before it is declared

• Note functions are first class objects in JS

Page 16: Wk6 WebGL 2

9/28/2015

16

JS Arrays

• JS arrays are objects

– inherit methods

– var a = [1, 2, 3]; 

is not the same as in C++ or Java

– a.length     // 3

– a.push(4); // length now 4

– a.pop();   // 4

– avoids use of many loops and indexing

– Problem for WebGL which expects C‐style arrays

Typed Arrays

JS has typed arrays that are like C arrays

var a = new Float32Array(3)

var b = new Uint8Array(3)

Generally, we prefer to work with standard JS arrays and convert to typed arrays only when we need to send data to the GPU with the flatten function in MV.js

Page 17: Wk6 WebGL 2

9/28/2015

17

A Minimalist Approach

• We will use only core JS and HTML– no extras or variants

• No additional packages– CSS

– JQuery

• Focus on graphics– examples may lack beauty

• You are welcome to use other variants as long as I can run them from your URL

2D Gasket in Points

Page 18: Wk6 WebGL 2

9/28/2015

18

35

A Simple Program in pseudocode

main() # Draw a sequence of points{

initialize_system();p = initial_point();

for (some number of points){

q = generate_a_point_based_on(p);display_point(q);p = q;

}cleanup();

}

36

Alternative

main() # Draw a sequence of points{

initialize_system();p = initial_point();

for (some number of points){

q = generate_a_point_based_on(p);store_point(q);p = q;

}display_all_points();cleanup();

}

Page 19: Wk6 WebGL 2

9/28/2015

19

37

Alternative #2

main() # Draw a sequence of points{

initialize_system();p = initial_point();

for (some number of points) {

q = generate_a_point_based_on(p);store_point(q);p = q;

}send_all_points_to_GPU();display_points_on_GPU();cleanup();

}

38

Chaos Game

Chaos Game is due to Michael Barnsley

Given a starting dot and a goal triangle (green)Goal is to move dot into green triangle in fewest number of moves 

http://math.bu.edu/DYSYS/applets/chaos‐game.htmlJohanna Voolich and Robert L. Devaney

Page 20: Wk6 WebGL 2

9/28/2015

20

39

Chaos Gamehttp://math.bu.edu/DYSYS/applets/chaos-game.html

40

gasket1.html

<script … src="../Common/webgl-utils.js"></script><script … src="../Common/initShaders.js"></script><script … src="../Common/Angel.js"></script><script … src="gasket1.js"></script>

<body><canvas id="gl-canvas" width="512"" height="512"Oops ... your browser doesn't support the HTML5 canvas element</canvas>

</body></html>

Page 21: Wk6 WebGL 2

9/28/2015

21

41

gasket1.js

var gl;var points;

const NumPoints = 5000;

window.onload = function init(){

canvas = document.getElementById( "gl-canvas" );

gl = WebGLUtils.setupWebGL( canvas );if ( !gl ) { alert( "WebGL isn't available" ); }

42

gasket1.js

//// Initialize our data for the Sierpinski Gasket

// Initialize corners of our gasket with 3 points.var vertices = [

vec2( -1, -1 ),vec2( 0, 1 ),vec2( 1, -1 )

];

var u = add( vertices[0], vertices[1] );var v = add( vertices[0], vertices[2] );var p = scale( 0.5, add( u, v ) );

Page 22: Wk6 WebGL 2

9/28/2015

22

43

gasket1.js

// Add randomly chosen point into array of points

points = [ p ];

for ( var i = 0; points.length < NumPoints; ++i ) {var j = Math.floor(Math.random() * 3);

p = add( points[i], vertices[j] );p = scale( 0.5, p );points.push( p );

}

44

gasket1.js

//// Configure WebGL//gl.viewport( 0, 0, canvas.width, canvas.height );gl.clearColor( 1.0, 1.0, 1.0, 1.0 );

// Load shaders and initialize attribute buffersvar program = initShaders( gl, "vertex-shader",

"fragment-shader" );gl.useProgram( program );

// Load the data into the GPUvar bufferId = gl.createBuffer();

Page 23: Wk6 WebGL 2

9/28/2015

23

45

gasket1.js

// Load the data into the GPUvar bufferId = gl.createBuffer();gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );gl.bufferData( gl.ARRAY_BUFFER, flatten(points),

gl.STATIC_DRAW );

var vPos = gl.getAttribLocation( program, "vPosition" );

gl.vertexAttribPointer( vPos, 2, gl.FLOAT, false, 0, 0 );

gl.enableVertexAttribArray( vPos );

render();}

46

gasket1.js

render();}

function render(){

gl.clear( gl.COLOR_BUFFER_BIT );gl.drawArrays( gl.POINTS, 0, points.length

);}

Page 24: Wk6 WebGL 2

9/28/2015

24

47

Picking the points

points = [ p ];

for ( var i = 0; points.length < NumPoints; ++i )

{

var j = Math.floor(Math.random() * 3);

p = add( points[i], vertices[j] );

p = scale( 0.5, p );

points.push( p );

}

48

Add some comments

points = [ p ];

// Compute and store N-1 new pointsfor ( var i = 0; points.length < NumPoints; ++i ) {

// Pick one of three corners at random var j = Math.floor(Math.random() * 3);

// Compute point halfway between vertex and prior point p = add( points[i], vertices[j] );p = scale( 0.5, p );

// Add it to the listpoints.push( p );

}

Starting point

Second point

Second Random Vertex

Page 25: Wk6 WebGL 2

9/28/2015

25

49

Why does this work?

• In my version the starting point is in the center of the middle triangle

• Each time we move halfway towards a corner, we move into a blank triangle

• We will never land in a shaded triangle 

• So why does the resulting set look the the Sierpinski Gasket?

50

Why does this work?

Imagine our random vertex is on the north, so we map all points north

At each step, our point is in the center of a blank triangle

But at every step, the new triangle is half as big, so point is closer to gasket

In the limit, point lies within epsilon of the Sierpinski gasket

If the choice of next vertex is not random, we do not get the full setA

B C

Page 26: Wk6 WebGL 2

9/28/2015

26

2D Gasket in Polygons

52

Three‐dimensional Applications

• In WebGL, two‐dimensional applications are a special case of three‐dimensional graphics

• Going to 3D– Not much changes

– Use vec3, gl.uniform3f– Have to worry about the order in which primitives are rendered or use hidden‐surface removal

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 27: Wk6 WebGL 2

9/28/2015

27

53

Sierpinski Gasket (2D)

• Start with a triangle

• Connect bisectors of sides and remove central triangle

• Repeat

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

54

Example 

• Five subdivisions

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 28: Wk6 WebGL 2

9/28/2015

28

55

The gasket as a fractal

• Consider the filled area (black) and the perimeter (the length of all the lines around the filled triangles)

• As we continue subdividing– the area goes to zero

– but the perimeter goes to infinity

• This is not an ordinary geometric object– It is neither two‐ nor three‐dimensional

• It is a fractal (fractional dimension) object

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Gasket Program

• HTML file

– Same as in other examples

– Pass through vertex shader

– Fragment shader sets color

– Read in JS file

56Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 29: Wk6 WebGL 2

9/28/2015

29

57

Gasket Program

var points = [];var NumTimesToSubdivide = 5;

/* initial triangle */

var vertices = [vec2( -1, -1 ),vec2( 0, 1 ),vec2( 1, -1 )

];

divideTriangle( vertices[0],vertices[1],vertices[2], NumTimesToSubdivide);

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

58

Draw one triangle

/* display one triangle */

function triangle( a, b, c ){points.push( a, b, c );

}

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 30: Wk6 WebGL 2

9/28/2015

30

59

Triangle Subdivision

function divideTriangle( a, b, c, count ){// check for end of recursion

if ( count === 0 ) {triangle( a, b, c );}else {

//bisect the sidesvar ab = mix( a, b, 0.5 );var ac = mix( a, c, 0.5 );var bc = mix( b, c, 0.5 );--count;

// three new trianglesdivideTriangle( a, ab, ac, count-1 );divideTriangle( c, ac, bc, count-1 );divideTriangle( b, bc, ab, count-1 );}

}

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

60

init()

var program = initShaders( gl, "vertex-shader", "fragment-shader" );

gl.useProgram( program );var bufferId = gl.createBuffer();

gl.bindBuffer( gl.ARRAY_BUFFER, bufferId ) gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );

var vPosition = gl.getAttribLocation( program, "vPosition" );

gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );

gl.enableVertexAttribArray( vPosition );render();

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 31: Wk6 WebGL 2

9/28/2015

31

61

Render Function

function render(){gl.clear( gl.COLOR_BUFFER_BIT );gl.drawArrays( gl.TRIANGLES, 0, points.length );

}

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

3D Gasket in Tets

Page 32: Wk6 WebGL 2

9/28/2015

32

63

Moving to 3D

• We can easily make the program three‐dimensional by using three dimensional points and starting with a tetrahedron

var vertices = [

vec3(  0.0000,  0.0000, ‐1.0000 ),        vec3(  0.0000,  0.9428,  0.3333 ),        vec3( ‐0.8165, ‐0.4714,  0.3333 ),        vec3(  0.8165, ‐0.4714,  0.3333 )    

];

subdivide each face

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

64

3D Gasket

• We can subdivide each of the four faces

• Appears as if we remove a solid tetrahedron from the center leaving four smaller tetrahedra

• Code almost identical to 2D example

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 33: Wk6 WebGL 2

9/28/2015

33

65

Almost Correct

• Because the triangles are drawn in the order they are specified in the program, the front triangles are not always rendered in front of triangles behind them

get this

want this

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

66

Hidden‐Surface Removal

• We want to see only those surfaces in front of other surfaces

• OpenGL uses a hidden‐surfacemethod called the z‐buffer algorithm that saves depth information as objects are rendered so that only the front objects appear in the image

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 34: Wk6 WebGL 2

9/28/2015

34

67

Using the z‐buffer algorithm

• The algorithm uses an extra buffer, the z‐buffer, to store depth information as geometry travels down the pipeline

• Depth buffer is required to be available in WebGL

• It must be

– Enabled• gl.enable(gl.DEPTH_TEST)

– Cleared in for each render• gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

68

Surface vs Volume Subdvision

• In our example, we divided the surface of each face

• We could also divide the volume using the same midpoints

• The midpoints define four smaller tetrahedrons, one for each vertex

• Keeping only these tetrahedrons removes a volume in the middle

• See text for code

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Page 35: Wk6 WebGL 2

9/28/2015

35

69

Volume Subdivision

Angel and Shreiner: Interactive Computer Graphics 7E © Addison‐Wesley 2015 

Input Positions

• Learn to use the mouse to give locations

–Must convert from position on canvas to position in application

• Respond to window events such as reshapes triggered by the mouse

Page 36: Wk6 WebGL 2

9/28/2015

36

Window Coordinates

w

h

(0, 0)

(w ‐1, h‐1)

(xw, yw)

Window to Clip Coordinates

x 12* wx

w

y 12* w(h y )

h

(0,h) (1,1)

(w,0) (1,1)

Page 37: Wk6 WebGL 2

9/28/2015

37

Returning Position from Click Event

Canvas specified in HTML file of size canvas.widthx canvas.height

Returned window coordinates are event.clientXand event.clientY

// add a vertex to GPU for each clickcanvas.addEventListener("click", function() {gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);var t = vec2(‐1 + 2*event.clientX/canvas.width,‐1 + 2*(canvas.height‐event.clientY)/canvas.height);gl.bufferSubData(gl.ARRAY_BUFFER,sizeof[’vec2’]*index, t);index++;

});

CAD‐like Examples

www.cs.unm.edu/~angel/WebGL/7E/03

square.html: puts a colored square at location of each mouse 

click

triangle.html: first three mouse clicks define first triangle of 

triangle strip. Each succeeding mouse clicks adds a new triangle at end of strip

cad1.html: draw a rectangle for each two successive mouse clicks

cad2.html: draws arbitrary polygons

Page 38: Wk6 WebGL 2

9/28/2015

38

Window Events

• Events can be generated by actions that affect the canvas window

– moving or exposing a window

– resizing a window

– opening a window

– iconifying/deiconifying a window a window

• Note that events generated by other application that use the canvas can affect the WebGL canvas

– There are default callbacks for some of these events

Reshape Events

• Suppose we use the mouse to change the size of our canvas

• Must redraw the contents

• Options

– Display the same objects but change size

– Display more or fewer objects at the same size

• Almost always want to keep proportions

Page 39: Wk6 WebGL 2

9/28/2015

39

onresize Event

• Returns size of new canvas is available through  window.innerHeight and window. innerWidth

• Use innerHeight and innerWidth to change canvas.height and canvas.width 

• Example (next slide): maintaining a square display

Keeping Square Proportions

window.onresize = function() {var min = innerWidth;if (innerHeight < min) {min = innerHeight;}if (min < canvas.width || min < canvas.height) {gl.viewport(0, canvas.height‐min, min, min);

}};

Page 40: Wk6 WebGL 2

9/28/2015

40

Picking

• How do we identify objects on the display

• Overview three methods

– selection

– using an off‐screen buffer and color

– bounding boxes

Why is Picking Difficult?

• Given a point in the canvas how do map this point back to an object?

• Lack of uniqueness

• Forward nature of pipeline

• Take into account difficulty of getting an exact position with a pointing device

Page 41: Wk6 WebGL 2

9/28/2015

41

Selection

• Supported by fixed function OpenGL pipeline

• Each primitive is given an id by the application indicating to which object it belongs 

• As the scene is rendered, the id’s of primitives that render near the mouse are put in a hit list

• Examine the hit list after the rendering

Selection

• Implement by creating a window that corresponds to small area around mouse– We can track whether or not a primitive renders to this window

– Do not want to display this rendering

– Render off‐screen to an extra color buffer or user back buffer and don’t do a swap

• Requires a rendering which puts depths into hit record

• Possible to implement with WebGL

Page 42: Wk6 WebGL 2

9/28/2015

42

Picking with Color

• We can use gl.readPixels to get the color at any location in window

• Idea is to use color to identify object but–Multiple objects can have the same color

– A shaded object will display many colors

• Solution: assign a unique color to each object and render off‐screen– Use gl.readPixels to get color at mouse location

– Use a table to map this color to an object

Picking with Bounding Boxes

• Both previous methods require an extra rendering each time we do a pick

• Alternative is to use a table of (axis‐aligned) bounding boxes 

• Map mouse location to object through table

inside bounding boxoutside triangle

inside bounding boxinside triangle

outside bounding boxoutside triangle