Introducció

Els vertex shaders són una part fonamental de la pipeline de renderització en Direct3D. Són programes que s'executen per cada vèrtex d'un objecte 3D i permeten transformar i manipular les seves propietats abans de passar-les a la següent etapa de la pipeline. En aquest tema, aprendrem a escriure vertex shaders utilitzant HLSL (High-Level Shading Language).

Objectius

  • Comprendre la funció dels vertex shaders en la pipeline de renderització.
  • Aprendre la sintaxi bàsica de HLSL per escriure vertex shaders.
  • Escriure un vertex shader senzill que transformi vèrtexs.
  • Integrar el vertex shader en una aplicació DirectX.

Conceptes Clau

  • Vertex Shader: Un programa que s'executa per cada vèrtex per transformar-lo i manipular les seves propietats.
  • HLSL: High-Level Shading Language, el llenguatge utilitzat per escriure shaders en DirectX.
  • Pipeline de Renderització: La seqüència d'etapes per les quals passen els vèrtexs i fragments per ser renderitzats a la pantalla.

Estructura d'un Vertex Shader

Un vertex shader en HLSL té una estructura bàsica que inclou:

  1. Entrades: Les dades d'entrada per al shader, com les posicions dels vèrtexs.
  2. Sortides: Les dades de sortida que es passaran a la següent etapa de la pipeline.
  3. Funció principal: La funció que defineix les operacions a realitzar sobre cada vèrtex.

Exemple Bàsic

A continuació, es mostra un exemple bàsic d'un vertex shader que transforma les posicions dels vèrtexs utilitzant una matriu de transformació:

// Estructura d'entrada
struct VS_INPUT
{
    float4 Pos : POSITION; // Posició del vèrtex
};

// Estructura de sortida
struct VS_OUTPUT
{
    float4 Pos : SV_POSITION; // Posició transformada del vèrtex
};

// Matriu de transformació
cbuffer Transform : register(b0)
{
    matrix WorldViewProj;
};

// Funció principal del vertex shader
VS_OUTPUT main(VS_INPUT input)
{
    VS_OUTPUT output;
    output.Pos = mul(input.Pos, WorldViewProj); // Transformar la posició del vèrtex
    return output;
}

Explicació del Codi

  • Estructura d'entrada (VS_INPUT): Defineix les dades d'entrada per al shader. En aquest cas, només inclou la posició del vèrtex.
  • Estructura de sortida (VS_OUTPUT): Defineix les dades de sortida del shader. Inclou la posició transformada del vèrtex.
  • Matriu de transformació (cbuffer Transform): Una matriu que s'utilitza per transformar les posicions dels vèrtexs. Es declara com un constant buffer.
  • Funció principal (main): La funció que s'executa per cada vèrtex. Transforma la posició del vèrtex utilitzant la matriu de transformació i retorna la posició transformada.

Integració en una Aplicació DirectX

Per utilitzar el vertex shader en una aplicació DirectX, hem de compilar el shader i configurar la pipeline de renderització per utilitzar-lo.

Compilar el Shader

Utilitzem la funció D3DCompileFromFile per compilar el shader des d'un fitxer:

ID3DBlob* vertexShaderBlob = nullptr;
ID3DBlob* errorBlob = nullptr;

HRESULT hr = D3DCompileFromFile(
    L"VertexShader.hlsl", // Nom del fitxer del shader
    nullptr,              // Definicions de macros
    nullptr,              // Incloure fitxers
    "main",               // Nom de la funció principal
    "vs_5_0",             // Perfil del shader
    0,                    // Flags de compilació
    0,                    // Flags d'efectes
    &vertexShaderBlob,    // Blob del shader compilat
    &errorBlob            // Blob d'errors
);

if (FAILED(hr))
{
    if (errorBlob)
    {
        OutputDebugStringA((char*)errorBlob->GetBufferPointer());
        errorBlob->Release();
    }
    if (vertexShaderBlob)
    {
        vertexShaderBlob->Release();
    }
    return hr;
}

Crear el Vertex Shader

Un cop compilat el shader, creem el vertex shader object:

ID3D11VertexShader* vertexShader = nullptr;
hr = device->CreateVertexShader(
    vertexShaderBlob->GetBufferPointer(),
    vertexShaderBlob->GetBufferSize(),
    nullptr,
    &vertexShader
);

if (FAILED(hr))
{
    vertexShaderBlob->Release();
    return hr;
}

Configurar la Pipeline

Finalment, configurem la pipeline de renderització per utilitzar el vertex shader:

context->VSSetShader(vertexShader, nullptr, 0);

Exercici Pràctic

Exercici

Escriu un vertex shader que, a més de transformar la posició dels vèrtexs, també passi el color del vèrtex a la següent etapa de la pipeline.

Solució

// Estructura d'entrada
struct VS_INPUT
{
    float4 Pos : POSITION; // Posició del vèrtex
    float4 Color : COLOR;  // Color del vèrtex
};

// Estructura de sortida
struct VS_OUTPUT
{
    float4 Pos : SV_POSITION; // Posició transformada del vèrtex
    float4 Color : COLOR;     // Color del vèrtex
};

// Matriu de transformació
cbuffer Transform : register(b0)
{
    matrix WorldViewProj;
};

// Funció principal del vertex shader
VS_OUTPUT main(VS_INPUT input)
{
    VS_OUTPUT output;
    output.Pos = mul(input.Pos, WorldViewProj); // Transformar la posició del vèrtex
    output.Color = input.Color;                 // Passar el color del vèrtex
    return output;
}

Conclusió

En aquest tema, hem après a escriure un vertex shader bàsic utilitzant HLSL. Hem vist com transformar les posicions dels vèrtexs i com integrar el shader en una aplicació DirectX. Els vertex shaders són una eina poderosa per manipular vèrtexs i crear efectes visuals avançats. En els següents temes, explorarem altres tipus de shaders i tècniques avançades de renderització.

Proper Tema: Escriure Pixel Shaders

© Copyright 2024. Tots els drets reservats