WebGL: 3D real time e OpenGL su HTML5

22 novembre 2010

Hello Triangle!

Uno script WebGL si può dividere sommariamente in 2 fasi:

  • la prima, che possiamo chiamare di setup, crea il contesto WebGL sul <canvas> scelto, inizializza gli shaders e crea i buffer necessari a contenere le informazioni sui modelli 3D della scena;
  • la seconda fase, che invece possiamo chiamare di disegno, ha il compito di effettuare continuamente il refresh della scena 3D gestendo in questo modo il movimento degli oggetti in essa contenuti, le luci e la posizione dell’inquadratura.

Nell’applicazione di prova che stiamo per creare mostreremo a video un singolo triangolo bianco; tale risultato non rientra esattamente nelle massima espressione possibile della grafica tridimensionale, ma è quanto basta per poter sperimentare tutti gli aspetti principali delle specifiche WebGL senza diventare troppo prolissi.

Iniziamo scrivendo un file index.html (demo):

<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
<script type="text/javascript" src="hello_triangle.js"></script>

<script id="shader-fs" type="x-shader/x-fragment">
void main(void) {
  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>

<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition; // posizione (x,y,z) del vertice
// Imprime al vertice le modifiche dovute al movimento dell'oggetto sulla scena
uniform mat4 uMVMatrix;
// Imprime al vertice le modifiche dovute al punto di vista
uniform mat4 uPMatrix;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}
</script>
</head>
<body onload="webGLStart();">
<canvas id="mycanvas" style="border: none;" width="500" height="500"></canvas>
</body>
</html>

Già in questo piccolo file possiamo evidenziare un numero di elementi interessanti, come le definizioni dei due shaders:

  • shader-fs, che si comporta tingendo di bianco ogni pixel per il quale viene invocato, e shader-vs che invece decide dove posizionare il vertice;
  • aVertexPosition sulla base di due parametri di tipo matrice 4x4 che vengono settati durante la fase di disegno in base alla posizione del punto di vista e a quella dell’oggetto sulla scena.

Il metodo webGLStart(), invocato al load della pagina, è contenuto all’interno del file hello_triangle.js, che si fa’ carico dell’intera logica della demo e che di seguito è stato diviso in sezioni per poter essere più facilmente illustrato:

var gl;
var shaderProgram;
var triangleVertexPositionBuffer;

function webGLStart() {
  var canvas = document.getElementById("mycanvas");
  
  gl = canvas.getContext("experimental-webgl");
  gl.viewportWidth = canvas.width;
  gl.viewportHeight = canvas.height;
  
  initShaders();
  initBuffers();
  
  gl.clearColor(0.0, 0.0, 0.0, 1.0); // imposto lo sfondo a nero
  gl.clearDepth(1.0);
  setInterval(drawScene, 15);
}

La funzione webGLStart() inizializza il corretto contesto sul canvas di riferimento e successivamente invoca le due funzioni della fase di setup (initShaders e initBuffers). Fatto questo imposta il colore di sfondo della scena 3D a nero e lancia la funzione drawScene ogni 15 millisecondi.

function initShaders() {
  shaderProgram = gl.createProgram();
  $.each([[gl.FRAGMENT_SHADER,"#shader-fs"], 
         [gl.VERTEX_SHADER,"#shader-vs"]], 
		 function (ind,val) {
           var shader = gl.createShader(val[0]);
		   gl.shaderSource(shader, $(val[1]).text());
		   gl.compileShader(shader);
		   gl.attachShader(shaderProgram, shader);
		 });
		 
  gl.linkProgram(shaderProgram);
  gl.useProgram(shaderProgram);
  
  shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); 
  gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
  shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
  shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}

In questa porzione di codice vengono istanziati e compilati i due shaders all’interno di un contenitore preposto (shaderProgram) che poi viene agganciato al contesto 3D. Le ultime righe di questo listato servono a notificare le variabili che verranno valorizzate nello shader durante la fase di disegno: aVertexPosition per il vertice corrente e uPMatrix e uMVMatrix per le matrici illustrate precedentemente.

Se vuoi aggiornamenti su WebGL: 3D real time e OpenGL su HTML5 inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su WebGL: 3D real time e OpenGL su HTML5

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy