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

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

11

29.06.2012, 13:26

1) Ich weiß nicht, was teurer ist ... Dot weiß es bestimmt :)

2) glDrawArrays, glDrawElements

3) Nicht unbedingt. Wenn du die Anzahl der Z-Werte fest setzt, geht auch ein Array aus Vektoren:

Quellcode

1
std::vector<Object*> objectLists[10];


Noch eine wichtige Sache:
Wenn du Rechtecke renderst, benutze Triangle Strips, die sind am schnellsten.

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

12

29.06.2012, 13:38

Du kannst eventuell auch versuchen, 2-dimensionale Vektoren zu umgehen und sie auf 1-dimensionale zu mappen. Zugriffsformel ist dann vVector[x+y*(Anzahl der Daten in einer Reihe)].

Wurde mir letztens empfohlen, weil es sonst unnötig kompliziert wird.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

13

29.06.2012, 13:47

Ich habe die Erfahrung gemacht, dass Rendern nach Texturen + Texturatlanten ordentlich Performance bringt. Mittlerweile werden die meisten Sachen eh mit notwendigerweise Alpha-Blending gerendert - allein wenn etwas nicht rechteckig ist auf der Textur. Daher is meiner Meinung nach eher nach Texturen batchen sinnvoller - kommt wie immer auf die Geometrie an. Das müsste man auch einfach mal ausprobieren und messen :)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

14

29.06.2012, 14:04

Drei Fragen hab ich allerdings noch:
  1. Was hat Priorität, dass gleiche Alphablending oder die gleiche Textur?
Das hängt genau genommen davon ab, wo Du am meisten einsparst. Diese Frage kann man nicht generell beantworten. Hast du 500 Texturen und nur 2 Blending-States, hat ein Textur-Atlas die höchste Prio. Hast Du nur 2 Texturen und 500 verschiedene Blend-States, dann solltest Du Dich um letzteres kümmern. Wie Bomml schon sagte lässt sich aber vermutlich beides machen, weil "die meisten Sachen eh mit notwendigerweise Alpha-Blending gerendert" werden.
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]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

15

29.06.2012, 14:17

Musst du wirklich sämtliche möglichen Kombinationen von Blend States unterstützen? Normalerweise braucht man kaum mehr als einfaches lineares und additives Blending.
Abgesehen davon brauchst du vermutlich eigentlich gar keine beliebigen z-Koordinaten, sondern willst einfach nur eine Handvoll Layer haben. Wie schon gesagt wurde, wäre es da wohl besser, nicht ständig zu sortieren, sondern einfach für jeden Layer ein eigenes Array zu haben.
GPUs haben Vertexdaten normalerweise lieber interleaved, also nicht als Structure of Arrays, sondern als Array of Structures.
Und es wäre vermutlich sinnvoll, die Koordinaten gleich als floats zu speichern.
Innerhalb eines Layers sollte man vermutlich (in absteigender Priorität) nach Shader (Blend State) und Texture sortieren, wobei du beachten musst, dass die Art des Blending vielleicht schon ein bestimmtes Ordering vorgibt, das erhalten bleiben muss. Möglicherweise wäre es sinnvoll, das Blending an den Layer zu binden, sodass einfach jeder Layer fix eine Art von Blending durchführt!?

Und ganz wesentlich ist generell die Frage, ob du jetzt statische oder dynamische Geometrie rendern willst und wenn dynamisch, was genau dynamisch ist. Ändern sich nur die Vertexpositionen oder ändert sich generell die Geometrie, i.e., kommen ständig Vertices dazu und andere weg? Und wie oft ändert sich was, ständig oder nur ab und zu? Vermutlich willst du mehr als eine Variante...

Rein prinzipiell haben wir hier das Problem, dass es nicht einfach die eine beste Lösung gibt, die, einmal implementiert, alle Wünsche erfüllt. Und die Ansätze unterscheiden sich grundlegend...

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »dot« (29.06.2012, 14:27)


David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

16

29.06.2012, 14:38

Du kannst eventuell auch versuchen, 2-dimensionale Vektoren zu umgehen und sie auf 1-dimensionale zu mappen. Zugriffsformel ist dann vVector[x+y*(Anzahl der Daten in einer Reihe)].

Wurde mir letztens empfohlen, weil es sonst unnötig kompliziert wird.

