Partager via


Référence GLSL à HLSL

Vous portez votre code GLSL (OpenGL Shader Language) vers le code HLSL (High Level Shader Language) Microsoft lorsque vous portez votre architecture graphique d’OpenGL ES 2.0 vers Direct3D 11 pour créer un jeu pour plateforme Windows universelle (UWP). Le GLSL mentionné ici est compatible avec OpenGL ES 2.0 ; HLSL est compatible avec Direct3D 11. Pour plus d’informations sur les différences entre Direct3D 11 et les versions précédentes de Direct3D, consultez Mappage des fonctionnalités.

Comparaison d’OpenGL ES 2.0 avec Direct3D 11

OpenGL ES 2.0 et Direct3D 11 présentent de nombreuses similitudes. Ils ont tous deux des pipelines de rendu similaires et des fonctionnalités graphiques. Mais Direct3D 11 est une implémentation de rendu et une API, et non une spécification ; OpenGL ES 2.0 est une spécification de rendu et une API, et non une implémentation. Direct3D 11 et OpenGL ES ES 2.0 diffèrent généralement de ces façons :

OpenGL ES 2.0 Direct3D 11
Spécification indépendante du matériel et du système d’exploitation avec des implémentations fournies par le fournisseur Implémentation Microsoft de l’abstraction matérielle et de la certification sur les plateformes Windows
Abstrait pour la diversité matérielle, le runtime gère la plupart des ressources Accès direct à la disposition matérielle ; l’application peut gérer les ressources et le traitement
Fournit des modules de niveau supérieur via des bibliothèques tierces (par exemple, Simple DirectMedia Layer (SDL)) Les modules de niveau supérieur, comme Direct2D, sont basés sur des modules inférieurs pour simplifier le développement pour les applications Windows
Les fournisseurs de matériel se différencient par le biais d’extensions Microsoft ajoute des fonctionnalités facultatives à l’API de manière générique afin qu’elles ne soient pas spécifiques à un fournisseur de matériel particulier

 

GLSL et HLSL diffèrent généralement de ces façons :

GLSL HLSL
Procédure, centrée sur les étapes (C like) Orienté objet, centré sur les données (C++ comme)
Compilation du nuanceur intégrée à l’API graphique Le compilateur HLSL compile le nuanceur en une représentation binaire intermédiaire avant que Direct3D ne le passe au pilote.
Notez que cette représentation binaire est indépendante du matériel. Il est généralement compilé au moment de la génération de l’application, plutôt qu’au moment de l’exécution de l’application.
 
Modificateurs de stockage variable Mémoires tampons constantes et transferts de données via des déclarations de disposition d’entrée

Types

Type de vecteur classique : vec2/3/4

lowp, mediump, highp

Type de vecteur classique : float2/3/4

min10float, min16float

texture2D [Fonction] texture. Exemple [type de données. Fonction]
sampler2D [datatype] Texture2D [type de données]
Matrices principales de lignes (par défaut) Matrices principales de colonnes (par défaut)
Remarque : Utilisez le modificateur de type row_major pour modifier la disposition d’une variable. Pour plus d’informations, consultez Syntaxe des variables. Vous pouvez également spécifier un indicateur de compilateur ou un pragma pour modifier la valeur par défaut globale.
 
Nuanceur de fragments Nuanceur de pixels

 

Notez que HLSL a des textures et des échantillonneurs sous la forme de deux objets distincts. Dans GLSL, comme Direct3D 9, la liaison de texture fait partie de l’état de l’échantillonneur.

 

Dans GLSL, vous présentez une grande partie de l’état OpenGL en tant que variables globales prédéfinies. Par exemple, avec GLSL, vous utilisez la variable gl_Position pour spécifier la position de vertex et la variable gl_FragColor pour spécifier la couleur du fragment. Dans HLSL, vous passez explicitement l’état Direct3D du code de l’application au nuanceur. Par exemple, avec Direct3D et HLSL, l’entrée du nuanceur de vertex doit correspondre au format de données dans la mémoire tampon de vertex, et la structure d’une mémoire tampon constante dans le code de l’application doit correspondre à la structure d’une mémoire tampon constante (cbuffer) dans le code du nuanceur.

Portage des variables GLSL vers HLSL

Dans GLSL, vous appliquez des modificateurs (qualificateurs) à une déclaration de variable de nuanceur globale pour donner à cette variable un comportement spécifique dans vos nuanceurs. Dans HLSL, vous n’avez pas besoin de ces modificateurs, car vous définissez le flux du nuanceur avec les arguments que vous passez à votre nuanceur et que vous revenez de votre nuanceur.

Comportement des variables GLSL ÉQUIVALENT HLSL

