Share via


하나 이상의 스트림 프로그래밍(Direct3D 9)

이 섹션에서는 프로그래밍 가능한 스트림 모델에 사용할 수 있는 셰이더에 대해 설명합니다.

스트림 사용

DirectX 8은 셰이더에서 사용하기 위해 입력 레지스터에 데이터를 바인딩하는 스트림의 개념을 도입했습니다. 스트림은 구성 요소 데이터의 균일한 배열로, 각 구성 요소는 위치, 법선, 색 등과 같은 단일 엔터티를 나타내는 하나 이상의 요소로 구성됩니다. 스트림을 사용하면 그래픽 칩이 여러 꼭짓점 버퍼에서 병렬로 직접 메모리 액세스를 수행하고 애플리케이션 데이터에서 보다 자연스러운 매핑을 제공할 수 있습니다. 또한 간단한 멀티텍스처와 멀티패스를 사용할 수 있습니다. 다음과 같이 생각해 보세요.

  • 꼭짓점은 n개의 스트림으로 구성됩니다.
  • 스트림은 m 요소로 구성됩니다.
  • 요소는 [위치, 색, 보통, 질감 좌표]입니다.

IDirect3DDevice9::SetStreamSource 메서드는 꼭짓점 버퍼를 디바이스 데이터 스트림에 바인딩하여 꼭짓점 데이터와 기본 처리 함수를 공급하는 여러 데이터 스트림 포트 중 하나 간에 연결을 만듭니다. 스트림 데이터에 대한 실제 참조는 IDirect3DDevice9::D rawPrimitive와 같은 그리기 메서드가 호출될 때까지 발생하지 않습니다.

프로그래밍 가능한 꼭짓점 셰이더에 대한 꼭짓점 입력 레지스터에 대한 입력 꼭짓점 요소의 매핑은 셰이더 선언에 정의되어 있지만 입력 꼭짓점 요소에는 사용에 대한 특정 의미 체계가 없습니다. 입력 꼭짓점 요소의 해석은 셰이더 지침을 사용하여 프로그래밍됩니다. 꼭짓점 셰이더 함수는 각 꼭짓점에 적용되는 명령의 배열에 의해 정의됩니다. 꼭짓점 출력 레지스터는 셰이더 함수의 지침을 사용하여 명시적으로 기록됩니다.

그러나 이 논의에서는 레지스터에 대한 요소의 의미 체계 매핑에 덜 관심이 있고 스트림을 사용하는 이유와 스트림을 사용하여 해결되는 문제에 더 관심이 있습니다. 스트림의 기본 이점은 이전에 다중 텍스트와 관련된 꼭짓점 데이터 비용을 제거한다는 것입니다. 스트림 전에 사용자는 사용되지 않는 데이터 요소가 없는 단일 및 다중 텍스트 대/소문자를 처리하기 위해 꼭짓점 데이터 집합을 복제하거나 다중 텍스트 케이스를 제외하고 사용되지 않는 데이터 요소를 전달해야 했습니다.

다음은 두 개의 꼭짓점 데이터 집합을 사용하는 예입니다. 하나는 단일 텍스처용이고 다른 하나는 다중 텍스트 변환용입니다.

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
};

대안은 두 텍스처 좌표 집합을 모두 포함하는 단일 꼭짓점 요소를 갖는 것이었습니다.

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
};

이 꼭짓점 데이터를 사용하면 단일 텍스처 케이스에서도 렌더링을 위해 두 텍스처 좌표 집합을 모두 전달하는 대신 위치 및 색 데이터의 복사본 하나만 메모리에 전달됩니다.

이제 절충이 명확해졌으므로 스트림은 이 딜레마에 대한 우아한 수정을 제공합니다. 다음은 세 개의 스트림을 지원하는 꼭짓점 정의 집합입니다. 하나는 위치와 색, 하나는 첫 번째 텍스처 좌표 집합, 다른 하나는 텍스처 좌표 집합입니다.

// 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)

꼭짓점 선언은 다음과 같습니다.

// 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()
};

이제 꼭짓점 선언 개체를 만들고 다음과 같이 설정합니다.

LPDIRECT3DVERTEXDECLARATION9 m_pVertexDeclaration;
g_d3dDevice->CreateVertexDeclaration(dwDecl3, &m_pVertexDeclaration);

m_pd3dDevice->SetVertexDeclaration(m_pVertexDeclaration);

조합의 예

하나의 스트림 확산 색

확산 색 렌더링에 대한 꼭짓점 선언 및 스트림 설정은 다음과 같습니다.

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);

색과 질감이 있는 두 개의 스트림

단일 텍스처 렌더링에 대한 꼭짓점 선언 및 스트림 설정은 다음과 같습니다.

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);

색이 있는 스트림 2개와 텍스처 2개

두 텍스처 다중 텍스처 렌더링에 대한 꼭짓점 선언 및 스트림 설정은 다음과 같습니다.

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));

모든 경우에 다음 IDirect3DDevice9::D rawPrimitive 호출로 충분합니다.

       m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, NUM_TRIS);

버스 간 데이터 중복/중복 데이터 전송 문제(즉, 대역폭 낭비)를 해결하는 스트림의 유연성을 보여 줍니다.

꼭짓점 선언