Schlechte Idee in diesem Fall, weil die Listen alle unterschiedlich lang sind. Dazu müsstest du ein oberes Limit haben, das dann für alle Listen gilt.
Eine Liste aus Listen (Zeigern auf Listen) ist doch kein Problem.

17

29.06.2012, 14:40

Danke für die Antworten.
Ich möchte soviele Blending States wie möglich unterstützen, vorallendingen weil sich mit ihnen interessante Effekte erzielen lassen, nur additives Blending ist mir da entschieden zu wenig. Da gibts noch viel interessantere Dinge, wie z.B. subtraktives oder multiplikatives Blending und die Möglichkeit auch später noch etwas zu experimentieren reizt mich.
Ich denke eine Handvoll Ebenen wird auch für den Anfang erstmal reichen. Wie soll ich denn deiner Meinung nach die Koordinaten gleich als Float abspeichern wenn ein Graphikobjekt voher noch garnicht weiß, wieviele Eckpunkte es hat? Wenn ich z.B. nur Dreiecke zeichne, mag das vielleicht okay sein aber bei Polygonen wird das äußerst schwierig, außer natürlich ich verzichte komplett auf diese.
Das Blending an den Layer zu binden, halte ich allerdings für absolut nicht sinnvoll, da mir dann das ganze System für meine Zwecke zu statisch wird.
Was die Geometrie angeht, ist es relativ schwierig zu beantworten, ich möchte kein starres System programmieren, sondern eins was genug Features bietet, ohne Geschwindigkeitsbußen in Kauf zu nehmen. Von daher ist mit allem zu rechen, was einigermaßen "normal" ist, d.h. Vertexpositionen, Texturpositionen, sowie Farben ändern sich regelmäßig, die Art des Blendings und die Textur an sich, sowie Ebenenposition eher selten bis garnicht.
Außerdem, geht nicht, gibts in der Regel nicht, zumindest was Programmieren angeht. ;)

Du kannst eventuell auch versuchen, 2-dimensionale Vektoren zu umgehen und sie auf 1-dimensionale zu mappen. Zugriffsformel ist dann vVector[x+y*(Anzahl der Daten in einer Reihe)].


Das wird nicht funktionieren, da ich voher die Anazahl der Daten in einer Reihe nicht kenne. ;)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

18

29.06.2012, 14:53

Wie soll ich denn deiner Meinung nach die Koordinaten gleich als Float abspeichern wenn ein Graphikobjekt voher noch garnicht weiß, wieviele Eckpunkte es hat? Wenn ich z.B. nur Dreiecke zeichne, mag das vielleicht okay sein aber bei Polygonen wird das äußerst schwierig, außer natürlich ich verzichte komplett auf diese.

Ich seh nicht ganz den Zusammenhang. Du hast eben einfach ein Array aus Vertices, deren Koordinaten eben vom Typ float und nicht int sein sollten!? Irgendwann musst du die kennen, sonst kannst du nix zeichnen...

Was die Geometrie angeht, ist es relativ schwierig zu beantworten, ich möchte kein starres System programmieren, sondern eins was genug Features bietet, ohne Geschwindigkeitsbußen in Kauf zu nehmen. Von daher ist mit allem zu rechen, was einigermaßen "normal" ist, d.h. Vertexpositionen, Texturpositionen, sowie Farben ändern sich regelmäßig, die Art des Blendings und die Textur an sich, sowie Ebenenposition eher selten bis garnicht.

Wie sieht es mit der Anzahl der Vertices/Grafikobjekte aus? Ist die zumindest über viele Frames konstant, oder ändert sich die ständig? Und ändern sich wirklich potentiell alle Objekte oder ist mit einem nennenswerten Anteil statischer Objekte zu rechnen, sodass es sinnvoll sein könnte, diese extra zu handhaben? Handelt es sich großteils um einzelne, unzusammenhängende Dreiecke, oder sind vor allem eher komplexere Polygone zu erwarten, sodass es möglicherweise sinnvoll sein wird, einen Indexbuffer zu verwenden? Von wievielen Objekten pro Frame reden wir hier eigentlich überhaupt?

Außerdem, geht nicht, gibts in der Regel nicht, zumindest was Programmieren angeht. ;)

Aber was für den einen Anwendungsfall die effizienteste Lösung ist, ist für den anderen Anwendungsfall eine sehr ineffiziente Lösung. Ein System, das einfach alles unterstützt, ohne irgendwo dafür zu bezahlen, kann es rein prinzipiell nicht geben. Du kannst immer nur einen guten Trade-off für einen bestimmten Anwendungsfall suchen. Und wenn wir dir dabei helfen sollen, müssen wir deinen konkreten Awendungsfall kennen...

