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