Dibujar un elemento sencillo


Este objeto que vemos es un sólido platónico conocido como Octaedro, a continuación se presenta el codigo del script:

         var canvas = document.getElementById('my_Canvas');
         gl = canvas.getContext('experimental-webgl');

         var a = 3;

         var vertices = [
             0, a, 0,    0, 0, a,   a, 0, 0, //Cara 1
             0, a, 0,    a, 0, 0,   0, 0,-a, //Cara 2
             0, a, 0,    0, 0,-a,  -a, 0, 0, //Cara 3
             0, a, 0,   -a, 0, 0,   0, 0, a, //Cara 4
             0,-a, 0,    a, 0, 0,   0, 0, a, //Cara 5
             0,-a, 0,    0, 0,-a,   a, 0, 0, //Cara 6
             0,-a, 0,   -a, 0, 0,   0, 0,-a, //Cara 7
             0,-a, 0,    0, 0, a,  -a, 0, 0, //Cara 8
         ];

         var colors = [
            1,1,1, 1,1,1, 1,1,1,
            1,0,0, 1,0,0, 1,0,0,
            0,1,0, 0,1,0, 0,1,0,
            0,0,1, 0,0,1, 0,0,1,
            0,0,1, 0,0,1, 0,0,1,
            0,1,0, 0,1,0, 0,1,0,
            1,0,0, 1,0,0, 1,0,0,
            1,1,1, 1,1,1, 1,1,1
         ];

         var indices = [
            0,1,2,
            3,4,5,
            6,7,8,
            9,10,11,
            12,13,14,
            15,16,17,
            18,19,20,
            21,22,23 
         ];

         var vertex_buffer = gl.createBuffer ();
         gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
         gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

         var color_buffer = gl.createBuffer ();
         gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
         gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

         var index_buffer = gl.createBuffer ();
         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
         gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
         
         var vertCode = 'attribute vec3 position;'+
            'uniform mat4 Pmatrix;'+
            'uniform mat4 Vmatrix;'+
            'uniform mat4 Mmatrix;'+
            'attribute vec3 color;'+//the color of the point
            'varying vec3 vColor;'+
   
            'void main(void) { '+//pre-built function
               'gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);'+
               'vColor = color;'+
            '}';

         var fragCode = 'precision mediump float;'+
            'varying vec3 vColor;'+
            'void main(void) {'+
               'gl_FragColor = vec4(vColor, 1.);'+
            '}';
         
         var vertShader = gl.createShader(gl.VERTEX_SHADER);
         gl.shaderSource(vertShader, vertCode);
         gl.compileShader(vertShader);

         var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
         gl.shaderSource(fragShader, fragCode);
         gl.compileShader(fragShader);

         var shaderProgram = gl.createProgram();
         gl.attachShader(shaderProgram, vertShader);
         gl.attachShader(shaderProgram, fragShader);
         gl.linkProgram(shaderProgram);

         var Pmatrix = gl.getUniformLocation(shaderProgram, "Pmatrix");
         var Vmatrix = gl.getUniformLocation(shaderProgram, "Vmatrix");
         var Mmatrix = gl.getUniformLocation(shaderProgram, "Mmatrix");

         gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
         var position = gl.getAttribLocation(shaderProgram, "position");
         gl.vertexAttribPointer(position, 3, gl.FLOAT, false,0,0) ;
         
         gl.enableVertexAttribArray(position);
         gl.bindBuffer(gl.ARRAY_BUFFER, color_buffer);
         var color = gl.getAttribLocation(shaderProgram, "color");
         gl.vertexAttribPointer(color, 3, gl.FLOAT, false,0,0) ;
         
         gl.enableVertexAttribArray(color);
         gl.useProgram(shaderProgram);

         function get_projection(angle, a, zMin, zMax) {
            var ang = Math.tan((angle*.5)*Math.PI/180);//angle*.5
            return [
               0.5/ang, 0 , 0, 0,
               0, 0.5*a/ang, 0, 0,
               0, 0, -(zMax+zMin)/(zMax-zMin), -1,
               0, 0, (-2*zMax*zMin)/(zMax-zMin), 0 
            ];
         }
   
         var proj_matrix = get_projection(40, canvas.width/canvas.height, 1, 100);

         var mov_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];
         var view_matrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1];

         view_matrix[14] = view_matrix[14]-6;//zoom

          function rotateX(m, angle) {
             var c = Math.cos(angle);
             var s = Math.sin(angle);
             var mv1 = m[1], mv5 = m[5], mv9 = m[9];
    
             m[1] = m[1]*c-m[2]*s;
             m[5] = m[5]*c-m[6]*s;
             m[9] = m[9]*c-m[10]*s;

             m[2] = m[2]*c+mv1*s;
             m[6] = m[6]*c+mv5*s;
             m[10] = m[10]*c+mv9*s;
          }

         function rotateY(m, angle) {
            var c = Math.cos(angle);
            var s = Math.sin(angle);
            var mv0 = m[0], mv4 = m[4], mv8 = m[8];
    
            m[0] = c*m[0]+s*m[2];
            m[4] = c*m[4]+s*m[6];
            m[8] = c*m[8]+s*m[10];

            m[2] = c*m[2]-s*mv0;
            m[6] = c*m[6]-s*mv4;
            m[10] = c*m[10]-s*mv8;
         }

         var time_old = 0;
   
         var animate = function(time) {

            var dt = time-time_old;
            rotateY(mov_matrix, dt*0.002);
            rotateX(mov_matrix, dt*0.003);
            time_old = time;

            gl.enable(gl.DEPTH_TEST);
            gl.depthFunc(gl.LEQUAL);
            gl.clearColor(0.5, 0.5, 0.5, 0.9);
            gl.clearDepth(1.0);

            gl.viewport(0.0, 0.0, canvas.width, canvas.height);
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
            gl.uniformMatrix4fv(Pmatrix, false, proj_matrix);
            gl.uniformMatrix4fv(Vmatrix, false, view_matrix);
            gl.uniformMatrix4fv(Mmatrix, false, mov_matrix);
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
            gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
    
            window.requestAnimationFrame(animate);
         }
         animate(0);

