Condividi tramite


Informazioni di riferimento sulla conversione da GLSL a HLSL

Convertire il codice OpenGL Shader Language (GLSL) nel codice Microsoft High Level Shader Language (HLSL) quando si converte l'architettura grafica da OpenGL ES 2.0 a Direct3D 11 per creare un gioco per piattaforma UWP (Universal Windows Platform). Il GLSL a cui si fa riferimento in questo documento è compatibile con OpenGL ES 2.0; HLSL è compatibile con Direct3D 11. Per informazioni sulle differenze tra Direct3D 11 e le versioni precedenti di Direct3D, vedere Mapping delle funzionalità.

Confronto tra OpenGL ES 2.0 e Direct3D 11

OpenGL ES 2.0 e Direct3D 11 condividono molte caratteristiche. Entrambi hanno pipeline di rendering e funzionalità grafiche simili. Ma Direct3D 11 è un'implementazione del rendering e un'API, non una specifica; OpenGL ES 2.0 è una specifica di rendering e un'API, non un'implementazione. Direct3D 11 e OpenGL ES 2.0 in genere differiscono in questi modi:

OpenGL ES 2.0 Direct3D 11
Specifica indipendente dall'hardware e dal sistema operativo con implementazioni direttamente dal fornitore Implementazione Microsoft dell'astrazione hardware e certificazione nelle piattaforme Windows
Astratto per diversità hardware, il runtime gestisce la maggior parte delle risorse Accesso diretto al layout hardware; l'app può gestire le risorse e l'elaborazione
Fornisce moduli di livello superiore tramite librerie di terze parti (ad esempio Simple DirectMedia Layer, SDL) I moduli di livello superiore, ad esempio Direct2D, sono basati su moduli inferiori per semplificare lo sviluppo per le app di Windows
I fornitori di hardware si differenziano per via delle estensioni Microsoft aggiunge funzionalità facoltative all'API in modo generico, in modo che non siano specifiche di alcun fornitore hardware

 

GLSL e HLSL in genere differiscono in questi modi:

GLSL HLSL
Procedurale, incentrato sui passaggi (come C) Orientato agli oggetti, incentrato sui dati (come C++)
Compilazione shader integrata nell'API grafica Il compilatore HLSL compila lo shader in una rappresentazione binaria intermedia prima che Direct3D lo passi al driver.
Nota Questa rappresentazione binaria è indipendente dall'hardware. In genere viene compilato in fase di compilazione, anziché in fase di runtime.
 
Modificatori di archiviazione variabili Buffer costanti e trasferimenti di dati tramite dichiarazioni di layout di input

Tipi

Tipo di vettore tipico: vec2/3/4

lowp, mediump, highp

Tipo vettore tipico: float2/3/4

min10float, min16float

texture2D [Function] texture.Sample [datatype.Function]
sampler2D [datatype] Texture2D [datatype]
Matrici principali di riga (impostazione predefinita) Matrici principali di colonna (impostazione predefinita)
Nota Usare il modificatore di tipo row_major per modificare il layout per una variabile. Per maggiori informazioni, vedere Sintassi delle variabili. È anche possibile specificare un flag del compilatore o un pragma per modificare l'impostazione predefinita globale.
 
Fragment shader Pixel shader

 

Nota HLSL include texture e campionatori come due oggetti separati. In GLSL, ad esempio Direct3D 9, l'associazione di texture fa parte dello stato del campionatore.

 

In GLSL gran parte dello stato OpenGL viene presentato in forma di variabili globali predefinite. Ad esempio, con GLSL si usa la variabile gl_Position per specificare la posizione dei vertici e la variabile gl_FragColor per specificare il colore del frammento. In HLSL si passa lo stato Direct3D in modo esplicito dal codice dell'app allo shader. Ad esempio, con Direct3D e HLSL, l'input per il vertex shader deve corrispondere al formato dei dati nel buffer dei vertici e la struttura di un buffer costante nel codice dell'app deve corrispondere alla struttura di un buffer costante (cbuffer) nel codice dello shader.

Conversione di variabili GLSL in HLSL

In GLSL si applicano modificatori (qualificatori) a una dichiarazione di variabile shader globale per assegnare a tale variabile un comportamento specifico negli shader. In HLSL non sono necessari questi modificatori perché si definisce il flusso dello shader con gli argomenti passati allo shader e restituiti dallo shader.

Comportamento delle variabili GLSL Equivalente HLSL

uniform

