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

daG

Treue Seele

  • »daG« ist der Autor dieses Themas

Beiträge: 130

Wohnort: Hamburg

  • Private Nachricht senden

1

24.04.2011, 19:19

C#: OpenGL VBO und VAO

Frohe Ostern alle zusammen :)

Ich versuch schon das ganze WE ein Beispiel mit VAOs zu programmieren. VBO funktioniert schon und so wie ich es verstanden habe ist ein VAO ein Array von VBOs doch leider verstehe ich nicht wie ich das umsetzen muss.

Ziel ist es, für VBOs und VAOs C# Klassen zu haben, die möglichst für jeden Anwendungsfall von VBOs und VAOs benutzt werden können. Da ich noch nicht so viel Erfahrung mit OpenGL hab, kann es durchaus sein, das ich da etwas naiv ran gehe aber so ungefähr soll es später aussehen:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
var vbo = new VertexBufferObject(texture);

vbo.AddArray(new ArrayBuffer<float>(2, ArrayCap.TextureCoordArray, new float[] {...}));
vbo.AddArray(new ArrayBuffer<float>(3, ArrayCap.NormalArray, new float[] {...}));
vbo.AddArray(new ArrayBuffer<float>(3, ArrayCap.VertexArray, new float[] {...}));
vbo.AddArray(new IndexBuffer<uint>(indicesData));

vbo.UploadData();

// Beim rendern:
vbo.Draw();


Folgendes passiert bei jedem ArrayBuffer wenn vbo.UploadData() aufgerufen wird:

C#-Quelltext

1
2
3
4
5
6
GL.GenBuffers(1, out id);

GL.BindBuffer(this.bufferTarget, id);
GL.BufferData(this.bufferTarget, (IntPtr)(this.data.Length * this.sizeInBytes), this.data, bufferUsage);

GL.GetBufferParameter(this.bufferTarget, BufferParameterName.BufferSize, out bufferSize);


Beim Zeichnen der ArrayBuffer:

C#-Quelltext

1
2
3
4
5
6
7
8
if(this.arrayType == ArrayCap.TextureCoordArray)
{
    GL.TexCoordPointer(this.itemSize, (TexCoordPointerType)this.pointerType, this.ItemSizeInBytes, IntPtr.Zero);
}
else if(this.arrayType == ArrayCap.VertexArray)
{
    GL.VertexPointer(this.itemSize, (VertexPointerType)this.pointerType, this.ItemSizeInBytes, IntPtr.Zero);
}


Beim Zeichnen des IndexBuffers:

C#-Quelltext

1
2
3
GL.BindBuffer(BufferTarget.ElementArrayBuffer, this.id);

GL.DrawElements(mode, this.Length, (DrawElementsType)this.pointerType, IntPtr.Zero);


Das funktioniert soweit. Auch wenn ich nicht weiß ob das so alles richtig verstanden ist.

Aber jeder Versuch mit

GL.GenVertexArrays(1, out this.id);
GL.BindVertexArray(this.id);
GL.DrawArrays(BeginMode.Triangles, 0, length);

Schlägt fehl.

So jetzt den eigentlichen Fragen :) Hab ich das überhaupt alles richtig verstanden? Was wäre die richtige Lösung wenn man keine deprecated Funktionen benutzen möchte? Wie ich gelesen habe sind die GL.VertexPointer etc mittlerweile deprecated. Wie genau passen VOAs und VBOs zusammen?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

24.04.2011, 22:03

So jetzt den eigentlichen Fragen :) Hab ich das überhaupt alles richtig verstanden? Was wäre die richtige Lösung wenn man keine deprecated Funktionen benutzen möchte?

Ich bin mir nach deiner Beschreibung nicht ganz sicher was genau du tust, also vielleicht einfach mal eine kleine Erklärung was genau VAOs sind:

Wenn du mit VBOs renderst folgst du prinzipiell diesem Schema:
  • Buffer Binden
  • Vertex Attribute Pointer setzen
  • Vertex Attribute enablen
  • (Buffer Binden)
  • Vertex Attribute Pointer setzen
  • Vertex Attribute enablen
  • (Buffer Binden)
  • Vertex Attribute Pointer setzen
  • Vertex Attribute enablen
  • ...
  • Draw Call
