WebGL - Rotazione del Cubo

Ciao a tutti, futuri maghi di WebGL! Oggi ci imbarchiamo in un viaggio emozionante nel mondo della grafica 3D. Alla fine di questo tutorial, sarete in grado di creare un cubo rotante utilizzando WebGL. Non è fantastico? Tuffiamoci dentro!

WebGL - Cube Rotation

Comprensione delle Basi

Prima di iniziare a far girare i cubi come un DJ, cerchiamo di capire alcuni concetti fondamentali.

Cos'è WebGL?

WebGL (Web Graphics Library) è una API JavaScript che ci permette di rendere grafica 3D in un browser web. È come dare al tuo browser un paio di occhiali 3D!

Perché un Cubo?

Potresti chiederti, "Perché stiamo iniziando con un cubo?" Bene, miei cari studenti, un cubo è come il "Hello World" della grafica 3D. È semplice abbastanza da comprendere ma complesso abbastanza per insegnarci concetti importanti. E chi non adora un buon cubo?

Configurazione del Nostro Ambiente WebGL

Il Canvas HTML

Prima di tutto, abbiamo bisogno di un palco per il nostro cubo per esibirsi. In WebGL, questo palco si chiama canvas. Impostiamolo:

<canvas id="glcanvas" width="640" height="480">
Il tuo browser non supporta HTML5 canvas
</canvas>

Questo crea un canvas di 640x480 pixel. Se non lo vedi, non preoccuparti - è come un'inedibile pista da ballo in questo momento.

Inizializzazione di WebGL

Ora, prepariamo WebGL per la festa:

var canvas = document.getElementById('glcanvas');
var gl = canvas.getContext('webgl');

if (!gl) {
console.log('WebGL non supportato, ripiego su experimental-webgl');
gl = canvas.getContext('experimental-webgl');
}

if (!gl) {
alert('Il tuo browser non supporta WebGL');
}

Questo codice ottiene il nostro contesto WebGL. Se il tuo browser non supporta WebGL, è come cercare di giocare un DVD su un lettore VHS - semplicemente non funzionerà!

Creazione del Nostro Cubo 3D

Definizione dei Vertici

Un cubo ha 8 angoli (vertici). Dobbiamo dire a WebGL dove questi angoli sono:

var vertices = [
// Facce frontale
-1.0, -1.0,  1.0,
1.0, -1.0,  1.0,
1.0,  1.0,  1.0,
-1.0,  1.0,  1.0,

// Facce posteriore
-1.0, -1.0, -1.0,
-1.0,  1.0, -1.0,
1.0,  1.0, -1.0,
1.0, -1.0, -1.0,

// Facce superiore
-1.0,  1.0, -1.0,
-1.0,  1.0,  1.0,
1.0,  1.0,  1.0,
1.0,  1.0, -1.0,

// Facce inferiore
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0,  1.0,
-1.0, -1.0,  1.0,

// Facce destra
1.0, -1.0, -1.0,
1.0,  1.0, -1.0,
1.0,  1.0,  1.0,
1.0, -1.0,  1.0,

// Facce sinistra
-1.0, -1.0, -1.0,
-1.0, -1.0,  1.0,
-1.0,  1.0,  1.0,
-1.0,  1.0, -1.0
];

Ogni tripletta di numeri rappresenta un angolo del nostro cubo nello spazio 3D. È come dare a WebGL una mappa del nostro cubo!

Creazione del Buffer

Ora dobbiamo inviare questi dati alla GPU:

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

Questo è come mettiamo il nostro cubo in una valigia (buffer) e lo inviamo alla GPU.

Shader - I Maghi di WebGL

Vertex Shader

Il vertex shader posiziona i nostri vertici:

var vertexShaderSource = `
attribute vec3 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}
`;

Questo shader prende ogni vertice e applica le nostre matrici di trasformazione. È come un mago che muove gli angoli del nostro cubo!

Fragment Shader

Il fragment shader colora il nostro cubo:

var fragmentShaderSource = `
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;

Questo semplice shader colora tutto bianco. È come verniciare il nostro cubo!

Compilazione e Collegamento degli Shader

Ora dobbiamo compilare i nostri shader e collegarli in un programma:

function getShader(gl, source, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('Si è verificato un errore durante la compilazione degli shader: ' + gl.getShaderInfoLog(shader));
return null;
}

return shader;
}

var vertexShader = getShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
var fragmentShader = getShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);

var 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 degli shader: ' + gl.getProgramInfoLog(shaderProgram));
}

gl.useProgram(shaderProgram);

Questo è come insegniamo ai nostri maghi (shader) i loro trucchi e li mettiamo sul palco!

Far Girare il Nostro Cubo

Impostazione della Rotazione

Per far girare il nostro cubo, dobbiamo aggiornare l'angolo di rotazione nel tempo:

var cubeRotation = 0.0;
var then = 0;

function render(now) {
now *= 0.001;  // convert to seconds
const deltaTime = now - then;
then = now;

cubeRotation += deltaTime;

drawScene();

requestAnimationFrame(render);
}

Questa funzione viene chiamata ripetutamente, aggiornando la rotazione del nostro cubo ogni volta.

Disegno della Scena

Ora mettiamo tutto insieme e disegniamo il nostro cubo rotante:

function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.1, 100.0);

const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotate(modelViewMatrix, modelViewMatrix, cubeRotation, [0, 1, 1]);

gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'), false, projectionMatrix);
gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'), false, modelViewMatrix);

gl.drawArrays(gl.TRIANGLE_STRIP, 0, 36);
}

Questa funzione pulisce il canvas, imposta la nostra prospettiva, applica la nostra rotazione e infine disegna il nostro cubo.

Conclusione

Eccoci, ragazzi! Abbiamo creato un cubo 3D rotante utilizzando WebGL. Ricorda, padroneggiare WebGL è come imparare a gjuggare - richiede pratica, ma una volta che lo fai, puoi fare cose incredibili!

Ecco una tabella che riassume i principali metodi che abbiamo utilizzato:

Metodo Descrizione
gl.createBuffer() Crea un nuovo oggetto buffer
gl.bindBuffer() Associa un oggetto buffer a un target
gl.bufferData() Crea e inizializza il deposito dati di un 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() Associa 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.clear() Pulisce i buffer a valori predefiniti
gl.uniformMatrix4fv() Specifica il valore di una variabile uniforme per l'oggetto programma corrente
gl.drawArrays() Rende primitivi da dati array

Continua a praticare, continua a codificare e presto creerai grafica 3D incredibile nel tuo browser. Buon coding!

Credits: Image by storyset