WebGL: Guida per Principianti alla Grafica 3D nel Browser

Ciao there, futuri maghi della grafica 3D! Sono entusiasta di essere il tuo guida in questo emozionante viaggio nel mondo di WebGL. Come qualcuno che ha insegnato grafica computerizzata per anni, posso dirti che WebGL è come una bacchetta magica per il tuo browser web. Ti permette di creare grafica 3D e animazioni mozzafiato direttamente nelle tue pagine web. Non è fantastico? Immergiamoci!

WebGL - Home

Cos'è WebGL?

WebGL, acronimo di Web Graphics Library, è un'API JavaScript che ti permette di rendere grafica 2D e 3D interattiva in qualsiasi browser compatibile senza la necessità di plugin. È come dare al tuo browser web superpoteri per creare esperienze visive straordinarie!

Una Breve Storia

WebGL è stato introdotto per la prima volta nel 2011, e da allora ha rivoluzionato il modo in cui pensiamo alla grafica sul web. Prima di WebGL, se volevi creare grafica 3D in un browser, dovevi affidarti a plugin come Flash o applet Java. Ora, con WebGL, possiamo fare tutto questo nativamente nel browser. È come passare da una bicicletta a una macchina sportiva!

Prerequisiti

Prima di iniziare la nostra avventura con WebGL, assicuriamoci di avere gli strumenti giusti nel nostro zaino:

  1. Un browser web moderno (Chrome, Firefox, Safari o Edge)
  2. Un editor di testo (raccomando Visual Studio Code, ma va bene qualunque altro)
  3. Conoscenze di base di HTML e JavaScript (non preoccuparti se sei un po' arrugginito, ripasseremo tutto man mano)

Iniziare con WebGL

Creiamo il nostro primo programma WebGL! Inizieremo con un semplice esempio "Ciao, WebGL!" che visualizza un triangolo colorato sullo schermo.

Passo 1: Configurare l'HTML

Prima, dobbiamo creare un file HTML con un elemento canvas. Questo canvas è dove avverrà la magia di WebGL.

<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Ciao, WebGL!</title>
<style>
canvas { border: 1px solid black; }
</style>
</head>
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
<script src="webgl-demo.js"></script>
</body>
</html>

In questo HTML, abbiamo creato un elemento canvas con un ID di "glCanvas" e impostato le sue dimensioni a 640x480 pixel. Abbiamo anche collegato un file JavaScript chiamato "webgl-demo.js" dove scriveremo il nostro codice WebGL.

Passo 2: Inizializzare WebGL

Ora, creiamo il nostro file "webgl-demo.js" e iniziamo a scrivere un po' di JavaScript per inizializzare WebGL:

function main() {
const canvas = document.getElementById("glCanvas");
const gl = canvas.getContext("webgl");

if (!gl) {
alert("Impossibile inizializzare WebGL. Il tuo browser o computer potrebbe non supportarlo.");
return;
}

// Impostare il colore di sfondo a nero, completamente opaco
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Pulire il buffer dei colori con il colore specificato
gl.clear(gl.COLOR_BUFFER_BIT);
}

window.onload = main;

Spieghiamo un po' questo codice:

  1. Prendiamo un riferimento al nostro elemento canvas.
  2. Tentiamo di ottenere un contesto WebGL dal canvas. Se questo fallisce, significa che WebGL non è supportato, e mostriamo un messaggio di errore.
  3. Se ha successo, impostiamo il colore di sfondo (il colore di background) a nero e puliamo il buffer dei colori.

Passo 3: Creare i Shader

I shader sono programmi speciali che vengono eseguiti sulla GPU. Sono scritti in un linguaggio chiamato GLSL (OpenGL Shading Language). Abbiamo bisogno di due tipi di shader: shader di vertice e shader di frammento.

// Programma shader di vertice
const vsSource = `
attribute vec4 aVertexPosition;

void main() {
gl_Position = aVertexPosition;
}
`;

// Programma shader di frammento
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

Lo shader di vertice posiziona i nostri vertici, mentre lo shader di frammento colora i nostri pixel (in questo caso, rosso).

Passo 4: Inizializzare un Programma Shader

Ora dobbiamo compilare e collegare questi shader in un programma shader:

function initShaderProgram(gl, vsSource, fsSource) {
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Impossibile inizializzare il programma shader: ' + gl.getProgramInfoLog(shaderProgram));
return null;
}

return shaderProgram;
}

function loadShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('Errore durante la compilazione degli shader: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

Questo codice compila i nostri shader, li collega in un programma e verifica eventuali errori.

Passo 5: Creare il Triangolo

Ora, creiamo i dati per il nostro triangolo:

function initBuffers(gl) {
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

const positions = [
-1.0,  1.0,
1.0,  1.0,
-1.0, -1.0,
];

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

return {
position: positionBuffer,
};
}

Questo crea un buffer e lo riempie con le posizioni dei vertici del nostro triangolo.

Passo 6: Disegnare la Scena

Finalmente, mettiamo tutto insieme e disegniamo il nostro triangolo:

function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.useProgram(programInfo.program);

gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
2,        // 2 componenti per iterazione
gl.FLOAT, // i dati sono float a 32 bit
false,    // non normalizzare
0,        // passo (0 = automatico)
0         // offset nel buffer
);

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

Questa funzione pulisce il canvas, imposta il nostro programma shader, connette i dati del buffer e infine disegna il nostro triangolo.

Mettere Tutto Insieme

Ora, aggiorniamo la nostra funzione main per utilizzare tutti questi pezzi:

function main() {
const canvas = document.getElementById("glCanvas");
const gl = canvas.getContext("webgl");

if (!gl) {
alert("Impossibile inizializzare WebGL. Il tuo browser o computer potrebbe non supportarlo.");
return;
}

const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
},
};

const buffers = initBuffers(gl);

drawScene(gl, programInfo, buffers);
}

window.onload = main;

Ecco il tuo primo programma WebGL. Quando apri il tuo file HTML in un browser, dovresti vedere un triangolo rosso su sfondo nero. Congratulazioni!

Metodi Comuni di WebGL

Ecco una tabella di alcuni metodi comuni di WebGL che abbiamo utilizzato e i loro scopi:

Metodo Scopo
gl.createBuffer() Crea un nuovo oggetto buffer
gl.bindBuffer() Collega un oggetto buffer a un target
gl.bufferData() Inizializza e crea il magazzino dei dati dell'oggetto buffer
gl.createShader() Crea un oggetto shader
gl.shaderSource() Imposta il codice sorgente di un oggetto shader
gl.compileShader() Compila un oggetto shader
gl.createProgram() Crea un oggetto programma
gl.attachShader() Collega un oggetto shader a un oggetto programma
gl.linkProgram() Collega un oggetto programma
gl.useProgram() Imposta l'oggetto programma come parte dello stato di rendering corrente
gl.getAttribLocation() Restituisce la posizione di una variabile attributo
gl.enableVertexAttribArray() Abilita un array di attributi vertex
gl.vertexAttribPointer() Specifica il layout dei dati dell'attributo vertex
gl.drawArrays() Rende primitivi da dati array

Conclusione

Wow, abbiamo coperto molto terreno oggi! Abbiamo imparato cos'è WebGL, configurato il nostro ambiente di sviluppo e creato il nostro primo programma WebGL. Ricorda, imparare WebGL è come imparare a guidare una bicicletta - all'inizio potrebbe sembrare un po' instabile, ma con la pratica, diventerai rapidissimo!

Nei prossimi lesson, esploreremo forme più complesse, aggiungeremo interattività e persino immergerci nella grafica 3D. Il mondo di WebGL è vasto ed entusiasmante, e non vedo l'ora di esplorarlo ulteriormente con te. Fino alla prossima volta, happy coding!

Credits: Image by storyset