1. Nascita del linguaggio HLSL e la sua sintassi

5
Il tuo voto: Nessuno Media: 5 (2 voti)

L'HLSL, acronimo di High Level Shading Language, nasce come linguaggio di alto livello per la programmazione di shader complessi; prima della sua apparizione gli shader erano codificati in assembly specifico delle GPU (analogo a quello utilizzato dalle CPU di qualsiasi computer). Possiamo quindi vedere l'HLSL come il linguaggio C appositamente pensato per gli acceleratori grafici. Da questo linguaggio eredita infatti gran parte della sintassi come: la definizione di funzioni, l'utilizzo di blocchi condizionali, la definizione di espressioni matematiche, ecc... mentre proprie dell'HLSL sono parole chiave specifiche per la definizione di vettori, matrici, textures, samplers e altri componeneti specifici di una pipeline grafica.

Nelle librerie DirectX, e quindi in XNA, il linguaggio HLSL è utilzzato per scrivere i file .fx che incapsulano al loro interno una o più tecniche di shading. Ogni tecnica include sempre almeno un Pixel Shader, ma nella maggior parte dei casi è necessario anche un Vertex Shader e, in opzione, dei flags che indicano proprietà della rendering-pipeline come l'abilitazione/diabilitazione di: z-buffer, stencil-buffer, alpha blending, backface-culling ecc... noti come RenderState.

Un Vertex Shader è una funzione che riceve come input uno stream di vertici, delle matrici di trasformazione e, in opzione, altre variabili di vario tipo definite dall'utente. Possiamo quindi vedere un Vertex Shader come un frammento di codice che si occupa principalmente di trasformare i vertici proiettandoli sullo schermo e di passare altre informazioni utili al Pixel Shader.

In realtà è utile sapere che tra i dati processati da un Vertex Shader e quelli acquisiti da un Pixel Shader esiste uno step intermedio chiamato rasterizzazione, proccesso per cui della grafica vettoriale (in questo caso triangoli o linee) viene scomposta in linee di scansione e in pixels. I valori che escono dal Vertex Shader vengono quindi interpolati per tutta la superficie della primitiva grafica rendendoli disponibili al Pixel Shader.

Un Pixel Shader, dal canto suo, prende come input i dati provenienti dalla rasterizzazione e, per ogni pixel facente parte della primitiva grafica, esegue il frammento di codice da noi specificato. In questo frammento in genere si effettuano calcoli di ombraggiatura (shading) e di lettura dei texel dalla textures (texel deriva da texture element, in pratica il pixel di un a texture) in modo da generare l'immagine finale, o un suo step intermedio per le tecniche che prevedono più passaggi.

È da notare che con l'evoluzione esponenziale delle GPU gli shader si stanno generalizzando sempre più (vedi nVidia CUDA), e che l'utilizzo descritto è solamente quello standard, ma anche il più utile, soprattutto per chi si avvicina per la prima volta a questo mondo.