<<

10/24/2017

1 2 What is “WebGL”?

WebGL From WikiPedia: http://cs.oregonstate.edu/~mjb/webgl WebGL (Web Graphics ) is a JavaScript API for rendering interactive 3D graphics and 2D graphics within any compatible without the use of plug-ins. WebGL is integrated completely into all the web standards of the browser allowing GPU accelerated usage of physics and image processing and effects as part of the web page . WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background. WebGL programs consist of control code written in JavaScript and code that is executed on a 's (GPU). WebGL is designed and maintained by the non-profit .

[… of which OSU is a member]

Mike Bailey [email protected]

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License

Computer Graphics .pptx mjb – October 24, 2017 mjb – October 24, 2017

3 4 What are the Important Things to Know about WebGL? What are the Important Things to Know about OpenGL-ES 2.0?

1. WebGL programs are written in JavaScript. This means that the code is downloaded 1. WebGL uses OpenGL-ES 2.0 as its graphics API. and run by the browser. 2. There is no fixed-function pipeline -- you must use vertex and fragment . 2. WebGL programs are written in JavaScript. This means that the code is interpreted, not compiled. This makes the code slower than the equivalent /C++. 3. You can’t use glBegin…glEnd to draw things. You must use VBOs.

3. The JavaScript API for WebGL talks to the C-OpenGL library which in turn talks to the 4. You can’t use built-in transformation functions (e.g., glRotatef, glScalef, graphics hardware on the web browser client’s system. This gives you access to all glTranslatef, gluLookAt, glOrtho, gluPerspective). You must use your own of the speed and capability that the hardware provides. Use it! Especially use the matrices passed in as vertex shader attribute variables. vertex buffer object capability to store your displayable geometry on the graphics card, and be sure to bind your textures into GPU memory. Anything that you can put 5. Attribute variables for the vertex shader are declared as “attribute”, not “in”. on the GPU side minimizes the amount of code necessary to get it drawn. 6. Output variables from the vertex shader which are then rasterized to become input 4. WebGL uses the OpenGL-ES 2.0 as its graphics API. “ES” stands for “Embedded variables for the fragment shader are declared as “varying”, not “out” and “in”. Systems”. This is the same flavor of OpenGL that mobile devices use. 7. Fragment shaders must set the precision to be used, for example: precision highp float;

Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

5 6 Cube Example Cube Example

2 3

6 7

01

45

Cube Vertices = Cube Colors = { -1., -1., -1. }, { 0., 0., 0. }, Cube Indices = { 1., -1., -1. }, { 1., 0., 0. }, { 1, 0, 2, 3 }, { -1., 1., -1. }, { 0., 1., 0. }, { 4, 5, 7, 6 }, { 1., 1., -1. }, { 1., 1., 0. }, { 5, 1, 3, 7 }, { -1., -1., 1. }, { 0., 0., 1. }, { 0, 4, 6, 2 }, { 1., -1., 1. }, { 1., 0., 1. }, { 6, 7, 3, 2 }, { -1., 1., 1. }, { 0., 1., 1. }, { 0, 1, 5, 4 } { 1., 1., 1. } { 1., 1., 1. }

Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

1 10/24/2017

A Sample WebGL Program 7 The Vertex Shader Code in the HTML File 8

sample.

Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

The Fragment Shader Source Code in the HTML File 9 The General Format of the HTML File 10

sample.html sample.html Must set the precision in OpenGL-ES uniform sampler2D uTexture; Uniform variable varying vec3 vColor; varying vec2 vST; Fragment shader input variables varying float vZ; that were interpolated through the rasterizer Get the CSS style sheet and void get the jQuery user interface main( ) JavaScript code { if( vZ <= 0.99 ) Used to identify which face to texture { gl_FragColor = vec4( vColor, 1. ); } Decide to use the color or the else texture, based on the Z model { vec4 rgba = texture2D( uTexture, vST ); coordinate gl_FragColor = vec4( rgba.rgb, 1. ); } }

Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

The General Format of the HTML File 11 What is in Webgl-Utils.js? 12

sample.html Setup the buttons

Bring in all of the support code and the main program Oops ... your browser doesn't support the HTML5

Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

2 10/24/2017

What is in InitShaders.js? 13 What is in GlMatrix.js? 14

