GLSL-to-HLSL 參考
將圖形架構從 OpenGL ES 2.0 轉移到 Direct3D 11,為Universal Windows Platform (UWP) 建立遊戲時,可以將 OpenGL Shader Language (GLSL) 程式碼移植到 Microsoft High Level Shader Language (HLSL) 程式碼。 此處所提到的 GLSL 與 OpenGL ES 2.0 相容;HLSL 與 Direct3D 11 相容。 如需 Direct3D 11 與舊版 Direct3D 之間的差異資訊,請參閱 Feature mapping。
- 比較 OpenGL ES 2.0 與 Direct3D 11
- 將 GLSL 變數移轉至HLSL
- 將 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 |
---|---|
具有供應商提供的實現的硬體和作業系統不可知規範 | 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 [Function] | texture.Sample [datatype.Function] |
sampler2D [datatype] | 紋理 2D [datatype] |
列主矩陣 (預設) | 欄主要矩陣 (預設)
備註:使用 row_major 型態修正因子來變更一個變數的版面配置。 如需詳細資訊,請參閱 Variable Syntax。 您也可以指定編譯器旗標或編譯指示來變更全域預設值。
|
片段著色器 | 像素著色器 |
備註:HLSL將紋理和取樣器作為兩個獨立的對象。 與 Direct3D 9 一樣,在 GLSL 中,紋理繫結是取樣器狀態的一部分。
在 GLSL 中,您將大部分 OpenGL 狀態顯示為預定義的全域性變數。 例如,在 GLSL 中,您可以使用 gl_Position 變數指定頂點位置,使用 gl_FragColor 變數指定片段顏色。 在 HLSL 中,您可以將 Direct3D 狀態明確地從應用程式程式碼傳遞至著色器。 例如,使用 Direct3D 和 HLSL,頂點著色器的輸入必須與頂點緩衝區中的資料格式匹配,並且應用程式碼中的常數緩衝區的結構必須與著色器碼中的常數緩衝區 (cbuffer ) 的結構匹配。
將 GLSL 變數移轉至 HLSL
在 GLSL 中,您可以將修飾詞 (限定詞) 應用於全域性著色器變數宣告,以便在著色器中為該變數提供特定的行為。 在 HLSL 中,您不需要這些修飾詞,因為您使用傳遞給著色器並從著色器返回的參數來定義著色器的流程。
GLSL 變數行為 | HLSL 對等項目 |
---|---|
uniform 您可以將應用程式程式碼中的統一變數傳遞至頂點和片段著色器中的任一或兩者。 在使用這些著色器繪製任何三角形之前,您必須設定所有制服的值,以便在繪製三角形網格的整個過程中,它們的值保持不變。 這些值是統一的。 有些校樣是針對整個影格設定的,其他校樣則只針對一個特定的頂點畫素著色器配對。 統一變數是每個多邊形的變數。 |
使用常數緩衝區。 請參閱 How to: Create a Constant Buffer and Shader Constants。 |
varying 您初始化頂點著色器內的變化變數,並將它傳遞至片段著色器中的同名變化變數。 由於頂點著色器僅設定每個頂點上的變化變數的值,因此點陣化程式會插入這些值 (以透視校正的方式),以產生每個片段值,以傳入片段著色器中。 這些變數在每個三角形上有所不同。 |
使用從頂點著色器傳回的結構做為畫素著色器的輸入。 確保語義值匹配。 |
attribute 屬性是頂點描述的一部分,您只從應用程式碼傳遞至頂點著色器。 與統一不同,您可以為每個頂點設定每個屬性的值,這又允許每個頂點有不同的值。 屬性變數是每個頂點的變數。 |
在 Direct3D 應用程式碼中定義頂點緩衝區,並將其與頂點著色器中所定義的頂點輸入比對。 選擇性地定義索引緩衝區。 請參閱 How to: Create a Vertex Buffer 和 How to: Create a Index Buffer。 在 Direct3D 應用程式程式碼中建立輸入配置,並將語義值與頂點輸入中的值進行比對。 請參閱 建立輸入版面配置。 |
const 編譯至著色器且永不變更的常數。 |
使用靜態常數。 static 表示值不會暴露給常數緩衝區,而 const 表示著色器無法變更值。 因此,在編譯時,根據值的初始設定式可知該值。 |
在 GLSL 中,沒有修飾詞的變數只是普通全域性變數,是每個著色器所獨有的。
當您將資料傳遞至紋理 (Texture2D in HLSL) 及其相關取樣器 (SamplerState in HLSL) 時,通常會在畫素著色器中將其宣告為全域變數。
將 GLSL 型別移轉至 HLSL
使用此表格將 GLSL 型別移轉至 HLSL。
GLSL 類型 | HLSL 類型 |
---|---|
純量型別:float、int、bool | 純量型別:float、int、bool 還有,uint,double 如需詳細資訊,請參閱 Scalar Types。 |
向量型別
|
向量型別
如需詳細資訊,請參閱 Vector Type 和 Keywords。 <vector 也是定義為 float4 的型別 >(typedef vector float,4 vector)。 如需詳細資訊,請參閱 User-Defined Type。 |
矩陣型別
|
矩陣型別
您也可以使用 矩陣型別,來定義矩陣。 例如:矩陣<浮點,2,2 f 矩陣= {0.0f, 0.1, >2.1f, 2.2f}; matrix 也是定義為 float4x4 (typedef matrix <float, 4, 4 matrix;) >的型別。 如需詳細資訊,請參閱 User-Defined Type。 |
float、int、sampler 的精確度限定詞
|
精確度型別
|
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 中的色彩 此語意為 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 語意的詳細資訊,請參閱 Semantics。
將 GLSL 變數移轉至 HLSL 的範例
這裡我們給出在 OpenGL/GLSL 程式碼中使用 GLSL 變數的例項,以及在 Direct3D /HLSL 程式碼中使用的等價例項。
GLSL 中的統一、屬性和變化
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 頂點著色器,然後流經畫素著色器。 在您的應用程式碼中,定義頂點與常數緩衝區。 然後,在您的頂點著色器程式碼中,將常數緩衝區定義為緩衝區,並儲存每個頂點資料與畫素著色器輸入資料。 這裡我們使用稱為 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);
相關主題
- 連線埠從 OpenGL ES 2.0 到 Direct3D 11