Sdílet prostřednictvím


Použití shaderů v Direct3D 10

Potrubí má tři stádia shaderů a každé z nich je naprogramováno v HLSL shaderu. Všechny shadery Direct3D 10 jsou napsané v HLSL a cílí na model shaderu 4.

Rozdíly mezi Direct3D 9 a Direct3D 10:

  • Na rozdíl od modelů shaderu Direct3D 9, které by mohly být vytvořené v přechodném jazyce sestavení, shader model 4.0 jsou vytvořené pouze v HLSL. Offline kompilace shaderů do bajtového kódu spotřebního zařízení je stále podporovaná a doporučuje se pro většinu scénářů.

V tomto příkladu se používá pouze vrcholový shader. Vzhledem k tomu, že všechny shadery jsou vytvořené z běžného jádra shaderu, je učení se používání vrcholového shaderu velmi podobné použití geometrického nebo pixelového shaderu.

Jakmile vytvoříte HLSL shader (v tomto příkladu se použije vrcholový shader HLSLWithoutFX.vsh), budete ho muset připravit pro konkrétní fázi zpracovatelského kanálu, která ho bude používat. K tomu potřebujete:

Tyto kroky je potřeba opakovat pro každý shader v pipeline.

Zkompiluj shader

Prvním krokem je kompilace shaderu, abyste zjistili, že jste správně naprogramovali příkazy HLSL. To se provádí voláním D3D10CompileShader a zadáním několika parametrů, jak je znázorněno zde:

    IPD3D10Blob * pBlob;
    
        
    // Compile the vertex shader from the file
    D3D10CompileShader( strPath, strlen( strPath ), "HLSLWithoutFX.vsh", 
        NULL, NULL, "Ripple", "vs_4_0", dwShaderFlags, &pBlob, NULL );

Tato funkce přebírá následující parametry:

  • Název souboru (a délka řetězce názvu v bajtech), který obsahuje shader. Tento příklad používá pouze vrcholový shader (v souboru HLSLWithoutFX.vsh, kde přípona souboru .vsh je zkratka pro vrcholový shader).

  • Název funkce shaderu. Tento příklad zkompiluje shader vrcholů z funkce Ripple, která přebírá jeden vstup a vrací výstupní strukturu (funkce je z ukázky HLSLWithoutFX):

    VS_OUTPUT Ripple( in float2 vPosition : POSITION )
    
  • Ukazatel na všechna makra používaná shaderem Použijte D3D10_SHADER_MACRO k definování svých maker; jednoduše vytvořte řetězec s názvy, který obsahuje všechny názvy maker (každý název oddělený mezerou), a definiční řetězec (každé tělo makra oddělené mezerou). Oba řetězce musí být ukončeny hodnotou NULL.

  • Odkaz na jakékoliv jiné soubory, které musíte zahrnout, aby vaše shadery byly úspěšně zkompilovány. Používá se rozhraní ID3D10Include se dvěma metodami implementovanými uživatelem: Open a Close. Chcete-li tuto práci provést, budete muset implementovat tělo metody Open a Close; v metodě Open přidejte kód, který byste použili k otevření libovolného zahrnutého souboru, ve funkci Zavřít přidejte kód pro zavření souborů, jakmile s nimi skončíte.

  • Název funkce shaderu, která se má zkompilovat. Tento shader zkompiluje funkci Ripple.

  • Profil shaderu, který se má cílit při kompilaci. Vzhledem k tomu, že funkci můžete zkompilovat do vertexového, geometrického nebo pixelového shaderu, profil určuje kompilátoru, s jakým typem shaderu a modelem shaderu má porovnávat kód.

  • Příznaky kompilátoru shaderu Tyto příznaky kompilátoru říkají, jaké informace mají být vloženy do zkompilovaného výstupu a jak chcete optimalizovat výstupní kód: pro rychlost, ladění atd. Seznam dostupných příznaků najdete v konstanty efektu (Direct3D 10). Ukázka obsahuje nějaký kód, který můžete použít k nastavení hodnot přepínačů kompilátoru pro váš projekt – hlavně záleží na tom, jestli chcete generovat ladicí informace.

  • Ukazatel na vyrovnávací paměť, která obsahuje zkompilovaný kód shaderu. Vyrovnávací paměť obsahuje také všechny vložené informace o tabulce ladění a symbolů požadované příznakem kompilátoru.

  • Ukazatel na vyrovnávací paměť, která obsahuje seznam chyb a upozornění, ke kterým došlo během kompilace. Jsou to stejné zprávy, které byste viděli ve výstupu z ladicího procesu, pokud byste spustili ladicí program při kompilaci shaderu. null je přijatelná hodnota, pokud nechcete, aby se chyby vrátily do vyrovnávací paměti.

