Wie wirkt sich ein HLSL-Shader tatsächlich auf die Renderausgabe aus?


11

Ich verstehe die Syntax von HLSL. Nehmen wir zum Beispiel an, ich hätte dies als meine HLSL:

struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.position.xy *= 0.7f;    // "shrink" the vertex on the x and y axes
    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

und ich kompiliere es so:

D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
D3DX11CompileFromFile(L"shaders.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0);

Wie gefällt es ... zu ändern ... Ich bin verwirrt darüber, wie genau die Pipeline zwischen HLSL und den tatsächlichen Pixeln / Eckpunkten auf dem Bildschirm ist.

Ist es das, was sie tatsächlich "anwendet"?

dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

// set the shader objects
devcon->VSSetShader(pVS, 0, 0);
devcon->PSSetShader(pPS, 0, 0);

Denken Sie daran, ich bin wie ein Anfänger in diesem Bereich. Kann jemand vielleicht erklären, was es tut? Ich gehe davon aus, dass die Vertex-HLSL-Funktion jeden Vertex durchläuft und sie dann in das ändert, was ich in der Funktion habe, und die Ausgabe wurde geändert ... und ähnlich für den Pixel-Shader?

Eine weitere Verwirrung: Ich weiß, was ein Pixel ist, und ich verstehe, was ein Scheitelpunkt ist ... aber was genau macht der Pixel-Shader?


Das ist in
Ordnung

Antworten:


10

Wie mag es ...... zu ändern wissen .... Ich bin genau an der Pipeline zwischen HLSL und den tatsächlichen Pixeln / Vertex auf dem Bildschirm verwirrt.

Das funktioniert ungefähr so: Wenn Sie einen Draw-Aufruf ausgeben (DrawPrimitives, DrawIndexedPrimitives in D3D, Draw in 10+ usw.), werden die Geometriedaten verarbeitet, die Sie an die Pipeline gebunden haben (Ihre Vertex-Puffer). Für jeden Scheitelpunkt wird der Scheitelpunkt-Shader ausgeführt, um einen Ausgabescheitelpunkt im Clip-Bereich zu erzeugen.

Die GPU führt dann einige feste Funktionen an diesem Scheitelpunkt des Clip-Bereichs aus, z. B. Abschneiden / Keulen und Bringen des Scheitelpunkts in den Bildschirmbereich, wo die Dreiecke gerastert werden. Während der Rasterung jedes Dreiecks interpoliert die GPU Scheitelpunktattribute über die Oberfläche dieses Dreiecks und speist jedes interpolierte Attribut dem Pixel-Shader zu, um eine Halbfinalfarbe für dieses Pixel zu erzeugen (das Mischen wird angewendet, nachdem der Pixel-Shader ausgeführt wurde, also "Semi-" Finale").

ist es das, was sie tatsächlich "anwendet":

Der Code, den Sie zuerst gepostet haben, kompiliert die Shader und bindet sie dann an die Pipeline, wo sie für alle nachfolgenden Draw-Aufrufe aktiv bleiben, bis sie geändert werden. Es führt nicht dazu, dass sie ausgeführt werden.

Kann jemand vielleicht erklären, WAS es tut, wenn ich davon ausgehe, dass die Vertex HLSL-Funktion jeden Vertex durchläuft (als Eingabeposition: POSITION und Farbe: COLOR) und sie dann in das ändert, was ich in der Funktion habe, und die Ausgabe wurde geändert. ... (Gleiches gilt für Pixel Shader).

Eine weitere Verwirrung, ich weiß, was ein Pixel ist, und ich verstehe, was ein Scheitelpunkt ist ..... aber was genau macht der Pixel-Shader ......

Der Vertex-Shader ist für die Transformation von Vertices vom Modellraum in den Clipraum verantwortlich.

Der Pixel-Shader ist für die Berechnung der vorletzten Farbe / Tiefe für ein Pixel basierend auf interpolierten Scheitelpunktattributen verantwortlich.


9

Ich werde versuchen zu erklären, wie die Dinge funktionieren, ohne viel Jargon zu verwenden.

Wenn es um Einfachheit und nicht um interaktive Geschwindigkeit geht, ist eine 3D-Oberfläche im Computer nur eine riesige Wolke von Punkten im Raum, die dicht genug ist, damit wir jeden Punkt einzeln und ohne Lücken zwischen ihnen rendern können.

Sie möchten ein Modell nur einmal im Speicher speichern, müssen es jedoch in verschiedenen Größen und aus verschiedenen Winkeln anzeigen. Wenn Sie also ein 3D-Modell rendern, müssen Sie alle Punkte "transformieren", während Sie sie aus dem Speicher lesen. Um das Modell beispielsweise zu 50% so groß zu machen, müssen Sie die Positionen der Punkte um die Hälfte skalieren:

out.position = in.position * 0.5;
out.color = in.color;

Dies ist fast der einfachste "Vertex-Shader", den man sich vorstellen kann: In geht eine Vertex-Position aus dem Speicher, und aus kommt eine neue Vertex-Position, halb so groß. Der halb so große Scheitelpunkt wird nicht im Speicher gespeichert - er wird sofort zum Rendern verwendet und dann weggeworfen.

Obwohl es sich um eine grobe Vereinfachung handelt, der Schlüsselkonzepte fehlen , beschreibt dies im Geiste Aspekte der Art und Weise, wie Filme Grafiken erstellen.

Interaktive Grafiken (Spiele) können es sich nicht leisten, so einfach zu sein, da sie Grafiken mehrere Größenordnungen schneller als ein Film rendern müssen.

In Spielen können wir es uns nicht leisten, einen Punkt für jedes Pixel auf dem Bildschirm sowie Extras zu rendern, um die Lücken zu schließen. Als Kompromiss wird die Lücke zwischen jeweils drei nahe gelegenen Punkten als Dreieck dargestellt, das aus verschiedenen technischen Gründen mindestens 10 Pixel auf dem Bildschirm bevorzugt.

Ein 3D - Dreieck kann projiziert auf einem 2D - Bildschirm, dann unterteilt in einen Stapel von 1D - Linien, die jeweils in einem Stapel von 0D Pixel unterteilt werden kann. Auf diese Weise können wir das Problem des Renderns eines 3D-Dreiecks in das einfachere Problem des isolierten Renderns vieler 0D-Pixel unterteilen und überwinden. Ein Computer kann einfachere Probleme in kürzerer Zeit lösen.

Ein Pixel-Shader ist ein kleines Programm, das wir für jedes Pixel ausführen, das durch Zerlegen eines Dreiecks erzeugt wird.

out.color = in.color;

Dies ist fast der einfachste "Pixel-Shader", den man sich vorstellen kann: In geht eine Mischung aus den Farben von drei Dreiecksscheitelpunkten und in geht die gleiche Farbe. Die Eingaben stammen von den Ausgaben des "Vertex Shader" und die Ausgaben werden auf den Bildschirm im Speicher geschrieben.

Der "Vertex Shader" ist ein Programm, das im GPU-Chip ausgeführt wird. Seine Eingabe ist ein "Vertex-Puffer" im GPU-Speicher, und seine Ausgabe wird direkt in einen "Pixel-Shader" eingespeist. Ein "Pixel Shader" ist auch ein Programm, das im GPU-Chip ausgeführt wird. Seine Eingaben sind eine Mischung aus drei Scheitelpunkten aus dem Scheitelpunkt-Shader, und seine Ausgabe ist ein Pixel auf dem Bildschirm.



-2

Mach dir jetzt keine Sorgen um einen Pixel-Shader. Wenn Sie ein absoluter Anfänger sind, sollten Sie die Hallo-Welt von GLSL / HLSL nur mit Vertex- und Fragment-Shadern sein. Sobald Sie vertraut sind und beginnen, variable Bewegungen und dergleichen zu verstehen, erweitern Sie Ihren Horizont.

Ich empfehle dringend ein Lehrbuch, um zu erfahren, wie die API funktioniert. OpenGL-Bücher machen auch einen guten Job und veranschaulichen, wie sich die Dinge im Laufe der Jahre von der festen Pipeline zur dynamisch programmierbaren Pipeline verändert haben.

Geh Meister!


1
Ein Fragment-Shader erfüllt die gleiche Funktion wie ein Pixel-Shader.

1
Ich glaube nicht, dass wir anhand der Frage erkennen können, ob das OP überhaupt ein Anfänger in der Spielprogrammierung ist - er gab nur an, dass er ein Anfänger im Schreiben von Shader-Code ist. Lernen Shadern zu schreiben , ist ein sehr wichtiges Instrument in einem Spiel Entwickler-Schuppen haben, würde ich sie nicht nur beschönigen , wenn Sie nur an dem sind sehr Anfangsphase der Lernspielentwicklung.
Olhovsky
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.