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

1

29.06.2012, 12:58

Schnelles rendering mit OpenGL (2D, Verbesserungsvorschläge)

Moin.
Ich arbeite noch nicht so lange mit OpenGL, von daher weiß ich auch noch nicht genau, wie ich das Rendering möglichst schnell gestalten kann, ich wäre für einige Verbesserungsvorschlage oder Vorschläge generell, wie man das Rendering möglichst schnell gestalten kann sehr dankbar, auch Links zu Tutorials wären gut. Hintergrund ist, dass ich den Rendering Code gerne für jegliche Programme wiederverwenden möchte, ohne ihn jedesmal bearbeiten zu müssen.

Ich stelle an meinen Code folgende Anforderungen:
  • Er muss schnell und effektiv arbeiten.
  • Er muss in der Lage sein, verschiedene 2D-Dimensionale Flächen zu zeichnen (Dreicke, Vierecke, Polygone).
  • Er muss in der Lage sein, verschiedene Z Ebenen zu behandeln, das heißt gewisse Dinge zuerst zu zeichnen und andere erst hinterher.
  • Er muss in der Lage sein, Alphablending auszuführen (unzwar mit sämtlichen Kombinationsmöglichkeiten die sich aus SFactor, DFactor und Euqation ergeben).
  • Er muss natürlich auch in der Lage sein, das Texturieren und Einfärbungen (Eckpunkte von Vertices) an Primitiven vorzunehmen.
  • Das wars eigentlich schon, außer jemand hat noch eine tolle Idee, was man sonst noch so machen könnte.

Zurzeit ist mein Ansatz, einen vector zu erstellen (dynamisches Array), welcher alle Graphikelemente beeinhaltet, anschließend werde diese mit Quicksort anhand ihrer Position auf der Z Ebene sortiert, der Struct sah bei meinem Testdurchlauf in etwa so aus:

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
// Punkte
struct PointS
{
    GLint X;
    GLint Y;
};

// Farben
struct ColorS
{
    GLubyte R;
    GLubyte G;
    GLubyte B;
    GLubyte A;
};

// Graphikobjekte
struct GraphicS
{
    GLenum Mode;
    vector <PointS> Point;
    vector <PointS> TPoint;
    vector <ColorS> Color;
    unsigned short Z;
    unsigned long Texture;
    bool Blend;
    GLenum SFactor;
    GLenum DFactor;
    GLenum Equation;
};


Wahrscheinlich nicht der beste Ansatz, immerhin reden die erfahrenen Leute hier meistens von VBO. Ist es das was ich suche? Jedenfalls wäre ich für Vorschläge das ganze möglichst schnell zu gestalten offen, ich kann auch gerne Beispielcode zeigen, wie das Rendering momentan abläuft, es ist wahrscheinlich aber kein guter Code, da noch nicht besonders optimiert.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

29.06.2012, 13:02

Zurzeit ist mein Ansatz, einen vector zu erstellen (dynamisches Array), welcher alle Graphikelemente beeinhaltet, anschließend werde diese mit Quicksort anhand ihrer Position auf der Z Ebene sortiert, der Struct sah bei meinem Testdurchlauf in etwa so aus:

Quellcode

1
2
3
4
5
// Graphikobjekte
struct GraphicS
{
    /* super viel Zeugs */
};

Ich hoffe, dass du in deinem Vektor nur Zeiger auf GraphicS-Objekte speicherst und nicht die Objekte selbst.
Ansonsten würden beim Sortieren bei jeder Vertauschungsoperation komplette Kopien der Objekte angefertigt und wieder weggeworfen, inklusive der darin enthaltenen möglicherweise sehr großen Vektoren.

Ansonsten:
- Eine Idee wäre es, zwischen statischen und dynamischen Objekten zu unterscheiden. Die statischen kannst du alle in einem VBO speichern, den du dann nicht in jedem Frame ändern musst, und in einem Rutsch zeichnen (zumindest diejenigen, die mit denselben Rendering-Einstellungen gezeichnet werden müssen).
- Wenn du dir das Sortieren ersparen willst (Zeitaufwand wächst ja mit O(n*log(n))), schlage ich vor, dass du nur eine gewisse Anzahl verschiedener Z-Werte zulässt, z.B. von -10 bis +10. Dann machst du für jeden Z-Wert eine eigene Liste mit Objekten und brauchst am Ende nur noch die Listen von hinten nach vorne zu zeichnen -> kein Sortieraufwand.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

3

29.06.2012, 13:06

Ich schlage Assembler vor.[/sarcasm]