Si passa una variabile uniforme dal codice dell'app in uno o entrambi i vertex shader e fragment shader. È necessario impostare i valori di tutte le uniformi prima di disegnare qualsiasi triangolo con tali shader in modo che i relativi valori rimangano invariati durante il disegno di una mesh di triangoli. Questi valori sono uniformi. Alcune uniformi sono impostate per l'intero frame e altre in modo univoco su una particolare coppia vertex-pixel shader.

Le variabili uniformi sono variabili per poligono.

Usare il buffer costante.

Vedere Procedura: Creare un buffer costante e costanti shader.

varying

Inizializzare una variabile varying all'interno del vertex shader e passarla a una variabile varying con nome identico nel frammento shader. Poiché il vertex shader imposta solo il valore delle variabili varying in ogni vertice, il rasterizzatore interpola tali valori (in modo prospetticamente corretto) per generare valori per frammento da passare al fragment shader. Queste variabili variano in ogni triangolo.

Usare la struttura restituita dal vertex shader come input per il pixel shader. Assicurarsi che i valori semantici corrispondano.

attribute

Un attributo fa parte della descrizione di un vertice passato dal codice dell'app al vertex shader da solo. A differenza di un'uniforme, si imposta il valore di ogni attributo per ogni vertice, che a sua volta consente a ogni vertice di avere un valore diverso. Le variabili di attributo sono variabili per vertice.

Definire un buffer dei vertici nel codice dell'app Direct3D e abbinarlo all'input del vertice definito nel vertex shader. Facoltativamente, definire un buffer degli indici. Vedere Procedura: Creare un vertex Buffer e Procedura: Creare un buffer degli indici.

Creare un layout di input nel codice dell'app Direct3D e associare i valori semantici a quelli nell'input del vertice. Vedere Creare il layout di input.

const

Costanti compilate nello shader e che non cambiano mai.

Usare un const statico. static indica che il valore non è esposto ai buffer costanti, const significa che lo shader non può modificare il valore. Pertanto, il valore è noto in fase di compilazione in base al relativo inizializzatore.

 

In GLSL le variabili senza modificatori sono solo variabili globali normali private per ogni shader.

Quando si passano i dati alle texture (Texture2D in HLSL) e ai relativi campionatori associati (SamplerState in HLSL), in genere li si dichiara come variabili globali nel pixel shader.

Conversione di tipi GLSL in HLSL

Usare questa tabella per convertire i tipi GLSL in HLSL.

Tipo di GLSL Tipo di HLSL
tipi scalari: float, int, bool

tipi scalari: float, int, bool

anche uint, double

Per maggiori informazioni, vedere Tipi scalari.

tipo di vettore

  • vettore a virgola mobile: vec2, vec3, vec4
  • Vettore booleano: bvec2, bvec3, bvec4
  • vettore integer firmato: ivec2, ivec3, ivec4

tipo di vettore

  • float2, float3, float4 e float1
  • bool2, bool3, bool4 e bool1
  • int2, int3, int4 e int1
  • Questi tipi hanno anche espansioni vettoriali simili a float, bool e int:

    • uint
    • min10float, min16float
    • min12int, min16int
    • min16uint

Per maggiori informazioni, vedere Tipo di vettore e Parole chiave.

vector è anche un tipo definito come float4 (typedef vector <float, 4> vector;). Per maggiori informazioni, vedere Tipo definito dall'utente.

tipo matrice

  • mat2: matrice float 2x2
  • mat3: matrice float 3x3
  • mat4: matrice float 4x4

tipo matrice

  • float2x2
  • float3x3
  • float4x4
  • anche float1x1, float1x2, float1x3, float1x4, float2x1, float2x3, float2x4, float3x1, float3x2, float3x4, float4x1, float4x2, float4x3
  • Questi tipi hanno anche espansioni di matrice simili a float:

    • int, uint, bool
    • min10float, min16float
    • min12int, min16int
    • min16uint

È anche possibile usare il tipo matrice per definire una matrice.

Ad esempio: matrix <float, 2, 2> fMatrix = {0.0f, 0.1, 2.1f, 2.2f};

matrix è anche un tipo definito come float4x4 (matrix <typedef float, 4, 4> matrix;). Per maggiori informazioni, vedere Tipo definito dall'utente.

qualificatori di precisione per float, int, sampler

  • highp

    Questo qualificatore fornisce requisiti minimi di precisione maggiori di quelli forniti da min16float e minori di un float a 32 bit completo. Equivalente in HLSL è:

    highp float -> float

    highp int -> int

  • mediump

    Questo qualificatore applicato a float e int equivale a min16float e min12int in HLSL. Minimo 10 bit di mantissa, non come min10float.

  • lowp

    Questo qualificatore applicato a float fornisce un intervallo a virgola mobile compreso tra -2 e 2. Equivalente a min10float in HLSL.

