Share via


Informations de référence sur le passage de GLSL vers HLSL

Vous portez votre code GLSL (OpenGL Shader Language) vers le code HLSL (High Level Shader Language) de Microsoft lorsque vous transférez votre architecture graphique d’OpenGL ES 2.0 vers Direct3D 11 pour créer un jeu pour plateforme Windows universelle (UWP). Les exemples de cette rubrique utilisent du code GLSL et du code HLSL compatibles avec OpenGL ES 2.0 et avec Direct3D 11, respectivement. Pour plus d’informations sur les différences entre Direct3D 11 et les versions antérieures de Direct3D, voir Mappage des fonctionnalités.

Comparaison entre OpenGL ES 2.0 et Direct3D 11

OpenGL ES 2.0 et Direct3D 11 présentent de nombreuses similitudes. Ils offrent tous deux à peu près les mêmes pipelines de rendu et fonctionnalités graphiques. En revanche, alors que Direct3D 11 constitue une API et une implémentation de rendu, mais pas une spécification, OpenGL ES 2.0 est une spécification de rendu et une API, mais pas une implémentation. Direct3D 11 et OpenGL ES 2.0 diffèrent généralement sur les points suivants :

OpenGL ES 2.0 Direct3D 11
Spécification agnostique du matériel et du système d’exploitation avec des implémentations propres à chaque fournisseur Implémentation Microsoft de l’abstraction et de la certification matérielles sur les plateformes Windows
Gestion de la plupart des ressources par le runtime grâce à l’abstraction pour la diversité du matériel Accès direct à la disposition matérielle ; gestion des ressources et du traitement par l’application
Obtention de modules de niveau supérieur via des bibliothèques tierces, telles que Simple DirectMedia Layer (SDL) Construction des modules de niveau supérieur, comme Direct2D, à partir de modules de niveau inférieur pour simplifier le développement pour les applications Windows
Différenciation des fabricants de matériel par les extensions Ajout à l’API, par Microsoft, de fonctionnalités facultatives génériques, indépendantes des fabricants de matériel

 

GLSL et HLSL diffèrent généralement sur les points suivants :

GLSL HLSL
Langage procédural et orienté étape (type C) Langage orienté objet et centré sur les données (type C++)
Compilation des nuanceurs intégrée à l’API graphique Le compilateur HLSL compile le nuanceur en une représentation binaire intermédiaire, que Direct3D transmet ensuite au pilote.
Note Cette représentation binaire est indépendante du matériel. Elle est généralement compilée au moment de la création de l’application, plutôt qu’au moment de l’exécution de cette dernière.
 
Modificateurs de stockage des variables Mémoires tampons constantes et transferts de données via des déclarations de dispositions d’entrée

Types

Type de vecteur standard : vec2/3/4

lowp, mediump, highp

Type de vecteur standard : float2/3/4

min10float, min16float

texture2D [Function] texture.Sample [datatype.Function]
sampler2D [datatype] Texture2D [datatype]
Matrices row-major (par défaut) Matrices column-major (par défaut)
Note Utilisez le modificateur de type row_major pour modifier la disposition d’une variable. Pour plus d’informations, voir Syntaxe des variables. Vous pouvez aussi spécifier un indicateur de compilateur ou une instruction pragma pour modifier la configuration globale par défaut.
 
Nuanceur de fragments Nuanceur de pixels

 

Remarque HLSL expose les textures et les échantillonneurs dans deux objets distincts, alors que dans GLSL (Direct3D 9, par exemple), la liaison des textures est incluse dans l’état de l’échantillonneur.

 

Dans GLSL, l’état OpenGL est souvent présenté à l’aide de variables globales prédéfinies. Par exemple, avec GLSL, vous utilisez la variable gl_Position pour spécifier la position du vertex et la variable gl_FragColor pour spécifier la couleur du fragment. Dans HLSL, vous passez l’état Direct3D de manière explicite entre le code de l’application et le nuanceur. Par exemple, avec Direct3D et HLSL, les données d’entrée du nuanceur de vertex doivent être au même format que dans la mémoire tampon de vertex, tout comme la structure d’une mémoire tampon constante dans le code de l’application doit correspondre à la structure de mémoire tampon constante (cbuffer) indiquée dans le code du nuanceur.

Portage des variables GLSL vers HLSL

Dans GLSL, vous appliquez des modificateurs (qualificateurs) à la déclaration d’une variable de nuanceur globale lorsque vous souhaitez affecter à cette variable un comportement particulier dans vos nuanceurs. Dans HLSL, vous n’avez pas besoin de ces modificateurs, car vous définissez le flux du nuanceur à l’aide des arguments que vous passez au nuanceur et des arguments que celui-ci vous retourne.

Comportement des variables GLSL Équivalence HLSL

Uniforme

Vous passez une variable uniform du code de l’application au nuanceur de vertex et/ou au nuanceur de fragments. Vous devez définir les valeurs de toutes les variables uniform avant de dessiner des triangles avec ces nuanceurs. Ainsi, les valeurs ne changeront pas lors du processus de dessin d’un maillage de triangles. Ces valeurs sont uniformes. Certaines sont définies pour la trame entière, d’autres uniquement pour une paire spécifique de nuanceurs de vertex/pixels.

