Udostępnij przez


Używanie shaderów w Direct3D 10

Potok ma trzy etapy cieniowania, a każdy z nich jest zaprogramowany za pomocą cieniowania HLSL. Wszystkie shadery Direct3D 10 są pisane w języku HLSL, który jest przeznaczony dla modelu shaderów 4.

Różnice między direct3D 9 i Direct3D 10:

  • W przeciwieństwie do modeli shaderów Direct3D 9, które mogą być tworzone w języku zestawu pośredniego, modele shaderów 4.0 są tworzone wyłącznie w HLSL. Kompilacja cieniowania w trybie offline z użyciem kodu bajtowego urządzenia jest nadal obsługiwana i zalecana w przypadku większości scenariuszy.

W tym przykładzie użyto tylko cieniowania wierzchołków. Ponieważ wszystkie shadery są tworzone na podstawie wspólnego rdzenia shaderów, nauka korzystania z shaderów wierzchołkowych jest bardzo podobna do używania shaderów geometrycznych lub pikselowych.

Po napisaniu shadera HLSL (w tym przykładzie użyto vertex shadera HLSLWithoutFX.vsh), należy przygotować go do określonego etapu potoku, który będzie go używał. W tym celu należy wykonać następujące czynności:

Te kroki należy powtórzyć dla każdego shadera w potoku graficznym.

Kompilacja shadera

Pierwszym krokiem jest skompilowanie cieniowania, aby sprawdzić, czy instrukcje HLSL zostały poprawnie zakodowane. Odbywa się to przez wywołanie D3D10CompileShader i przekazanie mu kilku parametrów, jak pokazano tutaj.

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

Ta funkcja przyjmuje następujące parametry:

  • Nazwa pliku (oraz długość ciągu znaków nazwy w bajtach), który zawiera shader. W tym przykładzie użyto tylko cieniowania wierzchołków (w pliku HLSLWithoutFX.vsh, gdzie rozszerzenie pliku vsh jest skrótem cieniowania wierzchołków).

  • Nazwa funkcji cieniowania. W tym przykładzie kompiluje cieniowanie wierzchołków z funkcji Ripple, która przyjmuje pojedyncze dane wejściowe i zwraca strukturę danych wyjściowych (funkcja pochodzi z przykładu HLSLWithoutFX):

    VS_OUTPUT Ripple( in float2 vPosition : POSITION )
    
  • Wskaźnik na wszystkie makra używane przez shader. Użyj D3D10_SHADER_MACRO, aby ułatwić definiowanie makr; wystarczy utworzyć ciąg nazwy zawierający wszystkie nazwy makr (z każdą nazwą oddzieloną spacją) i ciąg definicji (z każdą treścią makra oddzieloną spacją). Oba ciągi muszą być zakończone wartością NULL.

  • Wskaźnik do jakichkolwiek innych plików, które należy dołączyć, aby skompilować shadery. Korzysta z interfejsu ID3D10Include, który ma dwie metody implementowane przez użytkownika: Otwórz i Zamknij. Aby wykonać tę pracę, należy zaimplementować treść metod Otwórz i Zamknij; w metodzie Open dodaj kod, który będzie używany do otwierania dowolnych plików dołączanych, w funkcji Close dodaj kod, aby zamknąć pliki po zakończeniu pracy z nimi.

  • Nazwa funkcji shadera do skompilowania. Ten moduł cieniowania kompiluje funkcję Ripple.

  • Profil cieniowania, który należy uwzględnić podczas kompilowania. Ponieważ można skompilować funkcję w wierzchołku, geometrii lub cieniowaniu pikseli, profil informuje kompilator o typie cieniowania i modelu cieniowania do porównania kodu.

  • Flagi kompilatora cieniowania. Te flagi informują kompilator o tym, jakie informacje mają zostać umieszczone w skompilowanych danych wyjściowych i jak chcesz zoptymalizować kod wyjściowy: pod kątem szybkości, debugowania itp. Zobacz Stałe efektu (Direct3D 10), aby zapoznać się z listą dostępnych flag. Przykład zawiera kod, którego można użyć do ustawiania wartości flag kompilatora dla projektu — jest to głównie pytanie, czy chcesz wygenerować informacje debugowania.

  • Wskaźnik do buforu zawierającego skompilowany kod cieniowania. Bufor zawiera również wszelkie osadzone informacje o tabeli debugowania i symboli żądane przez flagi kompilatora.

  • Wskaźnik do buforu zawierającego listę błędów i ostrzeżeń napotkanych podczas kompilacji, które są tymi samymi komunikatami, które są widoczne w danych wyjściowych debugowania, jeśli był uruchomiony debuger podczas kompilowania cieniowania. wartość NULL jest akceptowalną wartością, gdy nie chcesz, aby błędy zwracane do bufora.

