Unterschiedliche Shader für unterschiedliche Objekte DirectX 11

12

Ich lerne Direct3D 11und in allen grundlegenden Tutorials, die ich zum Schreiben von Shadern gefunden habe, sind Vertex- und Pixel-Shader so geschrieben, dass sie die gesamte Szene auf die gleiche Weise transformieren. Tutorials wie Renderwürfel mit Textur ...

Aber ich frage mich, wie unterscheidet man Objekte? Was ist, wenn Sie beispielsweise die Spiegeloberfläche eines Objekts simulieren und verschiedene Shader verwenden möchten, um den Rest der Szene zu rendern? Ich denke, dass die meisten Spiele viele Vertex- und Pixel-Shader verwenden müssen, um verschiedene Looks und Transformationen zu erzielen.

Vielen Dank.

Jantobola
quelle

Antworten:

22

Ja, eine Spiel-Engine verfügt im Allgemeinen über verschiedene Shader. Das typische Muster ist:

  1. Bereiten Sie beim Initialisieren der Engine und beim Laden der Spielwelt alle Shader vor, die Sie zum Rendern verwenden. Mit "vorbereiten" meine ich, sie in den Speicher zu laden, sie bei Bedarf zu kompilieren und alle ID3D11Device::CreatePixelShaderund ähnliche Aufrufe auszuführen, um die D3D-Shader-Objekte zuzuweisen und einsatzbereit zu machen. Behalten Sie die Objekte in einem Array oder einer anderen Datenstruktur.

    Normalerweise besteht eine Eins-zu-Eins-Beziehung zwischen Vertex-Shadern und Pixel-Shadern, die für die Zusammenarbeit ausgelegt sind. Ich stelle sie mir als ein einzelnes Objekt vor, das ich einfach als "Shader" bezeichne, obwohl es wirklich einen Vertex-Shader und einen Pixel-Shader enthält (und möglicherweise auch Geometrie- / Rumpf- / Domain-Shader).

  2. Wenn Sie die Liste der zu rendernden Objekte (Netze) gefunden haben, sortieren Sie sie nach Shader. Die Idee ist, die Häufigkeit zu minimieren, mit der Sie die Shader in einem Frame wechseln, indem Sie alle Objekte mit einem bestimmten Shader zusammen zeichnen. Dies liegt daran, dass das Wechseln von Shadern ein ziemlich teurer Vorgang ist (obwohl Sie dies sicherlich mehrere hundert oder tausend Mal pro Frame tun können, ist es also nicht wirklich so teuer).

    Tatsächlich können Sie einen Schritt weiter gehen und Netze zuerst nach Shader und dann nach Material sortieren. Mit "Material" meine ich eine Kombination aus einem Shader und einer Reihe von Texturen und Parametern dafür. Shader haben normalerweise einige Texturen und numerische Parameter (in konstanten Puffern gespeichert), die in sie eingespeist werden. So können beispielsweise ein Ziegelmaterial und ein Asphaltmaterial denselben Shader-Code verwenden, nur mit unterschiedlichen Texturen.

  3. Um zu zeichnen, durchlaufen Sie einfach die Shader, setzen Sie jeden Shader in den ID3D11DeviceContext, stellen Sie alle Parameter ein (konstante Puffer, Texturen usw.) und zeichnen Sie dann die Objekte. Im Pseudocode, einschließlich der von mir erwähnten Unterscheidung zwischen Shadern und Materialien:

    for each shader:
        // Set the device context to use this shader
        pContext->VSSetShader(shader.pVertexShader);
        pContext->PSSetShader(shader.pPixelShader);
    
        for each material that uses this shader:
            // Set the device context to use any constant buffers, textures, samplers,
            // etc. needed for this material
            pContext->VSSetConstantBuffers(...);
            pContext->PSSetConstantBuffers(...);
            pContext->PSSetShaderResources(...);
            pContext->PSSetSamplers(...);
    
            for each mesh that uses this material:
                // Set any constant buffers containing parameters specific to the mesh
                // (e.g. world matrix)
                pContext->VSSetConstantBuffers(...);
    
                // Set the context to use the vertex & index buffers for this mesh
                pContext->IASetInputLayout(mesh.pInputLayout);
                pContext->IASetVertexBuffers(...);
                pContext->IASetIndexBuffer(...);
                pContext->IASetPrimitiveTopology(...)
    
                // Draw it
                pContext->DrawIndexed(...)

Es kann noch viel mehr über die Verwaltung von Objekten, Netzen, Shadern, Eingabelayouts, konstanten Puffern usw. gesagt werden, aber dies sollte ausreichen, um Ihnen den Einstieg zu erleichtern. :) :)

Nathan Reed
quelle
Sie schlagen vor, nach Shader und dann nach Material zu sortieren. Haben Sie genaue Daten zu den Kosten für das Wechseln von Shadern gegenüber dem Wechseln von Materialien? Oh, und für DX9 heißt eine VS / PS-Kombination "Programm". Ich bin mir nicht sicher, ob sie diese Terminologie in DX11 noch verwenden.
Panda Pyjama
1
@PandaPajama Das ist eine gute Frage. Nein, ich habe oder kenne keine aktuellen Messungen der tatsächlichen Kosten für das Wechseln von Materialien oder Shadern. Dieser Ansatz ist seit Jahren die "allgemeine Weisheit", aber es lohnt sich, einige tatsächliche Messungen durchzuführen, um zu sehen, wie sich die Dinge geändert haben ... Vielleicht mache ich das, wenn ich die Zeit finde. :)
Nathan Reed