uniforme

Vous transmettez une variable uniforme à partir du code de l’application dans les nuanceurs de vertex et de fragments. Vous devez définir les valeurs de tous les uniformes avant de dessiner des triangles avec ces nuanceurs afin que leurs valeurs restent les mêmes tout au long du dessin d’un maillage de triangles. Ces valeurs sont uniformes. Certains uniformes sont définis pour l’ensemble du cadre et d’autres sont uniques à une paire de nuanceurs de vertex-pixels particulière.

Les variables uniformes sont des variables par polygone.

Utilisez une mémoire tampon constante.

Découvrez comment : créer une mémoire tampon constante et des constantes de nuanceur.

variable

Vous initialisez une variable variable à l’intérieur du nuanceur de vertex et passez-la à une variable identique nommée dans le nuanceur de fragments. Étant donné que le nuanceur de vertex définit uniquement la valeur des variables variables à chaque vertex, le rastériseur interpole ces valeurs (de manière correcte dans la perspective) pour générer les valeurs par fragment à passer dans le nuanceur de fragments. Ces variables varient selon chaque triangle.

Utilisez la structure que vous revenez de votre nuanceur de vertex comme entrée à votre nuanceur de pixels. Vérifiez que les valeurs sémantiques correspondent.

attribute

Un attribut fait partie de la description d’un sommet que vous passez du code de l’application au nuanceur de vertex seul. Contrairement à un uniforme, vous définissez la valeur de chaque attribut pour chaque vertex, ce qui, à son tour, permet à chaque vertex d’avoir une valeur différente. Les variables d’attribut sont des variables par vertex.

Définissez une mémoire tampon de vertex dans votre code d’application Direct3D et faites-la correspondre à l’entrée de vertex définie dans le nuanceur de vertex. Si vous le souhaitez, définissez une mémoire tampon d’index. Découvrez comment : créer une mémoire tampon de vertex et comment : créer une mémoire tampon d’index.

Créez une disposition d’entrée dans votre code d’application Direct3D et faites correspondre les valeurs sémantiques avec celles de l’entrée de vertex. Consultez Créer la disposition d’entrée.

const

Constantes compilées dans le nuanceur et ne changent jamais.

Utilisez un const statique. statique signifie que la valeur n’est pas exposée aux mémoires tampons constantes, const signifie que le nuanceur ne peut pas modifier la valeur. Par conséquent, la valeur est connue au moment de la compilation en fonction de son initialiseur.

 

Dans GLSL, les variables sans modificateurs sont simplement des variables globales ordinaires privées à 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

Utilisez ce tableau pour porter vos types GLSL vers HLSL.

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

types scalaires : float, int, bool

également, uint, double

Pour plus d’informations, consultez Types scalaires.

type de vecteur

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

type de vecteur

  • float2, float3, float4 et float1
  • bool2, bool3, bool4 et bool1
  • int2, int3, int4 et int1
  • Ces types ont également des expansions vectorielles similaires à float, bool et int :

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

Pour plus d’informations, consultez Le type de vecteur et les mots clés.

vector est également un type défini comme float4 (typedef vector <float, 4> vector ;). Pour plus d’informations, consultez Type défini par l’utilisateur.

type de matrice

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

type de matrice

  • float2x2
  • float3x3
  • float4x4
  • aussi, float1x1, float1x2, float1x3, float1x4, float2x1, float2x3, float2x4, float3x1, float3x2, float3x4, float4x1, float4x2, float4x2, float4x3
  • Ces types ont également des expansions de matrice similaires à float :

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

Vous pouvez également utiliser le type de matrice pour définir une matrice.

Par exemple : float de matrice <, 2, 2> fMatrix = {0.0f, 0.1, 2.1f, 2.2f} ;

la matrice est également un type défini comme float4x4 (matrice <typedef float, 4, 4> matrice ;). Pour plus d’informations, consultez Type défini par l’utilisateur.

qualificateurs de précision pour float, int, sampler

  • highp

    Ce qualificateur fournit des exigences de précision minimales supérieures à celles fournies par min16float et inférieures à un flotteur 32 bits complet. L’équivalent dans HLSL est le suivant :

    float highp -> float

    highp int -> int

  • mediump

    Ce qualificateur appliqué à float et int équivaut à min16float et min12int dans HLSL. Minimum 10 bits de mantissa, pas comme min10float.

  • lowp

    Ce qualificateur appliqué au float fournit une plage à virgule flottante de -2 à 2. Équivaut à min10float dans HLSL.