InitShaders.js contains the calls to gl.createShader, gl.shaderSource, GlMatrix.js came from Brandon Jones and Ed Angel. It contains gl.compileShader, gl.createProgram, gl.attachShader, and vec2, vec3, vec4, mat2, mat3, and mat4 data types along with methods to create gl.linkProgram to create the shader program from the vertex and fragment transformation matrices to pass into vertex shaders as attribute variables. shader source. Basically, it acts as a Javascript GLM. The logic is exactly the same as it is in C, but written in Javascript. Take a look through it sometime. It is very readable.

Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

The General Format of the JavaScript File 15 The General Format of the JavaScript File 16 var canvas; sample.js var gl; sample.js Compiled and linked function DrawTriangle( i, a, b, c, sta, stb, stc ) var Program; shader program { var Vertices; VertexArray[i+0] = Vertices[a]; DrawQuad( ) calls this twice to var Color; OpenGL arrays for ColorArray[i+0] = Colors[a]; draw two triangles per quad vertices, colors, and TexArray[i+0] = sta; var NumPoints; texture coordinates var VertexArray; VertexArray[i+1] = Vertices[b]; var ColorArray; ColorArray[i+1] = Colors[b]; var TexArray; Mouse and transformation TexArray[i+1] = stb; information var MouseDown = false; VertexArray[i+2] = Vertices[c]; var LastMouseX; ColorArray[i+2] = Colors[c]; var LastMouseY; TexArray[i+2] = stc; var Left, Middle, Right; var Perspective; return i+3; var SaveScale = 1.; } Matrix and texture var MvMatrix = mat4.create( ); information var PMatrix = mat4.create( ); Call this to draw a var MvLoc; function DrawQuad( i, a, b, c, d ) quadrilateral var PLoc; Texture coordinates { var TLoc; i = DrawTriangle( i, a, b, c, ST00, ST10, ST11 ); var SampleTexture; Function to call first i = DrawTriangle( i, a, c, d, ST00, ST11, ST01 ); var ModelMatrix = mat4.create( ); return i ; } var ST00, ST01, ST10, ST11;

window.onload = InitGraphics; // function to call first Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

The General Format of the JavaScript File 17 The General Format of the JavaScript File 18 // load shaders: sample.js sample.js Program = InitShaders( gl, "vertex-shader", "fragment-shader" ); gl.useProgram( Program ); function InitGraphics( ) Load, compile, and link the InitGraphics( ) sets everything up { MvLoc = gl.getUniformLocation( Program, "uModelViewMatrix" ); shaders canvas = document.getElementById( "gl-canvas" ); CheckError( “MvLoc " ); PLoc = gl.getUniformLocation( Program, "uProjectionMatrix" ); gl = WebGLUtils.setupWebGL( canvas ); CheckError( "PLoc " ); Obtain the symbol table if( ! gl ) TLoc = gl.getUniformLocation( Program, "uTexture" ); location of the uniform { CheckError( "TLoc " ); variables alert( "WebGL isn't available" ); } // setup the texture:

