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

flux

Treue Seele

  • »flux« ist der Autor dieses Themas
  • Private Nachricht senden

1

09.12.2010, 20:10

OpenGL VBO und IndexBuffer Fragen

Hallo Zusammen,

ich habe mal ein paar Fragen zu VBO und Indexbuffern in OpenGL.
Ich habe ein Terrain erstellt. Das habe ich in ein VBO geladen.
Dazu habe ich 2 Buffer generiert.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
buffers = new GLuint[2];
glGenBuffers(2, buffers);

glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex3D) * vertexCount, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex3D) * vertexCount, heightData);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex3D), BUFFER_OFFSET(0));
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex3D), BUFFER_OFFSET(12));
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex3D), BUFFER_OFFSET(20));

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * vertexCount, indexBuffer, GL_STATIC_DRAW);


Danach habe ich ein Model geladen und wollte es auch in ein VBO laden.
Der Code sieht so aus wie oben.

Wenn ich das ganze dann zeichne, wird nur ein kleiner Teil des Terrain angezeigt.
Also habe ich den Indexbuffer vom Model wieder rausgenommen und es wird alles richtig gezeichnet.

Jetzt die Fragen:
1) Warum?
2) Gehören Indexbuffer und VBO nicht zusammen?
3) Wofür ist denn dann der Indexbuffer da?
4) Kann man den Indexbuffer nicht weglassen?

Gruß
Philipp

n0_0ne

1x Contest-Sieger

  • Private Nachricht senden

2

09.12.2010, 22:39

Also soweit sieht es eigentlich nicht falsch aus. Hab es mal mit Code von mir verglichen und es sieht ziemlich identisch aus. Eine Frage habe ich allerdings: du verwendest sowohl für das VBO als auch für das IBO die variable vertexCounter. Ist das ein Fehler, oder hast du jeden Vertex mehrfach gespeichert? Weil eigentlich solltest du mehr indizes als vertices haben... vielleicht wird deshalb auch nur ein teil dargestellt?

Wie sieht denn der renderaufruf aus?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

09.12.2010, 22:49

Hast du mit und ohne IndexBuffer den selben VertexBuffer verwendet!? Wenn ja schau dir nochmal an für was man einen IndexBuffer verwendet.

flux

Treue Seele

  • »flux« ist der Autor dieses Themas
  • Private Nachricht senden

4

09.12.2010, 22:52

Ich habe jeden Vertex mehrfach gespeichert. Der Indexbuffer ist deshalb durchnummeriert( [0] = 0, [1] = 1,...). Ist nicht die beste Lösung, aber für meine Zwecke reicht das.

Falsch wird es nur dargestellt, wenn ich einen zweiten Indexbuffer verwende.

Hier noch der Renderaufruf:

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
// Bind colormap
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
texture->bind();

// Bind detailtexture
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
detailTexture->bind();

// Bind VBO & texture coords
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glVertexPointer(3, GL_FLOAT, sizeof(Vertex3D), BUFFER_OFFSET(0));

// Bind colormap to VBO
glClientActiveTexture(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex3D), BUFFER_OFFSET(12));

// Bind detailtexture to VBO
glClientActiveTexture(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex3D), BUFFER_OFFSET(20));

// Draw VBO
glDrawElements(GL_QUADS, vertexCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

// Unbind textures
glActiveTextureARB(GL_TEXTURE1_ARB);
detailTexture->unbind();
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
texture->unbind();
glDisable(GL_TEXTURE_2D);

// Set default texture
glActiveTexture(GL_TEXTURE0);

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

09.12.2010, 22:57

Es ist komplett sinnlos einen IndexBuffer so zu verwenden. Was meinst du mit einem zweiten IndexBuffer und wo bindest du den IndexBuffer überhaupt!?

flux

Treue Seele

  • »flux« ist der Autor dieses Themas
  • Private Nachricht senden

6

09.12.2010, 23:10

Ich hab den Indexbuffer nur benutzt, weil ich einen verwenden muss (oder geht das auch ohne?).
Wofür der da ist, hab ich denk ich verstanden (damit man nicht alle Vertices doppelt und dreifach halten muss).

Terrain
->bindet Vertexbuffer
->bindet Indexbuffer

Model
->bindet Vertexbuffer

Wenn ich jetzt beim Model auch noch einen Indexbuffer binden würde, dann wird dieser auch für das Terrain verwendet, obwohl ich jeweils neue Buffer generiert habe.
Und jetzt, wo ich das beim Model weglasse, verwendet dieses wohl auch den Indexbuffer vom Terrain.

Muss ich beim jedem Renderaufruf den Indexbuffer neu setzten?
Sprich:

C-/C++-Quelltext

1
2
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * vertexCount, indexBuffer, GL_STATIC_DRAW);

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

09.12.2010, 23:16

Ich hab den Indexbuffer nur benutzt, weil ich einen verwenden muss (oder geht das auch ohne?).

Natürlich geht das auch ohne.

Wofür der da ist, hab ich denk ich verstanden (damit man nicht alle Vertices doppelt und dreifach halten muss).

Exakt. Aber so wie du ihn verwendest ist er sinnlos da du erst wieder alle Vertices doppelt und dreifach in deinem VBO hast. Was du also tust ist die Nachteile beider Varianten kombinieren.

Muss ich beim jedem Renderaufruf den Indexbuffer neu setzten?

Ja klar musst du das, aber nur binden, die Daten brauchst du nicht jedesmal wieder zur Grafikkarte schicken, du verwendest doch erst BufferObjects um genau das zu verhindern...

flux

Treue Seele

  • »flux« ist der Autor dieses Themas
  • Private Nachricht senden

8

09.12.2010, 23:34

Danke. Jetzt geht es.
Ich hatte beim Rendern die Indexbuffer nicht neu gebunden. Klar, dass dann der zuletzt gesetzte verwendet wird :wacko:

So jetzt mach ich aus der sinnlosen noch ein sinnvolle Verwendung ;)
...und dann kommt der Shader fürs Instancing. (Da werden also bald neue Fragen kommen :P )

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

10.12.2010, 00:06

Im Prinzip ist es ganz einfach:
glGenBuffers() erzeugt ein Handle über das du ein BufferObject identifizieren kannst (in OpenGL nennt man sowas einen Object Name)
glBindBuffer() bindet das angegebene Object, d.h. setzt es als das aktive Object.
glBufferData() reserviert den Speicher für den Inhalt deines BufferObject.
glGenBuffers() und glBufferData() machst du normalerweise nur einmal wenn du das Object erzeugst. Um ein Object zu verwenden musst du es dann jedesmal einfach nurmehr mit glBindBuffer() binden.
Das Prinzip ist übrigens übertragbar, praktisch alles in OpenGL funktioniert nach mehr oder weniger diesem Schema (für Texturen gibts dann eben z.B. glGenTextures(), glBindTexture() und glTexImage2D()).

Werbeanzeige