Im konkreten Beispiel könnte ich z.B. in jedem Frame dynamische Batches aus einem VBO fixer Größe rendern, was eine sehr effiziente Lösung wäre, wenn sämtliche Geometrie sich in jedem Frame komplett ändert. Für Geometrie, die sich kaum ändert, wäre das dagegen die denkbar schlechteste Lösung...

Dieser Beitrag wurde bereits 13 mal editiert, zuletzt von »dot« (29.06.2012, 15:09)


19

02.07.2012, 01:23

Ich seh nicht ganz den Zusammenhang. Du hast eben einfach ein Array aus Vertices, deren Koordinaten eben vom Typ float und nicht int sein sollten!? Irgendwann musst du die kennen, sonst kannst du nix zeichnen...


Dann versteh ich nicht ganz, was du mir voher sagen solltest, ist aber auch egal. Warum sollte ich lieber float als int benutzen?

Wie sieht es mit der Anzahl der Vertices/Grafikobjekte aus? Ist die zumindest über viele Frames konstant, oder ändert sich die ständig? Und ändern sich wirklich potentiell alle Objekte oder ist mit einem nennenswerten Anteil statischer Objekte zu rechnen, sodass es sinnvoll sein könnte, diese extra zu handhaben? Handelt es sich großteils um einzelne, unzusammenhängende Dreiecke, oder sind vor allem eher komplexere Polygone zu erwarten, sodass es möglicherweise sinnvoll sein wird, einen Indexbuffer zu verwenden? Von wievielen Objekten pro Frame reden wir hier eigentlich überhaupt?


Das kommt ganz darauf an, ich möchte das ganze sowohl für RPGs, bei denen sich bekanntermaßen auf einer Map eher viele statische, zusammenhängende Objekte befinden (die einzellnen Tiles), die je nach Spielerposition entweder gezeichnet werden oder auch nicht und deren Position sich nur beim scrollen verändert, als auch für Bullet Hell Shooter, bei denen eher viele nicht zusammehängende, dynamische Objekte (die Kugeln) auf dem Bildschirm sind. Dort würden sich pro Frame natürlich alle Objekte bewegen. Es sind eher weniger komplexere Polygone zu erwaten, falls sie die Performance wirklich dermaßen bremsen, kann ich sie auch ganz rausnehmen und nur Quadrate (die in 2 Dreiecke "konvertiert" werden) und Dreiecke zeichnen. Wir reden hier mindestens von 12000 Objekten pro Frame und höchstens sind es an die 65000 (die meisten werden entweder statisch oder dynamisch sein) denke ich. Das kommt ganz darauf an, wie ich sie zeichnen lasse, wenn es sich nur um Dreicke handelt, kannst du die Anzahl nocheinmal verdoppeln, da die meisten Objekte quadratisch sein werden.

Aber was für den einen Anwendungsfall die effizienteste Lösung ist, ist für den anderen Anwendungsfall eine sehr ineffiziente Lösung. Ein System, das einfach alles unterstützt, ohne irgendwo dafür zu bezahlen, kann es rein prinzipiell nicht geben. Du kannst immer nur einen guten Trade-off für einen bestimmten Anwendungsfall suchen. Und wenn wir dir dabei helfen sollen, müssen wir deinen konkreten Awendungsfall kennen...


Du redest aber von einem äußerst statischem Systen. Was ist denn wenn ich einen Struct für Listen erstelle, in dem befindet sich ein Vector, welche die Graphikobjekte speichert und einige Variablen die angeben auf welcher Z Position sich das ganze befindet, hinzu kommt noch ein bool, welcher angibt ob es dynamisch oder statisch gezeichnet werden soll. Dann noch einen Vector Pointer dafür und dann jeden Frame ordnen lassen, da es nicht viele Listen sind und es sich um einen Pointer handelt, wird dabei auch nicht sonderlich viel Rechenleistung verbraten und das ganze bleibt trozdem effizient.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

20

02.07.2012, 01:55

Warum sollte ich lieber float als int benutzen?

Weil die Daten spätestens auf der GPU sowieso wieder in float umgewandelt werden müssten, warum also nicht gleich in dem Format an die GPU schicken, mit dem diese am effizientesten umgehen kann!?

