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

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

21

21.03.2014, 16:42

Grundsätzlich sollte man sowas weitestgehend vermeiden.
Mach es ruhig erstmal für jedes Quad (oder auch 3D Geometrie), das wird erstmal nicht stören.

Später kann man Instanzen gleicher Objekte sowieso besser instanziert rendern, dann hast du keine Bufferwechsel und auch keine Texturwechsel. Je weniger desto schneller.
Für unsere Zwecke (gerade 2D) ist das aber alles eigentlich auch irrelevant. Wann hat man schon > 1000 Sprites im Bild?
Wenn es um Grafikperformance geht ist die Devise eigentlich immer: möglichst wenig Kommunikation mit der Grafikkarte.

Wenn du weißt das deine 1000 Quads die gleiche Textur haben kannst du diese natürlich besser außerhalb binden, also dort wo ich auch meine Buffer binde. Nach der for Schleife dann das unbind().
Den Shader solltest du nur einmal binden, der macht ja für alle das gleiche (sollte er zumindest).

Falls dich das übrigens verwirrt kannst du immer in die Klasse gucken, dort siehst du dann in den Methoden welche GL Funktionen ich aufrufe. Ich habs teilweise selbst schon wieder verlernt weil ichs abstrahiert habe :P
Aktueller branch ist "light", ich änder häufiger Kleinkram in den Klassen... also evt. immer beim aktuellen gucken.

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

22

21.03.2014, 17:43

Hi,

Zitat

Wann hat man schon > 1000 Sprites im Bild?

Bei ner 2D Tilemap?!

Oder gibts da schonwieder andere Optimierungsmöglichkeiten?


Gruß

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

23

21.03.2014, 18:19

Ja, ein Grid in den Buffer packen und rendern ^^
Sprite heißt für mich abgetrenntes Quad, bei einem Grid hält man alle Tiles in einem Buffer (bzw. mehrere jeweils für Vertices, Texturkoords, ...).

Geht es hier darum?

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

24

21.03.2014, 18:20

jap ;)

Powerpaule

Treue Seele

Beiträge: 162

Wohnort: Berlin

Beruf: Softwareentwickler

  • Private Nachricht senden

25

21.03.2014, 19:01

C-/C++-Quelltext

1
2
3
4
5
shader->bind();
[...]
texture->bind();
[...]
texture->unbind();

Wie schauts denn da mit der Performance aus?
Ist es OK wenn man das bei jedem Quad aufruft? D.H. man hat keinen Geschwindigkeitsverlust wenn man ein ShaderProgram, Texture, etc. bindet, obwohl es ja eigentlich schon gebunden ist?


Gruß
Also den Shader öfter als nötig zu binden muss man unbedingt vermeiden. Jedenfalls als ich das vor ca. 2 Jahren mal geprüft hatte, hatte es zu sehr starken Performance-Einbrüchen geführt, als ich den Shader jedes Mal neu aktiviert habe. Anscheinend wird das durch die Grafikkarte/Treiber nicht geprüft (was an sich sinnvoll ist, reicht wenn die Anwendung das richtig organisiert). Aber vielleicht ist das heute auch schon anders...

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

26

22.03.2014, 12:09

Hi,

Zitat

bei einem Grid hält man alle Tiles in einem Buffer (bzw. mehrere jeweils für Vertices, Texturkoords, ...).

Wie genau soll ich meinen Renderer da jetzt aufbauen?

Muss ich dann doch, so wie ich es hatte, in jeder Frame die Buffer neu aufbauen und an die GPU schicken? Oder gibts da nen schnelleren Weg?


Gruß

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

27

22.03.2014, 14:21

Du wirst doch sicherlich wissen wie groß deine Tilemap ist, dann reicht es natürlich wieder diese einmal in den Buffer zu schreiben.

Vorgehen könntest du dann so dass jedes Tile aus 4 Vertices, 4 Texturkoordinaten und 6 Indices besteht. Diese erstellst du dann grundsätzlich genau wie meine Sprites, nur dass du sie um die x bzw. y Koordinaten verschiebst.
Also für eine 10x10 Tilemap 3 Buffer anlegen, Tile 0|0 hat dann die Vertices 0|0, 1|0, 1|1 und 0|1. Das nächste (sagen wir mal x+1) hätte dann die Vertices 0|0+1|0, 1|0+1|0, 1|1+1|0 und 0|1+1|0. Das schreibst du alles erstmal in ein array und lädst es dann als großen Datenhaufen in den Buffer.
Vorteil ist dass du die gesamte Tilemap dann wieder über eine Matrix skalieren kannst, also z.B. x32 dann wäre jedes Tile (bei orthogonaler Projektion) 32px breit.

Nochmal: das ständige neu Erstellen ist langsam und überflüssig. Nur wenn sich die Daten tatsächlich ändern (und sich dies nicht im Shader dynamisch erledigen lässt), dann solltest du den Buffer updaten. Eine Tilemap ist ein statisches Objekt. Trenne einfach zwischen Initialisierung und dem render Durchlauf selbst.

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

28

22.03.2014, 15:21

Hi,

Zitat

4 Vertices, 4 Texturkoordinaten und 6 Indices besteht

soweit klar.
Also wieder 3 Buffer, und die komplette Map da rein laden.

Was ist aber mit den Texture-Koordianten? Da muss ich ja eigentlich bei jeder Frame den Buffer neu laden, oder? (viele Tiles sind ja animiert, dass sich die TextureKoordinaten von Frame zu Frame ändern können).

Und was ist mit den Texturen? Da wird man ja sicher auch mehrere pro Map verwenden.


Gruß

Evrey

Treue Seele

Beiträge: 245

Beruf: Weltherrscher

  • Private Nachricht senden

29

22.03.2014, 16:11

Ich hab das so gelöst, dass ein Layer aus Quads einem Tileset zugeordnet ist, und damit pro Layer nur einmalig das Tileset, also die Textur gewechselt werden muss.

C-/C++-Quelltext

1
2
3
4
int main(int _argc, char** _argv) noexcept {
  asm volatile("lock cmpxchg8b %eax");
  return 0;
} // ::main
(Dieses kleine Biest vermochte einst x86-Prozessoren lahm zu legen.)

=> Und er blogt unter Hackish.Codes D:

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

30

22.03.2014, 16:29

Hi,

2 andere Möglichkeiten, die mir wegen den Texturen einfallen: (ohne zu wissen wie praktikabel die sind ;))

1. Man läd einfach alle Texturen in die Grafikkarte und gibt bei den Texture-Koordinaten noch nen Index an, auf welche Texture sich bezogen wird.
2. Pro verwendeter Texture eigene Buffer, die dann nacheinander gerendert werden.

Bei beiden Möglichkeiten sollte natürlich darauf geachtet werden, nicht zu viele Texturen zu verwenden.


Keine Ahnung, wie gut/schlecht die Lösungen sind.


Gruß

Werbeanzeige