Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

1

14.08.2013, 22:30

D3D11: Geometry-Shader aber kein Vertex-Shader

Hi,
seit dem es den Geometry-Shader gibt, kann man ja im Shader Code Vertices nach belieben generieren.
Dass man einen Vertex Shader haben kann, der keinen Input hat, also ohne Vertex-Buffer, das weiß ich.
Aber kann man auch komplett auf den Vertex-Shader verzichten, bzw. einen Vertex-Shader ohne Output?

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

2

14.08.2013, 22:54

Afaik nein. Und ich meine, es wird im allgemeinen davon abgeraten, den Geometry Shader groß zum Generieren von Geometrie zu benutzen (aber manchmal im Zusammenspiel mit Cube Maps für Schatten doch getan).
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

3

14.08.2013, 23:02

Der Geometry Shader operiert auf Punkten, Strecken, oder Dreiecken, die er zuvor durch Vertex Shader-Ausgaben gesammelt hat. Hätte der Vertex Shader keine Ausgabe, würde auch nichts gesammelt, womit später der Geometry Shader aufgerufen werden könnte. Du hättest damit die einzige Eingabequelle abgedreht.

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

4

14.08.2013, 23:11

Du hättest damit die einzige Eingabequelle abgedreht.

Nicht ganz, es gibt noch "uint PrimID : SV_PrimitiveID" und natürlich die Constant Buffer.

Simples Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
cbuffer MyBuffer : register(b0)
{
    float4 SomeData[1024];
};
struct SGeometryOutput
{
    float4 Position : SV_Position;
};
struct SDummy
{
};

/* ... */

[maxvertexcount(4)]
void GeometryMain(
    point SDummy In[1],
    uint PrimID : SV_PrimitiveID,
    inout TriangleStream<SGeometryOutput> OutStream)
{
    SGeometryOutput Out = (SGeometryOutput)0;

    for (uint i = 0; i < 4; ++i)
    {
        Out.Position = SomeData[PrimID*4 + i];
        OutStream.Apped(Out);
    }

    OutStream.RestartStrip();
}

Meine Idee ist es, Text mit Hardware-Instancing zu rendern, damit ich pro Zeile Text nur noch einen Draw-Call habe.
Der Geometry-Shader soll also gar keine Unmengen an Vertices generieren. Eben nur 4, also ein Quad für jeden Glyphen ;-)

Der GPU Shader Analyzer von AMD hat mir aber auch gerade gesagt, dass der Geometry Shader Immer einen Input braucht.
Man muss in diesem Fall eine leere Struct angeben, wie oben im Beispiel.

5

14.08.2013, 23:16

Deine Frage war, ob du komplett auf den Vertex Shader verzichten kannst. Nein kannst du nicht; auch ein Vertex Shader, der nur Leerdaten ausgibt, ist noch ein Vertex Shader.

In deinem Beispiel ist es auch zweifelhaft, die Daten via Constant Buffer zu übergeben. Eigentlich ist der Input Assembler genau zu diesem Zweck entwickelt worden … warum also nicht vom Input Assembler fetchen lassen und durch den Vertex Shader zum Geometry Shader durchreichen?

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

6

14.08.2013, 23:25

Da ich Text zeichnen will, kann für jedes Quad ein anderer Glyph dran kommen.
Das soll dann im Vertex-Buffer ausgewählt werden. Der Geometry-Shader kann aber nicht auf den Vertex-Buffer zugreifen.
Und ich kann auch nicht den gesamten Vertex-Buffer vom Vertex- and den Geometry-Shader übergeben.

Bis her hatte ich alle Font-Glyphen in einem Vertex-Buffer und über das Index-Offset in der Funktion "ID3D11DeviceContext::Draw" habe ich dann ausgewählt, welchen Glyphen ich rendern will.
Aber dabei habe ich leider sehr viele Draw-Calls die ich ja nun durch Hardware-Instancing vermeiden will.

Und im Vertex-Shader kann ich auch nicht nach belieben auswählen, welchen Teil des Vertex-Buffers ich haben will,
daher die Idee mit dem Geometry-Shader und den Constant-Buffern.

7

14.08.2013, 23:30

