Introduction to WebGL CS 418: Interactive Computer Graphics UNIVERSITY OF ILLINOIS AT URBANA-CHAMPAIGN Eric Shaffer You Need a Text Editor Brackets is a good choice…but whatever works for you is fine http://brackets.io/ Time to Write Some HTML A few notes • We will keep everything in a single HTML file for this example • …for larger programs we will separate the HTML and JavaScript Using WebGL entails writing a bunch of startup code • Complexity comes from the flexibility of the API • Will enable you to do really sophisticated stuff later on…. • Eventually we’ll use a helper library for the startup code… You can grab code from https://courses.engr.illinois.edu/cs418/Examples/HelloTriangle.html The HTML <!DOCTYPE HTML> We create an HTML page <html lang="en"> <head> Notice: <title>Hello Triangle</title> We create an HTML5 <canvas> That is 500 x 500 <meta charset="utf-8"> pixels which we will draw into. </head> We give it an id so we can refer to it in the javascript that <body onload="startup();"> we will write. <canvas id="myGLCanvas" width="500“ height="500"> onload specifies an entry point into the JavaScript we </canvas> will write…a function named startup() will be called on a </body> page load </html> Adding JavaScript <script type="text/javascript"> var gl; var canvas; JavaScript is included inside <script> var shaderProgram; tags var vertexBuffer; We have some global variables… …and our initial function calls some other functions. function startup(){ canvas=document.getElementById("myGLCanvas"); Bolded functions are the ones we will write. gl=createGLContext(canvas); clearColor is a WebGL function that sets the initial color setupShaders(); of the pixels in the raster setupBuffers(); gl.clearColor(0.0, 0.0, 0.0, 1.0); getElementByID is a Document Object Model (DOM) function that gets us a reference to the canvas created in draw(); the HTML document } </script> Getting a WebGL Context function createGLContext(canvas) { var names = ["webgl", "experimental-webgl"]; var context = null; We need to make sure the browser supports for (var i=0; i < names.length; i++) { WebGL…so we try to get a reference to a WebGL try { context using the two names under which it might context = canvas.getContext(names[i]); exist } catch(e) {} if (context) { break;} If we get a context, we set the viewport dimensions } of the context to match the size of the canvas. if (context) { context.viewportWidth = canvas.width; You can choose to use less than the full canvas. context.viewportHeight = canvas.height; } else { alert("Failed to create WebGL context!"); } return context; } Creating Vertex Shader We’ll talk more about shaders later but for now you should know: var vertexShaderSource = "attribute vec3 aVertexPosition; \n" + We need to create a vertex shader program written in GLSL "void main() { \n" + We will use a JavaScript string to hold the source " gl_Position = vec4(aVertexPosition, 1.0); \n" + code for thevertex shader. We’ll see a better way to do this later. "} \n" The shader must assign a valueto gl_Position Our shader basically just takes the position of an incoming vertex and assigns that position to gl_Position. It actually does one thing to the incoming position…do you know what that is? Creating Fragment Shader var fragmentShaderSource = Like the vertex shader program, "precision mediump float; the fragment shader code is \n"+ written in GLSL and held in a "void main() { \n"+ string. " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n"+ "} You can think of fragments as \n"; being almost pixels…they are produced by the WebGL rasterizer and have a screen space position and some other data related to them. Our shader simply assigns each fragment the same color. Again, we’ll talk more about what the shaders do later… Compiling the Shaders function setupShaders() { var vertexShaderSource = … We have a homemade helper function that compiles the shader and var fragmentShaderSource = … checks if there were compilation errors. var vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource); If there was an error, a JavaScript alert is issued and the shader object var fragmentShader = loadShader(gl.FRAGMENT_SHADER, deleted. fragmentShaderSource); … Otherwise the compiled shader is returned. } Important: function loadShader(type, shaderSource) { • You can create multiple shader programs var shader = gl.createShader(type); gl.shaderSource(shader, shaderSource); gl.compileShader(shader); • You can switch which one you use while drawing a single frame if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { • …just use the useProgram function in WebGL alert("Error compiling shader" + gl.getShaderInfoLog(shader)); gl.deleteShader(shader); Each shader program needs a vertex shader and fragment shader return null; • } return shader; } Creating the Program Object Linking the Shaders function setupShaders() { We create a program object andattach the … compiled shaders and link. At this point, we shaderProgram = gl.createProgram(); have a complete shader program that WebGL gl.attachShader(shaderProgram, vertexShader); can use. gl.attachShader(shaderProgram, fragmentShader); attributes are user-defined variables that gl.linkProgram(shaderProgram); contain data specific to a vertex. The attributes used in the vertex shader are if (!gl.getProgramParameter(shaderProgram, bound to an index (basically a number given gl.LINK_STATUS)) { alert("Failed to setup shaders"); to a slot). Our code needs to know the index } associatedwith the attributes we use in the shader so that our draw function can feed the gl.useProgram(shaderProgram); data correctly. shaderProgram.vertexPositionAttribute = vertexPositionAttribute is a user-defined gl.getAttribLocation(shaderProgram, property in which we remember the index "aVertexPosition"); value } Setting up the Vertex Buffers We next need to create a buffer that will hold function setupBuffers() { the vertex data…this is the geometric data of vertexBuffer = gl.createBuffer(); the shapes we wish to render. gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); var triangleVertices = [ We create a WebGL buffer object and bind 0.0, 0.5, 0.0, it so that WebGL knows it is the current buffer to work with. -0.5, -0.5, 0.0, 0.5, -0.5, 0.0 triangleVertices is a user-defined ]; JavaScript array containing the 3D gl.bufferData(gl.ARRAY_BUFFER, coordinates of a single triangle. new Float32Array(triangleVertices), gl.STATIC_DRAW); We call a magic function to copy the vertex vertexBuffer.itemSize = 3; positions into the current WebGL buffer. vertexBuffer.numberOfItems = 3; } Two user-defined properties are used to remember how many vertices we have and how many coordinates per vertex. Drawing the Scene function draw() { gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); The viewport method lets us tell WebGLhow to convert from clipspace in which coordinates range from -1 to 1 into gl.clear(gl.COLOR_BUFFER_BIT); pixel coordinates. gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, Here we use our two user-defined properties to set it to the vertexBuffer.itemSize, gl.FLOAT, false, 0, 0); full size of the canvas. gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); Clear initializes the color buffer to the color set with clearColor. gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems); We then tell WebGLto take values for aVertexPosition from } the buffer currently bound to gl.ARRAY_BUFFER….and then we draw. …a little more about attributes shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, • What is happening here? "aVertexPosition"); gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, What is happening here? vertexBuffer.itemSize, gl.FLOAT, false, 0, • 0); gl.enableVertexAttribArray( • And here? shaderProgram.vertexPositionAttribute); …a little more about attributes shaderProgram.vertexPositionAttribute = • Get an index for a variable from the gl.getAttribLocation(shaderProgram, "aVertexPosition"); shader program and remember it in a property tied to the shader program object gl.vertexAttribPointer( shaderProgram.vertexPositionAttribute, • Set size, type, etc, of data for the vertexBuffer.itemSize, gl.FLOAT, false, 0, 0); attribute gl.enableVertexAttribArray( • Start feeding the attribute from the shaderProgram.vertexPositionAttribute); data in the array Result… Can You? Change the triangle color? Change the background color? Change the triangle shape? Draw multiple triangles?.
Details
- 
                                File Typepdf
 - 
                                Upload Time-
 - 
                                Content LanguagesEnglish
 - 
                                Upload UserAnonymous/Not logged-in
 - 
                                File Pages16 Page
 - 
                                File Size-