WebGL - Colori: Una Guida per Principianti per dare Vita alle Tue Grafiche 3D

Ciao là, appassionati di WebGL! Sono entusiasta di essere il tuo guida in questo viaggio colorato attraverso il mondo di WebGL. Come qualcuno che ha insegnato grafica computerizzata per oltre un decennio, posso dirti che aggiungere colori alle tue scene 3D è come dare vita a una fotografia in bianco e nero. È magico, e oggi, sbloccheremo insieme quella magia!

WebGL - Colors

Comprendere i Colori in WebGL

Prima di immergerci nei dettagli dell'applicazione dei colori, prendiamo un momento per comprendere cosa significano i colori nel contesto di WebGL. In questo mondo digitale, i colori sono rappresentati utilizzando il modello di colore RGB (Rosso, Verde, Blu). Ogni colore è una combinazione di questi tre colori primari, con valori che vanno da 0.0 a 1.0.

Per esempio:

  • Rosso: (1.0, 0.0, 0.0)
  • Verde: (0.0, 1.0, 0.0)
  • Blu: (0.0, 0.0, 1.0)
  • Bianco: (1.0, 1.0, 1.0)
  • Nero: (0.0, 0.0, 0.0)

Pensa a esso come mescolare vernici, ma con la luce invece dei pigmenti. È un po' come essere un artista digitale con una palette infinita alle tue dita!

Applicare i Colori in WebGL

Ora che abbiamo capito le basi, mettiamo le mani al lavoro (o dovremmo dire, colorate?) con l'applicazione dei colori in WebGL.

Passaggi per Applicare i Colori

  1. Definisci gli attributi del colore nel tuo vertex shader
  2. Passa i dati del colore dal tuo codice JavaScript
  3. Usa il colore nel tuo fragment shader

Diamo un'occhiata a questi passaggi con alcuni esempi di codice.

Passaggio 1: Definire gli Attributi del Colore nel Vertex Shader

Prima, dobbiamo dire al nostro vertex shader che lavoreremo con i colori. Ecco come facciamo:

attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}

In questo codice, stiamo definendo un attributo a_Color per ricevere i dati del colore e una variabile varying v_Color per passare il colore allo shader fragment. È come impostare un tubo di vernice per il nostro viaggio dal codice JavaScript ai nostri pixel!

Passaggio 2: Passare i Dati del Colore dal JavaScript

Ora, dobbiamo inviare i dati del colore dal nostro codice JavaScript allo shader. Ecco un esempio di come potremmo farlo:

// Definisci vertici e colori
var vertices = new Float32Array([
0.0, 0.5, 1.0, 0.0, 0.0,  // Vertice 1: x, y, r, g, b
-0.5, -0.5, 0.0, 1.0, 0.0,  // Vertice 2: x, y, r, g, b
0.5, -0.5, 0.0, 0.0, 1.0   // Vertice 3: x, y, r, g, b
]);

// Crea un buffer e invia i dati
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// Dice a WebGL come leggere il buffer
var FSIZE = vertices.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0);
gl.enableVertexAttribArray(a_Position);

var a_Color = gl.getAttribLocation(program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);
gl.enableVertexAttribArray(a_Color);

Questo codice potrebbe sembrare intimidatorio a prima vista, ma analizziamolo:

  1. Definiamo i nostri vertici e colori in un singolo array. Ogni vertice ha 5 valori: x, y, r, g, b.
  2. Creiamo un buffer e inviamo i nostri dati.
  3. Diciamo a WebGL come leggere questo buffer, sia per la posizione (primi 2 valori) che per il colore (ultimi 3 valori).

È come.packare una valigia con vestiti e toilette e poi dire al tuo amico esattamente come sballarla!

Passaggio 3: Usare il Colore nel Fragment Shader

Infine, usiamo il colore nel nostro fragment shader:

precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}

Questo shader semplice prende il colore che abbiamo passato dallo shader vertex e lo applica al nostro fragment (pixel). È l'ultimo passo del nostro viaggio colorato, dove il colore finalmente splende sullo schermo!

Esempio – Applicare il Colore

Mettiamo tutto insieme con un esempio completo. Creeremo un triangolo colorato utilizzando il codice che abbiamo discusso.

<!DOCTYPE html>
<html>
<head>
<title>Triangolo Colorato WebGL</title>
</head>
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
<script>
// Shader programma vertex
const vsSource = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
v_Color = a_Color;
}
`;

// Shader programma fragment
const fsSource = `
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;

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

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

// Inizializza uno shader programma
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

// Ottieni le posizioni degli attributi
const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'a_Position'),
vertexColor: gl.getAttribLocation(shaderProgram, 'a_Color'),
},
};

// Crea il buffer
const buffers = initBuffers(gl);

// Disegna la scena
drawScene(gl, programInfo, buffers);
}

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

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

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

return {
position: positionBuffer,
};
}

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);

{
const numComponents = 2;  // Estrai 2 valori per iterazione
const type = gl.FLOAT;    // I dati nel buffer sono float a 32 bit
const normalize = false;  // Non normalizzare
const stride = 20;        // Quanti byte per passare da un set di valori all'altro
const offset = 0;         // Quanti byte all'interno del buffer per iniziare
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition);
}

{
const numComponents = 3;
const type = gl.FLOAT;
const normalize = false;
const stride = 20;
const offset = 8;
gl.vertexAttribPointer(
programInfo.attribLocations.vertexColor,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexColor);
}

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

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 lo shader programma: ' + 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('Si è verificato un errore durante la compilation degli shader: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

window.onload = main;
</script>
</body>
</html>

Quando esegui questo codice, vedrai un bellissimo triangolo con vertici rossi, verdi e blu. È come vedere un arcobaleno venire alla vita sullo schermo!

Conclusione

Eccoci, gente! Abbiamo intrapreso un viaggio attraverso il mondo colorato di WebGL, dalla comprensione di come i colori sono rappresentati all'applicazione delle nostre grafiche 3D. Ricorda, questo è solo l'inizio. Con queste basi, sei ben preparato per creare grafiche 3D splendide e vivaci.

Mentre chiudiamo, mi viene in mente una studentessa che mi disse che imparare i colori di WebGL era come imparare a dipingere con la luce. E aveva assolutamente ragione. Quindi vai avanti, miei cari studenti, e dipingi le tue tele digitali con tutti i colori del vento (sì, è un riferimento Disney, e non sono affatto imbarazzato per questo!).

Buon coding, e che le tue avventure WebGL siano sempre colorate!

Credits: Image by storyset