I'm doing a project that I have to move a camera with an object in the scene. I can move the camera correctly in the scene. However there's not the object.
I don't understand which is the error because I transform the object and then I multiply that matrix with the camera matrix and I think it's the steps I have to follow.
Hope you can help me.
const {mat4} = glMatrix;
var examplePlane = { // 4 vértices, 2 triángulos
"vertices" : [-0.5, 0.0, 0.5,
0.5, 0.0, 0.5,
0.5, 0.0,-0.5,
-0.5, 0.0,-0.5],
"indices" : [0, 1, 2, 0, 2, 3]
};
var exampleCube = { // 8 vértices, 12 triángulos
"vertices" : [-0.5,-0.5, 0.5,
0.5,-0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5,-0.5, -0.5,
0.5,-0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5],
"indices" : [ 0, 1, 2, 0, 2, 3,
1, 5, 6, 1, 6, 2,
3, 2, 6, 3, 6, 7,
5, 4, 7, 5, 7, 6,
4, 0, 3, 4, 3, 7,
4, 5, 1, 4, 1, 0]
};
var exampleCover = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 0],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCone = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 1],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCylinder = { // 24 vértices, 24 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
1, 0, 1, 0.866, 0.5, 1, 0.5, 0.866, 1,
0, 1, 1, -0.5, 0.866, 1, -0.86, 0.5, 1,
-1, 0, 1, -0.866, -0.5, 1, -0.5, -0.866, 1,
0, -1, 1, 0.5, -0.866, 1, 0.866, -0.5, 1],
"indices" : [ 0, 1, 12, 1, 2, 13, 2, 3, 14, 3, 4, 15, 4, 5, 16, 5, 6, 17,
6, 7, 18, 7, 8, 19, 8, 9, 20, 9, 10, 21, 10, 11, 22, 11, 0, 23,
1, 13, 12, 2, 14, 13, 3, 15, 14, 4, 16, 15, 5, 17, 16, 6, 18, 17,
7, 19, 18, 8, 20, 19, 9, 21, 20, 10, 22, 21, 11, 23, 22, 0, 12, 23]
};
var exampleSphere = { // 42 vértices, 80 triángulos
"vertices" : [ 0.000000, 0.850651, 0.525731,
-0.309017, 0.500000, 0.809017,
0.309017, 0.500000, 0.809017,
-0.525731, 0.000000, 0.850651,
0.000000, 0.000000, 1.000000,
0.525731, 0.000000, 0.850651,
-0.850651, 0.525731, 0.000000,
-0.809017, 0.309017, 0.500000,
-0.500000, 0.809017, 0.309017,
0.000000, 0.850651,-0.525731,
-0.500000, 0.809017,-0.309017,
0.000000, 1.000000, 0.000000,
0.500000, 0.809017,-0.309017,
0.500000, 0.809017, 0.309017,
0.850651, 0.525731, 0.000000,
0.809017, 0.309017, 0.500000,
0.850651,-0.525731, 0.000000,
1.000000, 0.000000, 0.000000,
0.809017,-0.309017, 0.500000,
0.525731, 0.000000,-0.850651,
0.809017, 0.309017,-0.500000,
0.809017,-0.309017,-0.500000,
0.309017, 0.500000,-0.809017,
-0.525731, 0.000000,-0.850651,
-0.309017, 0.500000,-0.809017,
0.000000, 0.000000,-1.000000,
0.000000,-0.850651,-0.525731,
-0.309017,-0.500000,-0.809017,
0.309017,-0.500000,-0.809017,
0.500000,-0.809017,-0.309017,
0.000000,-0.850651, 0.525731,
0.000000,-1.000000, 0.000000,
0.500000,-0.809017, 0.309017,
-0.850651,-0.525731, 0.000000,
-0.500000,-0.809017,-0.309017,
-0.500000,-0.809017, 0.309017,
-0.809017,-0.309017, 0.500000,
-0.309017,-0.500000, 0.809017,
0.309017,-0.500000, 0.809017,
-1.000000, 0.000000, 0.000000,
-0.809017,-0.309017,-0.500000,
-0.809017, 0.309017,-0.500000],
"indices" : [ 1, 2, 0, 4, 1, 3, 2, 4, 5, 4, 2, 1, 7, 8, 6, 1, 7, 3, 8, 1, 0, 1, 8, 7,10,11, 9, 8,10, 6,
11, 8, 0, 8,11,10,11,12, 9,13,11, 0,12,13,14,13,12,11,13,15,14, 2,13, 0,15, 2, 5, 2,15,13,
17,18,16,15,17,14,18,15, 5,15,18,17,20,21,19,17,20,14,21,17,16,17,21,20,22,20,19,12,22, 9,
20,12,14,12,20,22,24,25,23,22,24, 9,25,22,19,22,25,24,27,28,26,25,27,23,28,25,19,25,28,27,
29,21,16,28,29,26,21,28,19,28,21,29,31,32,30,29,31,26,32,29,16,29,32,31,34,35,33,31,34,26,
35,31,30,31,35,34,36,37, 3,35,36,33,37,35,30,35,37,36, 4,38, 5,37, 4, 3,38,37,30,37,38, 4,
38,18, 5,32,38,30,18,32,16,32,18,38, 7,36, 3,39, 7, 6,36,39,33,39,36, 7,39,40,33,41,39, 6,
40,41,23,41,40,39,41,24,23,10,41, 6,24,10, 9,10,24,41,27,40,23,34,27,26,40,34,33,34,40,27]
};
function makeTorus (innerRadius, outerRadius, nSides, nRings) {
var torus = {
"vertices" : [],
"indices" : []
};
if (nSides < 3 ) nSides = 3;
if (nRings < 3 ) nRings = 3;
var dpsi = 2.0 * Math.PI / nRings ;
var dphi = -2.0 * Math.PI / nSides ;
var psi = 0.0;
for (var j = 0; j < nRings; j++) {
var cpsi = Math.cos ( psi ) ;
var spsi = Math.sin ( psi ) ;
var phi = 0.0;
for (var i = 0; i < nSides; i++) {
var offset = 3 * ( j * (nSides+1) + i ) ;
var cphi = Math.cos ( phi ) ;
var sphi = Math.sin ( phi ) ;
torus.vertices[offset + 0] = cpsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 1] = spsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 2] = sphi * innerRadius ;
phi += dphi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3; i++)
torus.vertices[offset + i] = torus.vertices[offset-nSides*3+i];
psi += dpsi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3*(nSides+1); i++)
torus.vertices[offset+i] = torus.vertices[i];
for (var j = 0; j < nRings; j++){
var desp = j * (nSides + 1);
for (var i = 0; i < nSides; i++){
torus.indices.push(desp + i, desp + i + 1, desp + i + (nSides+1));
torus.indices.push(desp + i + 1, desp + i + (nSides+1) + 1, desp + i + (nSides+1));
}
}
return torus;
}
var gl, program;
var myTorus;
var myZeta = 0.0, myPhi = Math.PI/2.0, radius = 1.4, fovy = 1.4;
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
try {
return canvas.getContext("webgl2",{antialias:true});
}
catch(e) {
}
return null;
}
function initShaders() {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, document.getElementById("myVertexShader").text);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(vertexShader));
return null;
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.getElementById("myFragmentShader").text);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(fragmentShader));
return null;
}
program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
idMyColor = gl.getUniformLocation (program, "myColor" );
program.vertexPositionAttribute = gl.getAttribLocation(program, "VertexPosition");
gl.enableVertexAttribArray(program.vertexPositionAttribute);
program.modelViewMatrixIndex = gl.getUniformLocation(program,"modelViewMatrix");
program.projectionMatrixIndex = gl.getUniformLocation(program,"projectionMatrix");
}
function initRendering() {
gl.clearColor(0.95,0.95,0.95,1.0);
gl.lineWidth(1.5);
gl.enable(gl.DEPTH_TEST);
}
function initBuffers(model) {
model.idBufferVertices = gl.createBuffer ();
gl.bindBuffer (gl.ARRAY_BUFFER, model.idBufferVertices);
gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW);
model.idBufferIndices = gl.createBuffer ();
gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW);
}
function draw(model) {
console.log(model);
gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
for (var i = 0; i < model.indices.length; i += 3)
// Si paint es true vol dir que volem pintar per tant farem el triangle_fan
gl.drawElements (gl.TRIANGLE_FAN, 3, gl.UNSIGNED_SHORT, i*2);
}
// set projection (apliquem una projecció al dibuix)
function setProjection() {
// obtiene la matriz de transformación de la proyección perspectiva
var projectionMatrix = mat4.create();
// perspective
mat4.perspective(projectionMatrix, Math.PI/4.0, 1., 0.1, 100.0);
// envía la matriz de transformación de la proyección al shader de vértices
gl.uniformMatrix4fv(program.projectionMatrixIndex,false,projectionMatrix);
}
function initPrimitives() {
initBuffers(examplePlane);
initBuffers(exampleCube);
initBuffers(exampleCover);
initBuffers(exampleCone);
initBuffers(exampleCylinder);
initBuffers(exampleSphere);
myTorus = makeTorus(0.4, 1.0, 8, 12);
initBuffers(myTorus);
}
function getCameraMatrix() {
// coordenadas esféricas a rectangulares: https://en.wikipedia.org/wiki/Spherical_coordinate_system
var x = radius * Math.sin(myPhi) * Math.sin(myZeta);
var y = radius * Math.cos(myPhi);
var z = radius * Math.sin(myPhi) * Math.cos(myZeta);
return mat4.lookAt(mat4.create(), [x, y, z], [0, 0, 0], [0, 1, 0]);
}
////////////////////
// move the Eye
////////////////////
var eye = [0, 0, 1.4];
var center = [0, 0, 0];
function moveEye () {
return mat4.lookAt(mat4.create(), eye, center, [0, 1, 0]);
}
///////////////////
///////////////////
function start_draw(model, rx, ry, rz, r1x, r1y, r1z, sx, sy, sz, tx, ty, tz, c1, c2, c3, c4){
// 1. calcula la matriz de transformación
var modelMatrix = mat4.create();
var rotationmatr = mat4.create();
var rotation2 = mat4.create();
var transmatr = mat4.create();
var scalematr = mat4.create();
mat4.fromRotation (rotationmatr, Math.PI/2, [rx, ry, rz]);
mat4.fromRotation (rotation2, Math.PI/2, [r1x, r1y, r1z]);
mat4.fromScaling (scalematr, [sx, sy, sz]);
mat4.multiply (modelMatrix, rotationmatr, rotation2);
mat4.fromTranslation(transmatr,[tx, ty, tz]);
mat4.multiply(modelMatrix, transmatr, modelMatrix);
mat4.multiply(modelMatrix, modelMatrix, scalematr);
var modelMatrixM = mat4.create();
var modelViewMatrixM = mat4.create();
mat4.fromScaling(modelMatrixM, [0.5, 0.5, 0.5]);
mat4.multiply(modelViewMatrixM, moveEye(), modelMatrixM);
mat4.multiply(modelViewMatrixM, getCameraMatrix(), modelViewMatrixM);
var finalProj = mat4.create();
mat4.multiply(finalProj, modelViewMatrixM, modelMatrix);
// 2. establece la matriz modelMatrix en el shader de vértices
console.log(finalProj);
gl.uniformMatrix4fv(program.modelMatrixIndex, false, finalProj);
gl.uniform4f (idMyColor, c1, c2, c3, c4);
setProjection();
draw(model);
}
function drawall(){
start_draw(exampleCylinder, .5, 0, 0, 0, 0, 0, .1, .1, .6, -.6, .1, -3, .5, 0, .5, .7);
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
drawall();
}
function initHandlers() {
var mouseDown = false;
var lastMouseX;
var lastMouseY;
var canvas = document.getElementById("myCanvas");
var htmlPhi = document.getElementById("Phi");
var htmlZeta = document.getElementById("Zeta");
var htmlRadius = document.getElementById("Radius");
var htmlFovy = document.getElementById("Fovy");
htmlPhi.innerHTML = (myPhi * 180 / Math.PI).toFixed(1);
htmlZeta.innerHTML = (myZeta * 180 / Math.PI).toFixed(1);
htmlRadius.innerHTML = radius.toFixed(1);
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
canvas.addEventListener("wheel",
function (event) {
var delta = 0.0;
if (event.deltaMode == 0)
delta = event.deltaY * 0.001;
else if (event.deltaMode == 1)
delta = event.deltaY * 0.03;
else
delta = event.deltaY;
if (event.shiftKey == 1) { // fovy
fovy *= Math.exp(-delta)
fovy = Math.max (0.1, Math.min(3.0, fovy));
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
} else {
radius *= Math.exp(-delta);
radius = Math.max(Math.min(radius, 30), 0.05);
htmlRadius.innerHTML = radius.toFixed(1);
}
event.preventDefault();
requestAnimationFrame(drawScene);
}, false);
}
function handleKeyDown(event) {
console.log(event.keyCode);
switch (event.keyCode) {
//MOVEMENT
case 87: // ’w’ key
eye[2] -= 0.01;
center[2] -=0.01;
break;
// right
case 83: // ’s’ key
eye[2] += 0.01;
center[2] +=0.01;
break;
case 65: // ’a’ key
eye[0] -= 0.01;
center[0] -=0.01;
break;
// right
case 68: // ’d’ key
eye[0] += 0.01;
center[0] +=0.01;
break;
//CAMERA MOVEMENT
case 38: // ’up arrow’ key
myPhi+=0.01;
break;
// right
case 40: // ’down arrow’ key
myPhi-=0.01;
break;
case 37: // ’up arrow’ key
myZeta+=0.01;
break;
// right
case 39: // ’down arrow’ key
myZeta-=0.01;
break;
break;
}
requestAnimationFrame(drawScene);
}
function initWebGL() {
gl = getWebGLContext();
if (!gl) {
alert("WebGL 2.0 no está disponible");
return;
}
document.onkeydown = handleKeyDown;
initShaders();
initPrimitives();
initRendering();
initHandlers();
requestAnimationFrame(drawScene);
}
initWebGL();
canvas {border: 1px solid black;}
<script id="myVertexShader"
type="x-shader/x-vertex">#version 300 es
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
in vec3 VertexPosition;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(VertexPosition, 1.0);
}
</script>
<script id="myFragmentShader"
type="x-shader/x-fragment">#version 300 es
// Shader de fragmentos
precision mediump float;
uniform vec4 myColor;
out vec4 fragmentColor;
void main() {
fragmentColor = myColor;
}
</script>
<br>
<strong>Phi: </strong><span id="Phi"></span>°
<br>
<strong>Zeta: </strong><span id="Zeta"></span>°
<br>
<strong>Fovy: </strong><span id="Fovy"></span>°
<br>
<strong>Radius: </strong><span id="Radius"></span>
<br>
<canvas id="myCanvas" width="600" height="600">
El Navegador no soporta HTML5
</canvas>
<script src="https://cdn.jsdelivr.net/npm/gl-matrix#3.3.0/gl-matrix-min.js"></script>
So the first thing I did once I got your code to run is add in webgl-lint with
<script src="https://greggman.github.io/webgl-lint/webgl-lint.js" crossorigin></script>
That immediately brought up this error in the JavaScript console
webgl-lint.js:2163 Uncaught Error: https://greggman.github.io/webgl-lint/webgl-lint.js:2942: error in uniformMatrix4fv(undefined, false, [0.05000000074505806, 0, 0, 0, 0, -4.5621650389774436e-26, 0.05000000074505806, 0, 0, -0.30000001192092896, -7.29946406236391e-25, 0, -0.30000001192092896, 0.05000000074505806, -4.300000190734863, 1]): argument 0 is undefined
at reportError (VM9 webgl-lint.js:2163)
at reportFunctionError (VM9 webgl-lint.js:2924)
at checkArgs (VM9 webgl-lint.js:2942)
at WebGL2RenderingContext.ctx. [as uniformMatrix4fv] (VM9 webgl-lint.js:3016)
at start_draw (js:417)
at drawall (js:428)
at drawScene (js:435)\
clicking the first stack trace line related to your code brought me here
// 2. establece la matriz modelMatrix en el shader de vértices
console.log(finalProj);
---> gl.uniformMatrix4fv(program.modelViewMatrix, false, finalProj);
It's not program.modelMatrixIndex it's program.modelViewMatrixIndex
and that got something on the screen
const {mat4} = glMatrix;
var examplePlane = { // 4 vértices, 2 triángulos
"vertices" : [-0.5, 0.0, 0.5,
0.5, 0.0, 0.5,
0.5, 0.0,-0.5,
-0.5, 0.0,-0.5],
"indices" : [0, 1, 2, 0, 2, 3]
};
var exampleCube = { // 8 vértices, 12 triángulos
"vertices" : [-0.5,-0.5, 0.5,
0.5,-0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5,-0.5, -0.5,
0.5,-0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5],
"indices" : [ 0, 1, 2, 0, 2, 3,
1, 5, 6, 1, 6, 2,
3, 2, 6, 3, 6, 7,
5, 4, 7, 5, 7, 6,
4, 0, 3, 4, 3, 7,
4, 5, 1, 4, 1, 0]
};
var exampleCover = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 0],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCone = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 1],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCylinder = { // 24 vértices, 24 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
1, 0, 1, 0.866, 0.5, 1, 0.5, 0.866, 1,
0, 1, 1, -0.5, 0.866, 1, -0.86, 0.5, 1,
-1, 0, 1, -0.866, -0.5, 1, -0.5, -0.866, 1,
0, -1, 1, 0.5, -0.866, 1, 0.866, -0.5, 1],
"indices" : [ 0, 1, 12, 1, 2, 13, 2, 3, 14, 3, 4, 15, 4, 5, 16, 5, 6, 17,
6, 7, 18, 7, 8, 19, 8, 9, 20, 9, 10, 21, 10, 11, 22, 11, 0, 23,
1, 13, 12, 2, 14, 13, 3, 15, 14, 4, 16, 15, 5, 17, 16, 6, 18, 17,
7, 19, 18, 8, 20, 19, 9, 21, 20, 10, 22, 21, 11, 23, 22, 0, 12, 23]
};
var exampleSphere = { // 42 vértices, 80 triángulos
"vertices" : [ 0.000000, 0.850651, 0.525731,
-0.309017, 0.500000, 0.809017,
0.309017, 0.500000, 0.809017,
-0.525731, 0.000000, 0.850651,
0.000000, 0.000000, 1.000000,
0.525731, 0.000000, 0.850651,
-0.850651, 0.525731, 0.000000,
-0.809017, 0.309017, 0.500000,
-0.500000, 0.809017, 0.309017,
0.000000, 0.850651,-0.525731,
-0.500000, 0.809017,-0.309017,
0.000000, 1.000000, 0.000000,
0.500000, 0.809017,-0.309017,
0.500000, 0.809017, 0.309017,
0.850651, 0.525731, 0.000000,
0.809017, 0.309017, 0.500000,
0.850651,-0.525731, 0.000000,
1.000000, 0.000000, 0.000000,
0.809017,-0.309017, 0.500000,
0.525731, 0.000000,-0.850651,
0.809017, 0.309017,-0.500000,
0.809017,-0.309017,-0.500000,
0.309017, 0.500000,-0.809017,
-0.525731, 0.000000,-0.850651,
-0.309017, 0.500000,-0.809017,
0.000000, 0.000000,-1.000000,
0.000000,-0.850651,-0.525731,
-0.309017,-0.500000,-0.809017,
0.309017,-0.500000,-0.809017,
0.500000,-0.809017,-0.309017,
0.000000,-0.850651, 0.525731,
0.000000,-1.000000, 0.000000,
0.500000,-0.809017, 0.309017,
-0.850651,-0.525731, 0.000000,
-0.500000,-0.809017,-0.309017,
-0.500000,-0.809017, 0.309017,
-0.809017,-0.309017, 0.500000,
-0.309017,-0.500000, 0.809017,
0.309017,-0.500000, 0.809017,
-1.000000, 0.000000, 0.000000,
-0.809017,-0.309017,-0.500000,
-0.809017, 0.309017,-0.500000],
"indices" : [ 1, 2, 0, 4, 1, 3, 2, 4, 5, 4, 2, 1, 7, 8, 6, 1, 7, 3, 8, 1, 0, 1, 8, 7,10,11, 9, 8,10, 6,
11, 8, 0, 8,11,10,11,12, 9,13,11, 0,12,13,14,13,12,11,13,15,14, 2,13, 0,15, 2, 5, 2,15,13,
17,18,16,15,17,14,18,15, 5,15,18,17,20,21,19,17,20,14,21,17,16,17,21,20,22,20,19,12,22, 9,
20,12,14,12,20,22,24,25,23,22,24, 9,25,22,19,22,25,24,27,28,26,25,27,23,28,25,19,25,28,27,
29,21,16,28,29,26,21,28,19,28,21,29,31,32,30,29,31,26,32,29,16,29,32,31,34,35,33,31,34,26,
35,31,30,31,35,34,36,37, 3,35,36,33,37,35,30,35,37,36, 4,38, 5,37, 4, 3,38,37,30,37,38, 4,
38,18, 5,32,38,30,18,32,16,32,18,38, 7,36, 3,39, 7, 6,36,39,33,39,36, 7,39,40,33,41,39, 6,
40,41,23,41,40,39,41,24,23,10,41, 6,24,10, 9,10,24,41,27,40,23,34,27,26,40,34,33,34,40,27]
};
function makeTorus (innerRadius, outerRadius, nSides, nRings) {
var torus = {
"vertices" : [],
"indices" : []
};
if (nSides < 3 ) nSides = 3;
if (nRings < 3 ) nRings = 3;
var dpsi = 2.0 * Math.PI / nRings ;
var dphi = -2.0 * Math.PI / nSides ;
var psi = 0.0;
for (var j = 0; j < nRings; j++) {
var cpsi = Math.cos ( psi ) ;
var spsi = Math.sin ( psi ) ;
var phi = 0.0;
for (var i = 0; i < nSides; i++) {
var offset = 3 * ( j * (nSides+1) + i ) ;
var cphi = Math.cos ( phi ) ;
var sphi = Math.sin ( phi ) ;
torus.vertices[offset + 0] = cpsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 1] = spsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 2] = sphi * innerRadius ;
phi += dphi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3; i++)
torus.vertices[offset + i] = torus.vertices[offset-nSides*3+i];
psi += dpsi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3*(nSides+1); i++)
torus.vertices[offset+i] = torus.vertices[i];
for (var j = 0; j < nRings; j++){
var desp = j * (nSides + 1);
for (var i = 0; i < nSides; i++){
torus.indices.push(desp + i, desp + i + 1, desp + i + (nSides+1));
torus.indices.push(desp + i + 1, desp + i + (nSides+1) + 1, desp + i + (nSides+1));
}
}
return torus;
}
var gl, program;
var myTorus;
var myZeta = 0.0, myPhi = Math.PI/2.0, radius = 1.4, fovy = 1.4;
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
try {
return canvas.getContext("webgl2",{antialias:true});
}
catch(e) {
}
return null;
}
function initShaders() {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, document.getElementById("myVertexShader").text);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(vertexShader));
return null;
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.getElementById("myFragmentShader").text);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(fragmentShader));
return null;
}
program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
idMyColor = gl.getUniformLocation (program, "myColor" );
program.vertexPositionAttribute = gl.getAttribLocation(program, "VertexPosition");
gl.enableVertexAttribArray(program.vertexPositionAttribute);
program.modelViewMatrixIndex = gl.getUniformLocation(program,"modelViewMatrix");
program.projectionMatrixIndex = gl.getUniformLocation(program,"projectionMatrix");
}
function initRendering() {
gl.clearColor(0.95,0.95,0.95,1.0);
gl.lineWidth(1.5);
gl.enable(gl.DEPTH_TEST);
}
function initBuffers(model) {
model.idBufferVertices = gl.createBuffer ();
gl.bindBuffer (gl.ARRAY_BUFFER, model.idBufferVertices);
gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW);
model.idBufferIndices = gl.createBuffer ();
gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW);
}
function draw(model) {
console.log(model);
gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
for (var i = 0; i < model.indices.length; i += 3)
// Si paint es true vol dir que volem pintar per tant farem el triangle_fan
gl.drawElements (gl.TRIANGLE_FAN, 3, gl.UNSIGNED_SHORT, i*2);
}
// set projection (apliquem una projecció al dibuix)
function setProjection() {
// obtiene la matriz de transformación de la proyección perspectiva
var projectionMatrix = mat4.create();
// perspective
mat4.perspective(projectionMatrix, Math.PI/4.0, 1., 0.1, 100.0);
// envía la matriz de transformación de la proyección al shader de vértices
gl.uniformMatrix4fv(program.projectionMatrixIndex,false,projectionMatrix);
}
function initPrimitives() {
initBuffers(examplePlane);
initBuffers(exampleCube);
initBuffers(exampleCover);
initBuffers(exampleCone);
initBuffers(exampleCylinder);
initBuffers(exampleSphere);
myTorus = makeTorus(0.4, 1.0, 8, 12);
initBuffers(myTorus);
}
function getCameraMatrix() {
// coordenadas esféricas a rectangulares: https://en.wikipedia.org/wiki/Spherical_coordinate_system
var x = radius * Math.sin(myPhi) * Math.sin(myZeta);
var y = radius * Math.cos(myPhi);
var z = radius * Math.sin(myPhi) * Math.cos(myZeta);
return mat4.lookAt(mat4.create(), [x, y, z], [0, 0, 0], [0, 1, 0]);
}
////////////////////
// move the Eye
////////////////////
var eye = [0, 0, 1.4];
var center = [0, 0, 0];
function moveEye () {
return mat4.lookAt(mat4.create(), eye, center, [0, 1, 0]);
}
///////////////////
///////////////////
function start_draw(model, rx, ry, rz, r1x, r1y, r1z, sx, sy, sz, tx, ty, tz, c1, c2, c3, c4){
// 1. calcula la matriz de transformación
var modelMatrix = mat4.create();
var rotationmatr = mat4.create();
var rotation2 = mat4.create();
var transmatr = mat4.create();
var scalematr = mat4.create();
mat4.fromRotation (rotationmatr, Math.PI/2, [rx, ry, rz]);
mat4.fromRotation (rotation2, Math.PI/2, [r1x, r1y, r1z]);
mat4.fromScaling (scalematr, [sx, sy, sz]);
mat4.multiply (modelMatrix, rotationmatr, rotation2);
mat4.fromTranslation(transmatr,[tx, ty, tz]);
mat4.multiply(modelMatrix, transmatr, modelMatrix);
mat4.multiply(modelMatrix, modelMatrix, scalematr);
var modelMatrixM = mat4.create();
var modelViewMatrixM = mat4.create();
mat4.fromScaling(modelMatrixM, [0.5, 0.5, 0.5]);
mat4.multiply(modelViewMatrixM, moveEye(), modelMatrixM);
mat4.multiply(modelViewMatrixM, getCameraMatrix(), modelViewMatrixM);
var finalProj = mat4.create();
mat4.multiply(finalProj, modelViewMatrixM, modelMatrix);
// 2. establece la matriz modelMatrix en el shader de vértices
console.log(finalProj);
gl.uniformMatrix4fv(program.modelViewMatrixIndex, false, finalProj);
gl.uniform4f (idMyColor, c1, c2, c3, c4);
setProjection();
draw(model);
}
function drawall(){
start_draw(exampleCylinder, .5, 0, 0, 0, 0, 0, .1, .1, .6, -.6, .1, -3, .5, 0, .5, .7);
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
drawall();
}
function initHandlers() {
var mouseDown = false;
var lastMouseX;
var lastMouseY;
var canvas = document.getElementById("myCanvas");
var htmlPhi = document.getElementById("Phi");
var htmlZeta = document.getElementById("Zeta");
var htmlRadius = document.getElementById("Radius");
var htmlFovy = document.getElementById("Fovy");
htmlPhi.innerHTML = (myPhi * 180 / Math.PI).toFixed(1);
htmlZeta.innerHTML = (myZeta * 180 / Math.PI).toFixed(1);
htmlRadius.innerHTML = radius.toFixed(1);
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
canvas.addEventListener("wheel",
function (event) {
var delta = 0.0;
if (event.deltaMode == 0)
delta = event.deltaY * 0.001;
else if (event.deltaMode == 1)
delta = event.deltaY * 0.03;
else
delta = event.deltaY;
if (event.shiftKey == 1) { // fovy
fovy *= Math.exp(-delta)
fovy = Math.max (0.1, Math.min(3.0, fovy));
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
} else {
radius *= Math.exp(-delta);
radius = Math.max(Math.min(radius, 30), 0.05);
htmlRadius.innerHTML = radius.toFixed(1);
}
event.preventDefault();
requestAnimationFrame(drawScene);
}, false);
}
function handleKeyDown(event) {
console.log(event.keyCode);
switch (event.keyCode) {
//MOVEMENT
case 87: // ’w’ key
eye[2] -= 0.01;
center[2] -=0.01;
break;
// right
case 83: // ’s’ key
eye[2] += 0.01;
center[2] +=0.01;
break;
case 65: // ’a’ key
eye[0] -= 0.01;
center[0] -=0.01;
break;
// right
case 68: // ’d’ key
eye[0] += 0.01;
center[0] +=0.01;
break;
//CAMERA MOVEMENT
case 38: // ’up arrow’ key
myPhi+=0.01;
break;
// right
case 40: // ’down arrow’ key
myPhi-=0.01;
break;
case 37: // ’up arrow’ key
myZeta+=0.01;
break;
// right
case 39: // ’down arrow’ key
myZeta-=0.01;
break;
break;
}
requestAnimationFrame(drawScene);
}
function initWebGL() {
gl = getWebGLContext();
if (!gl) {
alert("WebGL 2.0 no está disponible");
return;
}
document.onkeydown = handleKeyDown;
initShaders();
initPrimitives();
initRendering();
initHandlers();
requestAnimationFrame(drawScene);
}
initWebGL();
canvas {border: 1px solid black;}
<script id="myVertexShader"
type="x-shader/x-vertex">#version 300 es
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
in vec3 VertexPosition;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(VertexPosition, 1.0);
}
</script>
<script id="myFragmentShader"
type="x-shader/x-fragment">#version 300 es
// Shader de fragmentos
precision mediump float;
uniform vec4 myColor;
out vec4 fragmentColor;
void main() {
fragmentColor = myColor;
}
</script>
<br>
<strong>Phi: </strong><span id="Phi"></span>°
<br>
<strong>Zeta: </strong><span id="Zeta"></span>°
<br>
<strong>Fovy: </strong><span id="Fovy"></span>°
<br>
<strong>Radius: </strong><span id="Radius"></span>
<br>
<canvas id="myCanvas" width="600" height="600">
El Navegador no soporta HTML5
</canvas>
<script src="https://cdn.jsdelivr.net/npm/gl-matrix#3.3.0/gl-matrix-min.js"></script>
PS: Please learn how to use snippets and CDNs for libraries
Also, just FYI, getContext never throws so this code
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
try {
return canvas.getContext("webgl2",{antialias:true});
}
catch(e) {
}
return null;
}
makes no sense. It should just be
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
return canvas.getContext("webgl2",{antialias:true});
}
and further, antialias: true is the default so
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
return canvas.getContext("webgl2");
}
I am learning WebGL from few weeks and I've got a problem with drawing some 3D shapes. Guess I am corectly counting vertices and indices, as well as a color for each triangle, but it does not work. Could someone tell me what am I doing wrong ?
I would like to make pyramide which will looks like :
And here is the code :
var gl = null,
canvas = null,
glProgram = null,
fragmentShader = null,
vertexShader = null;
var coordinateArray = [ ],
triangleVerticeColors = [ ],
verticesArray = [ ],
verticesIndexArray = [ ];
var vertexPositionAttribute = null,
trianglesVerticeBuffer = null,
vertexColorAttribute = null,
trianglesColorBuffer = null,
triangleVerticesIndexBuffer = null;
var P = mat4.create(),
V = mat4.create();
M = mat4.create();
function initWebGL() {
canvas = document.getElementById("my-canvas");
try {
gl = canvas.getContext("webgl") ||
canvas.getContext("experimental-webgl");
} catch (e) {
}
if (gl) {
setupWebGL();
initShaders();
setupBuffers();
getMatrixUniforms();
setMatrixUniforms();
animationLoop();
//drawScene();
} else {
alert("Error: Your browser does not appear to" + "support WebGL.");
}
}
function animationLoop() {
var R = mat4.create();
var angle = 0;
var i = 0;
var loop = function() {
angle = performance.now() / 1000 / 6 * 2 * Math.PI;
i++;
mat4.rotate(M, R, angle, [ 0, 1, 0 ]);
gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M);
gl.clearColor(0.1, 0.5, 0.1, 1.0);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
drawScene();
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
}
function setupWebGL() {
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.1, 0.5, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
console.log(P);
console.log(V);
console.log(M);
mat4.lookAt(V, [ 3, -1, -5 ], [ 0, 0, 0 ], [ 0, 1, 0 ]);
mat4.perspective(P, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 1000.0);
}
function initShaders() {
var fs_source = document.getElementById('shader-fs').innerHTML,
vs_source = document.getElementById('shader-vs').innerHTML;
vertexShader = makeShader(vs_source, gl.VERTEX_SHADER);
fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER);
glProgram = gl.createProgram();
gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
alert("Unable to initialize the shader program.");
}
gl.useProgram(glProgram);
}
function makeShader(src, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("Error compiling shader: " + gl.getShaderInfoLog(shader));
}
return shader;
}
function setupBuffers() {
// n-sides polygon
var n = 6;
var radius = 1;
var angle = (Math.PI * 2) / n;
var xCoordinate = 0;
var yCoordinate = 0;
for (var i = 0; i < n; i++) {
var a = angle * i;
var xNewCoordinate = xCoordinate + radius * Math.cos(a);
var yNewCoordinate = yCoordinate + radius * Math.sin(a);
var zNewCoordinate = 0;
coordinateArray.push(xNewCoordinate);
coordinateArray.push(yNewCoordinate);
coordinateArray.push(zNewCoordinate);
}
verticesArray = [
//Bottom Face
0.0, 0.0, 0.0,
0.0, 0.0, -1.0,
1.0, 0.0, -1.0,
0.0, 0.0, 0.0,
1.0, 0.0, -1.0,
1.0, 0.0, 0.0,
//Front Face
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.5, 1.0, -0.5,
//Right Face
1.0, 0.0, 0.0,
1.0, 0.0, -1.0,
0.5, 1.0, -0.5,
//Back Face
1.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.5, 1.0, -0.5,
//Left Face
0.0, 0.0, -1.0,
0.0, 0.0, 0.0,
0.5, 1.0, -0.5,
];
trianglesVerticeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArray), gl.STATIC_DRAW);
verticesIndexArray = [
3, 2, 1,
3, 1, 0,
3, 0, 4,
0, 1, 4,
1, 2, 4,
2, 3, 4,
];
triangleVerticesIndexBuffer = gl.createBuffer();
triangleVerticesIndexBuffer.number_vertext_points = verticesIndexArray.length;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleVerticesIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(verticesIndexArray), gl.STATIC_DRAW);
triangleVerticeColors = [
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 1.0,
1.0, 0.0, 1.0,
1.0, 0.0, 1.0,
0.5, 0.0, 0.0,
0.5, 0.0, 0.0,
0.5, 0.0, 0.0,
0.0, 5.0, 0.0,
0.0, 5.0, 0.0,
0.0, 5.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
];
trianglesColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVerticeColors), gl.STATIC_DRAW);
}
function getMatrixUniforms() {
glProgram.mvMatrixUniform = gl.getUniformLocation(glProgram, "uMVMatrix");
glProgram.pMatrixUniform = gl.getUniformLocation(glProgram, "uPMatrix");
glProgram.vMatrixUniform = gl.getUniformLocation(glProgram, "uVMatrix");
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M);
gl.uniformMatrix4fv(glProgram.pMatrixUniform, false, P);
gl.uniformMatrix4fv(glProgram.vMatrixUniform, false, V);
}
function drawScene() {
vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
vertexColorAttribute = gl.getAttribLocation(glProgram, "aVertexColor");
gl.enableVertexAttribArray(vertexColorAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.vertexAttribPointer(vertexColorAttribute, 3, gl.FLOAT, false, 0, 0);
gl.drawElements(gl.TRIANGLE_STRIP, triangleVerticesIndexBuffer.number_vertext_points, gl.UNSIGNED_SHORT, 0);
}
initWebGL();
body{ background-color: grey; }
canvas{ background-color: white; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 aVertexPosition;
attribute vec4 aVertexColor;
varying vec4 vColor;
// Model matrix
uniform mat4 uMVMatrix;
// Projection matrix
uniform mat4 uPMatrix;
// View matrix
uniform mat4 uVMatrix;
void main(void) {
vColor = aVertexColor;
gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</script>
<canvas id="my-canvas" width="400" height="300">
Your browser does not support the HTML5 canvas element.
</canvas>
With output looking like :
Second thing on which I am working atm is couting 'gl_position' in GPU
gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition;
How can I count in on CPU ?
Thanks in advance!
The vertex indices are wrong. Try
verticesIndexArray = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
];
var gl = null,
canvas = null,
glProgram = null,
fragmentShader = null,
vertexShader = null;
var coordinateArray = [ ],
triangleVerticeColors = [ ],
verticesArray = [ ],
verticesIndexArray = [ ];
var vertexPositionAttribute = null,
trianglesVerticeBuffer = null,
vertexColorAttribute = null,
trianglesColorBuffer = null,
triangleVerticesIndexBuffer = null;
var P = mat4.create(),
V = mat4.create();
M = mat4.create();
function initWebGL() {
canvas = document.getElementById("my-canvas");
try {
gl = canvas.getContext("webgl") ||
canvas.getContext("experimental-webgl");
} catch (e) {
}
if (gl) {
setupWebGL();
initShaders();
setupBuffers();
getMatrixUniforms();
setMatrixUniforms();
animationLoop();
//drawScene();
} else {
alert("Error: Your browser does not appear to" + "support WebGL.");
}
}
function animationLoop() {
var R = mat4.create();
var angle = 0;
var i = 0;
var loop = function() {
angle = performance.now() / 1000 / 6 * 2 * Math.PI;
i++;
mat4.rotate(M, R, angle, [ 0, 1, 0 ]);
gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M);
gl.clearColor(0.1, 0.5, 0.1, 1.0);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
drawScene();
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
}
function setupWebGL() {
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.1, 0.5, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.lookAt(V, [ 3, -1, -5 ], [ 0, 0, 0 ], [ 0, 1, 0 ]);
mat4.perspective(P, glMatrix.toRadian(45), canvas.width / canvas.height, 0.1, 1000.0);
}
function initShaders() {
var fs_source = document.getElementById('shader-fs').innerHTML,
vs_source = document.getElementById('shader-vs').innerHTML;
vertexShader = makeShader(vs_source, gl.VERTEX_SHADER);
fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER);
glProgram = gl.createProgram();
gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
alert("Unable to initialize the shader program.");
}
gl.useProgram(glProgram);
}
function makeShader(src, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert("Error compiling shader: " + gl.getShaderInfoLog(shader));
}
return shader;
}
function setupBuffers() {
// n-sides polygon
var n = 6;
var radius = 1;
var angle = (Math.PI * 2) / n;
var xCoordinate = 0;
var yCoordinate = 0;
for (var i = 0; i < n; i++) {
var a = angle * i;
var xNewCoordinate = xCoordinate + radius * Math.cos(a);
var yNewCoordinate = yCoordinate + radius * Math.sin(a);
var zNewCoordinate = 0;
coordinateArray.push(xNewCoordinate);
coordinateArray.push(yNewCoordinate);
coordinateArray.push(zNewCoordinate);
}
verticesArray = [
//Bottom Face
0.0, 0.0, 0.0,
0.0, 0.0, -1.0,
1.0, 0.0, -1.0,
0.0, 0.0, 0.0,
1.0, 0.0, -1.0,
1.0, 0.0, 0.0,
//Front Face
0.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.5, 1.0, -0.5,
//Right Face
1.0, 0.0, 0.0,
1.0, 0.0, -1.0,
0.5, 1.0, -0.5,
//Back Face
1.0, 0.0, -1.0,
0.0, 0.0, -1.0,
0.5, 1.0, -0.5,
//Left Face
0.0, 0.0, -1.0,
0.0, 0.0, 0.0,
0.5, 1.0, -0.5,
];
trianglesVerticeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesArray), gl.STATIC_DRAW);
verticesIndexArray = [
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
15, 16, 17,
];
triangleVerticesIndexBuffer = gl.createBuffer();
triangleVerticesIndexBuffer.number_vertext_points = verticesIndexArray.length;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, triangleVerticesIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(verticesIndexArray), gl.STATIC_DRAW);
triangleVerticeColors = [
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 1.0,
1.0, 0.0, 1.0,
1.0, 0.0, 1.0,
0.5, 0.0, 0.0,
0.5, 0.0, 0.0,
0.5, 0.0, 0.0,
0.0, 5.0, 0.0,
0.0, 5.0, 0.0,
0.0, 5.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
];
trianglesColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVerticeColors), gl.STATIC_DRAW);
}
function getMatrixUniforms() {
glProgram.mvMatrixUniform = gl.getUniformLocation(glProgram, "uMVMatrix");
glProgram.pMatrixUniform = gl.getUniformLocation(glProgram, "uPMatrix");
glProgram.vMatrixUniform = gl.getUniformLocation(glProgram, "uVMatrix");
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(glProgram.mvMatrixUniform, false, M);
gl.uniformMatrix4fv(glProgram.pMatrixUniform, false, P);
gl.uniformMatrix4fv(glProgram.vMatrixUniform, false, V);
}
function drawScene() {
vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
vertexColorAttribute = gl.getAttribLocation(glProgram, "aVertexColor");
gl.enableVertexAttribArray(vertexColorAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesColorBuffer);
gl.vertexAttribPointer(vertexColorAttribute, 3, gl.FLOAT, false, 0, 0);
gl.drawElements(gl.TRIANGLES, triangleVerticesIndexBuffer.number_vertext_points, gl.UNSIGNED_SHORT, 0);
}
initWebGL();
body{ background-color: grey; }
canvas{ background-color: white; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec4 aVertexPosition;
attribute vec4 aVertexColor;
varying vec4 vColor;
// Model matrix
uniform mat4 uMVMatrix;
// Projection matrix
uniform mat4 uPMatrix;
// View matrix
uniform mat4 uVMatrix;
void main(void) {
vColor = aVertexColor;
gl_Position = uPMatrix * uVMatrix * uMVMatrix * aVertexPosition;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
</script>
<canvas id="my-canvas" width="400" height="300">
Your browser does not support the HTML5 canvas element.
</canvas>
These indices will also work
verticesIndexArray = [
0, 1, 2,
0, 2, 5,
5, 0, 8,
0, 1, 8,
1, 2, 8,
2, 5, 8,
];
The difference being if you share vertices they will also share colors. If you want each face to be able to have unique colors then each vertex has to be unique (or you have to use complex texture based vertex indexing).
Looking at your vertice the first 6 vertices from the base
verticesArray = [
//Bottom Face
0.0, 0.0, 0.0, // 0
0.0, 0.0, -1.0, // 1
1.0, 0.0, -1.0, // 2
0.0, 0.0, 0.0, // 3
1.0, 0.0, -1.0, // 4
1.0, 0.0, 0.0, // 5
The square they make puts each vertex at these locations
1----24
| |
| |
03----5
So you can use
0, 1, 2,
3, 4, 5,
Or (for example)
0, 1, 2,
0, 2, 5,
Looking at the rest of the points
//Front Face
0.0, 0.0, 0.0, // 6
1.0, 0.0, 0.0, // 7
0.5, 1.0, -0.5, // 8
//Right Face
1.0, 0.0, 0.0, // 9
1.0, 0.0, -1.0, // 10
0.5, 1.0, -0.5, // 11
//Back Face
1.0, 0.0, -1.0, // 12
0.0, 0.0, -1.0, // 13
0.5, 1.0, -0.5, // 14
//Left Face
0.0, 0.0, -1.0, // 15
0.0, 0.0, 0.0, // 16
0.5, 1.0, -0.5, // 18
Points 8, 11, 14, 18 are all the same point above the base. All the other points are copies of the base points.
As mentioned above you need copies if you want to be able to specify different colors and or normals and or texture coordinates for each vertex's use on a specific face.
There's one more issue. The code is using gl.TRIANGLE_STRIP instead of gl.TRIANGLES
So given that you can see the difference. If you use the individual vertices you get this
If you use the shared vertices you get this