Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
API Importanti
Dopo aver spostato il codice che crea e configura i buffer e gli oggetti shader, è il momento di convertire il codice all'interno di tali shader dal linguaggio GL Shader (GLSL) di OpenGL ES 2.0 a Direct3D 11 High Level Shader Language (HLSL).
In OpenGL ES 2.0 gli shader restituiscono dati dopo l'esecuzione usando oggetti intrinseci come gl_Position, gl_FragColoro gl_FragData[n] (dove n è l'indice per una destinazione di rendering specifica). In Direct3D non esistono funzioni intrinseche specifiche e gli shader restituiscono dati come tipo di ritorno delle rispettive funzioni main().
I dati da interpolare tra le fasi dello shader, ad esempio la posizione del vertice o la normale, vengono gestiti tramite l'uso della dichiarazione varying. Tuttavia, Direct3D non ha questa dichiarazione; i dati che si desidera passare tra le fasi dello shader devono invece essere contrassegnati con un semantico HLSL. La semantica specifica scelta indica lo scopo dei dati e è . Ad esempio, si dichiarano i dati dei vertici che si desidera interpolare tra il vertex shader e il fragment shader come:
float4 vertPos : POSITION;
o
float4 vertColor : COLOR;
Dove POSITION è la semantica usata per indicare i dati di posizione dei vertici. POSITION è anche un caso speciale, poiché dopo l'interpolazione non è possibile accedervi dal pixel shader. Pertanto, è necessario specificare l'input per il pixel shader con SV_POSITION e i dati dei vertici interpolati verranno inseriti in tale variabile.
float4 position : SV_POSITION;
La semantica può essere dichiarata nei metodi body (main) degli shader. Per i pixel shader, SV_TARGET[n], che indica una destinazione di rendering, è obbligatorio nel metodo body. (SV_TARGET senza un suffisso numerico utilizza per impostazione predefinita l'indice di destinazione di rendering 0.)
Si noti anche che i vertex shader sono necessari per restituire la semantica del valore di sistema SV_POSITION. Questa semantica risolve i dati della posizione dei vertici in valori di coordinate in cui x è compreso tra -1 e 1, y è compreso tra -1 e 1, z è diviso per il valore w omogeneo originale (z/w) e w è 1 diviso per il valore w originale (1/w). I pixel shaders utilizzano la semantica del valore di sistema SV_POSITION per recuperare la posizione del pixel sullo schermo, dove x è tra 0 e la larghezza del target di rendering e y è tra 0 e l'altezza del target di rendering, entrambi con un offset di 0,5. I livelli di funzionalità 9_x dei pixel shader non possono leggere dal valore SV_POSITION.
I buffer costanti devono essere dichiarati con cbuffer ed essere associati a un registro iniziale specifico per la ricerca.
Direct3D 11: una dichiarazione di un buffer costante HLSL
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix mvp;
};
In questo caso, il buffer costante usa il registro b0 per contenere il buffer compresso. Tutti i registri sono indicati nel formato b#. Per ulteriori informazioni sull'implementazione HLSL di buffer costanti, registri e impacchettamento dei dati, consulta Costanti shader (HLSL).
Disposizioni
Passaggio 1: Portare il vertex shader
Nell'esempio semplice di OpenGL ES 2.0, il vertex shader ha tre input: una matrice 4x4 costante di model-view-projection e due vettori a 4 coordinate. Questi due vettori contengono la posizione del vertice e il relativo colore. Lo shader trasforma il vettore di posizione in coordinate prospettiche e lo assegna al gl_Position intrinseco per la rasterizzazione. Il colore del vertice viene copiato anche in una variabile variabile per l'interpolazione durante la rasterizzazione.
OpenGL ES 2.0: Vertex shader per l'oggetto cubo (GLSL)
uniform mat4 u_mvpMatrix;
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 destColor;
void main()
{
gl_Position = u_mvpMatrix * a_position;
destColor = a_color;
}
A questo punto, in Direct3D la matrice costante model-view-projection è contenuta in un buffer costante compresso in corrispondenza del registro b0 e la posizione e il colore dei vertici sono contrassegnati specificamente con la rispettiva semantica HLSL appropriata: POSITION e COLOR. Poiché il layout di input indica una disposizione specifica di questi due valori di vertice, crei una struct per tenerli e dichiararla come tipo per il parametro di input nella funzione principale dello shader (main). È anche possibile specificarli come due parametri separati, ma questo potrebbe risultare complesso. Devi anche specificare un tipo di output per questa fase, che contiene la posizione e il colore interpolati e lo dichiari come valore restituito per la funzione principale del vertex shader.
Direct3D 11: Shader di vertice per l'oggetto cubo (HLSL)
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix mvp;
};
// Per-vertex data used as input to the vertex shader.
struct VertexShaderInput
{
float3 pos : POSITION;
float3 color : COLOR;
};
// Per-vertex color data passed through the pixel shader.
struct PixelShaderInput
{
float3 pos : SV_POSITION;
float3 color : COLOR;
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f); // add the w-coordinate
pos = mul(mvp, projection);
output.pos = pos;
output.color = input.color;
return output;
}
Il tipo di dati di output, PixelShaderInput, viene popolato durante la rasterizzazione e fornito allo shader di frammento (pixel).
Passaggio 2: Portare il fragment shader
Il frammento shader di esempio in GLSL è estremamente semplice: fornire il gl_FragColor intrinseco con il valore del colore interpolato. OpenGL ES 2.0 lo scriverà nella destinazione di rendering predefinita.
OpenGL ES 2.0: fragment shader per l'oggetto cubo (GLSL)
varying vec4 destColor;
void main()
{
gl_FragColor = destColor;
}
Direct3D è quasi semplice. L'unica differenza significativa è che la funzione body del pixel shader deve restituire un valore. Poiché il colore è un valore float a 4 coordinate (RGBA), si indica float4 come tipo restituito e quindi si specifica la destinazione di rendering predefinita come semantica del valore di sistema SV_TARGET.
Direct3D 11: Shader di pixel per l'oggetto a forma di cubo (HLSL)
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color, 1.0f);
}
Il colore per il pixel alla posizione specificata viene scritto nel target di rendering. Vediamo ora come visualizzare il contenuto della destinazione di rendering in Disegnare sullo schermo!
Passaggio precedente
Trasferisci i buffer di vertici e i dati
Passo successivo
Osservazioni:
Comprendere la semantica HLSL e l'impacchettamento dei buffer costanti può ridurre i problemi legati al debug, oltre a offrire opportunità di ottimizzazione. Se hai l'opportunità, leggi Sintassi delle variabili (HLSL), Introduzione ai buffer in Direct3D 11e Creare un buffer costante. In caso contrario, ecco alcuni suggerimenti iniziali da tenere presenti sulla semantica e sui buffer costanti:
- Controllare sempre due volte il codice di configurazione Direct3D del renderer per assicurarsi che le strutture per i buffer costanti corrispondano alle dichiarazioni delle struct cbuffer nell'HLSL e che i tipi scalari dei componenti siano coerenti in entrambe le dichiarazioni.
- Nel codice C++ del renderer usare tipi di DirectXMath nelle dichiarazioni di buffer costanti per garantire la compressione corretta dei dati.
- Il modo migliore per usare in modo efficiente i buffer costanti consiste nell'organizzare le variabili shader in buffer costanti in base alla frequenza di aggiornamento. Ad esempio, se si dispone di dati uniformi che vengono aggiornati una volta per fotogramma e altri dati uniformi aggiornati solo quando la fotocamera si sposta, prendere in considerazione la separazione dei dati in due buffer costanti separati.
- La semantica che hai dimenticato di applicare o che hai applicato erroneamente sarà la prima fonte di errori di compilazione shader (FXC). Controllali due volte! La documentazione può creare confusione, poiché molte pagine e esempi meno recenti fanno riferimento a versioni diverse della semantica HLSL prima di Direct3D 11.
- Assicurati di conoscere il livello di funzionalità Direct3D che desideri utilizzare per ogni shader. La semantica per il livello di funzionalità 9_* è diversa da quella per 11_1.
- La semantica SV_POSITION risolve i dati della posizione post-interpolazione associata in valori di coordinate in cui x è compreso tra 0 e la larghezza della destinazione di rendering, y è compreso tra 0 e l'altezza della destinazione di rendering, z viene diviso per il valore w omogeneo originale (z/w) e w è 1 diviso per il valore w originale (1/w).
Argomenti correlati
Come portare un semplice renderer OpenGL ES 2.0 su Direct3D 11
Trasferisci i buffer di vertici e i dati