WebGL - Escalonamento

Neste capítulo, vamos dar um exemplo para demonstrar como modificar a escala de um triângulo usando WebGL.

Dimensionamento

O dimensionamento nada mais é do que aumentar ou diminuir o tamanho de um objeto. Por exemplo, se um triângulo tem vértices do tamanho [a, b, c], então o triângulo com os vértices [2a, 2b, 2c] terá o dobro de seu tamanho. Portanto, para dimensionar um triângulo, você deve multiplicar cada vértice pelo fator de escala. Você também pode escalar um determinado vértice.

Para dimensionar um triângulo, no sombreador de vértice do programa, criamos uma matriz uniforme e multiplicamos os valores das coordenadas com esta matriz. Posteriormente, passamos por uma matriz diagonal 4 × 4 com os fatores de escala das coordenadas x, y, z nas posições diagonais (última posição diagonal 1).

Passos Requeridos

As etapas a seguir são necessárias para criar um aplicativo WebGL para dimensionar um triângulo.

Step 1 − Prepare the Canvas and Get the WebGL Rendering Context

Nesta etapa, obtemos o objeto de contexto de renderização WebGL usando getContext().

Step 2 − Define the Geometry and Store it in the Buffer Objects

Como estamos desenhando um triângulo, temos que passar três vértices do triângulo e armazená-los em buffers.

var vertices = [ -0.5,0.5,0.0, -0.5,-0.5,0.0, 0.5,-0.5,0.0, ];

Step 3 − Create and Compile the Shader Programs

Nesta etapa, você precisa escrever os programas do sombreador de vértice e do sombreador de fragmento, compilá-los e criar um programa combinado vinculando esses dois programas.

  • Vertex Shader- No sombreador de vértice do programa, definimos um atributo de vetor para armazenar coordenadas 3D. Junto com isso, definimos uma matriz uniforme para armazenar os fatores de escala e, finalmente, multiplicamos esses dois valores e atribuímos agl_position que mantém a posição final dos vértices.

var vertCode =
   'attribute vec4 coordinates;' +
   'uniform mat4 u_xformMatrix;' +
   'void main(void) {' +
      ' gl_Position = u_xformMatrix * coordinates;' +
   '}';
  • Fragment Shader - No shader de fragmento, simplesmente atribuímos a cor do fragmento ao gl_FragColor variável.

var fragCode = 'void main(void) {' +' gl_FragColor = vec4(1, 0.5, 0.0, 1);' +'}';

Step 4 − Associate the Shader Programs with the Buffer Objects

Nesta etapa, associamos os objetos buffer ao programa shader.

Step 5 − Drawing the Required Object

Uma vez que estamos desenhando o triângulo usando índices, usamos o drawArrays()método. Para este método, temos que passar o número de vértices / elementos a serem considerados. Como estamos desenhando um triângulo, passaremos 3 como parâmetro.

gl.drawArrays(gl.TRIANGLES, 0, 3);

Exemplo - dimensionar um triângulo

O exemplo a seguir mostra como dimensionar um triângulo -

<!doctype html>
<html>
   <body>
      <canvas width = "300" height = "300" id = "my_Canvas"></canvas>

      <script>
         /*=================Creating a canvas=========================*/
         var canvas = document.getElementById('my_Canvas');
         gl = canvas.getContext('experimental-webgl'); 

         /*===========Defining and storing the geometry==============*/
         var vertices =  [
            -0.5,0.5,0.0, 	
            -0.5,-0.5,0.0, 	
            0.5,-0.5,0.0,   
         ];

         //Create an empty buffer object and store vertex data

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

         /*========================Shaders============================*/

         //Vertex shader source code
         var vertCode =
            'attribute vec4 coordinates;' + 
            'uniform mat4 u_xformMatrix;' +
            'void main(void) {' +
               '  gl_Position = u_xformMatrix * coordinates;' +
            '}';

         //Create a vertex shader program object and compile it                
         var vertShader = gl.createShader(gl.VERTEX_SHADER);
         gl.shaderSource(vertShader, vertCode);
         gl.compileShader(vertShader);

         //fragment shader source code
         var fragCode =
            'void main(void) {' +
               '   gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
            '}';

         //Create a fragment shader program object and compile it 
         var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
         gl.shaderSource(fragShader, fragCode);
         gl.compileShader(fragShader);

         //Create and use combiened shader program
         var shaderProgram = gl.createProgram();
         gl.attachShader(shaderProgram, vertShader);
         gl.attachShader(shaderProgram, fragShader);
         gl.linkProgram(shaderProgram);

         gl.useProgram(shaderProgram); 

         /*===================scaling==========================*/

         var Sx = 1.0, Sy = 1.5, Sz = 1.0;
         var xformMatrix = new Float32Array([
            Sx,   0.0,  0.0,  0.0,
            0.0,  Sy,   0.0,  0.0,
            0.0,  0.0,  Sz,   0.0,
            0.0,  0.0,  0.0,  1.0  
         ]);

         var u_xformMatrix = gl.getUniformLocation(shaderProgram, 'u_xformMatrix');
         gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);

         /* ===========Associating shaders to buffer objects============*/
         gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);   

         var coordinatesVar = gl.getAttribLocation(shaderProgram, "coordinates"); 
         gl.vertexAttribPointer(coordinatesVar, 3, gl.FLOAT, false, 0, 0);  
         gl.enableVertexAttribArray(coordinatesVar);

         /*=================Drawing the Quad========================*/ 
         gl.clearColor(0.5, 0.5, 0.5, 0.9);
         gl.enable(gl.DEPTH_TEST);

         gl.clear(gl.COLOR_BUFFER_BIT);
         gl.viewport(0,0,canvas.width,canvas.height);
         gl.drawArrays(gl.TRIANGLES, 0, 3);
      </script>
   </body>
</html>

Se você executar este exemplo, ele produzirá a seguinte saída -