Ein mehr ernsthafterer Vorschlag wäre eventuell ausgeschaltetes Alignment wieder zu aktivieren. *hust*
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

4

29.06.2012, 13:06

Oh, das habe ich noch garnicht bedacht, da hast du natürlich völlig recht, ich werde mir das umgehend aufschreiben und dementsprechend ändern. Das wäre natürlich im Gegensatz dazu wie ich es momentan löse ein extremer Geschwindigkeitsaufschub.
Allerdings sind die enthaltenden Vektoren meist nur Quader und keine riesigen Polygone.

@BlueCobold: Alignment ist an, wieso sollte ich es ausschalten? Viel wichtiger wäre es da, die Structs dementsprechend zu ordnen. Es ist auch völlig Wumpe, es geht hier um OpenGL, in dem anderen Thread gabs schon genug Offtopic, das muss hier jetzt auch nicht noch sein. :rolleyes:

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

29.06.2012, 13:08

Gut :)
Ich habe meiner Antwort oben noch zwei Punkte hinzugefügt.

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

6

29.06.2012, 13:08

Prinzipiell gilt: Batching, Batching, Batching! Das bedeutet: möglichst viel mit einem Draw()-Call zeichnen und VBOs benutzen. Das bringt dir am meisten Performance. Zu den Punkten, zu denen ich dir konkrete Tipps geben kann:

Zitat

Er muss in der Lage sein, verschiedene Z Ebenen zu behandeln, das heißt gewisse Dinge zuerst zu zeichnen und andere erst hinterher.
Dazu eignet sich der Z-Buffer hervorragend. Es gibt auch Fälle, wo sortieren Sinn machen kann: statische Geometrie. Diese solltest du möglichst schon in der Reihenfolge in der Liste haben und ohne Z-Buffer rendern. EDIT: Für Transparente Objekte muss man per Hand sortieren (Danke für die Erinnerung David!).

Zitat

Er muss in der Lage sein, Alphablending auszuführen (unzwar mit sämtlichen Kombinationsmöglichkeiten die sich aus SFactor, DFactor und Euqation ergeben).
Das "welche" ist nicht das Problem - das "AlphaBlending Art X oder nicht" ist der Punkt. Wichtig ist, dass du zweckes Performance Primitives serselben Alpha-Blending Einstellung möglichst zusammen zeichnest.

Zitat

Er muss natürlich auch in der Lage sein, das Texturieren und Einfärbungen (Eckpunkte von Vertices) an Primitiven vorzunehmen.
Batching: Primitives mit derselben Textur zusammen in einem Draw-Call zeichnen! Farben sind eigentlich unkritisch, das geht unabhängig performant gleichschnell.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

7

29.06.2012, 13:09

Transparenz erfordert Sortieren, da geht nix mit Z-Buffer ...

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

8

29.06.2012, 13:10

Transparenz erfordert Sortieren, da geht nix mit Z-Buffer ...
Allein durch andere ClientStates muss es eh eigener Draw-Call sein - dann muss man natürlich auch sortieren ;) Ja Korrekterweise ohne Z-Buffer!

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

29.06.2012, 13:15

Was auch enorm wichtig ist, um die "Batchbarkeit" ;) zu steigern, sind Textur-Atlanten.
Prinzip: Packe viele kleine Texturen in eine große und wähle dann über die Texturkoordinaten die jeweils gewünschte Textur. Nun kannst du Objekte in einem Draw-Call zeichnen, für die du ansonsten mehrere gebraucht hättest (weil du zwischendurch die Textur ändern müsstest). Sehr häufig anzutreffen bei Bitmap Fonts und Tile-Maps.

10

29.06.2012, 13:21

Danke für die Antworten.

Drei Fragen hab ich allerdings noch:
  1. Was hat Priorität, dass gleiche Alphablending oder die gleiche Textur?
  2. Wie zeichne ich in einem einzigen Draw-Call? Dafür habe ich leider noch kein einziges Beispiel gefunden, obwohl ich schon öfters danach gesucht habe.
  3. Eine eigene Liste erfordert ein zweidimensionales Array, ich habe schon Beispielcode und Erklärungen für zweidimensionale Vektoren gesehen, allerdings erschien mir das ganze eine nicht ganz so einfache Angelegenheit zu sein. Vorschläge, Hilfe?

Edit: "Textur-Atlanten" benutze ich bereits, irgendwo gibt es aber bei der Größe auch eine Obergrenze oder? Oder gibt es die Möglichkeit zur Laufzeit Texutren ohne Wrapping und mit gleichen Flags zu einer einzigen zusammen zu schließen?

Werbeanzeige