当您将图形架构从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有许多相似之处。它们都具有类似的渲染管道和图形功能。但Direct3D 11是一个渲染实现和API,而不是规范; OpenGL ES 2.0是一个渲染规范和API,而不是一个实现。Direct3D 11和OpenGL ES 2.0通常在以下方面有所不同:
OpenGL ES 2.0 | Direct3D 11 |
---|---|
与供应商提供的实现的硬件和操作系统无关的规范 | Microsoft在Windows平台上实现硬件抽象和认证 |
为了硬件多样性,运行时管理大多数资源 | 直接访问硬件布局; 应用程序可以管理资源和处理 |
通过第三方库提供更高级别的模块(例如,Simple DirectMedia Layer(SDL)) | 更高级别的模块,如Direct2D,构建在较低的模块上,以简化Windows应用程序的开发 |
硬件供应商通过扩展区分 | Microsoft以通用方式向API添加可选功能,因此它们并非特定于任何特定硬件供应商 |
GLSL和HLSL通常在以下方面有所不同:
GLSL | HLSL |
---|---|
程序性,以步为中心(C之类) | 面向对象,以数据为中心(类似C ++) |
着色器编译集成到图形API中 | 在Direct3D将着色器传递给驱动程序之前,HLSL编译器将着色器编译为中间二进制表示。 注意 此二进制表示与硬件无关。它通常在应用程序构建时编译,而不是在应用程序运行时编译。
|
可变存储修饰符 | 通过输入布局声明传递常量缓冲区和数据 |
类型 典型矢量类型:vec2 / 3/4 lowp,mediump,highp |
典型矢量类型:float2 / 3/4 min10float,min16float |
texture2D [功能] | texture.Sample [datatype.Function] |
sampler2D [数据类型] | Texture2D [数据类型] |
行主矩阵(默认) | 列主矩阵(默认) 注意 使用row_major type-modifier更改一个变量的布局。有关详细信息,请参阅变量语法。您还可以指定编译器标志或编译指示以更改全局默认值。
|
片段着色器 | 像素着色器 |
注意 HLSL将纹理和采样器作为两个单独的对象。在GLSL中,如Direct3D 9,纹理绑定是采样器状态的一部分。
在GLSL中,您将大部分OpenGL状态呈现为预定义的全局变量。例如,使用GLSL,您可以使用gl_Position变量指定顶点位置,使用gl_FragColor变量指定片段颜色。在HLSL中,您将Direct3D状态从应用程序代码显式传递到着色器。例如,对于Direct3D和HLSL,顶点着色器的输入必须与顶点缓冲区中的数据格式匹配,并且应用程序代码中常量缓冲区的结构必须与着色器代码中的常量缓冲区(cbuffer)的结构相匹配。
在GLSL中,将修饰符(限定符)应用于全局着色器变量声明,以便为着色器中的特定行为赋予该变量。在HLSL中,您不需要这些修改器,因为您使用传递给着色器的参数以及从着色器返回的参数定义着色器的流。
GLSL变量行为 | HLSL等价物 |
---|---|
制服 您将应用程序代码中的统一变量传递到顶点和片段着色器之一或两者中。在使用这些着色器绘制任何三角形之前,必须设置所有制服的值,以便在整个三角形网格的绘制过程中它们的值保持不变。这些值是统一的。一些制服被设置为整个帧,而其他制服被唯一地设置为一个特定的顶点像素着色器对。 统一变量是每个多边形变量。 |
使用常量缓冲区。 请参见如何:创建常量缓冲区和着色器常量。 |
不同 您在顶点着色器内初始化变量变量,并将其传递给片段着色器中具有相同名称的变量变量。由于顶点着色器仅在每个顶点设置变量变量的值,因此光栅化器会插入这些值(以透视校正方式)以生成每个片段值以传递到片段着色器。每个三角形的变量都不同。 |
使用从顶点着色器返回的结构作为像素着色器的输入。确保语义值匹配。 |
属性 属性是您从应用程序代码单独传递到顶点着色器的顶点描述的一部分。与制服不同,您可以为每个顶点设置每个属性的值,从而允许每个顶点具有不同的值。属性变量是每顶点变量。 |
在Direct3D应用程序代码中定义顶点缓冲区,并将其与顶点着色器中定义的顶点输入相匹配。(可选)定义索引缓冲区。请参见如何:创建顶点缓冲区以及如何:创建索引缓冲区。 在Direct3D应用程序代码中创建输入布局,并将语义值与顶点输入中的语义值进行匹配。请参见创建输入布局。 |
常量 编译到着色器中的常量永远不会更改。 |
使用静态const。static表示该值不会暴露给常量缓冲区,const表示着色器无法更改该值。因此,该值在编译时基于其初始化程序而已知。 |
在GLSL中,没有修饰符的变量只是每个着色器专用的普通全局变量。
将数据传递给纹理(HLSL中的Texture2D)及其关联的采样器(HLSL中的SamplerState)时,通常会将它们声明为像素着色器中的全局变量。
使用此表将GLSL类型移植到HLSL。
GLSL类型 | HLSL类型 |
---|---|
标量类型:float,int,bool | 标量类型:float,int,bool 另外,uint,double 有关更多信息,请参阅标量类型。 |
矢量类型
|
矢量类型
有关详细信息,请参阅矢量类型和关键字。 vector也是类型定义为float4(typedef vector |
矩阵类型
|
矩阵类型
您还可以使用矩阵类型来定义矩阵。 例如:matrix matrix也被定义为float4x4(typedef matrix |
float,int,sampler的精度限定符
|
精度类型
有关更多信息,请参阅标量类型和使用HLSL最小精度。 |
sampler2D | 的Texture2D |
samplerCube | TextureCube |
使用此表将GLSL预定义的全局变量移植到HLSL。
GLSL预定义的全局变量 | HLSL语义 |
---|---|
GL_POSITION 此变量的类型为vec4。 顶点位置 例如 - gl_Position = position; |
SV_Position Direct3D中的位置9 这个语义是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中的颜色 这个语义是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中的VFACE 9 SV_IsFrontFace是bool类型。 VFACE是float类型。 像素着色器输入 原始面对 |
gl_PointCoord 此变量的类型为vec2。 点内的片段位置(仅限光栅化点) |
SV_Position Direct3D中的VPOS 9 SV_Position是float4类型。 VPOS是float2类型。 像素着色器输入 屏幕空间中的像素或样本位置 例如 - float4 pos:SV_Position |
gl_FragDepth 这个变量是float类型。 深度缓冲数据 |
SV_Depth 深入Direct3D 9 SV_Depth是float类型。 像素着色器输出 深度缓冲数据 |
您可以使用语义为顶点着色器输入和像素着色器输入指定位置,颜色等。您必须将输入布局中的语义值与顶点着色器输入相匹配。有关示例,请参阅将GLSL变量移植到HLSL的示例。有关HLSL语义的更多信息,请参阅语义。
这里我们展示在OpenGL / GLSL代码中使用GLSL变量的示例,然后是Direct3D / HLSL代码中的等效示例。
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顶点着色器然后流入像素着色器的示例。在您的应用程序代码中,定义顶点和常量缓冲区。然后,在顶点着色器代码中,将常量缓冲区定义为cbuffer并存储每顶点数据和像素着色器输入数据。这里我们使用名为VertexShaderInput和PixelShaderInput的结构。
Direct3D应用程序代码
C ++复制
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 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 asssembly
// 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渲染代码
C ++复制
// 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);
我们很想听听你的想法。选择您要提供的类型:
产品反馈
登录以提供文档反馈
我们的反馈系统建立在GitHub问题上。阅读我们的博客。