tipi di precisione

  • min16float: valore minimo a virgola mobile a 16 bit
  • min10float

    Valore minimo a virgola fissa con segno a 2.8 bit (2 bit di numero intero e componente frazionaria a 8 bit). Il componente frazionario a 8 bit può essere inclusivo di 1 anziché esclusivo per assegnargli l'intervallo inclusivo completo compreso tra -2 e 2.

  • min16int: intero con segno a 16 bit minimo
  • min12int: intero con segno a 12 bit minimo

    Questo tipo è per 10Level9 (9_x livelli di funzionalità) in cui i numeri interi sono rappresentati da numeri a virgola mobile. Questa è la precisione ottenibile quando si emula un intero con un numero a virgola mobile a 16 bit.

  • min16uint: intero senza segno a 16 bit minimo

Per maggiori informazioni, vedere Tipi scalari e Uso della precisione minima HLSL.

sampler2D Texture2D
samplerCube TextureCube

 

Conversione di variabili globali predefinite GLSL in HLSL

Usare questa tabella per convertire le variabili globali predefinite GLSL in HLSL.

Variabile globale predefinita GLSL Semantica HLSL

gl_Position

Questa variabile è di tipo vec4.

Posizione del vertice

ad esempio - gl_Position = position;

SV_Position

POSITION in Direct3D 9

Questa semantica è di tipo float4.

Output del vertex shader

Posizione del vertice

ad esempio - float4 vPosition : SV_Position;

gl_PointSize

Questa variabile è di tipo float.

Dimensione del punto

PSIZE

Nessun significato a meno di non destinare a Direct3D 9

Questa semantica è di tipo float.

Output del vertex shader

Dimensione del punto

gl_FragColor

Questa variabile è di tipo vec4.

Colore del frammento

ad esempio - gl_FragColor = vec4(colorVarying, 1,0);

SV_Target

COLOR in Direct3D 9

Questa semantica è di tipo float4.

Output del pixel shader

Colore del pixel

ad esempio - float4 Color[4] : SV_Target;

gl_FragData[n]

Questa variabile è di tipo vec4.

Colore del frammento per l'allegato colore n

SV_Target[n]

Questa semantica è di tipo float4.

Valore di output del pixel shader archiviato in destinazione di rendering n, dove 0 <= n <= 7.

gl_FragCoord

Questa variabile è di tipo vec4.

Posizione del frammento all'interno del buffer di frame

SV_Position

Non disponibile in Direct3D 9

Questa semantica è di tipo float4.

Input del pixel shader

Coordinate dello spazio dello schermo

ad esempio - float4 screenSpace : SV_Position

gl_FrontFacing

Questa variabile è di tipo bool.

Determina se il frammento appartiene a una primitiva rivolta verso il lato anteriore.

SV_IsFrontFace

VFACE in Direct3D 9

SV_IsFrontFace è di tipo bool.

VFACE è di tipo float.

Input del pixel shader

Direzione della primitiva

gl_PointCoord

Questa variabile è di tipo vec2.

Posizione del frammento all'interno di un punto (solo rasterizzazione del punto)

SV_Position

VPOS in Direct3D 9

SV_Position è di tipo float4.

VPOS è di tipo float2.

Input del pixel shader

Posizione del pixel o del campione nello spazio dello schermo

ad esempio - float4 pos : SV_Position

gl_FragDepth

Questa variabile è di tipo float.

Dati del buffer di profondità

SV_Depth

DEPTH in Direct3D 9

SV_Depth è di tipo float.

Output del pixel shader

Dati del buffer di profondità

 

Si usa la semantica per specificare la posizione, il colore e così via per l'input del vertex shader e del pixel shader. È necessario corrispondere ai valori semantici nel layout di input con l'input del vertex shader. Per esempi, vedere Esempi di conversione di variabili GLSL in HLSL. Per maggiori informazioni sulla semantica HLSL, vedere Semantica.

Esempi di conversione di variabili GLSL in HLSL

Di seguito vengono illustrati esempi di uso delle variabili GLSL nel codice OpenGL/GLSL e quindi dell'esempio equivalente nel codice Direct3D/HLSL.

Uniform, attribute e varying in GLSL

Codice app OpenGL

// Uniform values can be set in app code and then processed in the shader code.
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

// Incoming position of vertex
attribute vec4 position;
 
