GLSL 到 HLSL 参考
将图形体系结构从 OpenGL ES 2.0 移植到 Direct3D 11 以便为通用 Windows 平台 (UWP) 创建游戏时,需要将 OpenGL 着色器语言 (GLSL) 代码移植到 Microsoft 高级着色器语言 (HLSL) 代码。 此处所谈到的 GLSL 兼容 OpenGL ES 2.0;HLSL 兼容 Direct3D 11。 有关 Direct3D 11 和之前版本的 Direct3D 之间差别的信息,请参阅功能映射。
- 比较 OpenGL ES 2.0 与 Direct3D 11
- 将 GLSL 变量移植到 HLSL
- 将 GLSL 类型移植到 HLSL
- 将 GLSL 预定义的全局变量移植到 HLSL
- 将 GLSL 变量移植到 HLSL 的示例
- 将 OpenGL 呈现代码移植到 Direct3D 的示例
- 相关主题
比较 OpenGL ES 2.0 与 Direct3D 11
OpenGL ES 2.0 和 Direct3D 11 有很多相似之处。 它们都有相似的呈现管道和图形功能。 但是 Direct3D 11 是呈现实现和 API,而不是规范;OpenGL ES 2.0 是呈现规范和 API,而不是实现。 Direct3D 11 和 OpenGL ES 2.0 通常会在以下方面有所不同:
OpenGL ES 2.0 | Direct3D 11 |
---|---|
硬件和操作系统规范与供应商提供的实现无关 | 在 Windows 平台上硬件抽象和认证的 Microsoft 实现 |
对硬件多样性进行了抽象,运行时管理大多数资源 | 直接访问硬件布局;应用可以管理资源和处理 |
通过第三方库(例如,Simple DirectMedia Layer (SDL))提供更高级的模块 | 更高级的模块(如 Direct2D)构建在低级模块上,以简化 Windows 应用的开发 |
通过扩展名来区分硬件供应商 | Microsoft 采用常规方法向 API 中添加可选功能,以便这些功能不会特定于任何特定的硬件供应商 |
GLSL 和 HLSL 通常会在以下方面有所不同:
GLSL | HLSL |
---|---|
注重过程,以步骤为中心(如 C) | 面向对象,以数据为中心(如 C++) |
着色器编译被集成到了图形 API 中 | HLSL 编译器将着色器编译为中间二进制表示,然后 Direct3D 将其传递给驱动程序。
注意 此二进制表示与硬件无关。 通常在应用生成时对其进行编译,而不是在应用运行时编译。
|
可变存储修饰符 | 通过输入布局声明进行常量缓冲区和数据传输 |
典型的矢量类型:vec2/3/4 lowp、mediump、highp |
典型的矢量类型:float2/3/4 min10float、min16float |
texture2D [Function] | texture.Sample [datatype.Function] |
sampler2D [datatype] | Texture2D [datatype] |
行主序矩阵(默认设置) | 列主矩阵 (默认值)
注意 使用 row_major 类型修饰符来更改一个变量的布局。 有关详细信息,请参阅变量语法。 还可以指定编译器标志或 pragma 来更改全局默认设置。
|
片段着色器 | 像素着色器 |
注意 HLSL 让纹理和采样器作为两个不同的对象。 在 GLSL(如 Direct3D 9)中,纹理绑定是采样器状态的一部分。
在 GLSL 中,将大多数 OpenGL 状态呈现为预定义的全局变量。 例如,使用 GLSL,gl_Position 变量可用于指定顶点位置,而 gl_FragColor 变量可用于指定片段颜色。 在 HLSL 中,将 Direct3D 状态从应用代码显式传递到着色器。 例如,对于 Direct3D 和 HLSL,顶点着色器的输入必须与顶点缓冲区中的数据格式相匹配,并且应用代码中常量缓冲区的结构必须与着色器代码中常量缓冲区 (cbuffer) 的结构相匹配。
将 GLSL 变量移植到 HLSL
在 GLSL 中,将修饰符(限定符)应用于全局着色器变量声明,以为该变量提供一个你的着色器中的特定行为。 在 HLSL 中,不需要这些修饰符,因为你使用传递给着色器的参数以及从着色器返回的参数定义了着色器流。
GLSL 变量行为 | HLSL 等效内容 |
---|---|
uniform 将 uniform 变量从应用代码传递到顶点着色器和分段着色器或传递到两者。 必须在使用这些着色器绘制任何三角形之前,设置所有 uniform 的值,以便它们的值在绘制三角形网格的整个过程中保持不变。 这些值都是 uniform。 一些 uniform 是针对整个帧设置的,另一些 uniform 唯一对应于一个特定的顶点像素着色器对。 uniform 变量是每个多边形的变量。 |
使用常量缓冲区。 请参阅如何:创建常量缓冲区和着色器常量。 |
varying 在顶点着色器内初始化一个 varying 变量,并将其传递到片段着色器中具有相同名称的 varying 变量。 由于顶点着色器仅设置每个顶点上的 varying 变量的值,因此光栅器会插入这些值(采用透视校正的方式),以生成每个要传递到片段着色器中的片段值。 这些变量在各个三角形之间有所不同。 |
使用从顶点着色器返回的结构作为像素着色器的输入。 确保语义值相匹配。 |
attribute attribute 只是你从应用代码传递到顶点着色器的顶点描述的一部分。 与 uniform 不同,你为每个顶点设置每个 attribute 的值,但却允许每个顶点拥有不同的值。 attribute 变量是每个顶点的变量。 |
在 Direct3D 应用代码中定义顶点缓冲区并将其与顶点着色器中定义的顶点输入相匹配。 也可以定义索引缓冲区。 请参阅如何:创建顶点缓冲区和如何:创建索引缓冲区。 在 Direct3D 应用代码中创建输入布局并将语义值与顶点输入中的值相匹配。 请参阅创建输入布局。 |
const 常量编译到着色器中,从不更改。 |
使用 static const。 static 表示未向常量缓冲区显示该值,const 表示着色器无法更改该值。 因此,在编译时我们根据它的初始值来了解该值。 |
在 GLSL 中,没有修饰符的变量只是普通的全局变量,它们是每个着色器的私有变量。
当将数据传递到纹理(在 HLSL 中为 Texture2D)及其关联的采样器 (在 HLSL 中为 SamplerState)时,通常会在像素着色器中将它们声明为全局变量。
将 GLSL 类型移植到 HLSL
使用该表将 GLSL 类型移植到 HLSL。
GLSL 类型 | HLSL 类型 |
---|---|
标量类型:float、int、bool | 标量类型:float、int、bool also、uint、double 有关详细信息,请参阅标量类型。 |
矢量类型
|
矢量类型
vector 是定义为 float4 的 also 类型 (typedef vector <float, 4> vector;)。 有关详细信息,请参阅用户定义的类型。 |
矩阵类型
|
矩阵类型
也可以使用矩阵类型来定义矩阵。 例如:matrix <float, 2, 2> fMatrix = {0.0f, 0.1, 2.1f, 2.2f}; matrix 是定义为 float4x4 的 also 类型 (typedef matrix <float, 4, 4> matrix;)。 有关详细信息,请参阅用户定义的类型。 |
float、int、sampler 的精度限定符
|
精度类型
有关详细信息,请参阅标量类型和使用 HLSL 最低精度。 |
sampler2D | Texture2D |
samplerCube | TextureCube |
将 GLSL 预定义的全局变量移植到 HLSL
使用该表将 GLSL 预定义的全局变量移植到 HLSL。
GLSL 预定义的全局变量 | HLSL 语义 |
---|---|
gl_Position 该变量为 vec4 类型。 顶点位置 例如 - gl_Position = position; |
SV_Position 在 Direct3D 9 中为 POSITION 该语义为 float4 类型。 顶点着色器输出 顶点位置 例如 - float4 vPosition : SV_Position; |
gl_PointSize 该变量为 float 类型。 点大小 |
PSIZE 除非你的目标是 Direct3D 9,否则没有意义 该语义为 float 类型。 顶点着色器输出 点大小 |
gl_FragColor 该变量为 vec4 类型。 片段颜色 例如 - gl_FragColor = vec4(colorVarying, 1.0); |
SV_Target 在 Direct3D 9 中为 COLOR 该语义为 float4 类型。 像素着色器输出 像素颜色 例如 - float4 Color[4] : SV_Target; |
gl_FragData[n] 该变量为 vec4 类型。 颜色附件 n 的片段颜色 |
SV_Target[n] 该语义为 float4 类型。 n 呈现目标中存储的像素着色器输出值,其中 0 <= n <= 7。 |
gl_FragCoord 该变量为 vec4 类型。 帧缓冲区中的片段位置 |
SV_Position 在 Direct3D 9 中不可用 该语义为 float4 类型。 像素着色器输入 屏幕空间坐标 例如 - float4 screenSpace : SV_Position |
gl_FrontFacing 该变量为 bool 类型。 确定片段是否属于正面基元。 |
SV_IsFrontFace 在 Direct3D 9 中为 VFACE SV_IsFrontFace 为 bool 类型。 VFACE 为 float 类型。 像素着色器输入 基元朝向 |
gl_PointCoord 该变量为 vec2 类型。 某个点中的片段位置(仅限点光栅化) |
SV_Position 在 Direct3D 9 中为 VPOS SV_Position 为 float4 类型。 VPOS 为 float2 类型。 像素着色器输入 屏幕空间中的像素或示例位置 例如 - float4 pos : SV_Position |
gl_FragDepth 该变量为 float 类型。 深度缓冲区数据 |
SV_Depth 在 Direct3D 9 中为 DEPTH SV_Depth 为 float 类型。 像素着色器输出 深度缓冲区数据 |
使用语义指定位置、颜色等作为顶点着色器输入和像素着色器输入。 必须将输入布局中的语义值与顶点着色器输入相匹配。 例如,请参阅将 GLSL 变量移植到 HLSL 的示例。 有关 HLSL 语义的详细信息,请参阅语义。
将 GLSL 变量移植到 HLSL 的示例
下面我们介绍在 OpenGL/GLSL 代码中使用 GLSL 变量的示例,然后介绍在 Direct3D/HLSL 代码中的等效示例。
GLSL 中的 uniform、attribute 和 varying
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;
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
}
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);
}
HLSL 中的常量缓冲区和数据传输
下面是如何将数据传递到 HLSL 顶点着色器,然后流动到像素着色器的示例。 在你的应用代码中,定义一个顶点缓冲区和一个常量缓冲区。 然后,在你的顶点着色器代码中,将常量缓冲区定义为 cbuffer 并存储每个顶点数据以及像素着色器输入数据。 这里我们使用名为 VertexShaderInput 和 PixelShaderInput 的结构。
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.
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;
}
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;
}
将 OpenGL 呈现代码移植到 Direct3D 的示例
下面我们介绍一个在 OpenGL ES 2.0 代码中进行呈现的示例,然后介绍在 Direct3D 11 代码中的等效示例。
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);
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);
相关主题