Compartilhar via


Usando sombreadores no Direct3D 10

O pipeline tem três estágios de sombreador e cada um deles é programado com um sombreador HLSL. Todos os sombreadores direct3D 10 são escritos em HLSL, direcionando o modelo de sombreador 4.

Diferenças entre o Direct3D 9 e o Direct3D 10:

  • Ao contrário dos modelos de sombreador direct3D 9 que poderiam ser criados em uma linguagem de assembly intermediária, sombreadores do modelo de sombreador 4.0 são criados apenas em HLSL. A compilação offline de sombreadores no código de bytes consumível pelo dispositivo ainda é compatível e recomendada para a maioria dos cenários.

Este exemplo usa apenas um sombreador de vértice. Como todos os sombreadores são criados a partir do núcleo de sombreador comum, aprender a usar um sombreador de vértice é muito semelhante ao uso de um sombreador de geometria ou pixel.

Depois de criar um sombreador HLSL (este exemplo usa o sombreador de vértice HLSLWithoutFX.vsh), você precisará prepará-lo para o estágio de pipeline específico que o usará. Para fazer isso, você precisa:

Essas etapas precisam ser repetidas para cada sombreador no pipeline.

Compilar um sombreador

A primeira etapa é compilar o sombreador para marcar para ver se você codiou as instruções HLSL corretamente. Isso é feito chamando D3D10CompileShader e fornecendo-o com vários parâmetros, conforme mostrado aqui:

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

Essa função usa os seguintes parâmetros:

  • O nome do arquivo ( e o comprimento da cadeia de caracteres de nome em bytes ) que contém o sombreador. Este exemplo usa apenas um sombreador de vértice (no arquivo HLSLWithoutFX.vsh em que a extensão de arquivo .vsh é uma abreviação para sombreador de vértice).

  • O nome da função de sombreador. Este exemplo compila um sombreador de vértice da função Ripple que usa uma única entrada e retorna um struct de saída (a função é do exemplo HLSLWithoutFX):

    VS_OUTPUT Ripple( in float2 vPosition : POSITION )
    
  • Um ponteiro para todas as macros usadas pelo sombreador. Use D3D10_SHADER_MACRO para ajudar a definir suas macros; basta criar uma cadeia de caracteres de nome que contenha todos os nomes de macro (com cada nome separado por um espaço) e uma cadeia de caracteres de definição (com cada corpo de macro separado por um espaço). Ambas as cadeias de caracteres precisam ser terminadas em NULL.

  • Um ponteiro para todos os outros arquivos que você precisa incluir para que os sombreadores sejam compilados. Isso usa a interface ID3D10Include que tem dois métodos implementados pelo usuário: Abrir e Fechar. Para fazer isso funcionar, você precisará implementar o corpo dos métodos Open e Close; no método Open, adicione o código que você usaria para abrir os arquivos de inclusão desejados, na função Close, adicione o código para fechar os arquivos quando terminar de usá-los.

  • O nome da função de sombreador a ser compilada. Esse sombreador compila a função Ripple.

  • O perfil de sombreador a ser direcionado ao compilar. Como você pode compilar uma função em um sombreador de vértice, geometria ou pixel, o perfil informa ao compilador qual tipo de sombreador e com qual modelo de sombreador comparar o código.

  • Sinalizadores do compilador de sombreador. Esses sinalizadores informam ao compilador quais informações colocar na saída compilada e como você deseja otimizar o código de saída: para velocidade, para depuração etc. Consulte Constantes de efeito (Direct3D 10) para obter uma listagem dos sinalizadores disponíveis. O exemplo contém algum código que você pode usar para definir os valores de sinalizador do compilador para seu projeto. Essa é principalmente uma questão de se você deseja ou não gerar informações de depuração.

  • Um ponteiro para o buffer que contém o código do sombreador compilado. O buffer também contém qualquer informação de tabela de símbolo e de depuração inserida solicitada pelos sinalizadores do compilador.

  • Um ponteiro para um buffer que contém uma listagem de erros e avisos encontrados durante a compilação, que são as mesmas mensagens que você veria na saída de depuração se estivesse executando o depurador durante a compilação do sombreador. NULL é um valor aceitável quando você não deseja que os erros sejam retornados a um buffer.

Se o sombreador for compilado com êxito, um ponteiro para o código do sombreador será retornado como uma interface ID3D10Blob. Ele é chamado de interface blob porque o ponteiro é para um local na memória composto por uma matriz de DWORD. A interface é fornecida para que você possa obter um ponteiro para o sombreador compilado que será necessário na próxima etapa.

A partir do SDK de dezembro de 2006, o compilador HLSL do DirectX 10 agora é o compilador padrão no DirectX 9 e no DirectX 10. Consulte Effect-Compiler Tool para obter detalhes.

Obter um ponteiro para um sombreador compilado

Vários métodos de API exigem um ponteiro para um sombreador compilado. Esse argumento geralmente é chamado de pShaderBytecode porque aponta para um sombreador compilado representado como uma sequência de códigos de bytes. Para obter um ponteiro para um sombreador compilado, primeiro compile o sombreador chamando D3D10CompileShader ou uma função semelhante. Se a compilação for bem-sucedida, o sombreador compilado será retornado em uma interface ID3D10Blob . Por fim, use o método GetBufferPointer para retornar o ponteiro.

Criar um objeto shader

Depois que o sombreador for compilado, chame CreateVertexShader para criar o objeto de sombreador:

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

Para criar o objeto de sombreador, passe o ponteiro para o sombreador compilado em CreateVertexShader. Como você teve que compilar o sombreador com êxito primeiro, essa chamada certamente passará, a menos que você tenha um problema de memória em seu computador.

Você pode criar quantos objetos de sombreador desejar e simplesmente manter ponteiros para eles. Esse mesmo mecanismo funciona para sombreadores de geometria e pixel, supondo que você corresponda aos perfis de sombreador (quando você chama o método de compilação) com os nomes de interface (quando você chama o método create).

Definir o objeto shader

A última etapa é definir o sombreador para o estágio do pipeline. Como há três estágios de sombreador no pipeline, você precisará fazer três chamadas à API, uma para cada estágio.

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

A chamada para VSSetShader leva o ponteiro para o sombreador de vértice criado na etapa 1. Isso define o sombreador no dispositivo. O estágio do sombreador de vértice agora é inicializado com seu código de sombreador de vértice, tudo o que resta é inicializar quaisquer variáveis de sombreador.

Repetir para todos os três estágios do sombreador

Repita esse mesmo conjunto de etapas para criar qualquer sombreador de vértice ou pixel ou até mesmo um sombreador de geometria que produz para o sombreador de pixel.

Compilar um sombreador

Guia de programação para HLSL