Partager via


Porter le langage GLSL

API importantes

Une fois que vous avez déplacé le code qui crée et configure vos tampons et objets de nuanceur, il est temps de porter le code à l’intérieur de ces nuanceurs à partir du langage GL Shader Language (GLSL) de OpenGL ES 2.0 vers le langage de nuanceur de niveau supérieur (HLSL) de Direct3D 11.

Dans OpenGL ES 2.0, les nuanceurs retournent des données après l’exécution à l’aide d’intrinsèques telles que gl_Position, gl_FragColor ou gl_FragData[n] (où n est l’index d’une cible de rendu spécifique). Dans Direct3D, il n’existe pas d’intrinsèques spécifiques et les nuanceurs retournent des données comme type de retour de leurs fonctions principales().

Les données que vous souhaitez interpoler entre les étapes du nuanceur, telles que la position de vertex ou la normale, sont gérées à l’aide de la déclaration variable . Toutefois, Direct3D n’a pas cette déclaration ; au lieu de cela, toutes les données que vous souhaitez transmettre entre les étapes du nuanceur doivent être marquées avec une sémantique HLSL. La sémantique spécifique choisie indique l’objectif des données et est. Par exemple, vous déclarez des données de vertex que vous souhaitez interpoler entre le nuanceur de fragments comme suit :

float4 vertPos : POSITION;

or

float4 vertColor : COLOR;

Où POSITION est la sémantique utilisée pour indiquer les données de position de vertex. POSITION est également un cas spécial, car après l’interpolation, il n’est pas accessible par le nuanceur de pixels. Par conséquent, vous devez spécifier une entrée au nuanceur de pixels avec SV_POSITION et les données de vertex interpolées sont placées dans cette variable.

float4 position : SV_POSITION;

La sémantique peut être déclarée sur les méthodes de corps (main) des nuanceurs. Pour les nuanceurs de pixels, SV_TARGET[n], qui indique une cible de rendu, est nécessaire sur la méthode body. (SV_TARGET sans suffixe numérique par défaut pour afficher l’index cible 0.)

Notez également que les nuanceurs de vertex sont nécessaires pour générer la sémantique SV_POSITION valeur système. Cette sémantique résout les données de position de vertex pour coordonner les valeurs où x est compris entre -1 et 1, y est compris entre -1 et 1, z est divisé par la valeur de coordonnées homogènes d’origine (z/w), et w est 1 divisé par la valeur w d’origine (1/w). Les nuanceurs de pixels utilisent la sémantique de valeur système SV_POSITION pour récupérer l’emplacement des pixels à l’écran, où x est compris entre 0 et la largeur de la cible de rendu et y est comprise entre 0 et la hauteur de la cible de rendu (chaque décalage de 0,5). Le niveau de fonctionnalité 9_x nuanceurs de pixels ne peut pas lire à partir de la valeur SV_POSITION.

Les mémoires tampons constantes doivent être déclarées avec cbuffer et être associées à un registre de départ spécifique pour la recherche.

Direct3D 11 : déclaration de mémoire tampon constante HLSL

cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
  matrix mvp;
};

Ici, la mémoire tampon constante utilise le registre b0 pour contenir la mémoire tampon packée. Tous les registres sont référencés sous la forme b#. Pour plus d’informations sur l’implémentation HLSL des mémoires tampons constantes, des registres et de l’empaquetage des données, lisez les constantes du nuanceur (HLSL).

Instructions

Étape 1 : Porter le nuanceur de vertex

Dans notre exemple Simple OpenGL ES 2.0, le nuanceur de vertex a trois entrées : une matrice 4x4 de projection de modèle constante et deux vecteurs de coordonnées 4. Ces deux vecteurs contiennent la position du sommet et sa couleur. Le nuanceur transforme le vecteur de position en coordonnées de perspective et l’affecte à l’intrinsèque gl_Position pour la rastérisation. La couleur de vertex est également copiée dans une variable variable pour l’interpolation pendant la rastérisation.

OpenGL ES 2.0 : nuanceur de vertex pour l’objet cube (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;
}

Désormais, dans Direct3D, la matrice de projection de vue de modèle constante est contenue dans une mémoire tampon constante empaquetée au registre b0, et la position et la couleur de vertex sont spécifiquement marquées avec la sémantique HLSL appropriée : POSITION et COLOR. Étant donné que notre disposition d’entrée indique une disposition spécifique de ces deux valeurs de vertex, vous créez un struct pour les contenir et le déclarer comme type pour le paramètre d’entrée sur la fonction de corps du nuanceur (main). (Vous pouvez également les spécifier en tant que deux paramètres individuels, mais cela peut être fastidieux.) Vous spécifiez également un type de sortie pour cette étape, qui contient la position et la couleur interpolées, et déclarez-le comme valeur de retour pour la fonction de corps du nuanceur de vertex.