Les variables uniform s’appliquent au niveau de chaque polygone.

Utilisez une mémoire tampon constante.

Voir Procédure : Création d’une mémoire tampon constante et Constantes de nuanceur.

Variable

Vous initialisez une variable varying au sein du nuanceur de vertex, puis vous la passez à une variable varying de même nom dans le nuanceur de fragments. Le nuanceur de vertex définit la valeur des variables varying au niveau de chaque vertex. Par conséquent, le module de rastérisation effectue ensuite une interpolation de ces valeurs (en perspective) pour générer les valeurs de chaque fragment à passer au nuanceur de fragments. Ces variables diffèrent pour chaque triangle.

Utilisez la structure renvoyée par votre nuanceur de vertex comme structure d’entrée de votre nuanceur de pixels. Assurez-vous que les valeurs des sémantiques correspondent.

attribute

Un attribut est un élément de la description d’un vertex que vous passez du code de l’application au nuanceur de vertex (et seulement à lui). Contrairement à la variable uniform, vous définissez une variable attribute par vertex. Vous pouvez ainsi attribuer une valeur différente à chacun des vertex. Les variables attribute s’appliquent au niveau de chaque vertex.

Définissez une mémoire tampon de vertex dans le code de votre application Direct3D, puis mappez-la à l’entrée de vertex que vous avez définie dans le nuanceur de vertex. Vous pouvez éventuellement définir une mémoire tampon d’index. Voir Procédure : Création d’une mémoire tampon de vertex et Procédure : Création d’une mémoire tampon d’index.

Créez une disposition d’entrée dans le code de votre application Direct3D, puis mappez les valeurs de sémantiques à celles de l’entrée de vertex. Voir Créer la disposition d’entrée.

const

Les constantes sont compilées dans le nuanceur ; elles ne changent jamais.

Utilisez une constante static const. static signifie que la valeur n’est pas exposée à des mémoires tampons constantes, const signifie que le nuanceur ne peut pas modifier la valeur. La valeur est donc fournie au moment de la compilation, sur la base de l’initialiseur associé.

 

Dans GLSL, les variables sans modificateurs sont simplement des variables globales standards qui sont privées pour chaque nuanceur.

Lorsque vous transmettez des données à des textures (Texture2D dans HLSL) et à leurs échantillonneurs associés (SamplerState dans HLSL), vous les déclarez généralement en tant que variables globales dans le nuanceur de pixels.

Portage des types GLSL vers HLSL

Référez-vous au tableau ci-dessous lors du portage de vos types GLSL vers HLSL.

Type GLSL Type HLSL
Types scalaires : float, int, bool

Types scalaires : float, int, bool

(et uint, double)

Pour plus d’informations, voir Types scalaires.

Type vector

  • vecteur à virgule flottante : vec2, vec3, vec4
  • vecteur booléen : bvec2, bvec3, bvec4
  • vecteur avec entier signé : ivec2, ivec3, ivec4

Type vector

  • float2, float3, float4 et float1
  • bool2, bool3, bool4 et bool1
  • int2, int3, int4 et int1
  • Ces types comportent également des extensions de vecteur similaires aux types float, bool et int :

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

Pour plus d’informations, voir Type vector et Mots clés.

vector peut également être défini avec le type float4 (typedef vector <float, 4> vector;). Pour plus d’informations, voir Type défini par l’utilisateur.

Type matrix

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

Type matrix

  • float2x2
  • float3x3
  • float4x4
  • float1x1, float1x2, float1x3, float1x4, float2x1, float2x3, float2x4, float3x1, float3x2, float3x4, float4x1, float4x2, float4x3
  • Ces types comportent également des extensions de matrice similaires au type float :

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

Vous pouvez aussi définir une matrice avec le type matrix.

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

matrix peut également être défini avec le type float4x4 (typedef matrix <float, 4, 4> matrix;). Pour plus d’informations, voir Type défini par l’utilisateur.

Qualificateurs de précision pour les types float, int, sampler

  • highp

    Ce qualificateur fournit une précision minimale requise supérieure à celle des valeurs min16float, mais inférieure à celle des valeurs flottantes 32 bits. Équivalence HLSL :

    highp float -> float

    highp int -> int

  • mediump

    Ce qualificateur appliqué aux valeurs float et int équivaut aux valeurs min16float et min12int dans HLSL. Mantisse sur 10 bits au minimum, à la différence du type min10float.

  • lowp

    Ce qualificateur appliqué aux valeurs float fournit une plage de valeurs à virgule flottante comprises entre -2 et 2. Équivaut au type min10float dans HLSL.

Types de précision

  • min16float : valeur à virgule flottante sur 16 bits au minimum
  • min10float

    Valeur à virgule fixe signée sur 2,8 bits au minimum (2 bits pour la partie entière et 8 bits pour la partie fractionnaire). La partie fractionnaire sur 8 bits peut inclure la valeur 1, au lieu de l’exclure, afin de pouvoir attribuer n’importe quelle valeur de la plage de valeurs comprises entre -2 et 2.

  • min16int : entier signé sur 16 bits au minimum
  • min12int : entier signé 12 bits au minimum

    Ce type s’applique au niveau 10Level9 (voir les niveaux de fonctionnalité 9_x), où les entiers sont représentés par des valeurs à virgule flottante. C’est la précision que vous obtenez en émulant un entier avec une valeur à virgule flottante sur 16 bits.

  • min16uint : entier non signé 16 bits au minimum