Das kommt ganz darauf an, ich möchte das ganze sowohl für RPGs, bei denen sich bekanntermaßen auf einer Map eher viele statische, zusammenhängende Objekte befinden (die einzellnen Tiles), die je nach Spielerposition entweder gezeichnet werden oder auch nicht und deren Position sich nur beim scrollen verändert, als auch für Bullet Hell Shooter, bei denen eher viele nicht zusammehängende, dynamische Objekte (die Kugeln) auf dem Bildschirm sind. Dort würden sich pro Frame natürlich alle Objekte bewegen. Es sind eher weniger komplexere Polygone zu erwaten, falls sie die Performance wirklich dermaßen bremsen, kann ich sie auch ganz rausnehmen und nur Quadrate (die in 2 Dreiecke "konvertiert" werden) und Dreiecke zeichnen. Wir reden hier mindestens von 12000 Objekten pro Frame und höchstens sind es an die 65000 (die meisten werden entweder statisch oder dynamisch sein) denke ich. Das kommt ganz darauf an, wie ich sie zeichnen lasse, wenn es sich nur um Dreicke handelt, kannst du die Anzahl nocheinmal verdoppeln, da die meisten Objekte quadratisch sein werden.

Du kannst ja mal eben einen komplett dynamischen Spriterenderer basteln und schauen, ob der für deine Anwendungen schon schnell genug ist. Prinzipielles Vorgehen: Du legst dir ein dynamisches VBO an, welches groß genug ist um z.B. 2000 Sprites zu halten und mappest es. Beim Rendern packst du in jedem Frame die Vertices für ein Sprite nach dem anderen in dieses VBO. Wenn das VBO voll ist, oder der Shader, die Texture etc. gewechselt werden, musst du Flushen, i.e., das VBO unmappen, einen Drawcall absetzen, der sämtliche im Moment im VBO gebatchten Sprites rendert, das VBO wieder locken und den nächsten Spritehaufen reinschreiben und immer so weiter. Wenn du mit beliebigen Polygonen etc. arbeiten willst, wirst du vermutlich auch einen zusätzlichen, dynamischen Index Buffer brauchen. Und da sind wir dann auch schon wieder an so einem Punkt, wo es nun potentiell sinnvoll sein wird, einen eigenen Renderer für einfache Sprites zu haben (dynamische Indices wären unnötig verschwendete Bandbreite) und einen separaten für allgemeine Polygone (geht nicht ohne dynamische Indices). Ganz wichtig: Deine dynamischen Buffer vor jedem Mappen durch einen Aufruf von glBufferData() mit einem Nullpointer als data discarden um eine unnötige Synchronisation von GPU und CPU zu vermeiden.

Alternativ kannst du dir natürlich überlegen, einfach eine Engine zu benutzen, die sich dann um all diese Dinge kümmert...

Du redest aber von einem äußerst statischem Systen. Was ist denn wenn ich einen Struct für Listen erstelle, in dem befindet sich ein Vector, welche die Graphikobjekte speichert und einige Variablen die angeben auf welcher Z Position sich das ganze befindet, hinzu kommt noch ein bool, welcher angibt ob es dynamisch oder statisch gezeichnet werden soll. Dann noch einen Vector Pointer dafür und dann jeden Frame ordnen lassen, da es nicht viele Listen sind und es sich um einen Pointer handelt, wird dabei auch nicht sonderlich viel Rechenleistung verbraten und das ganze bleibt trozdem effizient.

Das Problem, um das es mir geht, ist nicht wirklich, wie du das alles auf der CPU managest. Falls das deine Frage war, hab ich dich wohl falsch verstanden. Das Problem ist, wie du die Daten effizient von der GPU zeichnen lässt und dabei die CPU soweit freihältst, dass die genug Zeit hat um den ganzen Kram auch noch zu simulieren während die GPU rendert, ohne dass GPU und CPU sich ständig gegenseitig blockieren...

Wobei, 65000 Dreiecke kannst du heutzutage auf einem PC wohl auch einfach mit Vertex Arrays oder sogar glBegin()/glEnd() mit einigermaßen annehmbarer Performance rendern, wenn du nicht gerade jedes einzeln malst...

Dieser Beitrag wurde bereits 20 mal editiert, zuletzt von »dot« (02.07.2012, 02:46)


Werbeanzeige