Fazer a portabilidade do GLSL
APIs importantes
Quando você tiver movido o código que cria e configura os seus buffers e objetos de sombreador, será o momento de fazer a portabilidade do código dentro dos sombreadores da linguagem de sombreadores GL do OpenGL ES 2.0 (GLSL) para a linguagem de sombreadores de alto nível do Direct3D 11 (HLSL).
No OpenGL ES 2.0, os sombreadores retornam dados após a execução usando intrínsecos como gl_Position, gl_FragColor ou gl_FragData[n] (em que n é o índice de um destino de renderização específico). No Direct3D, não há intrínsecos específicos e os sombreadores devolvem dados como o tipo de retorno das duas respectivas funções principais().
Dados que você quer interpolados entre estágios de sombreador, como a posição do vértice ou normal, são manipulados pelo uso da declaração varying. Entretanto, o Direct3D não tem essa declaração. Em vez disso, cada dado que você quer que passe entre os estágios de sombreador devem ser marcados com uma semântica HLSL. A semântica específica selecionada indica (e é) a finalidade dos dados. Por exemplo, você deve declarar os dados que deseja interpolar entre o sombreador de fragmento como:
float4 vertPos : POSITION;
ou
float4 vertColor : COLOR;
Onde POSITION é a semântica usada para indicar dados de posição de vértice. POSITION também é um caso especial, pois, após a interpolação, ele não pode ser acessado pelo sombreador de pixel. Portanto, você deve especificar a entrada para o sombreador de pixel com SV_POSITION e os dados de vértice interpolados serão colocados nessa variável.
float4 position : SV_POSITION;
A semântica pode ser declarada nos métodos de corpo (principais) dos sombreadores. Para sombreadores de pixel, SV_TARGET[n], que indica um destino de renderização, é necessário no método body. (SV_TARGET sem um sufixo numérico usa como padrão renderizar o índice de destino 0.)
Observe também que os sombreadores de vértice são necessários para gerar a semântica SV_POSITION valor do sistema. Essa semântica resolve os dados de posição de vértice para valores de coordenadas nos casos em que x fica entre -1 e 1, y fica entre -1 e 1, z é dividido pelo valor de w da coordenada homogênea original (z/w) e w é 1 dividido pelo valor original de w (1/w). Os sombreadores de pixel usam a semântica SV_POSITION valor do sistema para recuperar o local do pixel na tela, onde x está entre 0 e a largura de destino de renderização e y está entre 0 e a altura de destino de renderização (cada deslocamento em 0,5). Os sombreadores de 9_x pixel de nível de recurso não podem ler do valor SV_POSITION.
Buffers constantes devem ser declarados com cbuffer e associados a um registro de inicialização específico para pesquisa.
Direct3D 11: declaração de buffer constante HLSL
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix mvp;
};
Aqui, o buffer constante usa registro b0 para colocar em espera o buffer em pacote. Todos os registros são referenciados no formulário b#. Para saber mais sobre a implementação HLSL de buffers constantes, registros e remessa de dados, leia Shader Constants (HLSL).
Instruções
Etapa 1: compatibilizar o sombreador de vértice
No nosso exemplo simples de OpenGL ES 2.0, o sombreador de vértice tem três entradas: uma matriz 4x4 de projeção de exibição constante de modelo e dois vetores de 4 coordenadas. Esses dois vetores contêm a posição do vértice e sua cor. O sombreador transforma o vetor de posição em coordenadas de perspectiva e o atribui ao gl_Position intrínseco para rasterização. A cor de vértice é copiada para uma variável, que varia, para interpolação durante a rasterização também.
OpenGL ES 2.0: sombreador de vértice para objeto de cubo (GLSL)
uniform mat4 u_mvpMatrix;
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 destColor;
void main()
{
gl_Position = u_mvpMatrix * a_position;
destColor = a_color;
}
No Direct3D, a matriz constante de modelo-exibição-projeção está contida em um buffer constante, empacotado no Registro b0, e a posição e cor do vértice são marcadas especificamente com a semântica HLSL apropriada: POSITION e COLOR. Como o layout de entrada indica uma ordem específica desses dois valores de vértice, crie uma estrutura para armazená-los e declare-a como o tipo do parâmetro de entrada na função (principal) do corpo do sombreador (Você também pode especificá-los como dois parâmetros individuais, mas isso pode ser problemático). Você também especifica um tipo de saída para esse estágio, que contém a cor e a posição interpoladas, e declará-la como o valor de retorno para a função do corpo do sombreador de vértice.
Direct3D 11: sombreador de vértice para objeto de cubo (HLSL)
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix mvp;
};
// Per-vertex data used as input to the vertex shader.
struct VertexShaderInput
{
float3 pos : POSITION;
float3 color : COLOR;
};
// Per-vertex color data passed through the pixel shader.
struct PixelShaderInput
{
float3 pos : SV_POSITION;
float3 color : COLOR;
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f); // add the w-coordinate
pos = mul(mvp, projection);
output.pos = pos;
output.color = input.color;
return output;
}
O tipo de dados de saída, PixelShaderInput, é populado durante a rasterização e fornecido ao sombreador de fragmento (pixel).
Etapa 2: compatibilizar o sombreador de fragmento
Nosso sombreador de fragmento de exemplo no GLSL é extremamente simples: forneça o gl_FragColor intrínseco com o valor de cor interpolada. O OpenGL ES 2.0 o reescreverá no destino de renderização padrão.
OpenGL ES 2.0: sombreador de fragmento para objeto de cubo (GLSL)
varying vec4 destColor;
void main()
{
gl_FragColor = destColor;
}
O Direct3D é quase tão simples quanto o OpenGL ES 2.0. A única diferença importante é que a função do corpo do sombreador de pixel deve retornar um valor. Como a cor é um valor float de 4 coordenadas (RGBA), você indica float4 como o tipo de retorno e especifica o destino de renderização padrão como a semântica de valor do sistema SV_TARGET.
Direct3D 11: sombreador de pixel para o objeto cubo (HLSL)
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color, 1.0f);
}
A cor do pixel na posição é gravada no destino de renderização. Agora, vamos ver como exibir os conteúdos daquele destino de renderização em Desenhar na tela!
Etapa anterior
Fazer a portabilidade de dados e buffers de vértices
Próxima etapa
Comentários
Entender a semântica HLSL e o compactação de buffers constantes pode evitar certa dor de cabeça, e oferecer oportunidade de otimização. Caso tenha chance, leia Sintaxe variável (HLSL), Introdução a buffers no Direct3D 11 e Como: criar um buffer constante. Caso não consiga fazer isso, consulte algumas dicas iniciais sobre semântica e buffers constantes para ter sempre em mente:
- Sempre confira duas vezes o código da configuração Direct3D do renderizador para garantir que: as estruturas dos buffers constantes correspondam às declarações da estrutura cbuffer no HLSL; e que os tipos escalares do componente coincidam em ambas as declarações.
- No código C++ do renderizador, use os tipos DirectXMath nas declarações de buffer constante para garantir o empacotamento correto dos dados.
- O melhor modo de usar buffers constantes de modo eficiente é organizar as variáveis de sombreador em buffers constantes com base na frequência de atualização. Por exemplo, caso tenha alguns dados uniformes atualizados uma vez por quadro e outros atualizados somente quando a câmera se move, talvez seja o caso de separar os dados em dois buffers constantes distintos.
- Os primeiros erros de origem de compilação de sombreador (FXC) serão gerados pela semântica que você se esqueceu de aplicar ou aplicada incorretamente. Confira-as com atenção! Os documentos podem ser um pouco confusos, pois muitas páginas e exemplos antigos mencionam versões diferentes da semântica HLSL, anteriores ao Direct3D 11.
- Certifique-se de que sabe qual nível de recurso do Direct3D você tem como objetivo para cada sombreador. A semântica do nível de recurso 9_* é diferente daquelas para 11_1.
- A semântica SV_POSITION resolve os dados de posição pós-interpolação associados para coordenar valores em que x está entre 0 e a largura de destino de renderização, y está entre 0 e a altura de destino de renderização, z é dividido pelo valor w da coordenada homogênea original (z/w) e w é 1 dividido pelo valor w original (1/w).
Tópicos relacionados
Como: compatibilizar um renderizador simples do OpenGL ES 2.0 ao Direct3D 11
Fazer a portabilidade de objetos de sombreador
Fazer a portabilidade de dados e buffers de vértices
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de