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

04.07.2010, 19:25

GLSL Geometry Shader

Hi,
ich habe in zwischen etwas mit den Geometry Shadern in GLSL für OpenGL in Erfahrung (auch Praktische) bringen können.
Allerdings bin ich schon ein wenig verwundert über "gl_VerticesIn" das die Anzahl Vertices angibt - so dachte ich zumindest.
Ich habe einen Würfel mit 8 Vertices. Aber "gl_VerticesIn" scheint nur den Wert '3' zu haben. So sieht mein Geometry Shader aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#version 120 
#extension GL_EXT_geometry_shader4 : enable

void ProcessVertex(int i)
{
    gl_Position = gl_PositionIn[i];
    gl_TexCoord = gl_TexCoordIn[i];
    EmitVertex();
}

void main(void)
{
    int i;
    
    for (i = 0; i < gl_VerticesIn; ++i)
        ProcessVertex(i);
    
    EndPrimitive();
}


Dieser Geometry Shader sorgt dafür, dass mein Würfel bzw. das zu zeichnende Modell vollständig gerendert wird. Es werden Vertex Koordinaten und Texture Koordinaten übergeben.
So weit so gut, wenn ich jetzt in der for-Schleife "i < gl_VerticesIn - 1" schreibe sollte er ja eigentlich das letzte Vertex weg lassen.
Da zeichnet er aber gar nichts. Wenn ich "i < gl_VerticesIn + 1" schreibe macht er einen ganz widerligen Grafikfehler ^^.
Aber ich habe es schon mit einer festen Zahl getestet. Es geht nur mit "3" bzw. "i < 3" oder halt "i < gl_VerticesIn" also muss in gl_VerticesIn '3' stehen.
Aber warum?? Wenn ich doch einen Würfel mit ganzen 8 Vertices habe??
Kann mir bitte jamnd erklärem was genau ein Geometry Shader macht?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

04.07.2010, 20:05

Mir scheint du hast da was falsch verstanden. Der Geometry Shader wird für jedes einzelne Primitve (in deinem Fall wohl Dreieck) ausgeführt und nicht einmal für alle Primitves...

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

3

04.07.2010, 20:16

Ausgezeichnet, danke :D

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

4

04.07.2010, 20:32

Kann sein, dass Rekurive Funktionsaufrufe in Shadern bzw. Geometrie Shadern (GLSL) nicht möglich sind? ?(
Ich versuche mich nämlich gerade mal an Tessellation und dafür wäre sowas ganz nett.
Das ist mein Code:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#version 120 
#extension GL_EXT_geometry_shader4 : enable

void ProcessVertex(vec4 Pos, vec4 TexCoord)
{
    gl_Position = Pos;
    gl_TexCoord[0] = TexCoord;
    EmitVertex();
}

void ProcessPrimitive(
    vec4 Pos0, vec4 Pos1, vec4 Pos2,
    vec4 TexCoord0, vec4 TexCoord1, vec4 TexCoord2)
{
    ProcessVertex(Pos0, TexCoord0);
    ProcessVertex(Pos1, TexCoord1);
    ProcessVertex(Pos2, TexCoord2);
    EndPrimitive();
}

void TessellatePrimitive(
    vec4 Pos0, vec4 Pos1, vec4 Pos2,
    vec4 TexCoord0, vec4 TexCoord1, vec4 TexCoord2, inout int Fork)
{
    vec4 Pos3 = (Pos1 + Pos0) * 0.5;
    vec4 Pos4 = (Pos2 + Pos1) * 0.5;
    vec4 Pos5 = (Pos0 + Pos2) * 0.5;
    
    vec4 TexCoord3 = (TexCoord1 + TexCoord0) * 0.5;
    vec4 TexCoord4 = (TexCoord2 + TexCoord1) * 0.5;
    vec4 TexCoord5 = (TexCoord0 + TexCoord2) * 0.5;
    
    if (Fork > 0)
    {
        --Fork;
        TessellatePrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5, Fork);
        TessellatePrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4, Fork);
        TessellatePrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4, Fork);
        TessellatePrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2, Fork);
    }
    else
    {
        ProcessPrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5);
        ProcessPrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4);
        ProcessPrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4);
        ProcessPrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2);
    }
}

