GLSL-zu-HLSL-Referenz
Sie portieren Ihren OpenGL Shader Language (GLSL)-Code zu Microsoft High Level Shader Language (HLSL)-Code, wenn Sie die Grafikarchitektur von OpenGL ES 2.0 zu Direct3D 11 portieren, um ein Spiel für Universelle Windows-Plattform (UWP) zu erstellen. Die hierin genannte GLSL ist mit OpenGL ES 2.0 kompatibel; hlSL ist mit Direct3D 11 kompatibel. Informationen zu den Unterschieden zwischen Direct3D 11 und früheren Versionen von Direct3D finden Sie unter Featurezuordnung.
- Vergleich von OpenGL ES 2.0 mit Direct3D 11
- Portieren von GLSL-Variablen zu HLSL
- Portieren von GLSL-Typen zu HLSL
- Portieren vordefinierter globaler GLSL-Variablen zu HLSL
- Beispiele für das Portieren von GLSL-Variablen zu HLSL
- Beispiele für das Portieren von OpenGL-Renderingcode zu Direct3D
- Verwandte Themen
Vergleich von OpenGL ES 2.0 mit Direct3D 11
OpenGL ES 2.0 und Direct3D 11 weisen viele Ähnlichkeiten auf. Beide weisen ähnliche Renderingpipelinen und Grafikfeatures auf. Direct3D 11 ist jedoch eine Renderingimplementierung und API, keine Spezifikation; OpenGL ES 2.0 ist eine Renderingspezifikation und API, keine Implementierung. Direct3D 11 und OpenGL ES 2.0 unterscheiden sich in der Regel auf folgende Weise:
OpenGL ES 2.0 | Direct3D 11 |
---|---|
Hardware- und Betriebssystemunabhängige Spezifikation mit vom Anbieter bereitgestellten Implementierungen | Microsoft-Implementierung der Hardwarestraktion und -zertifizierung auf Windows-Plattformen |
Abstrahiert für die Hardwarevielfalt verwaltet die Laufzeit die meisten Ressourcen. | Direkter Zugriff auf das Hardwarelayout; App kann Ressourcen und Verarbeitung verwalten |
Stellt Module auf höherer Ebene über Drittanbieterbibliotheken bereit (z. B. Simple DirectMedia Layer (SDL)) | Module auf höherer Ebene wie Direct2D basieren auf niedrigeren Modulen, um die Entwicklung für Windows-Apps zu vereinfachen. |
Hardwareanbieter unterscheiden sich über Erweiterungen | Microsoft fügt der API optionale Features auf generische Weise hinzu, sodass sie nicht für einen bestimmten Hardwareanbieter spezifisch sind. |
GLSL und HLSL unterscheiden sich in der Regel auf folgende Weise:
GLSL | HLSL |
---|---|
Prozedural, schrittzentriert (Z wie) | Objektorientierte, datenorientierte (c++-like) |
In die Grafik-API integrierte Shaderkompilierung | Der HLSL-Compiler kompiliert den Shader zu einer binären Zwischendarstellung, bevor Direct3D ihn an den Treiber übergibt.
Beachten Sie , dass diese binäre Darstellung hardwareunabhängig ist. Sie wird in der Regel zur App-Buildzeit kompiliert und nicht zur App-Laufzeit.
|
Variable Speichermodifizierer | Konstantenpuffer und Datenübertragungen über Eingabelayoutdeklarationen |
Typischer Vektortyp: vec2/3/4 lowp, mediump, highp |
Typischer Vektortyp: float2/3/4 min10float, min16float |
texture2D [Funktion] | Textur. Beispiel [Datentyp. Funktion] |
sampler2D [Datentyp] | Texture2D [Datentyp] |
Zeilenmatrizen (Standard) | Spaltenmatrizen (Standard)
Hinweis : Verwenden Sie den row_major Typmodifizierer, um das Layout für eine Variable zu ändern. Weitere Informationen finden Sie unter Variable Syntax. Sie können auch ein Compilerflagge oder ein Pragma angeben, um den globalen Standardwert zu ändern.
|
Fragment-Shader | Pixel-Shader |
Beachten Sie, dass HLSL Texturen und Sampler als zwei separate Objekte enthält. In GLSL wie Direct3D 9 ist die Texturbindung Teil des Samplerzustands.
In GLSL stellen Sie einen Großteil des OpenGL-Zustands als vordefinierte globale Variablen dar. Bei GLSL verwenden Sie z. B. die gl_Position Variable, um die Vertexposition und die gl_FragColor Variable anzugeben, um die Fragmentfarbe anzugeben. In HLSL übergeben Sie den Direct3D-Zustand explizit vom App-Code an den Shader. Bei Direct3D und HLSL muss die Eingabe an den Vertex-Shader beispielsweise mit dem Datenformat im Vertexpuffer übereinstimmen, und die Struktur eines Konstantenpuffers im App-Code muss mit der Struktur eines Konstantenpuffers (cbuffer) im Shadercode übereinstimmen.
Portieren von GLSL-Variablen zu HLSL
In GLSL wenden Sie Modifizierer (Qualifizierer) auf eine globale Shadervariablendeklaration an, um dieser Variable ein bestimmtes Verhalten in Ihren Shadern zuzuweisen. In HLSL benötigen Sie diese Modifizierer nicht, da Sie den Fluss des Shaders mit den Argumenten definieren, die Sie an den Shader übergeben und von Ihrem Shader zurückgeben.
GLSL-Variablenverhalten | HLSL-Entsprechung |
---|---|
Uniform Sie übergeben eine einheitliche Variable aus dem App-Code entweder an Vertex- und Fragment-Shader. Sie müssen die Werte aller Uniformen festlegen, bevor Sie Dreiecke mit diesen Shadern zeichnen, damit ihre Werte während der Zeichnung eines Dreiecksgitters gleich bleiben. Diese Werte sind einheitlich. Einige Uniforms werden für den gesamten Frame und andere eindeutig auf ein bestimmtes Vertex-Pixelshaderpaar festgelegt. Uniform-Variablen sind Polygonvariablen. |
Verwenden Sie den Konstantenpuffer. Siehe Vorgehensweise: Erstellen eines Konstantenpuffers und Shaderkonstanten. |
variierend Sie initialisieren eine unterschiedliche Variable innerhalb des Vertex-Shaders und übergeben sie an eine identisch benannte variable im Fragment-Shader. Da der Vertex-Shader nur den Wert der unterschiedlichen Variablen an jedem Scheitelpunkt festlegt, interpoliert der Rasterizer diese Werte (perspektivisch korrekt), um pro Fragmentwerte zu generieren, die an den Fragmentshader übergeben werden. Diese Variablen variieren je nach Dreieck. |
Verwenden Sie die Struktur, die Sie vom Vertex-Shader als Eingabe für den Pixelshader zurückgeben. Stellen Sie sicher, dass die semantischen Werte übereinstimmen. |
attribute Ein Attribut ist Teil der Beschreibung eines Scheitelpunkts, den Sie allein vom App-Code an den Vertex-Shader übergeben. Im Gegensatz zu einer Uniform legen Sie den Wert jedes Attributs für jeden Scheitelpunkt fest, der wiederum jedem Scheitelpunkt einen anderen Wert zulässt. Attributvariablen sind Vertexvariablen. |
Definieren Sie einen Vertexpuffer im Direct3D-App-Code, und stimmen Sie ihn mit der im Vertex-Shader definierten Vertexeingabe überein. Definieren Sie optional einen Indexpuffer. Weitere Informationen finden Sie unter How to: Create a Vertex Buffer and How to: Create an Index Buffer. Erstellen Sie ein Eingabelayout in Ihrem Direct3D-App-Code, und stimmen Sie semantische Werte mit denen in der Vertexeingabe überein. Siehe Erstellen des Eingabelayouts. |
const Konstanten, die in den Shader kompiliert und nie geändert werden. |
Verwenden Sie einen statischen Konst. statisch bedeutet, dass der Wert nicht für Konstantenpuffer verfügbar gemacht wird. Const bedeutet, dass der Shader den Wert nicht ändern kann. Der Wert wird also zur Kompilierungszeit basierend auf seinem Initialisierer bekannt. |
In GLSL sind Variablen ohne Modifizierer nur gewöhnliche globale Variablen, die für jeden Shader privat sind.
Wenn Sie Daten an Texturen (Texture2D in HLSL) und die zugehörigen Sampler (SamplerState in HLSL) übergeben, deklarieren Sie sie in der Regel als globale Variablen im Pixelshader.
Portieren von GLSL-Typen zu HLSL
Verwenden Sie diese Tabelle, um Ihre GLSL-Typen zu HLSL zu portieren.
GLSL-Typ | HLSL-Typ |
---|---|
Skalare Typen: float, int, bool | Skalare Typen: float, int, bool auch, uint, double Weitere Informationen finden Sie unter Skalartypen. |
Vektortyp
|
Vektortyp
Weitere Informationen finden Sie unter Vektortyp und Schlüsselwörter. Vektor ist auch typ definiert als float4 (typedef vector <float, 4> vector;). Weitere Informationen finden Sie unter "Benutzerdefinierter Typ". |
Matrixtyp
|
Matrixtyp
Sie können auch den Matrixtyp verwenden, um eine Matrix zu definieren. Beispiel: Matrix <float, 2, 2> fMatrix = {0.0f, 0.1, 2.1f, 2.2f}; matrix is also type defined as float4x4 (typedef matrix <float, 4, 4> matrix;). Weitere Informationen finden Sie unter "Benutzerdefinierter Typ". |
Genauigkeitsqualifizierer für float, int, sampler
|
Genauigkeitstypen
Weitere Informationen finden Sie unter Scalar Types and Using HLSL minimum precision. |
Sampler2D | Texture2D |
samplerCube | TextureCube |
Portieren vordefinierter globaler GLSL-Variablen zu HLSL
Verwenden Sie diese Tabelle, um vordefinierte globale GLSL-Variablen zu HLSL zu portieren.
VORDEFINIERTE globale GLSL-Variable | HLSL-Semantik |
---|---|
gl_Position Diese Variable ist typ vec4. Vertexposition z. B. - gl_Position = Position; |
SV_Position POSITION in Direct3D 9 Diese Semantik ist " float4". Vertex-Shaderausgabe Vertexposition beispiel - float4 vPosition : SV_Position; |
gl_PointSize Diese Variable ist typ float. Punktgröße |
PSIZE Keine Bedeutung, es sei denn, Sie zielen auf Direct3D 9 ab Diese Semantik ist " Float". Vertex-Shaderausgabe Punktgröße |
gl_FragColor Diese Variable ist typ vec4. Fragmentfarbe beispiel - gl_FragColor = vec4(colorVarying, 1,0); |
SV_Target COLOR in Direct3D 9 Diese Semantik ist " float4". Pixelshaderausgabe Pixelfarbe beispiel - float4 Color[4] : SV_Target; |
gl_FragData[n] Diese Variable ist typ vec4. Fragmentfarbe für Farbanlage n |
SV_Target[n] Diese Semantik ist " float4". Der Ausgabewert des Pixelshaders, der im Renderziel n gespeichert ist, wobei 0 <= n <= 7 ist. |
gl_FragCoord Diese Variable ist typ vec4. Fragmentposition innerhalb des Framepuffers |
SV_Position In Direct3D 9 nicht verfügbar Diese Semantik ist " float4". Pixelshadereingabe Bildschirmraumkoordinaten beispiel - float4 screenSpace : SV_Position |
gl_FrontFacing Diese Variable ist typ bool. Bestimmt, ob das Fragment zu einem frontseitigen Grundtyp gehört. |
SV_IsFrontFace VFACE in Direct3D 9 SV_IsFrontFace ist typ bool. VFACE ist typ float. Pixelshadereingabe Grundtyp mit Vorrichtung |
gl_PointCoord Diese Variable ist typ vec2. Fragmentposition innerhalb eines Punkts (nur Punktrasterung) |
SV_Position VPOS in Direct3D 9 SV_Position ist " float4". VPOS ist typ float2. Pixelshadereingabe Die Pixel- oder Beispielposition im Bildschirmbereich beispiel - float4 pos : SV_Position |
gl_FragDepth Diese Variable ist typ float. Tiefenpufferdaten |
SV_Depth TIEFE in Direct3D 9 SV_Depth ist " Float". Pixelshaderausgabe Tiefenpufferdaten |
Mithilfe der Semantik können Sie Position, Farbe usw. für vertex-Shadereingaben und Pixelshadereingaben angeben. Sie müssen mit den Semantikwerten im Eingabelayout mit der Vertex-Shadereingabe übereinstimmen. Beispiele finden Sie unter Beispiele für das Portieren von GLSL-Variablen zu HLSL. Weitere Informationen zur HLSL-Semantik finden Sie unter Semantik.
Beispiele für das Portieren von GLSL-Variablen zu HLSL
Hier zeigen wir Beispiele für die Verwendung von GLSL-Variablen im OpenGL/GLSL-Code und dann das entsprechende Beispiel in Direct3D/HLSL-Code.
Uniform, Attribut und unterschiedliche In GLSL
OpenGL-App-Code
// 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-Vertex-Shadercode
//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-Fragmentshadercode
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);
}
Konstantenpuffer und Datenübertragungen in HLSL
Hier sehen Sie ein Beispiel dafür, wie Sie Daten an den HLSL-Vertex-Shader übergeben, der dann zum Pixelshader fließt. Definieren Sie im App-Code einen Scheitelpunkt und einen Konstantenpuffer. Definieren Sie dann im Vertex-Shadercode den Konstantenpuffer als cbuffer , und speichern Sie die Daten pro Vertex und die Pixel-Shadereingabedaten. Hier verwenden wir Strukturen namens "VertexShaderInput " und "PixelShaderInput".
Direct3D-App-Code
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-Vertex-Shadercode
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-Pixelshadercode
// 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;
}
Beispiele für das Portieren von OpenGL-Renderingcode zu Direct3D
Hier zeigen wir ein Beispiel für das Rendern in OpenGL ES 2.0-Code und dann das entsprechende Beispiel im Direct3D 11-Code.
OpenGL-Renderingcode
// 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-Renderingcode
// 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);
Zugehörige Themen