Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cette section décrit les nuanceurs qui peuvent être utilisés pour le modèle de flux programmable.
Utilisation de flux
DirectX 8 a introduit la notion d’un flux pour lier des données aux registres d’entrée à utiliser par des nuanceurs. Un flux est un tableau uniforme de données de composant, où chaque composant se compose d’un ou plusieurs éléments qui représentent une entité unique, comme la position, la normale, la couleur, etc. Les flux permettent aux puces graphiques d’effectuer un accès direct à la mémoire à partir de plusieurs mémoires tampons de vertex en parallèle et fournissent également un mappage plus naturel à partir de données d’application. Ils activent également la multitexture triviale par rapport au multipass. Pensez-y comme ceci :
- Un sommet est composé de n flux.
- Un flux est composé d’éléments m.
- Un élément est [position, couleur, normal, coordonnée de texture].
La méthode IDirect3DDevice9 ::SetStreamSource lie une mémoire tampon de vertex à un flux de données d’appareil, créant une association entre les données de vertex et l’un des ports de flux de données qui alimentent les fonctions de traitement primitives. Les références réelles aux données de flux ne se produisent pas tant qu’une méthode de dessin, telle que IDirect3DDevice9 ::D rawPrimitive, est appelée.
Le mappage des éléments de vertex d’entrée aux registres d’entrée de vertex pour les nuanceurs de vertex programmables est défini dans la déclaration du nuanceur, mais les éléments de vertex d’entrée n’ont pas de sémantique spécifique sur leur utilisation. L’interprétation des éléments de vertex d’entrée est programmée à l’aide des instructions du nuanceur. La fonction de nuanceur de vertex est définie par un tableau d’instructions appliquées à chaque vertex. Les registres de sortie de vertex sont explicitement écrits à l’aide d’instructions dans la fonction de nuanceur.
Pour cette discussion, cependant, soyez moins préoccupé par le mappage sémantique des éléments aux registres et plus préoccupé par la raison de l’utilisation de flux et le problème résolu par l’utilisation de flux. Le principal avantage des flux est qu’ils suppriment les coûts de données de vertex précédemment associés à la multitexturation. Avant les flux, un utilisateur doit soit dupliquer des jeux de données de vertex pour gérer le cas unique et multitexte sans éléments de données inutilisés, soit transporter des éléments de données qui ne seraient pas utilisés, sauf dans le cas multitexte.
Voici un exemple d’utilisation de deux jeux de données de vertex, un pour une texture unique et un pour la multitexturation.
struct CUSTOMVERTEX_TEX1
{
FLOAT x, y, z; // The untransformed position for the vertex
DWORD diffColor; // The vertex diffuse color
DWORD specColor; // The vertex specular color
float tu_1, tv_1; // Texture coordinates for a single texture
};
struct CUSTOMVERTEX_TEX2
{
FLOAT x, y, z; // The untransformed position for the vertex
DWORD diffColor; // The vertex diffuse color
DWORD specColor; // The vertex specular color
float tu_2, tv_2; // Texture coordinates for multitexturing
};
L’alternative consiste à avoir un seul élément de vertex qui contenait les deux ensembles de coordonnées de texture.
struct CUSTOMVERTEX_TEX2
{
FLOAT x, y, z; // The untransformed position for the vertex
DWORD diffColor; // The vertex diffuse color
DWORD specColor; // The vertex specular color
float tu_1, tv_1; // Texture coordinates for a single texture
float tu_2, tv_2; // Texture coordinates for multitexturing
};
Avec ces données de vertex, une seule copie des données de position et de couleur est portée en mémoire, au détriment du transport des deux ensembles de coordonnées de texture pour le rendu même dans le cas de texture unique.
Maintenant que le compromis est clair, les flux fournissent un correctif élégant à ce dilemme. Voici un ensemble de définitions de vertex pour prendre en charge trois flux : un avec position et couleur, un avec le premier ensemble de coordonnées de texture, et un avec le deuxième ensemble de coordonnées de texture.
// Multistream vertex
// Stream 0, pos, diffuse, specular
struct POSCOLORVERTEX
{
FLOAT x, y, z;
DWORD diffColor, specColor;
};
#define D3DFVF_POSCOLORVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_SPECULAR)
// Stream 1, tex coord 0
struct TEXC0VERTEX
{
FLOAT tu1, tv1;
};
#define D3DFVF_TEXC0VERTEX (D3DFVF_TEX1)
// Stream 2, tex coord 1
struct TEXC1VERTEX
{
FLOAT tu2, tv2;
};
#define D3DFVF_TEXC1VERTEX (D3DFVF_TEX0)
La déclaration de vertex est la suivante :
// Multitexture - multistream
D3DVERTEXELEMENT9 dwDecl3[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0},
{0, 16, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 1},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0},
{2, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 1},
D3DDECL_END()
};
Créez maintenant l’objet de déclaration de vertex et définissez-le comme indiqué :
LPDIRECT3DVERTEXDECLARATION9 m_pVertexDeclaration;
g_d3dDevice->CreateVertexDeclaration(dwDecl3, &m_pVertexDeclaration);
m_pd3dDevice->SetVertexDeclaration(m_pVertexDeclaration);
Exemples de combinaisons
Couleur diffuse d’un flux
La déclaration de vertex et les paramètres de flux pour le rendu de couleur diffuse ressemblent à ceci :
D3DVERTEXELEMENT9 dwDecl3[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0 ,
{0, 16, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 1},
D3DDECL_END()
};
m_pd3dDevice->SetStreamSource(0, m_pVBVertexShader0, 0,
sizeof(CUSTOMVERTEX));
m_pd3dDevice->SetStreamSource(1, NULL, 0, 0);
m_pd3dDevice->SetStreamSource(2, NULL, 0, 0);
Deux flux avec couleur et texture
La déclaration de vertex et les paramètres de flux pour le rendu de texture unique ressemblent à ceci :
D3DVERTEXELEMENT9 dwDecl3[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0},
{0, 16, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 1},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
m_pd3dDevice->SetStreamSource(0, m_pVBPosColor, 0,
sizeof(POSCOLORVERTEX));
m_pd3dDevice->SetStreamSource(1, m_pVBTexC0, 0,
sizeof(TEXC0VERTEX));
m_pd3dDevice->SetStreamSource(2, NULL, 0, 0);
Deux flux avec couleur et deux textures
Les paramètres de déclaration de vertex et de flux pour le rendu multi texture à deux textures ressemblent à ceci :
D3DVERTEXELEMENT9 dwDecl3[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0},
{0, 16, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 1},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0},
{2, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 1},
D3DDECL_END()
};
m_pd3dDevice->SetStreamSource(0, m_pVBPosColor, 0,
sizeof(POSCOLORVERTEX));
m_pd3dDevice->SetStreamSource(1, m_pVBTexC0, 0,
sizeof(TEXC0VERTEX));
m_pd3dDevice->SetStreamSource(2, m_pVBTexC1, 0,
sizeof(TEXC1VERTEX));
Dans tous les cas, l’appel IDirect3DDevice9 ::D rawPrimitive suffit.
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, NUM_TRIS);
Cela montre la flexibilité des flux dans la résolution du problème de duplication des données/transmission de données redondantes sur le bus (autrement dit, de la bande passante de gaspiller).
Rubriques connexes