Diferentes shaders para diferentes objetos DirectX 11

13

Estou aprendendo Direct3D 11e, em todos os tutoriais básicos que encontrei sobre a escrita de sombreadores, os sombreadores Vertex e Pixel são escritos para que transformem toda a cena da mesma maneira. Tutoriais como cubo de renderização com textura ...

Mas eu me pergunto, como você diferencia objetos? E se você quiser, por exemplo, simular a superfície do espelho em algum objeto e usar shaders diferentes para renderizar o restante da cena? Eu acho que a maioria dos jogos deve usar muitos shaders de vértice e pixel para conseguir várias aparências e transformações.

Obrigado.

jantobola
fonte

Respostas:

23

Sim, um mecanismo de jogo em geral terá uma variedade de shaders diferentes. O padrão típico é:

  1. Ao inicializar o mecanismo e carregar o mundo do jogo, prepare todos os shaders que você usará para renderizar. Por "preparação", quero dizer carregá-los na memória, compilá-los, se necessário, e fazer todas as ID3D11Device::CreatePixelShaderchamadas semelhantes para obter os objetos de sombreador D3D alocados e prontos para uso. Mantenha os objetos em uma matriz ou em alguma outra estrutura de dados.

    Normalmente, você terá um relacionamento individual entre os shaders de vértice e os shaders de pixel projetados para trabalhar juntos. Penso neles como um único objeto, que chamo de "sombreador", mesmo que ele realmente contenha um sombreador de vértice e um sombreador de pixel (e talvez sombreadores de geometria / casco / domínio também).

  2. Cada quadro, depois de encontrar a lista de objetos (malhas) a serem renderizados, classifique-os por sombreador. A idéia é minimizar o número de vezes que você alterna shaders em um quadro, desenhando todos os objetos com um determinado shader juntos. Isso ocorre porque a mudança shaders é uma operação um pouco caro (embora certamente você pode fazê-lo várias centenas ou milhares de vezes por quadro, por isso não é realmente que caro).

    De fato, você pode dar um passo adiante e classificar as malhas por shader primeiro e material por segundo. Por "material", quero dizer uma combinação de um sombreador e um conjunto de texturas e parâmetros para ele. Os shaders geralmente têm algumas texturas e parâmetros numéricos (armazenados em buffers constantes) que os alimentam; portanto, por exemplo, um material de tijolo e asfalto pode usar o mesmo código de shader, apenas com texturas diferentes.

  3. Para desenhar, faça um loop sobre os shaders, defina cada shader no ID3D11DeviceContext, defina quaisquer parâmetros (buffers constantes, texturas etc.) e desenhe os objetos. No pseudocódigo, incluindo a distinção shaders / materiais, mencionei:

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

Muito mais pode ser dito sobre o gerenciamento de objetos, malhas, shaders, layouts de entrada, buffers constantes, etc., mas isso deve ser suficiente para você começar. :)

Nathan Reed
fonte
Você propõe a classificação por sombreador e depois por material. Você tem dados concretos sobre o custo da troca de shaders versus troca de materiais? Ah, e para o DX9, uma combinação VS / PS é chamada "programa". Não tenho certeza se eles ainda usam essa terminologia no DX11.
Panda Pyjama
1
@PandaPajama Essa é uma boa pergunta. Não, não tenho ou tenho conhecimento de medições recentes do custo real da troca de materiais ou shaders. Essa abordagem tem sido a "sabedoria comum" há anos, mas vale a pena fazer algumas medições reais para ver como as coisas mudaram ... talvez eu faça isso se encontrar tempo. :)
Nathan Reed