1 <!DOCTYPE html> 2 <html> 3 <head> 4 <link rel="stylesheet" type="text/css" href="presentation.css" /> 5 </head> 6 7 <body> 8 <div class="content"> 9 <div class="codeExample"> 10 </div> 11 <div> 12 <div class="canvasFigure"> 13 <span class="topCoordinate">(0,1)</span> 14 <!--A blank area we can draw on with Javascript. --> 15 <canvas id="drawingSurface" width="300" height="300"></canvas> 16 <span class="lowerLeftCoordinate">(-1,-1)</span> 17 <span class="lowerRightCoordinate">(1,-1)</span> 18 </div> 19 </div> 20 <script> 21 // Fetch a WebGL context from the identified canvas. 22 function getGLContext(elementID) 23 { 24 // Lookup the canvas just like any other element on a we page. 25 var drawingSurface = document.getElementById(elementID); 26 27 // Work with a canvas by getting a 2d or 3d context 28 // Here we get a 3d context, experimental-webgl. The context 29 // presents a javascript API that is used to draw into it. 30 // The webgl context API is very similar to OpenGL for Embedded Systems, 31 // or OpenGL ES. 32 var gl = drawingSurface.getContext('webgl') 33 || drawingSurface.getContext('experimental-webgl'); 34 35 if (!gl) 36 { 37 alert("Can not get WebGL context."); 38 } 39 40 gl.enable(gl.DEPTH_TEST); 41 42 return gl; 43 } 44 45 // Create and compile a vertex or fragment shader as given by the shader type. 46 function compileShader(gl, shaderSource, shaderType) 47 { 48 var shader = gl.createShader(shaderType); 49 gl.shaderSource(shader, shaderSource); 50 gl.compileShader(shader); 51 52 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) 53 { 54 alert(gl.getShaderInfoLog(shader)); 55 shader = null; 56 } 57 58 return shader; 59 } 60 61 // Create a program from the shaders 62 function createProgram(gl, vertexShader, fragmentShader) 63 { 64 var program = gl.createProgram(); 65 // The program consists of our shaders 66 gl.attachShader(program, vertexShader); 67 gl.attachShader(program, fragmentShader); 68 69 // Create a runnable program for our graphics hardware. 70 // Allocates and assigns memory for attributes and uniforms (explained later) 71 // Shaders are checked for consistency. 72 gl.linkProgram(program); 73 74 if (!gl.getProgramParameter(program, gl.LINK_STATUS)) 75 { 76 alert("Could not initialise shaders"); 77 } 78 79 return program; 80 } 81 82 // Generate a buffer from a JS data array 83 function createBuffer(JSarray) 84 { 85 // This is a handle to what will be a buffer 86 var vertexBuffer = gl.createBuffer(); 87 // Binding an object in Open GL creates it, and makes it the target of subsequent manipulations. 88 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); 89 // loads the current buffer, the vertexBuffer found above, with the vertex data. 90 // The gl bufer is strongly types with 32 bit floating data. 91 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(JSarray), gl.STATIC_DRAW); 92 93 return vertexBuffer; 94 } 95 96 // Bind a buffer to a vertex shader attribute, 97 // Each atttribute takes size elements of the given type. 98 // There are stride bytes separating the beginning of each element. 99 // Data begins offset bytes into the array. 100 // Note that zero stride indicates also indicates values are adjacent. 101 function bindBuffer(buffer, attribute, size, type, stride, offset) 102 { 103 // Lookup a shader attribute location 104 var attributeLocation = gl.getAttribLocation(program, attribute); 105 // enable that attribute (location) to receive data from an array 106 // The vertexBuffer, defined above, is used because it is the currently bound buffer. 107 gl.enableVertexAttribArray(attributeLocation); 108 // Each element in the vector contains 3 floating point entries, they should not be normalized, 109 // there are no array entries between attribute values, and the first element is at position 110 // 0 in the array. 111 gl.vertexAttribPointer(attributeLocation, size, type, false, stride, offset); 112 } 113 114 var gl = getGLContext('drawingSurface'); 115 116 // Like any three dimensional polygon, we specify the vertices. 117 var vertices = [ 118 -1.0, -1.0, 0.0, 119 1.0, 0.0, 0.0, 1.0, 120 1.0, -1.0, 0.0, 121 0.0, 1.0, 0.0, 1.0, 122 0.0, 1.0, 0.0, 123 0.0, 0.0, 1.0, 1.0 124 ]; 125 126 // And more of almost the same, but z=0.5. 127 var moreVertices = [ 128 -1.0, -1.0, 0.5, 129 0.0, 0.0, 1.0, 1.0, 130 1.0, -1.0, 0.5, 131 0.0, 1.0, 0.0, 1.0, 132 0.0, 1.0, 0.5, 133 1.0, 0.0, 0.0, 1.0 134 ]; 135 136 // Shaders are, usually small, C like programs that are loaded onto the graphics card and control 137 // how a 3D model is rendered, that is drawn to the scren. 138 139 // A Vertex shader does per vertex computations. Here we set the predefined variable 140 // gl_Position to the position of the vertex. We will see many uses for the vertex shader later. 141 // For example, vertices can be moved in the vertex shader, producing animation or motion. 142 // When you move through a 3D game, you are seeing the effects of a vertex shader moving the 143 // polygons around. 144 var vertexShaderSource = "attribute vec3 position;" 145 + "attribute vec4 color;" 146 + "" 147 + "varying vec4 vColor;" 148 + "" 149 + "void main()" 150 + "{" 151 + " gl_Position = vec4(position, 1);" 152 + " vColor = color;" 153 + "}"; 154 155 // The fragment shader can be thought of for now as doing per pixel computations. It is the 156 // fragment shader the colors each pixel in a 3d scene. 157 var fragmentShaderSource = "precision mediump float;" 158 + "" 159 + "varying vec4 vColor;" 160 + "" 161 + "void main()" 162 + "{" 163 + " gl_FragColor = vColor;" 164 + "}"; 165 166 // Here we create and compile the vertex shader. This will compile to code for your specific 167 // graphics card. 168 var vertexShader = compileShader(gl, vertexShaderSource, gl.VERTEX_SHADER); 169 170 // And then compile the fragment shader too. 171 var fragmentShader = compileShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER); 172 173 // As you might expect, we are going to run some code, so we need a program. 174 var program = createProgram(gl, vertexShader, fragmentShader); 175 176 // Make this the currently active program 177 gl.useProgram(program); 178 179 // This is a handle to what will be a buffer 180 var vertexBuffer = createBuffer(vertices); 181 182 // Bind the buffer to the positon attribute 183 bindBuffer(vertexBuffer, 'position', 3, gl.FLOAT, 28, 0); 184 185 // And to the color attribute 186 bindBuffer(vertexBuffer, 'color', 4, gl.FLOAT, 28, 12); 187 188 // Finally run the program. Render, or draw, the data. Here we tell it to draw triangles starting 189 // with element zero of the vertexBuffer, and that there are three vertices. So there is 190 // one triangle. 191 gl.drawArrays(gl.TRIANGLES, 0, 3); 192 193 194 // Repeat the same process again, create another buffer with different vertices and draw them. 195 var anotherBuffer = createBuffer(moreVertices); 196 197 // Bind the buffer to the positon attribute 198 bindBuffer(anotherBuffer, 'position', 3, gl.FLOAT, 28, 0); 199 200 // And to the color attribute 201 bindBuffer(anotherBuffer, 'color', 4, gl.FLOAT, 28, 12); 202 203 // Finally run the program. Render, or draw, the data. Here we tell it to draw triangles starting 204 // with element zero of the buffer, and that there are three vertices. So there is 205 // one triangle. 206 gl.drawArrays(gl.TRIANGLES, 0, 3); 207 </script> 208 </div> 209 </body> 210 </html>
The full page displaying two triangles.