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
- Portage des variables GLSL vers HLSL
- Portage des types GLSL vers HLSL
- Portage des variables globales prédéfinies GLSL vers HLSL
- Exemples de portage de variables GLSL vers HLSL
- Exemples de portage du code de rendu OpenGL sur Direct3D
- Rubriques connexes
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 |
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
|
Type vector
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
|
Type matrix
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
|
Types de précision
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);
Rubriques connexes
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour