// Define geometry
var vertexPositionData = [
0.0, 0.0, 0.0, // vertex 0 position
1.0, 0.0, 0.0, // vertex 1 position
// ...
];
var vertexTexCoordData = [
0.0, 0.0, // vertex 0 tex coord
1.0, 0.0, // vertex 1 tex coord
// ...
];
var indexData = [
0, 1, 2, // indices of triangle 0
0, 3, 2, // indices of triangle 1
// ...
];
// Send data to the GPU
var vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
var vertexTexCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexTexCoordData), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
// Draw the geometry
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
var positionLocation = gl.getAttribLocation(program, "position");
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 4 * 3, 0); // 12 bytes per vertex, no offset
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
var texCoordLocation = gl.getAttribLocation(program, "texCoord");
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 4 * 2, 0); // 8 bytes per vertex, no offset
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.drawElements(gl.TRIANGLES, indexData.length, gl.UNSIGNED_SHORT, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
// Define geometry
var vertexData = [
0.0, 0.0, 0.0, // vertex 0 position
0.0, 0.0, // vertex 0 tex coord
1.0, 0.0, 0.0, // vertex 1 position
1.0, 0.0, // vertex 1 tex coord
// ...
];
var indexData = [
0, 1, 2, // indices of triangle 0
0, 3, 2, // indices of triangle 1
// ...
];
// Send data to the GPU
var vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
// Draw the geometry
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
var positionLocation = gl.getAttribLocation(program, "position");
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 4 * 5, 0); // 20 bytes per vertex, no offset
var texCoordLocation = gl.getAttribLocation(program, "texCoord");
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 4 * 5, 4 * 3); // 20 bytes per vertex, offset of 12 bytes
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.drawElements(gl.TRIANGLES, indexData.length, gl.UNSIGNED_SHORT, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
attribute mat3 basis;, but you still send the data in columns:
var basisLocation = gl.getAttributeLocation(program, "basis");
gl.enableVertexAttribArray(basisLocation);
gl.vertexAttribPointer(basisLocation, 3, gl.FLOAT, false, 4 * 3 * 3, 0);
gl.enableVertexAttribArray(basisLocation+1);
gl.vertexAttribPointer(basisLocation+1, 3, gl.FLOAT, false, 4 * 3 * 3, 4 * 3);
gl.enableVertexAttribArray(basisLocation+2);
gl.vertexAttribPointer(basisLocation+2, 3, gl.FLOAT, false, 4 * 3 * 3, 4 * 3 * 2);
gl.vertexAttrib[1234]f[v]()
(documentation here) and omitting the gl.enableVertexAttribArray() call (or calling gl.disableVertexAttribArray() if it has already been enabled). However, unless you plan on enabling the vertex attribute array at some point in your program, it would be better to use a uniform variable instead.glMatrixglMatrix is a JavaScript library for vectors and matrices. It is available here.gl.uniform[234]fv() expects a JavaScript typed array (Float32Array) as an argument. If we give it a JavaScript array of numbers, these will be converted to floats before being sent to the GPU.glMatrix objects store data as floats internally, and can be passed directly to gl.uniform[234]fv() calls without any casting.| Operation | GLSL | glMatrix |
|---|---|---|
| Declaration | vec3 a; | var a = vec3.create(); |
| Creating From Values | vec3 a = vec3(1.0, 2.0, 3.0); | var a = vec3.fromValues(1.0, 2.0, 3.0); |
| Cloning | vec3 a = b; | var a = vec3.clone(b); |
| Copying | a = b; | vec3.copy(a, b); |
| Addition | a = b + c; | vec3.add(a, b, c); |
| Scaled Addition | a = b + s * c; | vec3.scaleAndAdd(a, b, c, s); |
| Scaling | a = s * b; | vec3.scale(a, b, s); |
| Component-wise Multiplication | a = b * c; | vec3.multiply(a, b, c); // or vec3.mul() |
| Dot Product | float s = dot(a, b); | var s = vec3.dot(a, b); |
| Cross Product | a = cross(b, c); | vec3.cross(a, b, c); |
| Normalization | a = normalize(b); | vec3.normalize(a, b); |
| Euclidean Length | float s = length(a); | vec3.length(a) // or vec3.len() |
| Matrix-Vector Multiplication | a = m * b; | vec3.transformMat3(a, b, m); |
| Homogeneous Matrix-Vector Multiplication | vec4 c = m * vec4(b, 1.0); a = c.xyz / c.w; | vec3.transformMat4(a, b, m); |
| Matrix-Matrix Multiplication | a = b * c; | mat4.multiply(a, b, c); // or mat4.mul() |
| Matrix Inversion | Not available in WebGL 1 | mat4.invert(a, b); |
Float32Arrays, or glMatrix objects of the correct size.glMatrix also has several utility functions for creating special kinds of matrices, such mat4.fromTranslation(), mat4.fromRotation(), mat4.fromScaling(), mat4.lookAt() (for camera matrices), mat4.ortho(), and mat4.perspective().uniform mat4 viewProj;gl.uniform() variants.gl.uniformMartrix[234]fv(location, transpose, value)location is the uniform location returned by gl.getUniformLocation().transpose is a boolean; true if the matrix should be transposed as it is sent to the GPU. For WebGL, this should be false.value is a Float32Array or a glMatrix matrix of the appropriate size.gl.enable(gl.DEPTH_TEST);gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);gl.depthFunc(func).func is gl.LESS (meaning the fragment will overwrite the color value if its depth is less than the current value in the depth buffer).gl.GREATER, gl.EQUAL, gl.LEQUAL, gl.GEQUAL, gl.NOTEQUAL, gl.ALWAYS, and gl.NEVER. These are rarely used.