Referência de GLSL para HLSL
Você faz a portabilidade do código da GLSL (OpenGL Shader Language) para o código HLSL (High Level Shader Language) da Microsoft ao portar a arquitetura gráfica do OpenGL ES 2.0 para o Direct3D 11 para criar um jogo para a UWP (Plataforma Universal do Windows). O GLSL aqui referido é compatível com OpenGL ES 2.0; o HLSL é compatível com Direct3D 11. Para obter informações sobre as diferenças entre o Direct3D 11 e as versões anteriores do Direct3D, consulte Mapeamento de recursos.
- Comparando o OpenGL ES 2.0 com o Direct3D 11
- Portabilidade de variáveis GLSL para HLSL
- Portabilidade de tipos GLSL para HLSL
- Portabilidade de variáveis globais predefinidas GLSL para HLSL
- Exemplos de portabilidade de variáveis GLSL para HLSL
- Exemplos de portabilidade do código de renderização do OpenGL para o Direct3D
- Tópicos relacionados
Comparando o OpenGL ES 2.0 com o Direct3D 11
O OpenGL ES 2.0 e o Direct3D 11 têm muitas semelhanças. Ambos têm pipelines de renderização e recursos gráficos semelhantes. Mas o Direct3D 11 é uma implementação de renderização e API, não uma especificação; O OpenGL ES 2.0 é uma especificação de renderização e API, não uma implementação. O Direct3D 11 e o OpenGL ES 2.0 geralmente diferem das seguintes maneiras:
OpenGL ES 2.0 | Direct3D 11 |
---|---|
Especificação independente de hardware e sistema operacional com implementações fornecidas pelo fornecedor | Implementação da Microsoft de abstração e certificação de hardware em plataformas Windows |
Abstraído pela diversidade de hardware, o tempo de execução gerencia a maioria dos recursos | Acesso direto ao layout do hardware; O aplicativo pode gerenciar recursos e processamento |
Fornece módulos de nível superior por meio de bibliotecas de terceiros (por exemplo, Simple DirectMedia Layer (SDL)) | Módulos de nível superior, como Direct2D, são criados em módulos inferiores para simplificar o desenvolvimento de aplicativos do Windows |
Os fornecedores de hardware se diferenciam por meio de extensões | A Microsoft adiciona recursos opcionais à API de maneira genérica para que não sejam específicos de nenhum fornecedor de hardware específico |
GLSL e HLSL geralmente diferem das seguintes maneiras:
GLSL | HLSL |
---|---|
Processual, centrado na etapa (semelhante a C) | Orientado a objetos, centrado em dados (semelhante a C++) |
Compilação de sombreador integrada à API gráfica | O compilador HLSL compila o sombreador para uma representação binária intermediária antes que o Direct3D o passe para o driver.
Observação Essa representação binária é independente de hardware. Normalmente, ele é compilado no momento da compilação do aplicativo, em vez de no tempo de execução do aplicativo.
|
Modificadores de armazenamento variáveis | Buffers constantes e transferências de dados por meio de declarações de layout de entrada |
Tipo de vetor típico: vec2/3/4 lowp, mediump, highp |
Tipo de vetor típico: float2/3/4 min10float, min16float |
texture2D [Função] | textura. Exemplo [datatype. Função] |
sampler2D [tipo de dados] | Texture2D [tipo de dados] |
Matrizes principais de linha (padrão) | Matrizes principais de coluna (padrão)
Observação Use o modificador de tipo row_major para alterar o layout de uma variável. Para obter mais informações, consulte Sintaxe de variável. Você também pode especificar um sinalizador de compilador ou um pragma para alterar o padrão global.
|
Sombreador de fragmento | Sombreador de pixel |
Observação HLSL tem texturas e samplers como dois objetos separados. No GLSL, como no Direct3D 9, a associação de textura faz parte do estado do amostrador.
No GLSL, você apresenta grande parte do estado do OpenGL como variáveis globais predefinidas. Por exemplo, com GLSL, você usa a variável gl_Position para especificar a posição do vértice e a variável gl_FragColor para especificar a cor do fragmento. No HLSL, você passa o estado do Direct3D explicitamente do código do aplicativo para o sombreador. Por exemplo, com Direct3D e HLSL, a entrada para o sombreador de vértice deve corresponder ao formato de dados no buffer de vértice e a estrutura de um buffer constante no código do aplicativo deve corresponder à estrutura de um buffer constante (cbuffer) no código do sombreador.
Portabilidade de variáveis GLSL para HLSL
No GLSL, você aplica modificadores (qualificadores) a uma declaração de variável de sombreador global para dar a essa variável um comportamento específico em seus sombreadores. No HLSL, você não precisa desses modificadores porque define o fluxo do sombreador com os argumentos que você passa para o sombreador e que retorna do sombreador.
Comportamento da variável GLSL | Equivalente HLSL |
---|---|
uniforme Você passa uma variável uniforme do código do aplicativo para um ou ambos os sombreadores de vértice e fragmento. Você deve definir os valores de todos os uniformes antes de desenhar qualquer triângulo com esses sombreadores para que seus valores permaneçam os mesmos durante todo o desenho de uma malha de triângulo. Esses valores são uniformes. Alguns uniformes são definidos para todo o quadro e outros exclusivamente para um par específico de sombreador de vértice-pixel. Variáveis uniformes são variáveis por polígono. |
Use buffer constante. Consulte Como criar um buffer constante e constantes de sombreador. |
Variando Você inicializa uma variável variável dentro do sombreador de vértice e a passa para uma variável variável com nome idêntico no sombreador de fragmento. Como o sombreador de vértice define apenas o valor das variáveis variáveis em cada vértice, o rasterizador interpola esses valores (de maneira correta em perspectiva) para gerar valores por fragmento a serem passados para o sombreador de fragmento. Essas variáveis variam em cada triângulo. |
Use a estrutura que você retorna do sombreador de vértice como a entrada para o sombreador de pixel. Verifique se os valores semânticos correspondem. |
attribute Um atributo é uma parte da descrição de um vértice que você passa do código do aplicativo para o sombreador de vértice sozinho. Ao contrário de um uniforme, você define o valor de cada atributo para cada vértice, o que, por sua vez, permite que cada vértice tenha um valor diferente. As variáveis de atributo são variáveis por vértice. |
Defina um buffer de vértice no código do aplicativo Direct3D e corresponda-o à entrada de vértice definida no sombreador de vértice. Opcionalmente, defina um buffer de índice. Consulte Como criar um buffer de vértice e Como criar um buffer de índice. Crie um layout de entrada no código do aplicativo Direct3D e corresponda os valores semânticos com os da entrada de vértice. Consulte Criar o layout de entrada. |
const Constantes que são compiladas no sombreador e nunca mudam. |
Use uma const. static significa que o valor não é exposto a buffers constantes, const significa que o sombreador não pode alterar o valor. Portanto, o valor é conhecido em tempo de compilação com base em seu inicializador. |
No GLSL, as variáveis sem modificadores são apenas variáveis globais comuns que são privadas para cada sombreador.
Quando você passa dados para texturas (Texture2D em HLSL) e seus samplers associados (SamplerState em HLSL), você normalmente os declara como variáveis globais no sombreador de pixel.
Portabilidade de tipos GLSL para HLSL
Use esta tabela para portar seus tipos de GLSL para HLSL.
Tipo GLSL | Tipo HLSL |
---|---|
Tipos escalares: float, int, bool | Tipos escalares: float, int, bool também, uint, duplo Para obter mais informações, consulte Tipos escalares. |
tipo de vetor
|
tipo de vetor
Para obter mais informações, consulte Tipo de vetor e palavras-chave. vector também é o tipo definido como float4 (typedef vector <float, 4> vector;). Para obter mais informações, consulte Tipo definido pelo usuário. |
Tipo de matriz
|
Tipo de matriz
Você também pode usar o tipo de matriz para definir uma matriz. Por exemplo: matrix <float, 2, 2> fMatrix = {0.0f, 0.1, 2.1f, 2.2f}; matrix também é definido como float4x4 (typedef matrix <float, 4, 4> matrix;). Para obter mais informações, consulte Tipo definido pelo usuário. |
Qualificadores de precisão para float, int, sampler
|
Tipos de precisão
Para obter mais informações, consulte Tipos escalares e Usando a precisão mínima do HLSL. |
amostrador2D | Textura2D |
amostradorCube | TextureCube |
Portabilidade de variáveis globais predefinidas GLSL para HLSL
Use esta tabela para portar variáveis globais predefinidas GLSL para HLSL.
Variável global predefinida GLSL | Semântica HLSL |
---|---|
gl_Position Essa variável é do tipo vec4. Posição do vértice por exemplo - gl_Position = posição; |
SV_Position POSITION no Direct3D 9 Essa semântica é do tipo float4. Saída do sombreador de vértice Posição do vértice por exemplo - float4 vPosition : SV_Position; |
gl_PointSize Essa variável é do tipo float. Tamanho do ponto |
PSIZE Não há sentido, a menos que você direcione o Direct3D 9 Essa semântica é do tipo float. Saída do sombreador de vértice Tamanho do ponto |
gl_FragColor Essa variável é do tipo vec4. Cor do fragmento por exemplo - gl_FragColor = vec4(colorVarying, 1.0); |
SV_Target COLOR no Direct3D 9 Essa semântica é do tipo float4. Saída do sombreador de pixel Cor do pixel por exemplo - float4 Color[4] : SV_Target; |
gl_FragData[n] Essa variável é do tipo vec4. Cor do fragmento para anexo de cor n |
SV_Target[n] Essa semântica é do tipo float4. Valor de saída do sombreador de pixel armazenado em n destino de renderização, em que 0 <= n <= 7. |
gl_FragCoord Essa variável é do tipo vec4. Posição do fragmento no buffer de quadros |
SV_Position Não disponível no Direct3D 9 Essa semântica é do tipo float4. Entrada do sombreador de pixel Coordenadas do espaço da tela por exemplo - float4 screenSpace : SV_Position |
gl_FrontFacing Essa variável é do tipo bool. Determina se o fragmento pertence a um primitivo frontal. |
SV_IsFrontFace VFACE no Direct3D 9 SV_IsFrontFace é do tipo bool. VFACE é do tipo float. Entrada do sombreador de pixel Revestimento primitivo |
gl_PointCoord Essa variável é do tipo vec2. Posição do fragmento dentro de um ponto (somente rasterização de ponto) |
SV_Position VPOS no Direct3D 9 SV_Position é do tipo float4. VPOS é do tipo float2. Entrada do sombreador de pixel O pixel ou a posição de amostra no espaço da tela por exemplo - float4 pos: SV_Position |
gl_FragDepth Essa variável é do tipo float. Dados de buffer de profundidade |
SV_Depth DEPTH no Direct3D 9 SV_Depth é o tipo float. Saída do sombreador de pixel Dados de buffer de profundidade |
Você usa a semântica para especificar posição, cor e assim por diante para entrada de sombreador de vértice e entrada de sombreador de pixel. Você deve corresponder os valores semânticos no layout de entrada com a entrada do sombreador de vértice. Para obter exemplos, consulte Exemplos de portabilidade de variáveis GLSL para HLSL. Para obter mais informações sobre a semântica HLSL, consulte Semântica.
Exemplos de portabilidade de variáveis GLSL para HLSL
Aqui, mostramos exemplos de uso de variáveis GLSL no código OpenGL/GLSL e, em seguida, o exemplo equivalente no código Direct3D/HLSL.
Uniforme, atributo e variação em GLSL
Código do aplicativo OpenGL
// Uniform values can be set in app code and then processed in the shader code.
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
// Incoming position of vertex
attribute vec4 position;
// Incoming color for the vertex
attribute vec3 color;
// The varying variable tells the shader pipeline to pass it
// on to the fragment shader.
varying vec3 colorVarying;
Código do sombreador de vértice GLSL
//The shader entry point is the main method.
void main()
{
colorVarying = color; //Use the varying variable to pass the color to the fragment shader
gl_Position = position; //Copy the position to the gl_Position pre-defined global variable
}
Código do sombreador de fragmento GLSL
void main()
{
//Pad the colorVarying vec3 with a 1.0 for alpha to create a vec4 color
//and assign that color to the gl_FragColor pre-defined global variable
//This color then becomes the fragment's color.
gl_FragColor = vec4(colorVarying, 1.0);
}
Buffers constantes e transferências de dados no HLSL
Aqui está um exemplo de como você passa dados para o sombreador de vértice HLSL que, em seguida, flui para o sombreador de pixel. No código do aplicativo, defina um vértice e um buffer constante. Em seguida, no código do sombreador de vértice, defina o buffer constante como um cbuffer e armazene os dados por vértice e os dados de entrada do sombreador de pixel. Aqui, usamos estruturas chamadas VertexShaderInput e PixelShaderInput.
Código do aplicativo Direct3D
struct ConstantBuffer
{
XMFLOAT4X4 model;
XMFLOAT4X4 view;
XMFLOAT4X4 projection;
};
struct SimpleCubeVertex
{
XMFLOAT3 pos; // position
XMFLOAT3 color; // color
};
// Create an input layout that matches the layout defined in the vertex shader code.
const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
// Create vertex and index buffers that define a geometry.
Código do sombreador de vértice HLSL
cbuffer ModelViewProjectionCB : register( b0 )
{
matrix model;
matrix view;
matrix projection;
};
// The POSITION and COLOR semantics must match the semantics in the input layout Direct3D app code.
struct VertexShaderInput
{
float3 pos : POSITION; // Incoming position of vertex
float3 color : COLOR; // Incoming color for the vertex
};
struct PixelShaderInput
{
float4 pos : SV_Position; // Copy the vertex position.
float4 color : COLOR; // Pass the color to the pixel shader.
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput vertexShaderOutput;
// shader source code
return vertexShaderOutput;
}
Código do sombreador de pixel HLSL
// Collect input from the vertex shader.
// The COLOR semantic must match the semantic in the vertex shader code.
struct PixelShaderInput
{
float4 pos : SV_Position;
float4 color : COLOR; // Color for the pixel
};
// Set the pixel color value for the renter target.
float4 main(PixelShaderInput input) : SV_Target
{
return input.color;
}
Exemplos de portabilidade do código de renderização do OpenGL para o Direct3D
Aqui, mostramos um exemplo de renderização no código OpenGL ES 2.0 e, em seguida, o exemplo equivalente no código Direct3D 11.
Código de renderização OpenGL
// Bind shaders to the pipeline.
// Both vertex shader and fragment shader are in a program.
glUseProgram(m_shader->getProgram());
// Input assembly
// Get the position and color attributes of the vertex.
m_positionLocation = glGetAttribLocation(m_shader->getProgram(), "position");
glEnableVertexAttribArray(m_positionLocation);
m_colorLocation = glGetAttribColor(m_shader->getProgram(), "color");
glEnableVertexAttribArray(m_colorLocation);
// Bind the vertex buffer object to the input assembler.
glBindBuffer(GL_ARRAY_BUFFER, m_geometryBuffer);
glVertexAttribPointer(m_positionLocation, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, m_colorBuffer);
glVertexAttribPointer(m_colorLocation, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// Draw a triangle with 3 vertices.
glDrawArray(GL_TRIANGLES, 0, 3);
Código de renderização do Direct3D
// Bind the vertex shader and pixel shader to the pipeline.
m_d3dDeviceContext->VSSetShader(vertexShader.Get(),nullptr,0);
m_d3dDeviceContext->PSSetShader(pixelShader.Get(),nullptr,0);
// Declare the inputs that the shaders expect.
m_d3dDeviceContext->IASetInputLayout(inputLayout.Get());
m_d3dDeviceContext->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &stride, &offset);
// Set the primitive's topology.
m_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Draw a triangle with 3 vertices. triangleVertices is an array of 3 vertices.
m_d3dDeviceContext->Draw(ARRAYSIZE(triangleVertices),0);
Tópicos relacionados