canvas.onmousedown = HandleMouseDown; SampleTexture = gl.createTexture( ); SampleTexture.image = new Image( ); document.onmouseup = HandleMouseUp; Setup the texture document.onmousemove = HandleMouseMove; SampleTexture.image.onload = function( ) { HandleLoadedTexture( SampleTexture ); Here’s where the // set some handy constants for later: } texture can be found – Quadrilateral texture setting this causes the ST00 = vec2.create( [ 0., 0. ] ); coordinates SampleTexture.image.src = "http://cs.oregonstate.edu/~mjb/webgl/beaver.bmp"; texture to be loaded ST01 = vec2.create( [ 0., 1. ] ); CheckError( "Texture src " ); ST10 = vec2.create( [ 1., 0. ] ); What to do when a ST11 = vec2.create( [ 1., 1. ] ); // setup ui: button is pressed // set globals: var b1 = document.getElementById( "PerspButton" ); b1.addEventListener( "click", function( ) { Perspective = true; Display( ); }, false ); Perspective = true; mat4.identity( ModelMatrix ); b2 = document.getElementById( "OrthoButton" ) Computer Graphics Computerb2.addEventListener( Graphics "click", function( ) { Perspective = false; Display( ); }, false ); mjb – October 24, 2017 mjb – October 24, 2017

3 10/24/2017

The General Format of the JavaScript File 19 The General Format of the JavaScript File 20 // initialize the data: sample.js sample.js InitData( ); Fill the arrays with data function Animate( ) // put the data in buffers: Setup the vertex buffer to map { to the vertex shader attribute requestAnimFrame( Animate ); var vertexBufferId = gl.createBuffer( ); variable “aVertex” Ask for the next display gl.bindBuffer( gl.ARRAY_BUFFER, vertexBufferId ); Display( ); gl.bufferData( gl.ARRAY_BUFFER, flatten(VertexArray), gl.STATIC_DRAW ); } and then render the var vLoc = gl.getAttribLocation( Program, "aVertex" ); scene gl.vertexAttribPointer( vLoc, 3, gl.FLOAT, false, 0, 0 ); Setup the color buffer to map gl.enableVertexAttribArray( vLoc ); function Display( ) to the vertex shader attribute { variable “aColor” Typical OpenGL start-up var colorBufferId = gl.createBuffer( ); gl.clearColor( 0.0, 0.0, 0.0, 1.0 ); gl.bindBuffer( gl.ARRAY_BUFFER, colorBufferId ); gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT ); gl.bufferData( gl.ARRAY_BUFFER, flatten(ColorArray), gl.STATIC_DRAW ); gl.viewport( 0, 0, canvas.width, canvas.height ); var cLoc = gl.getAttribLocation( Program, "aColor" ); gl.enable( gl.DEPTH_TEST ); gl.vertexAttribPointer( cLoc, 3, gl.FLOAT, false, 0, 0 ); Setup the texture coordinate gl.enableVertexAttribArray( cLoc ); buffer to map to the vertex // projection matrix: shader attribute variable var texBufferId = gl.createBuffer( ); gl.bindBuffer( gl.ARRAY_BUFFER, texBufferId ); “aTexCoord0” if( Perspective ) gl.bufferData( gl.ARRAY_BUFFER, flatten(TexArray), gl.STATIC_DRAW ); { var tcLoc = gl.getAttribLocation( Program, "aTexCoord0" ); PMatrix = mat4.perspective( 60., 1., 0.1, 100.0 ); gl.vertexAttribPointer( tcLoc, 2, gl.FLOAT, false, 0, 0 ); } Use the correct gl.enableVertexAttribArray( tcLoc ); else projection matrix { // get everything running: PMatrix = mat4.ortho( -2., 2., -2., 2., 0.1, 100. ); } Animate( ); Start the display } Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

The General Format of the JavaScript File 21 The General Format of the JavaScript File 22 // read the scaling slider: sample.js sample.js var s = $( "#slider" ).slider( "value" ); if( s != SaveScale ) Read the slider; process function HandleLoadedTexture( texture ) { the value if the scale { var newScaleMatrix = mat4.create( ); factor has changed gl.bindTexture( gl.TEXTURE_2D, texture ); mat4.identity( newScaleMatrix ); gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, true ); var s2 = s / SaveScale; gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, texture.image ); mat4.scale( newScaleMatrix, [ s2, s2, s2 ] ); gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR ); mat4.multiply( newScaleMatrix, ModelMatrix, ModelMatrix ); gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR ); SaveScale = s; gl.generateMipmap( gl.TEXTURE_2D ); } gl.bindTexture( gl.TEXTURE_2D, null ); CheckError( "Loading texture " ); // modelview and projection matrices: } What to do with the texture after it’s gl.useProgram( Program ); been loaded (usual OpenGL procedure) mat4.identity( MvMatrix ); Process and load the function HandleMouseDown( event ) mat4.translate( MvMatrix, [0, 0, -4] ); // viewing ModelView and Projection { mat4.multiply( MvMatrix, ModelMatrix ); // modeling matrices MouseDown = true; gl.uniformMatrix4fv( MvLoc, false, MvMatrix ); LastMouseX = event.clientX; gl.uniformMatrix4fv( PLoc, false, PMatrix ); LastMouseY = event.clientY; WhichButton( event ); // texture sampler: } Handle mouse events

gl.activeTexture( gl.TEXTURE6 ); Tell the shader where to function HandleMouseUp( event ) gl.bindTexture( gl.TEXTURE_2D, SampleTexture ); find the texture sampler { gl.uniform1i( TLoc, 6 ); MouseDown = false; } // do the drawing: Draw the scene in the buffers gl.drawArrays( gl.TRIANGLES, 0, NumPoints ); Computer Graphics Computer Graphics } mjb – October 24, 2017 mjb – October 24, 2017

The General Format of the JavaScript File 23 The General Format of the JavaScript File 24

sample.js sample.js function HandleMouseMove( event ) Handle mouse events { function WhichButton( event ) Determine which mouse button was hit if( ! MouseDown ) { { var b = event.button; return; } Left = ( b == 0 ); var newX = event.clientX; Middle = ( b == 1 ); var newY = event.clientY; Right = ( b == 2 ); Here’s where a mouse }; var deltaX = newX - LastMouseX; movement gets turned into a var deltaY = newY - LastMouseY; rotation matrix . . . if( Left ) { var newModelMatrix = mat4.create( ); mat4.identity( newModelMatrix ); mat4.rotate( newModelMatrix, degToRad(deltaX / 2.), [0, 1, 0] ); mat4.rotate( newModelMatrix, degToRad(deltaY / 2.), [1, 0, 0] );

mat4.multiply( newModelMatrix, ModelMatrix, ModelMatrix ); }

LastMouseX = newX; . . . and gets multiplied into LastMouseY = newY; the running ModelMatrix } Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

4 10/24/2017

Initializing the Data 25 Initializing the Data 26

sampledata.js Generate the data arrays. (I like to put this in its own file so sampledata.js function InitData( ) that I can generate this with a NumPoints = 6 * 2 * 3; // sides * triangles/side * vertices/triangle { C/C++ program if I want) // define the data: VertexArray = new Array( NumPoints ); ColorArray = new Array( NumPoints ); Vertices = new Array(8); TexArray = new Array( NumPoints ); Colors = new Array(8); var index = 0; Vertices[0] = point3.create( [ -1., -1., -1. ] ); index = DrawQuad( index, 1, 0, 2, 3 ); Vertices[1] = point3.create( [ 1., -1., -1. ] ); index = DrawQuad( index, 4, 5, 7, 6 ); Vertices[2] = point3.create( [ -1., 1., -1. ] ); index = DrawQuad( index, 5, 1, 3, 7 ); Vertices[3] = point3.create( [ 1., 1., -1. ] ); index = DrawQuad( index, 0, 4, 6, 2 ); Vertices[4] = point3.create( [ -1., -1., 1. ] ); index = DrawQuad( index, 6, 7, 3, 2 ); Vertices[5] = point3.create( [ 1., -1., 1. ] ); index = DrawQuad( index, 0, 1, 5, 4 ); Vertices[6] = point3.create( [ -1., 1., 1. ] ); } Vertices[7] = point3.create( [ 1., 1., 1. ] );

Colors[0] = color3.create( [ 0., 0., 0. ] ); Colors[1] = color3.create( [ 1., 0., 0. ] ); Colors[2] = color3.create( [ 0., 1., 0. ] ); Colors[3] = color3.create( [ 1., 1., 0. ] ); Colors[4] = color3.create( [ 0., 0., 1. ] ); Colors[5] = color3.create( [ 1., 0., 1. ] ); Colors[6] = color3.create( [ 0., 1., 1. ] ); Colors[7] = color3.create( [ 1., 1., 1. ] ); Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

The Results 27 References 28

The Khronos Group's WebGL Page: http://khronos.org/webgl

Khronos Group’s WebGL Quick Reference Card: ://www.khronos.org/files/webgl/webgl-reference-card-1_0.pdf

The face that gets textured Kouichi Matsuda and Rodger Lea, WebGL Programming Guide, Addison-Wesley, 2013. because its at Z = +1.0 Tony Parisi, WebGL: Up and Running, O’Reilly, 2013.

OSU WebGL site: http://cs.oregonstate.edu/~mjb/webgl

A set of WebGL tutorials: http://learningwebgl.com

The jQuery user interface site: http://api.jqueryui.com/

Ed Angel’s WebGL site for his book examples: http://www.cs.unm.edu/~angel/BOOK/INTERACTIVE_COMPUTER_GRAPHICS/SIXTH_EDITION/CODE/WebGL/

Computer Graphics Computer Graphics mjb – October 24, 2017 mjb – October 24, 2017

29

Computer Graphics mjb – October 24, 2017

5