// Incoming color for the vertex
attribute vec3 color;
 
// The varying variable tells the shader pipeline to pass it  
// on to the fragment shader.
varying vec3 colorVarying;

Codice vertex shader GLSL

//The shader entry point is the main method.
void main()
{
colorVarying = color; //Use the varying variable to pass the color to the fragment shader
gl_Position = position; //Copy the position to the gl_Position pre-defined global variable
}

Codice del fragment shader GLSL

void main()
{
//Pad the colorVarying vec3 with a 1.0 for alpha to create a vec4 color
//and assign that color to the gl_FragColor pre-defined global variable
//This color then becomes the fragment's color.
gl_FragColor = vec4(colorVarying, 1.0);
}

Buffer costanti e trasferimenti di dati in HLSL

Di seguito è riportato un esempio di come si passano dati al vertex shader HLSL che passa quindi attraverso il pixel shader. Nel codice dell'app, definire un vertice e un buffer costante. Quindi, nel codice del vertex shader, definire il buffer costante come cbuffer e archiviare i dati per vertice e i dati di input del pixel shader. Qui si usano strutture chiamate VertexShaderInput e PixelShaderInput.

Codice app Direct3D

struct ConstantBuffer
{
    XMFLOAT4X4 model;
    XMFLOAT4X4 view;
    XMFLOAT4X4 projection;
};
struct SimpleCubeVertex
{
    XMFLOAT3 pos;   // position
    XMFLOAT3 color; // color
};

 // Create an input layout that matches the layout defined in the vertex shader code.
 const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
 {
     { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     { "COLOR",    0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
 };

// Create vertex and index buffers that define a geometry.

Codice vertex shader HLSL

cbuffer ModelViewProjectionCB : register( b0 )
{
    matrix model; 
    matrix view;
    matrix projection;
};
// The POSITION and COLOR semantics must match the semantics in the input layout Direct3D app code.
struct VertexShaderInput
{
    float3 pos : POSITION; // Incoming position of vertex 
    float3 color : COLOR; // Incoming color for the vertex
};

struct PixelShaderInput
{
    float4 pos : SV_Position; // Copy the vertex position.
    float4 color : COLOR; // Pass the color to the pixel shader.
};

PixelShaderInput main(VertexShaderInput input)
{
    PixelShaderInput vertexShaderOutput;

    // shader source code

    return vertexShaderOutput;
}

Codice pixel shader HLSL

// Collect input from the vertex shader. 
// The COLOR semantic must match the semantic in the vertex shader code.
struct PixelShaderInput
{
    float4 pos : SV_Position;
    float4 color : COLOR; // Color for the pixel
};

// Set the pixel color value for the renter target. 
float4 main(PixelShaderInput input) : SV_Target
{
    return input.color;
}

Esempi di conversione del codice di rendering OpenGL in Direct3D

Di seguito viene illustrato un esempio di rendering nel codice OpenGL ES 2.0 e quindi nell'esempio equivalente nel codice Direct3D 11.

Codice di rendering OpenGL

// Bind shaders to the pipeline. 
// Both vertex shader and fragment shader are in a program.
glUseProgram(m_shader->getProgram());
 
// Input assembly 
// Get the position and color attributes of the vertex.

m_positionLocation = glGetAttribLocation(m_shader->getProgram(), "position");
glEnableVertexAttribArray(m_positionLocation);

m_colorLocation = glGetAttribColor(m_shader->getProgram(), "color");
glEnableVertexAttribArray(m_colorLocation);
 
// Bind the vertex buffer object to the input assembler.
glBindBuffer(GL_ARRAY_BUFFER, m_geometryBuffer);
glVertexAttribPointer(m_positionLocation, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, m_colorBuffer);
glVertexAttribPointer(m_colorLocation, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 
// Draw a triangle with 3 vertices.
glDrawArray(GL_TRIANGLES, 0, 3);

Codice di rendering Direct3D

// Bind the vertex shader and pixel shader to the pipeline.
m_d3dDeviceContext->VSSetShader(vertexShader.Get(),nullptr,0);
m_d3dDeviceContext->PSSetShader(pixelShader.Get(),nullptr,0);
 
// Declare the inputs that the shaders expect.
m_d3dDeviceContext->IASetInputLayout(inputLayout.Get());
m_d3dDeviceContext->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &stride, &offset);

// Set the primitive's topology.
m_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

// Draw a triangle with 3 vertices. triangleVertices is an array of 3 vertices.
m_d3dDeviceContext->Draw(ARRAYSIZE(triangleVertices),0);