En aquest tema, aprendrem com compilar i utilitzar shaders en una aplicació DirectX. Els shaders són programes que s'executen en la GPU per realitzar operacions de renderització. En aquest mòdul, ens centrarem en els shaders de vèrtex i píxel, que són els més comuns.
- Introducció a la Compilació de Shaders
Què és la Compilació de Shaders?
La compilació de shaders és el procés de convertir el codi font del shader, escrit en un llenguatge com HLSL (High-Level Shading Language), en un format binari que la GPU pugui executar. Aquest procés es pot fer en temps de compilació o en temps d'execució.
Eines de Compilació
Per compilar shaders, utilitzarem el compilador de HLSL proporcionat per DirectX, conegut com a fxc.exe
. També podem utilitzar el compilador integrat en el SDK de DirectX.
- Escriure un Shader de Vèrtex i un Shader de Píxel
Exemple de Shader de Vèrtex
// Vertex Shader struct VS_INPUT { float4 Pos : POSITION; float4 Color : COLOR; }; struct PS_INPUT { float4 Pos : SV_POSITION; float4 Color : COLOR; }; PS_INPUT VS(VS_INPUT input) { PS_INPUT output; output.Pos = input.Pos; output.Color = input.Color; return output; }
Exemple de Shader de Píxel
// Pixel Shader struct PS_INPUT { float4 Pos : SV_POSITION; float4 Color : COLOR; }; float4 PS(PS_INPUT input) : SV_TARGET { return input.Color; }
- Compilar Shaders
Utilitzar fxc.exe
Podem compilar els shaders utilitzant la línia de comandes amb fxc.exe
. Aquí teniu un exemple de com compilar un shader de vèrtex i un shader de píxel:
fxc /T vs_5_0 /E VS /Fo VertexShader.cso VertexShader.hlsl fxc /T ps_5_0 /E PS /Fo PixelShader.cso PixelShader.hlsl
/T vs_5_0
especifica la versió del shader de vèrtex./E VS
especifica el punt d'entrada del shader de vèrtex./Fo VertexShader.cso
especifica el fitxer de sortida compilat.VertexShader.hlsl
és el fitxer de codi font del shader de vèrtex.
- Carregar i Utilitzar Shaders en DirectX
Carregar Shaders Compilats
Un cop tenim els shaders compilats, podem carregar-los en la nostra aplicació DirectX. Aquí teniu un exemple de com fer-ho en C++:
// Carregar el shader de vèrtex ID3DBlob* vertexShaderBlob; D3DReadFileToBlob(L"VertexShader.cso", &vertexShaderBlob); device->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &vertexShader); // Carregar el shader de píxel ID3DBlob* pixelShaderBlob; D3DReadFileToBlob(L"PixelShader.cso", &pixelShaderBlob); device->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &pixelShader);
Configurar el Pipeline de Renderització
Després de carregar els shaders, hem de configurar el pipeline de renderització per utilitzar-los:
// Configurar el shader de vèrtex context->VSSetShader(vertexShader, nullptr, 0); // Configurar el shader de píxel context->PSSetShader(pixelShader, nullptr, 0);
- Exercici Pràctic
Objectiu
Crea una aplicació DirectX que carregui i utilitzi un shader de vèrtex i un shader de píxel per renderitzar un triangle amb colors interpolats.
Passos
- Escriu els shaders de vèrtex i píxel en HLSL.
- Compila els shaders utilitzant
fxc.exe
. - Carrega els shaders compilats en la teva aplicació DirectX.
- Configura el pipeline de renderització per utilitzar els shaders.
- Renderitza un triangle amb colors interpolats.
Solució
// Vertex Shader (VertexShader.hlsl) struct VS_INPUT { float4 Pos : POSITION; float4 Color : COLOR; }; struct PS_INPUT { float4 Pos : SV_POSITION; float4 Color : COLOR; }; PS_INPUT VS(VS_INPUT input) { PS_INPUT output; output.Pos = input.Pos; output.Color = input.Color; return output; } // Pixel Shader (PixelShader.hlsl) struct PS_INPUT { float4 Pos : SV_POSITION; float4 Color : COLOR; }; float4 PS(PS_INPUT input) : SV_TARGET { return input.Color; } // Compilar els shaders // fxc /T vs_5_0 /E VS /Fo VertexShader.cso VertexShader.hlsl // fxc /T ps_5_0 /E PS /Fo PixelShader.cso PixelShader.hlsl // Codi C++ per carregar i utilitzar els shaders ID3DBlob* vertexShaderBlob; D3DReadFileToBlob(L"VertexShader.cso", &vertexShaderBlob); device->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &vertexShader); ID3DBlob* pixelShaderBlob; D3DReadFileToBlob(L"PixelShader.cso", &pixelShaderBlob); device->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &pixelShader); context->VSSetShader(vertexShader, nullptr, 0); context->PSSetShader(pixelShader, nullptr, 0); // Renderitzar el triangle // (Codi per configurar els buffers de vèrtex i índex, i per dibuixar el triangle)
Conclusió
En aquest tema, hem après com compilar i utilitzar shaders en una aplicació DirectX. Hem vist com escriure shaders de vèrtex i píxel en HLSL, com compilar-los utilitzant fxc.exe
, i com carregar-los i utilitzar-los en una aplicació DirectX. A més, hem realitzat un exercici pràctic per reforçar els conceptes apresos. En el proper tema, explorarem tècniques avançades de renderització.
Curs de Programació DirectX
Mòdul 1: Introducció a DirectX
- Què és DirectX?
- Configuració de l'Entorn de Desenvolupament
- Comprendre l'API de DirectX
- Crear la Teva Primera Aplicació DirectX
Mòdul 2: Conceptes Bàsics de Direct3D
- Introducció a Direct3D
- Inicialitzar Direct3D
- Renderitzar un Triangle
- Gestionar el Bucle de Renderització
Mòdul 3: Treballar amb Shaders
Mòdul 4: Tècniques Avançades de Renderització
Mòdul 5: Models 3D i Animació
Mòdul 6: Optimització del Rendiment
- Perfilat i Depuració
- Optimitzar el Rendiment de la Renderització
- Gestió de Memòria
- Multifil en DirectX