Pour plus d’informations, voir Types scalaires et Utilisation de la précision HLSL minimale.

sampler2D Texture2D
samplerCube TextureCube

 

Portage des variables globales prédéfinies GLSL vers HLSL

Référez-vous au tableau ci-dessous lors du portage de vos variables globales prédéfinies GLSL vers HLSL.

Variable globale prédéfinie GLSL Sémantiques HLSL

gl_Position

Variable du type vec4.

Position du vertex

Exemple : - gl_Position = position;

SV_Position

POSITION dans Direct3D 9

Sémantique du type float4.

Sortie du nuanceur de vertex

Position du vertex

Exemple : - float4 vPosition : SV_Position;

gl_PointSize

Variable du type float.

Taille du point

PSIZE

Pas de signification hormis pour Direct3D 9

Sémantique du type float.

Sortie du nuanceur de vertex

Taille du point

gl_FragColor

Variable du type vec4.

Couleur du fragment

Exemple : - gl_FragColor = vec4(colorVarying, 1.0);

SV_Target

COLOR dans Direct3D 9

Sémantique du type float4.

Sortie du nuanceur de pixels

Couleur du pixel

Exemple : - float4 Color[4] : SV_Target;

gl_FragData[n]

Variable du type vec4.

Couleur du fragment pour l’association de couleur n

SV_Target[n]

Sémantique du type float4.

Valeur de la sortie du nuanceur de pixels qui est stockée dans la cible de rendu n, où 0 <= n <= 7.

gl_FragCoord

Variable du type vec4.

Position du fragment dans le tampon de trame

SV_Position

Non disponible dans Direct3D 9

Sémantique du type float4.

Entrée du nuanceur de pixels

Coordonnées de l’espace à l’écran

Exemple : - float4 screenSpace : SV_Position

gl_FrontFacing

Variable du type bool.

Détermine si le fragment appartient à une primitive de face.

SV_IsFrontFace

VFACE dans Direct3D 9

SV_IsFrontFace est du type bool.

VFACE est du type float.

Entrée du nuanceur de pixels

Primitive de face

gl_PointCoord

Variable du type vec2.

Position du fragment dans un point (rastérisation des points uniquement)

SV_Position

VPOS dans Direct3D 9

SV_Position est du type float4.

VPOS est du type float2.

Entrée du nuanceur de pixels

Position du pixel ou de l’échantillon dans l’espace à l’écran

Exemple : - float4 pos : SV_Position

gl_FragDepth

Variable du type float.

Données de la mémoire tampon de profondeur

SV_Depth

DEPTH dans Direct3D 9

SV_Depth est du type float.

Sortie du nuanceur de pixels

Données de la mémoire tampon de profondeur

 

Les sémantiques vous permettent de définir diverses valeurs (position, couleur, etc.) pour les données d’entrée du nuanceur de vertex et les données de sortie du nuanceur de pixels. Les valeurs de sémantiques définies dans la disposition d’entrée doivent correspondre aux données d’entrée du nuanceur de vertex. Pour plus d’informations, voir Exemples de portage de variables GLSL vers HLSL, ci-dessous. Pour plus d’informations sur les sémantiques HLSL, voir Sémantiques.

Exemples de portage de variables GLSL vers HLSL

Dans cette section, vous trouverez des exemples d’utilisation de variables GLSL dans le code OpenGL/GLSL, suivis des exemples équivalents pour le code Direct3D/HLSL.

Variables uniform, attribute et varying dans GLSL

Code de l’application 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;

Code GLSL du nuanceur de vertex

//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
}

Code GLSL du nuanceur de fragments

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);
}

Mémoires tampons constantes et transferts de données dans HLSL

Voici un exemple du processus de passage des données au nuanceur de vertex HLSL, puis au nuanceur de pixels. Dans le code de votre application, définissez un vertex et une mémoire tampon constante. Ensuite, dans le code de votre nuanceur de vertex, définissez la mémoire tampon constante avec la constante cbuffer, et enregistrez les données de vertex et les données d’entrée du nuanceur de pixels. Dans cet exemple, nous utilisons les structures VertexShaderInput et PixelShaderInput.

Code de l’application 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.

Code HLSL du nuanceur de vertex

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;
}

Code HLSL du nuanceur de pixels

// 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;
}

Exemples de portage du code de rendu OpenGL sur Direct3D

Vous trouverez ci-dessous un exemple de code de rendu pour OpenGL ES 2.0 et son équivalent pour Direct3D 11.

Code de rendu pour OpenGL

// Bind shaders to the pipeline. 
// Both vertex shader and fragment shader are in a program.
glUseProgram(m_shader->getProgram());
 
// Input asssembly 
// 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);

Code de rendu pour 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);