void main(void)
{
    if (gl_VerticesIn != 3)
        return;
    
    int Fork = 0;
    TessellatePrimitive(
        gl_PositionIn[0], gl_PositionIn[1], gl_PositionIn[2],
        gl_TexCoordIn[0][0], gl_TexCoordIn[1][0], gl_TexCoordIn[2][0], Fork
    );
}


Und das die Fehlermeldung:

Quellcode

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
Geometry info
-------------
0(85) : error C5005: recursive call to function "void TessellatePrimitive(vec4, vec4, vec4, vec4, vec4, vec4, int){
  in vec4 Pos0; 
  in vec4 Pos1; 
  in vec4 Pos2; 
  in vec4 TexCoord0; 
  in vec4 TexCoord1; 
  in vec4 TexCoord2; 
  in out int Fork; 
  vec4 Pos3 = (Pos1 + Pos0) * 0.5f; 
  vec4 Pos4 = (Pos2 + Pos1) * 0.5f; 
  vec4 Pos5 = (Pos0 + Pos2) * 0.5f; 
  vec4 TexCoord3 = (TexCoord1 + TexCoord0) * 0.5f; 
  vec4 TexCoord4 = (TexCoord2 + TexCoord1) * 0.5f; 
  vec4 TexCoord5 = (TexCoord0 + TexCoord2) * 0.5f; 
  Pos3 := (Pos1 + Pos0) * 0.5f;
  Pos4 := (Pos2 + Pos1) * 0.5f;
  Pos5 := (Pos0 + Pos2) * 0.5f;
  TexCoord3 := (TexCoord1 + TexCoord0) * 0.5f;
  TexCoord4 := (TexCoord2 + TexCoord1) * 0.5f;
  TexCoord5 := (TexCoord0 + TexCoord2) * 0.5f;
  if (Fork > 0) {
    --Fork;
    TessellatePrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5, Fork);
    TessellatePrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4, Fork);
    TessellatePrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4, Fork);
    TessellatePrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2, Fork);
  } else {
    ProcessPrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5);
    ProcessPrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4);
    ProcessPrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4);
    ProcessPrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2);
  }
} 
"
0(85) : error C5005: recursive call to function "void TessellatePrimitive(vec4, vec4, vec4, vec4, vec4, vec4, int){
  in vec4 Pos0; 
  in vec4 Pos1; 
  in vec4 Pos2; 
  in vec4 TexCoord0; 
  in vec4 TexCoord1; 
  in vec4 TexCoord2; 
  in out int Fork; 
  vec4 Pos3 = (Pos1 + Pos0) * 0.5f; 
  vec4 Pos4 = (Pos2 + Pos1) * 0.5f; 
  vec4 Pos5 = (Pos0 + Pos2) * 0.5f; 
  vec4 TexCoord3 = (TexCoord1 + TexCoord0) * 0.5f; 
  vec4 TexCoord4 = (TexCoord2 + TexCoord1) * 0.5f; 
  vec4 TexCoord5 = (TexCoord0 + TexCoord2) * 0.5f; 
  Pos3 := (Pos1 + Pos0) * 0.5f;
  Pos4 := (Pos2 + Pos1) * 0.5f;
  Pos5 := (Pos0 + Pos2) * 0.5f;
  TexCoord3 := (TexCoord1 + TexCoord0) * 0.5f;
  TexCoord4 := (TexCoord2 + TexCoord1) * 0.5f;
  TexCoord5 := (TexCoord0 + TexCoord2) * 0.5f;
  if (Fork > 0) {
    --Fork;
    TessellatePrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5, Fork);
    TessellatePrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4, Fork);
    TessellatePrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4, Fork);
    TessellatePrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2, Fork);
  } else {
    ProcessPrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5);
    ProcessPrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4);
    ProcessPrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4);
    ProcessPrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2);
  }
} 
"
0(85) : error C5005: recursive call to function "void TessellatePrimitive(vec4, vec4, vec4, vec4, vec4, vec4, int){
  in vec4 Pos0; 
  in vec4 Pos1; 
  in vec4 Pos2; 
  in vec4 TexCoord0; 
  in vec4 TexCoord1; 
  in vec4 TexCoord2; 
  in out int Fork; 
  vec4 Pos3 = (Pos1 + Pos0) * 0.5f; 
  vec4 Pos4 = (Pos2 + Pos1) * 0.5f; 
  vec4 Pos5 = (Pos0 + Pos2) * 0.5f; 
  vec4 TexCoord3 = (TexCoord1 + TexCoord0) * 0.5f; 
  vec4 TexCoord4 = (TexCoord2 + TexCoord1) * 0.5f; 
  vec4 TexCoord5 = (TexCoord0 + TexCoord2) * 0.5f; 
  Pos3 := (Pos1 + Pos0) * 0.5f;
  Pos4 := (Pos2 + Pos1) * 0.5f;
  Pos5 := (Pos0 + Pos2) * 0.5f;
  TexCoord3 := (TexCoord1 + TexCoord0) * 0.5f;
  TexCoord4 := (TexCoord2 + TexCoord1) * 0.5f;
  TexCoord5 := (TexCoord0 + TexCoord2) * 0.5f;
  if (Fork > 0) {
    --Fork;
    TessellatePrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5, Fork);
    TessellatePrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4, Fork);
    TessellatePrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4, Fork);
    TessellatePrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2, Fork);
  } else {
    ProcessPrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5);
    ProcessPrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4);
    ProcessPrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4);
    ProcessPrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2);
  }
} 
"
0(85) : error C5005: recursive call to function "void TessellatePrimitive(vec4, vec4, vec4, vec4, vec4, vec4, int){
  in vec4 Pos0; 
  in vec4 Pos1; 
  in vec4 Pos2; 
  in vec4 TexCoord0; 
  in vec4 TexCoord1; 
  in vec4 TexCoord2; 
  in out int Fork; 
  vec4 Pos3 = (Pos1 + Pos0) * 0.5f; 
  vec4 Pos4 = (Pos2 + Pos1) * 0.5f; 
  vec4 Pos5 = (Pos0 + Pos2) * 0.5f; 
  vec4 TexCoord3 = (TexCoord1 + TexCoord0) * 0.5f; 
  vec4 TexCoord4 = (TexCoord2 + TexCoord1) * 0.5f; 
  vec4 TexCoord5 = (TexCoord0 + TexCoord2) * 0.5f; 
  Pos3 := (Pos1 + Pos0) * 0.5f;
  Pos4 := (Pos2 + Pos1) * 0.5f;
  Pos5 := (Pos0 + Pos2) * 0.5f;
  TexCoord3 := (TexCoord1 + TexCoord0) * 0.5f;
  TexCoord4 := (TexCoord2 + TexCoord1) * 0.5f;
  TexCoord5 := (TexCoord0 + TexCoord2) * 0.5f;
  if (Fork > 0) {
    --Fork;
    TessellatePrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5, Fork);
    TessellatePrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4, Fork);
    TessellatePrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4, Fork);
    TessellatePrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2, Fork);
  } else {
    ProcessPrimitive(Pos0, Pos3, Pos5, TexCoord0, TexCoord3, TexCoord5);
    ProcessPrimitive(Pos5, Pos3, Pos4, TexCoord5, TexCoord3, TexCoord4);
    ProcessPrimitive(Pos3, Pos1, Pos4, TexCoord3, TexCoord1, TexCoord4);
    ProcessPrimitive(Pos5, Pos4, Pos2, TexCoord5, TexCoord4, TexCoord2);
  }
} 
"

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

