WebGL - Modos de Dibujado

¡Hola, futuros magos de WebGL! ? Hoy vamos a sumergirnos en el emocionante mundo de los modos de dibujado en WebGL. Como tu amable profesor de informática del vecindario, estoy aquí para guiarte en este viaje, incluso si nunca has escrito una línea de código antes. Así que, toma tu pincel virtual, y ¡vamos a crear algunas obras maestras digitales!

WebGL - Modes of Drawing

El Parámetro mode

Antes de comenzar a dibujar, hablemos de la estrella de nuestro espectáculo: el parámetro mode. Piensa en él como la varita mágica que le dice a WebGL cómo conectar los puntos (o, en nuestro caso, vértices) para crear diferentes formas y patrones.

En WebGL, cuando llamamos a la función gl.drawArrays() o gl.drawElements(), necesitamos especificar un parámetro mode. Este parámetro es como dar instrucciones a un rompecabezas de conectar puntos: le dice a WebGL cómo unir los puntos que hemos definido.

Aquí tienes una tabla de los diferentes modos de dibujado disponibles en WebGL:

Modo Descripción
gl.POINTS Dibuja un punto para cada vértice
gl.LINES Dibuja una línea entre cada par de vértices
gl.LINE_STRIP Dibuja una línea continua conectando los vértices
gl.LINE_LOOP Similar a LINE_STRIP, pero cierra la forma
gl.TRIANGLES Dibuja un triángulo por cada tres vértices
gl.TRIANGLE_STRIP Dibuja un grupo conectado de triángulos
gl.TRIANGLE_FAN Dibuja una forma en abanico de triángulos conectados

No te preocupes si estos parecen confundirte ahora. Exploraremos cada uno de ellos con ejemplos a medida que avanzamos!

Ejemplo - Dibujar Tres Líneas Paralelas

Vamos a empezar con un ejemplo simple: dibujar tres líneas paralelas. Esto nos ayudará a entender cómo funciona el parámetro mode en la práctica.

// Primero, configuremos nuestro contexto WebGL
const canvas = document.getElementById('myCanvas');
const gl = canvas.getContext('webgl');

// Ahora, definamos nuestro vertex shader
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;

// Y nuestro fragment shader
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Color rojo
}
`;

// Crear y compilar los shaders (no te preocupes, explicaremos esto en detalle en lecciones futuras)
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);

const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);

// Crear un programa y enlazar los shaders
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// Definir las posiciones de nuestras líneas
const positions = new Float32Array([
-0.8, -0.8,  // Inicio de la línea 1
-0.8,  0.8,  // Fin de la línea 1
-0.3, -0.8,  // Inicio de la línea 2
-0.3,  0.8,  // Fin de la línea 2
0.2, -0.8,  // Inicio de la línea 3
0.2,  0.8   // Fin de la línea 3
]);

// Crear un buffer y poner las posiciones en él
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

// Decirle a WebGL cómo leer el buffer y atribuirlo a `a_position`
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

// Limpiar el lienzo
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// Dibujar las líneas
gl.drawArrays(gl.LINES, 0, 6);

Ahora, desglosemos esto:

  1. Configuramos nuestro contexto WebGL y definimos nuestros shaders. No te preocupes demasiado por estos ahora; cubriremos los shaders en profundidad en lecciones futuras.

  2. Creamos un programa y enlazamos nuestros shaders a él. Esto es como preparar nuestro pincel digital.

  3. Definimos las posiciones de nuestras líneas. Cada línea se define por dos puntos (su inicio y fin), y cada punto se define por dos coordenadas (x e y). Así que tenemos 6 puntos en total para nuestras 3 líneas.

  4. Creamos un buffer y ponemos nuestras posiciones en él. Piensa en esto como cargar nuestra pintura en el pincel.

  5. Le decimos a WebGL cómo leer este buffer y asociarlo con el atributo a_position en nuestro vertex shader.

  6. Finalmente, llamamos a gl.drawArrays(gl.LINES, 0, 6). ¡Aquí ocurre la magia!

  • gl.LINES es nuestro modo. Le dice a WebGL que dibuje líneas entre pares de vértices.
  • 0 es el índice de inicio en nuestro array de posiciones.
  • 6 es el número de vértices a considerar (recuerda, tenemos 6 puntos para nuestras 3 líneas).

Ejecuta este código, y ¡voilà! Deberías ver tres líneas rojas paralelas en un fondo negro. ¡Felicidades, acabas de crear tu primer dibujo en WebGL! ?

Modos de Dibujado

Ahora que hemos visto gl.LINES en acción, exploremos algunos otros modos de dibujado. Usaremos el mismo conjunto de configuración que antes, pero cambiaremos nuestras posiciones y el modo de dibujado.

gl.POINTS

Comencemos con el modo más simple: gl.POINTS. Este modo dibuja un punto para cada vértice.

// ... (código de configuración anterior)

const positions = new Float32Array([
-0.5, 0.5,
0.0, 0.0,
0.5, -0.5
]);

// ... (código de configuración del buffer)

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

Esto dibujará tres puntos rojos en tu lienzo. Simple, ¿verdad?

gl.LINE_STRIP

Ahora, probemos gl.LINE_STRIP. Este modo dibuja una línea continua conectando cada vértice con el siguiente.

// ... (código de configuración anterior)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (código de configuración del buffer)

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

Deberías ver una línea en forma de V conectando los tres puntos.

gl.LINE_LOOP

gl.LINE_LOOP es similar a LINE_STRIP, pero cierra la forma conectando el último vértice con el primero.

// ... (código de configuración anterior)

const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);

// ... (código de configuración del buffer)

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

Esto dibujará un contorno de triángulo.

gl.TRIANGLES

Ahora, pasemos a rellenar formas con gl.TRIANGLES. Este modo dibuja un triángulo por cada tres vértices.

// ... (código de configuración anterior)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5
]);

// ... (código de configuración del buffer)

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

Deberías ver un triángulo rojo sólido.

gl.TRIANGLE_STRIP

gl.TRIANGLE_STRIP es un poco más complejo. Dibuja un grupo conectado de triángulos, donde cada triángulo comparte dos vértices con el anterior.

// ... (código de configuración anterior)

const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, 0.5
]);

// ... (código de configuración del buffer)

gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

Esto dibujará dos triángulos conectados formando un rectángulo.

gl.TRIANGLE_FAN

Finalmente, veamos gl.TRIANGLE_FAN. Este modo dibuja una forma en abanico, donde todos los triángulos comparten el primer vértice como un punto común.

// ... (código de configuración anterior)

const positions = new Float32Array([
0.0, 0.0,    // Punto central
0.5, 0.0,    // Punto 1
0.35, 0.35,  // Punto 2
0.0, 0.5,    // Punto 3
-0.35, 0.35  // Punto 4
]);

// ... (código de configuración del buffer)

gl.drawArrays(gl.TRIANGLE_FAN, 0, 5);

Esto dibujará una forma que se parece a un cuarto de círculo.

Y ahí lo tienes! Hemos explorado todos los modos de dibujado en WebGL. Recuerda, la clave para dominar estos es la práctica. Intenta combinar diferentes modos, cambiar colores y jugar con las posiciones de los vértices. Antes de que te des cuenta, estarás creando escenas WebGL complejas con facilidad!

En nuestra próxima lección, profundizaremos en los shaders y aprenderemos a agregar un poco de brillo a nuestros dibujos con colores y texturas. ¡Hasta entonces, feliz codificación, futuros artistas de WebGL! ??‍??‍?

Credits: Image by storyset