Danke, das erklärt einiges. Es klang so, als wolltest du den Vertex Shader komplett aufgeben.

Noch eine Frage: Wenn du sowieso nur Quads renderst (und keine Buchstabengeometrie), was unterscheidet die Vertices im Vertex Buffer überhaupt noch von einander?

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

8

14.08.2013, 23:32

Naja alle Font-Glyphen sind ja in einer Texture (Sorry, hätte ich vlt. mal erwähnen sollen wie genau ich das mache ^^), für die Vertices wird Position und Texture-Koordinate gespeichert.
Die Position ist wichtig, weil die Quads bzw. die Glyphen ja unterschiedlich groß sein können ;-)

EDIT:
Eine Font-Texture sieht dann z.B. so wie im Anhang aus (hier "Arial Bold" Typ) - nur dass der Hintergrund normaler Weise Transparent ist.
Die Texture generiere ich zur Laufzeit mit WinAPI, Bitmap-Blitting in einen Raw-Buffer, das wird dann als Texture hochgeladen.
Einsortiert werden die einzelnen Glyphen genau so wie die einzelnen Tiles für meine Static Lightmaps.

Gruß,
Lukas
»LukasBanana« hat folgendes Bild angehängt:
  • FontArial.png

9

14.08.2013, 23:41

Und wo ist der Vorteil, diese Daten mit PrimitiveID aus einem Constant Buffer zu laden, statt sie mit dem Vertex Shader zu laden und an den Geometry Shader durchzureichen? Du brauchst für n Buchstaben 4n Einträge über Position und Texturkoordinaten in deinem Constant Buffer; dabei könntest du auch n Punkte mit diesen Informationen anlegen. Statt

C-/C++-Quelltext

1
2
3
4
x1, y1, u1, v1,
x2, y2, u2, v2
x3, y3, u3, v3
x4, y4, u4, v4
im Constant Buffer hättest du dann

C-/C++-Quelltext

1
2
3
4
x, y,
width, height,
u, v,
upixels, uvpixels
im Vertex Shader und würdest daraus im GS deine Quads erzeugen. Das wäre die halbe Bandbreite und nur ein Buffer statt zweien.

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

10

15.08.2013, 00:03

Ich hab noch einen Constant-Buffer der in etwa so aussieht (hier vereinfacht):

C-/C++-Quelltext

1
2
3
4
cbuffer BufferText : register(b1)
{
    uint Text[1024];
};

Da steht der Text drin. Ein Character braucht normaler Weise nur ein "unsigned char", also werden hier 4 Character pro Eintrag im Array gespeichert.
Damit kann der Text maximal 4192 Zeichen lang sein (reicht für eine Zeile Text). Dass da noch bit-weise geshiftet werden muss um aus dem 'uint' die 4 Chars raus zu lesen ignorieren wir jetzt einfach mal.

Im Geometry-Shader brauche ich die Primitive-ID nur um pro Quad zu ermitteln, welches Glyph denn nun gezeichnet werden soll.
Anhand dessen wird dann im anderen Constant-Buffer (der den Vertex-Buffer ersetzt) ausgewählt, welche Vertices benötigt werden:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct SVertex
{
    float2 Position;
    float2 TexCoord;
};
struct SGlyph
{
    SVertex Vertices[4];
};

cbuffer BufferFontGlyphs : register(b2)
{
    SGlyph FontGlyphs[256];
};

/* ... */

SGlyph Glyph = FontGlyphs[Text[PrimID]]; // Quasi so. Im Shader Code sieht's natürlich viel komplizierter aus ^^

Damit wird also Kreuz und Quer auf die Vertices zugegriffen und ich kann nicht davon ausgehen, das alle Vertices der Reihe nach dran kommen.
Also weiß ich nicht, wie ich das anders machen soll, als ich es bisher beschrieben habe.

Aber um noch mal auf die Hauptfrage zurück zukommen:
Ich werde also einen Vertex-Shader angeben, der einfach nichts tut:

C-/C++-Quelltext

1
2
3
4
5
6
7
struct SDummy
{
};
SDummy VertexMain(void)
{
    return (SDummy)0;
}

Werbeanzeige