04.07.2010, 20:44

Kann sein, dass Rekurive Funktionsaufrufe in Shadern bzw. Geometrie Shadern (GLSL) nicht möglich sind? ?(

Jop, Rekursion ist in Shadern nicht direkt möglich da es auf der GPU keinen Stack gibt. Du musst den rekursiven in einen iterativen Ansatz umwandeln.

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

6

04.07.2010, 21:26

Ich hab's jetzt mit ner for-Schleife gelöst, aber leider scheint es, als könne man nur eine stark begrenzte Anzahl an Primitiven im Geometry Shader erstellen.
Also für jedes Dreieck nur max. 50 (nur als Bsp.) Dreiecke erstellen.
Denn wenn ich in der folgenden Funktion "TessellatePrimitive" für "Forks" mehr als 6 angebe lässt er nachkommende Dreiecke einfach weg :-(

EDIT:
Anscheinend kann man im Geometry Shader gerade mal 42 Dreiecke rendern :huh:
/EDIT

Hier ist mein Geometry Shader für einen Tessellation Test:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//
// GLSL Geometry Shader
//

#version 120
#extension GL_EXT_geometry_shader4: enable

uniform int ForksCount;

void ProcessVertex(vec4 Pos, vec4 TexCoord)
{
    gl_Position = Pos;
    gl_TexCoord[0] = TexCoord;
    EmitVertex();
}

void ProcessPrimitive(
    vec4 Pos0, vec4 Pos1, vec4 Pos2,
    vec4 TexCoord0, vec4 TexCoord1, vec4 TexCoord2)
{
    ProcessVertex(Pos0, TexCoord0);
    ProcessVertex(Pos1, TexCoord1);
    ProcessVertex(Pos2, TexCoord2);
    EndPrimitive();
}

void TessellatePrimitive(
    vec4 Pos0, vec4 Pos1, vec4 Pos2,
    vec4 TexCoord0, vec4 TexCoord1, vec4 TexCoord2, int Forks)
{
    static const int MAX_VERTICES = 210;
    
    if (Forks > 20)
        Forks = 20;
    else if (Forks < 1)
        Forks = 1;
    
    vec4 Pos[MAX_VERTICES];
    vec4 TexCoord[MAX_VERTICES];
    
    vec4 PosA = gl_PositionIn[0];
    vec4 PosB = gl_PositionIn[1];
    vec4 PosC = gl_PositionIn[2];
    
    vec4 TexCoordA = gl_TexCoordIn[0][0];
    vec4 TexCoordB = gl_TexCoordIn[1][0];
    vec4 TexCoordC = gl_TexCoordIn[2][0];
    
    vec4 PosStepU = (PosB - PosA) / float(Forks);
    vec4 PosStepV = (PosC - PosA) / float(Forks);
    
    vec4 TexCoordStepU = (TexCoordB - TexCoordA) / float(Forks);
    vec4 TexCoordStepV = (TexCoordC - TexCoordA) / float(Forks);
    
    int u, v, i = 0;
    
    for (u = 0; u <= Forks; ++u)
    {
        for (v = 0; v <= Forks - u; ++v, ++i)
        {
            Pos[i] = PosA + PosStepU * float(u) + PosStepV * float(v);
            TexCoord[i] = TexCoordA + TexCoordStepU * float(u) + TexCoordStepV * float(v);
        }
    }
    
    int v0 = 0, v1 = v0 + 1, v2 = Forks + 1, v3 = v2 + 1;
    
    for (u = 0; u < Forks; ++u)
    {
        for (v = 0; v < Forks - u; ++v)
        {
            ProcessPrimitive(
                Pos[v2], Pos[v1], Pos[v0],
                TexCoord[v2], TexCoord[v1], TexCoord[v0]
            );
            
            if (v < Forks - u - 1)
            {
                ProcessPrimitive(
                    Pos[v3], Pos[v1], Pos[v2],
                    TexCoord[v3], TexCoord[v1], TexCoord[v2]
                );
                ++v3;
            }
            
            ++v0;
            ++v1;
            ++v2;
        }
        
        ++v0;
        ++v1;
        ++v3;
    }
}

void main(void)
{
    if (gl_VerticesIn == 3)
    {
        TessellatePrimitive(
            gl_PositionIn[0], gl_PositionIn[1], gl_PositionIn[2],
            gl_TexCoordIn[0][0], gl_TexCoordIn[1][0], gl_TexCoordIn[2][0],
            ForksCount
        );
    }
    else
    {
        for (int i = 0; i < gl_VerticesIn; ++i)
            ProcessVertex(gl_PositionIn[i], gl_TexCoordIn[i][0]);
        EndPrimitive();
    }
}

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »LukasBanana« (04.07.2010, 21:45)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

04.07.2010, 21:57

[...] leider scheint es, als könne man nur eine stark begrenzte Anzahl an Primitiven im Geometry Shader erstellen.

Volltreffer. Der Geometry Shader eignet sich nur sehr begrenzt für Tesselation. Die maximale Anzahl an Vertices die ein Geometry Shader in einem Durchgang emittiert kann man mit einem layout qualifier im Shader angeben. In GLSL 4.0 kann ein Geometry Shader pro Aufruf nicht mehr als 256 Vertices erzeugen.

Werbeanzeige