El pipeline d'OpenGL és una seqüència de passos que OpenGL segueix per processar les dades de renderització i produir la imatge final que es mostra a la pantalla. Comprendre aquest pipeline és fonamental per aprofitar al màxim les capacitats d'OpenGL i optimitzar el rendiment de les aplicacions gràfiques.

Conceptes Clau del Pipeline d'OpenGL

  1. Vertex Processing (Processament de Vèrtexs)

    • Els vèrtexs són els punts bàsics que defineixen les formes geomètriques.
    • En aquesta etapa, els vèrtexs es transformen des de les coordenades del model a les coordenades de la pantalla.
    • Es poden aplicar transformacions com la translació, la rotació i l'escalat.
  2. Primitive Assembly (Assemblatge de Primitives)

    • Els vèrtexs es combinen per formar primitives com triangles, línies i punts.
    • Aquesta etapa defineix com es connecten els vèrtexs per formar les formes geomètriques.
  3. Rasterization (Rasterització)

    • Les primitives es converteixen en fragments, que són els elements bàsics per a la generació de píxels.
    • La rasterització determina quins píxels de la pantalla seran afectats per cada primitiva.
  4. Fragment Processing (Processament de Fragments)

    • Cada fragment es processa per determinar el seu color final.
    • Es poden aplicar tècniques com la textura, l'ombrejat i la il·luminació.
  5. Per-Fragment Operations (Operacions per Fragment)

    • Es realitzen operacions finals com la prova de profunditat, la barreja i la prova de plantilla.
    • Aquestes operacions determinen si un fragment es dibuixa o es descarta.
  6. Framebuffer Operations (Operacions de Framebuffer)

    • Els fragments finals es combinen per formar la imatge final que es mostra a la pantalla.
    • Es poden aplicar efectes de postprocessament abans de la visualització final.

Diagrama del Pipeline d'OpenGL

A continuació es mostra un diagrama simplificat del pipeline d'OpenGL:

+-------------------+     +-------------------+     +-------------------+
| Vertex Processing | --> | Primitive Assembly| --> |   Rasterization   |
+-------------------+     +-------------------+     +-------------------+
                                                           |
                                                           v
+-------------------+     +-------------------+     +-------------------+
| Fragment Processing| --> | Per-Fragment Ops | --> | Framebuffer Ops  |
+-------------------+     +-------------------+     +-------------------+

Exemples Pràctics

Exemple 1: Transformació de Vèrtexs

// Vertex Shader
#version 330 core
layout(location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

Explicació:

  • aPos: Posició del vèrtex d'entrada.
  • model, view, projection: Matrius de transformació.
  • gl_Position: Posició del vèrtex transformada.

Exemple 2: Fragment Shader amb Textura

// Fragment Shader
#version 330 core
out vec4 FragColor;

in vec2 TexCoord;

uniform sampler2D texture1;

void main()
{
    FragColor = texture(texture1, TexCoord);
}

Explicació:

  • TexCoord: Coordenades de la textura d'entrada.
  • texture1: Sampler de la textura.
  • FragColor: Color del fragment resultant.

Exercici Pràctic

Exercici: Crear un Shader Program

  1. Escriu un vertex shader que transformi els vèrtexs utilitzant matrius de model, vista i projecció.
  2. Escriu un fragment shader que apliqui una textura als fragments.
  3. Compila i enllaça els shaders en un shader program.
  4. Utilitza el shader program per renderitzar un quadrat amb una textura.

Solució:

// Vertex Shader
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec2 TexCoord;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    TexCoord = aTexCoord;
}

// Fragment Shader
#version 330 core
out vec4 FragColor;

in vec2 TexCoord;

uniform sampler2D texture1;

void main()
{
    FragColor = texture(texture1, TexCoord);
}

// Codi C++ per compilar i enllaçar els shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);

GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

Resum

En aquesta secció, hem après sobre el pipeline d'OpenGL i els seus passos clau, des del processament de vèrtexs fins a les operacions de framebuffer. Hem vist exemples pràctics de shaders i hem realitzat un exercici per crear un shader program. Amb aquesta base, estem preparats per explorar tècniques de renderització més avançades en els següents mòduls.

© Copyright 2024. Tots els drets reservats