Direct3D 11 : nuanceur de vertex pour l’objet cube (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;
}

Le type de données de sortie, PixelShaderInput, est rempli pendant la rastérisation et fourni au nuanceur de fragments (pixels).

Étape 2 : Porter le nuanceur de fragments

Notre exemple de nuanceur de fragments dans GLSL est extrêmement simple : fournissez la gl_FragColor intrinsèque avec la valeur de couleur interpolée. OpenGL ES 2.0 l’écrit dans la cible de rendu par défaut.

OpenGL ES 2.0 : Nuanceur de fragments pour l’objet cube (GLSL)

varying vec4 destColor;

void main()
{
  gl_FragColor = destColor;
} 

Direct3D est presque aussi simple. La seule différence significative est que la fonction corps du nuanceur de pixels doit retourner une valeur. Étant donné que la couleur est une valeur flottante de 4 coordonnées (RVBA), vous indiquez float4 comme type de retour, puis spécifiez la cible de rendu par défaut comme sémantique de valeur système SV_TARGET.

Direct3D 11 : nuanceur de pixels pour l’objet cube (HLSL)

struct PixelShaderInput
{
  float4 pos : SV_POSITION;
  float3 color : COLOR;
};


float4 main(PixelShaderInput input) : SV_TARGET
{
  return float4(input.color, 1.0f);
}

La couleur du pixel à la position est écrite dans la cible de rendu. Voyons maintenant comment afficher le contenu de cette cible de rendu dans Dessiner à l’écran !

Étape précédente

Porter les mémoires tampons et les données de vertex

Étape suivante

Dessiner sur l’écran

Notes

Comprendre la sémantique HLSL et l’empaquetage des mémoires tampons constantes peuvent vous enregistrer un peu de mal de tête de débogage, ainsi que fournir des opportunités d’optimisation. Si vous avez une chance, lisez la syntaxe des variables (HLSL), introduction aux mémoires tampons dans Direct3D 11 et How to : Create a Constant Buffer. Si ce n’est pas le cas, voici quelques conseils de départ pour garder à l’esprit la sémantique et les mémoires tampons constantes :

  • Vérifiez toujours le code de configuration Direct3D de votre renderer pour vous assurer que les structures de vos mémoires tampons constantes correspondent aux déclarations de struct cbuffer dans votre HLSL, et que les types scalaires du composant correspondent entre les deux déclarations.
  • Dans le code C++ de votre convertisseur, utilisez les types DirectXMath dans vos déclarations de mémoire tampon constante pour garantir l’empaquetage des données approprié.
  • La meilleure façon d’utiliser efficacement des mémoires tampons constantes consiste à organiser les variables de nuanceur en mémoires tampons constantes en fonction de leur fréquence de mise à jour. Par exemple, si vous avez des données uniformes mises à jour une fois par image et d’autres données uniformes mises à jour uniquement lorsque la caméra se déplace, envisagez de séparer ces données en deux mémoires tampons constantes distinctes.
  • La sémantique que vous avez oubliée d’appliquer ou que vous avez appliquée de manière incorrecte sera votre première source d’erreurs de compilation de nuanceur (FXC). Vérifiez-les ! Les documents peuvent être un peu déroutants, car de nombreuses pages et exemples plus anciens font référence à différentes versions de la sémantique HLSL avant Direct3D 11.
  • Vérifiez que vous connaissez le niveau de fonctionnalité Direct3D que vous ciblez pour chaque nuanceur. La sémantique du niveau de fonctionnalité 9_* est différente de celle de 11_1.
  • La sémantique SV_POSITION résout les données de position post-interpolation associées pour coordonner les valeurs où x est compris entre 0 et la largeur de la cible de rendu, y est compris entre 0 et la hauteur de la cible de rendu, z est divisé par la valeur w homogène d’origine (z/w), et w est divisé par la valeur w d’origine (1/w).

Guide pratique pour porter un convertisseur OpenGL ES 2.0 simple vers Direct3D 11

Porter les objets nuanceur

Porter les mémoires tampons et les données de vertex

Dessiner sur l’écran