Pokud se shader úspěšně zkompiluje, vrátí se ukazatel na kód shaderu jako rozhraní ID3D10Blob. Označuje se jako rozhraní Blob, protože ukazatel směřuje na umístění v paměti, které se skládá z pole DWORD. Rozhraní je k dispozici, abyste mohli získat ukazatel na zkompilovaný shader, který budete potřebovat v dalším kroku.

Od sady SDK z prosince 2006 je kompilátor DirectX 10 HLSL nyní výchozím kompilátorem v DirectX 9 i DirectX 10. Podrobnosti najdete v nástroji Effect-Compiler.

Získejte ukazatel na zkompilovaný shader

Několik metod rozhraní API vyžaduje ukazatel na kompilovaný shader. Tento argument se obvykle nazývá pShaderBytecode, protože odkazuje na kompilovaný shader reprezentovaný jako posloupnost bajtů kódů. Pokud chcete získat ukazatel na kompilovaný shader, nejprve zkompilujte shader voláním D3D10CompileShader nebo podobné funkce. Pokud je kompilace úspěšná, kompilovaný shader se vrátí v rozhraní ID3D10Blob. Nakonec použijte metodu GetBufferPointer k vrácení ukazatele.

Vytvoření objektu shaderu

Jakmile je shader zkompilován, zavolejte CreateVertexShader a vytvořte objekt shaderu:

    ID3D10VertexShader ** ppVertexShader
    ID3D10Blob pBlob;


    // Create the vertex shader
    hr = pd3dDevice->CreateVertexShader( (DWORD*)pBlob->GetBufferPointer(),
        pBlob->GetBufferSize(), &ppVertexShader );

    // Release the pointer to the compiled shader once you are done with it
    pBlob->Release();

Pokud chcete vytvořit objekt shaderu, předejte ukazatel na zkompilovaný shader do CreateVertexShader. Vzhledem k tomu, že jste nejprve museli úspěšně zkompilovat shader, toto volání téměř jistě projde, pokud nemáte na svém počítači problém s pamětí.

Můžete vytvořit tolik objektů shaderu, kolik chcete, a jednoduše na ně zachovat ukazatele. Tento mechanismus funguje u geometrických a pixelových shaderů za předpokladu, že se při volání metody kompilace shodujete s profily shaderu a názvy rozhraní (při volání metody create).

Nastavení objektu shaderu

Posledním krokem je nastavení shaderu do fáze zpracování. Vzhledem k tomu, že v potrubí jsou tři fáze shaderu, budete muset provést tři volání rozhraní API, jedno pro každou fázi.

    // Set a vertex shader
    pd3dDevice->VSSetShader( g_pVS10 );

Volání VSSetShader vezme ukazatel na vertex shader vytvořený v kroku 1. Tím se nastaví shader v zařízení. Fáze shaderu vrcholů je nyní inicializována kódem shaderu vrcholů, vše, co zbývá, inicializuje všechny proměnné shaderu.

Opakujte pro všechny 3 fáze shaderu.

Opakujte stejnou sadu kroků, abyste vytvořili jakýkoli vrcholový nebo pixelový shader nebo dokonce geometrický shader, který má výstup do pixelového shaderu.

kompilování shaderů

Průvodce programováním pro HLSL