Compartilhar via


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

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

Types

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

  • vetor de ponto flutuante: vec2, vec3, vec4
  • Vetor booleano: bvec2, bvec3, bvec4
  • Vetor inteiro com sinal: iEC2, iVec3, Ivec4

tipo de vetor

  • float2, float3, float4 e float1
  • bool2, bool3, bool4 e bool1
  • int2, int3, int4 e int1
  • Esses tipos também têm expansões vetoriais semelhantes a float, bool e int:

    • uint
    • min10float, min16float
    • min12int, min16int
    • minuto 16 minutos

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

  • mat2: matriz flutuante 2x2
  • mat3: matriz flutuante 3x3
  • mat4: matriz flutuante 4x4

Tipo de matriz

  • flutuante2x2
  • flutuante3x3
  • flutuante4x4
  • também, float1x1, float1x2, float1x3, float1x4, float2x1, float2x3, float2x4, float3x1, float3x2, float3x4, float4x1, float4x2, float4x3
  • Esses tipos também têm expansões de matriz semelhantes a float:

    • int, uint, bool
    • min10float, min16float
    • min12int, min16int
    • minuto 16 minutos

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

  • alto nível

    Esse qualificador fornece requisitos mínimos de precisão maiores do que os fornecidos pelo min16float e menores do que um float completo de 32 bits. O equivalente em HLSL é:

    flutuador highp -> flutuador

    alta inteligência -> inteligência

  • médio

    Esse qualificador aplicado a float e int é equivalente a min16float e min12int em HLSL. Mínimo de 10 bits de mantissa, não como min10float.

  • baixo

    Esse qualificador aplicado ao float fornece um intervalo de pontos flutuantes de -2 a 2. Equivalente a min10float em HLSL.

Tipos de precisão

  • min16float: valor mínimo de ponto flutuante de 16 bits
  • min10float

    Valor mínimo de 2,8 bits com sinal de ponto fixo (2 bits de número inteiro e componente fracionário de 8 bits). O componente fracionário de 8 bits pode incluir 1 em vez de exclusivo para fornecer a faixa inclusiva completa de -2 a 2.

  • min16int: número inteiro com sinal mínimo de 16 bits
  • min12int: número inteiro com sinal mínimo de 12 bits

    Esse tipo é para 10Level9 (9_x níveis de recursos) em que os inteiros são representados por números de ponto flutuante. Essa é a precisão que você pode obter ao emular um inteiro com um número de ponto flutuante de 16 bits.

  • min16uint: número inteiro sem sinal mínimo de 16 bits

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