Jeśli moduł cieniowania zostanie pomyślnie skompilowany, wskaźnik do kodu programu cieniującego zostanie zwrócony jako interfejs ID3D10Blob. Jest nazywany interfejsem Blob, ponieważ wskaźnik prowadzi do lokalizacji w pamięci, która składa się z tablicy DWORDów. Interfejs jest dostarczany, aby można było uzyskać wskaźnik do skompilowanego cieniowania, który będzie potrzebny w następnym kroku.

Począwszy od zestawu SDK z grudnia 2006 r., kompilator DirectX 10 HLSL jest teraz domyślnym kompilatorem zarówno w trybie DirectX 9, jak i DirectX 10. Aby uzyskać szczegółowe informacje, zobacz Effect-Compiler Tool.

Pobierz wskaźnik do skompilowanego shadera

Kilka metod interfejsu API wymaga wskaźnika do skompilowanego shadera. Ten argument jest zwykle nazywany pShaderBytecode, ponieważ wskazuje on kompilowany moduł cieniowania reprezentowany jako sekwencja kodów bajtów. Aby uzyskać wskaźnik do skompilowanego cieniowania, najpierw skompiluj cieniowanie, wywołując D3D10CompileShader lub podobną funkcję. Jeśli kompilacja zakończy się pomyślnie, skompilowany moduł cieniowania zostanie zwrócony w interfejsie ID3D10Blob. Na koniec użyj metody GetBufferPointer, aby zwrócić wskaźnik.

Tworzenie obiektu cieniowania

Po skompilowaniu cieniowania wywołaj metodę CreateVertexShader, aby utworzyć obiekt cieniowania:

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

Aby utworzyć obiekt shaderu, przekaż wskaźnik do skompilowanego shaderu do funkcji CreateVertexShader. Ponieważ najpierw trzeba było pomyślnie skompilować moduł cieniowania, to wywołanie prawie na pewno przejdzie, chyba że masz problem z pamięcią na maszynie.

Możesz utworzyć dowolną liczbę obiektów cieniowania i po prostu zachować wskaźniki do nich. Ten sam mechanizm działa w przypadku cieniowania geometrii i pikseli przy założeniu dopasowania profilów cieniowania (podczas wywoływania metody kompilowania) do nazw interfejsów (podczas wywoływania metody create).

Ustawianie obiektu cieniowania

Ostatnim krokiem jest ustawienie shaderu na etap potokowy. Ponieważ w potoku znajdują się trzy etapy cieniowania, należy wykonać trzy wywołania interfejsu API, po jednym dla każdego etapu.

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

Wywołanie polecenia VSSetShader przenosi wskaźnik do cieniowania wierzchołka utworzonego w kroku 1. Ustawia shader na urządzeniu. Etap shadera wierzchołków jest teraz zainicjowany kodem shadera wierzchołków, pozostaje tylko zainicjowanie wszelkich zmiennych shadera.

Powtórz dla wszystkich 3 etapów cieniowania

Powtórz ten sam zestaw kroków, aby utworzyć dowolny shader wierzchołków lub pikseli, a nawet shader geometrii, który przekazuje dane do shadera pikseli.

Kompilowanie Shaderów

Przewodnik programowania dla HLSL