Cada uno de los puntos del Octaedro dependen de una variable "a" para que cada cara sea igual. En cuanto a los puntos para formar cada uno de los triángulos se sigue el mismo orden en que los vértices fueron definidos. Por otra parte se manejaron n total de 4 colores intercalados de 2 en 2 para una mejor experiencia de visualización para el usuario.
El siguiente paso es almacenar cada array en cada uno de los buffers correspondientes. También se definen los Shaders correspondientes para finalmente asociar cada atributo con su respectivo vertex shader (Posición y Color).
Posteriormente se procede a establecer la matriz de proyección de la figura que vamos a crear. A través de unos parámetros se define nuestro espacio de trabajo y podemos ver que cuando se tiene la matriz completa se puede definir que tan lejos queremos que se proyecte nuestro objeto en el view_matrix; si este valor se deja así como esta la cámara estará ubicada en todo el centro del objeto, en cambio si se le suman unidades el objeto estará detrás de la cámara y si se le restan unidades el objeto estará adelante de la cámara.
Para finalizar se procede a dibujar la figura con una función de animación que recibe el valor del tiempo como parámetro. En esta funciona se encuentran las principales funciones del dibujo del a figura:

  • Las funciones de rotación definidas anteriormente las cuales reciben como parámetro la matriz y el cambio en el tiempo.
  • Se establece como quiere que sea el fondo del entorno de trabajo con la función clearColor(r,g,b,a).
  • Y finalmente se procede a dibujar la imagen dada la forma de dibujo y los indicies, en este caso se dibujarán triángulos.

Comentarios

Entradas populares