Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tej sekcji opisano cieniowania, które mogą być używane do programowalnego modelu strumienia.
Korzystanie ze strumieni
DirectX 8 wprowadził pojęcie strumienia, aby powiązać dane z rejestrami wejściowymi do użycia przez cieniowanie. Strumień jest jednolitą tablicą danych składowych, gdzie każdy składnik składa się z co najmniej jednego elementu reprezentującego jedną jednostkę, taką jak pozycja, normalny, kolor itd. Strumienie umożliwiają układom graficznym bezpośredni dostęp do pamięci z wielu wierzchołków równolegle, a także zapewniają bardziej naturalne mapowanie danych aplikacji. Umożliwiają one również trywialne wielotekstowe i multipass. Pomyśl o tym w następujący sposób:
- Wierzchołek składa się z n strumieni.
- Strumień składa się z elementów m.
- Element to [pozycja, kolor, normalny, współrzędna tekstury].
Metoda IDirect3DDevice9::SetStreamSource wiąże bufor wierzchołka ze strumieniem danych urządzenia, tworząc skojarzenie między danymi wierzchołka a jednym z kilku portów strumienia danych, które zasilają funkcje przetwarzania pierwotnego. Rzeczywiste odwołania do danych strumienia nie występują, dopóki metoda rysunku, taka jak IDirect3DDevice9::D rawPrimitive, jest wywoływana.
Mapowanie elementów wierzchołka wejściowego na rejestry wejściowe wierzchołka programowalnego cieniowania wierzchołków jest zdefiniowane w deklaracji cieniowania, ale elementy wierzchołka wejściowego nie mają określonych semantyki dotyczących ich użycia. Interpretacja elementów wierzchołka wejściowego jest programowana przy użyciu instrukcji cieniowania. Funkcja cieniowania wierzchołków jest definiowana przez tablicę instrukcji, które są stosowane do każdego wierzchołka. Rejestry wyjściowe wierzchołków są jawnie zapisywane, korzystając z instrukcji w funkcji cieniowania.
W tej dyskusji należy jednak mniej zaniepokoić semantyczne mapowanie elementów na rejestry i bardziej zaniepokoić przyczynę używania strumieni oraz problem rozwiązany przy użyciu strumieni. Główną zaletą strumieni jest to, że usuwają koszty danych wierzchołków wcześniej skojarzone z wielotekstem. Przed przesyłaniem strumieniowym użytkownik musiał zduplikować zestawy danych wierzchołków w celu obsługi pojedynczego i wielotekstowego przypadku bez nieużywanych elementów danych lub przenoszenia elementów danych, które byłyby nieużywane, z wyjątkiem przypadku wielotekstowego.
Oto przykład użycia dwóch zestawów danych wierzchołków, jeden dla pojedynczej tekstury i jeden dla wielotekstowego.
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
};
Alternatywą było posiadanie pojedynczego elementu wierzchołka, który zawierał oba zestawy współrzędnych tekstury.
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
};
Dzięki tym danym wierzchołka tylko jedna kopia pozycji i danych kolorów są przenoszone w pamięci, kosztem przenoszenia obu zestawów współrzędnych tekstury do renderowania nawet w przypadku pojedynczej tekstury.
Teraz, gdy kompromis jest jasny, strumienie zapewniają elegancką poprawkę do tego dylematu. Oto zestaw definicji wierzchołków do obsługi trzech strumieni: jeden z położeniem i kolorem, jeden z pierwszym zestawem współrzędnych tekstury, a drugi zestaw współrzędnych tekstury.
// 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)
Deklaracja wierzchołka będzie następująca:
// 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()
};
Teraz utwórz obiekt deklaracji wierzchołka i ustaw go w następujący sposób:
LPDIRECT3DVERTEXDECLARATION9 m_pVertexDeclaration;
g_d3dDevice->CreateVertexDeclaration(dwDecl3, &m_pVertexDeclaration);
m_pd3dDevice->SetVertexDeclaration(m_pVertexDeclaration);
Przykłady kombinacji
Jeden strumień rozproszony kolor
Ustawienia deklaracji wierzchołka i strumienia dla renderowania kolorów rozproszonych wyglądają następująco:
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);
Dwa strumienie z kolorem i teksturą
Ustawienia deklaracji wierzchołka i strumienia renderowania pojedynczej tekstury będą wyglądać następująco:
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);
Dwa strumienie z kolorem i dwie tekstury
Ustawienia deklaracji wierzchołka i strumienia dla renderowania wielo teksturowego dwu tekstury będą wyglądać następująco:
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));
W każdym przypadku następujące IDirect3DDevice9::D rawPrimitive wywołania wystarczy.
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, NUM_TRIS);
Pokazuje to elastyczność strumieni w rozwiązywaniu problemu duplikowania/nadmiarowej transmisji danych w magistrali (czyli marnowania przepustowości).
Tematy pokrewne