VAOs (der Name ist imo extrem schlecht gewählt) dienen nun dazu das ganze State Setup in einem Objekt zu repräsentieren sodass der gesamte State auf einmal gesetzt werden kann. D.h. du erzeugst ein VAO, bindest dein VAO. Das VAO merkt sich alle Buffer die du von nun an bindest, alle Attribute Pointer die du setzt usw. Wann immer du dann das VAO dann wieder bindest ist automatisch dieser ganze State wie er beim letzten Mal als das VAO gebunden war wiederhergestellt. D.h. dein glBindVertexArray() ersetzt quasi sämtliche glBindBuffer(), glVertexAttribPointer(), glEnableVertexAttrib() calls. Damit reduziert sich der Ablauf beim Rendern auf:
  • VAO Binden
  • Draw Call

Wie ich gelesen habe sind die GL.VertexPointer etc mittlerweile deprecated. Wie genau passen VOAs und VBOs zusammen?

Ich denke die letzte Frage hab ich oben beantwortet. Was glVertexPointer() angeht: Ja das ist deprecated, man verwendet nun generische Vertex Attribute, also glVertexAttribPointer() und glBindAttribLocation() etc.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (24.04.2011, 22:20)


daG

Treue Seele

  • »daG« ist der Autor dieses Themas

Beiträge: 130

Wohnort: Hamburg

  • Private Nachricht senden

3

24.04.2011, 23:02

Ok, danke für die Erklärung. Mir stellen sich da aber gleich noch mehr Fragen :)

Woher weiß OpenGL welche Daten wofür sind bei dem generischen glVertexAttribPointer. Es fehlt ja die Info ob es TexturCoords sind oder was anderes. Und wie speichere ich dann die Daten? Wieder alle in einzelnen Arrays oder alle zusammengepackt in einem Struct und dieses dann als Array.

Wie genau sieht dann der Draw Call aus? Ist glDrawArrays die richtige Funktion dafür?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

24.04.2011, 23:09

Woher weiß OpenGL welche Daten wofür sind bei dem generischen glVertexAttribPointer. Es fehlt ja die Info ob es TexturCoords sind oder was anderes.

Naja, das kommt eben drauf an wie deine Shader die Daten interpretieren. Nachdem du ja nichts verwenden willst was deprecated ist ging ich davon aus dass du natürlich Shader verwendest da alles andere ja deprecated ist ;)

Und wie speichere ich dann die Daten? Wieder alle in einzelnen Arrays oder alle zusammengepackt in einem Struct und dieses dann als Array.

Naja, geht beides, hängt davon ab was du machen willst. Im Allgemeinen wird man die Daten meistens eher interleaved, d.h. in einem struct pro Vertex speichern.

Wie genau sieht dann der Draw Call aus? Ist glDrawArrays die richtige Funktion dafür?

Jop, glDrawArrays(), glDrawElements() oder glDrawRangeElements(), je nachdem.

daG

Treue Seele

  • »daG« ist der Autor dieses Themas

Beiträge: 130

Wohnort: Hamburg

  • Private Nachricht senden

5

24.04.2011, 23:12

Ok, langsam kommt Licht ins Dunkle :)

Eine Frage noch: Machen VAOs dann nur mit Shadern Sinn?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

24.04.2011, 23:15

Nein du kannst VAOs auch noch mit der alten Pipeline verwenden. Aber mir fällt kein Grund ein warum man das wollen würde ;)
(VAOs merken sich auch glVertexPointer() etc. und man kann den glVertexPointer() Kram theoretisch sogar mit glVertexAttribPointer() mischen und was einem sonst noch so an grobem Unfug einfallen mag. Das würd ich aber bleiben lassen und einfach Shader + VBOs + generische Attribute + VAOs benutzen. Das ist der saubere Weg.)

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (24.04.2011, 23:24)


daG

Treue Seele

  • »daG« ist der Autor dieses Themas

Beiträge: 130

Wohnort: Hamburg

  • Private Nachricht senden

7

24.04.2011, 23:36

Der Grund ist, dass ich noch keine Ahnung von Shadern habe :)

Das Problem ist, das ich es mit den GL Funktionen nicht hin bekommen habe. Ich werde dann noch mal ein einfaches Beispiel machen und hier noch mal nach Hilfe fragen...

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

24.04.2011, 23:46

Das Problem ist, das ich es mit den GL Funktionen nicht hin bekommen habe.

Was genau?

daG

Treue Seele

  • »daG« ist der Autor dieses Themas

Beiträge: 130

Wohnort: Hamburg

  • Private Nachricht senden

9

24.04.2011, 23:58

VAOs

Mir ist die exe immer abgeschmiert :S Ich werde es noch mal versuchen in einem kleinem Beispiel nach zustellen.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

25.04.2011, 00:01

Vielleicht unterstützt dein Treiber einfach keine VAOs oder die Library die du verwendest merkts nicht? Mit OpenGL ist das immer so ne Sache...

Werbeanzeige