types de précision

  • min16float : valeur à virgule flottante minimale de 16 bits
  • min10float

    Valeur 2,8 bits signée de point fixe minimum (2 bits de nombre entier et 8 bits de composant fractionnaire). Le composant fractionnaire 8 bits peut être inclus de 1 au lieu d’être exclusif pour lui donner la plage inclusive complète de -2 à 2.

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

    Ce type concerne 10Level9 (9_x niveaux de caractéristiques) dans lesquels les entiers sont représentés par des nombres à virgule flottante. Il s’agit de la précision que vous pouvez obtenir lorsque vous émulez un entier avec un nombre à virgule flottante 16 bits.

  • min16uint : entier non signé 16 bits minimum

Pour plus d’informations, consultez Types scalaires et utilisation de HLSL précision minimale.

sampler2D Texture2D
samplerCube TextureCube

 

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

Utilisez cette table pour porter des variables globales prédéfinies GLSL vers HLSL.

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

gl_Position

Cette variable est de type vec4.

Position de vertex

par exemple - gl_Position = position ;

SV_Position

POSITION dans Direct3D 9

Cette sémantique est de type float4.

Sortie du nuanceur de vertex

Position de vertex

par exemple - float4 vPosition : SV_Position ;

gl_PointSize

Cette variable est de type float.

Taille d’impression

PSIZE

Aucune signification, sauf si vous ciblez Direct3D 9

Cette sémantique est float de type.

Sortie du nuanceur de vertex

Taille d’impression

gl_FragColor

Cette variable est de type vec4.

Couleur de fragment

par exemple - gl_FragColor = vec4(colorVarying, 1.0) ;

SV_Target

COULEUR dans Direct3D 9

Cette sémantique est de type float4.

Sortie du nuanceur de pixels

Couleur de pixel

par exemple - Float4 Color[4] : SV_Target ;

gl_FragData[n]

Cette variable est de type vec4.

Couleur de fragment pour la pièce jointe de couleur n

SV_Target[n]

Cette sémantique est de type float4.

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

gl_FragCoord

Cette variable est de type vec4.

Position des fragments dans la mémoire tampon d’images

SV_Position

Non disponible dans Direct3D 9

Cette sémantique est de type float4.

Entrée du nuanceur de pixels

Coordonnées d’espace d’écran

par exemple - float4 screenSpace : SV_Position

gl_FrontFacing

Cette variable est de type bool.

Détermine si le fragment appartient à une primitive frontale.

SV_IsFrontFace

VFACE dans Direct3D 9

SV_IsFrontFace est de type bool.

VFACE est de type float.

Entrée du nuanceur de pixels

Primitive face à

gl_PointCoord

Cette variable est de type vec2.

Position de fragment dans un point (rastérisation de point uniquement)

SV_Position

VPOS dans Direct3D 9

SV_Position est de type float4.

VPOS est de type float2.

Entrée du nuanceur de pixels

Position du pixel ou de l’exemple dans l’espace d’écran

par exemple - pos float4 : SV_Position

gl_FragDepth

Cette variable est de type float.

Données de mémoire tampon de profondeur

SV_Depth

PROFONDEUR dans Direct3D 9

SV_Depth est de type float.

Sortie du nuanceur de pixels

Données de mémoire tampon de profondeur

 

Vous utilisez la sémantique pour spécifier la position, la couleur, et ainsi de suite pour l’entrée de nuanceur de vertex et l’entrée de nuanceur de pixels. Vous devez correspondre aux valeurs sémantiques de la disposition d’entrée avec l’entrée du nuanceur de vertex. Pour obtenir des exemples, consultez Exemples de portage des variables GLSL vers HLSL. Pour plus d’informations sur la sémantique HLSL, consultez Sémantiques.

Exemples de portage de variables GLSL vers HLSL

Ici, nous montrons des exemples d’utilisation de variables GLSL dans le code OpenGL/GLSL, puis l’exemple équivalent dans le code Direct3D/HLSL.

Uniform, attribut et variable dans GLSL

Code d’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 du nuanceur de vertex 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
}

Code du nuanceur de fragment 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);
}

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

Voici un exemple de la façon dont vous transmettez des données au nuanceur de vertex HLSL qui transite ensuite vers le nuanceur de pixels. Dans votre code d’application, définissez un sommet et une mémoire tampon constante. Ensuite, dans votre code de nuanceur de vertex, définissez la mémoire tampon constante en tant que cbuffer et stockez les données par vertex et les données d’entrée du nuanceur de pixels. Ici, nous utilisons des structures appelées 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 du nuanceur de vertex 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;
}

Code du nuanceur de pixels 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;
}

Exemples de portage du code de rendu OpenGL vers Direct3D

Ici, nous montrons un exemple de rendu dans le code OpenGL ES 2.0, puis l’exemple équivalent dans le code Direct3D 11.

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

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