Objekte sortieren die X'te
-
rapso schrieb:
wie soll das gehen? die sind doch in vertexbuffer drinne? ansonsten würdest du ja bei jedem frame den buffer locken müssen um vertices reinzustecken.
Nein das passiert am Anfang. Also beim Laden bzw zuweisen der Textur kann der Objectmanager erkenne zu welchen Skin das Objekt gehört und es in den Buffer für diesen Skin reinschieben.
Aber wie gesagt wer sagt das alle Objekte die selbe Worldmatrix verwenden. Es geht ja darum den Aufrug der DrawPrimitive-Methode so gering wie möglich zu halten. Und das geht ja nicht weil ich die Matrix setzen muss, das Objekt rendern und danach die Matirx für das zweite Objekt ect...
Wie gesagt das würde aus meiner Sicht nur Sinn bei statischen Objekten machen. z.B. einer Landschaft.
-
H.L.T.O schrieb:
Wie gesagt das würde aus meiner Sicht nur Sinn bei statischen Objekten machen. z.B. einer Landschaft.
Der größte Teil eines Levels ist i.d.R. "statisch"...
-
Hallo, eure Erafahrung ist wieder gefragt. Nach dem ich mir sehr viel Gedanken zum optimalen Rendern gemacht habe. Versuche mit Vertexcache gemacht habe. Und festgestellt habe das es sehr oft nicht viel bringt weil die Objekte alle eine andere Bewegung im Spiel machen. Bin ich zum Entschluss gekommen das ganze mal nur nach Textur/Material zu sortieren. Dazu habe ich mir ein kleines Programm zusammengehack das so eine Situation simuliert.
kann es sein, dass jeder programmierer am anfang seiner ersten grafikengine genau diese überlegungen macht?^^
ein paar optimierungshilfen:
1. pack alles in einen statischen buffer was irgendwie reingeht
2. pack alle indizes die zu den meshs aus punkt1 gehören in einen großen indexbuffer
3. worldmatrix setzen ist kostenlos, also benutz sie
4. streamsource wechseln ist sehr bösezu 1. pack wirklich alles rein was geht, von jeder einheit den mesh, dann die landschaft usw, mit einem richtig großen buffer der selten bis nie gewechselt wird kommt die graka besser klar als mit 1000 mini büfferchen
zu 2. indexbuffer sollten klar sein, sie sparen ne menge platz bei komplexen modellen. Hier ist es auch wieder sinnvoll nur einen großen indexbuffer zu verwenden, da man sich auch hier nicht leisten kann mit den indexbuffern zu jonglieren.
3. sie ist kostenlos da die graka sie eh automatisch mitberechnet, also kein grund sie nicht auszunutzen
4. no comment, einfach nur lahm^^ein rendervorgang sähe dann beispielsweise so aus:
//pseudocode vertexbuffer a indexbuffer b worldmatrix w1; worldmatrix w2; worldmatrix w3; //hier werden irgendwo die werte für die buffer und matritzen gesetzt... benutzeVertexBuffer(a); benutzeIndexBuffer(b); //modell nr1 setzeWorldmatrix(w1); renderIndex(1,150,300);//von Index 1-150 insgesamt 300 dreiecke zeichnen //modell nr2 setzeWorldmatrix(w2); renderIndex(1,150,300);//selbes modell wie das 1. nur an einer andren position //model nr3 setzeWorldmatrix(w3); renderIndex(151,350,500);
natürlich hab ich jetzt mal material/texture weggelassen, aber ich wollte erstmal nur auf diesen echten performance boost hinaus. Der liegt darin, dass man praktisch nie zwischen den buffern wechseln muss, und die daten in den buffern unverrückbar sind, was bedeuted, dass wir den buffer mit D3DPOOL_DEFAULT und D3DUSAGE_WRITEONLY erstellen können, was uns eine hohe chance auf eine schnelle position im speicher der graka bietet.
zum thema materialen: ein material zu wechseln kostet garnichts(naja fast^^).
nach texturen sortieren macht garkeinen sinn, sogut wie jedes model hat einzigartige texturen, und spätestens mit light/shadowmaps siehst du da kein land mehr(das gilt natürlich nicht für bewegliche meshs, die haben garantiert keine light/shadowmaps^^). eine sortierung macht wenn überhaupt nur dann sinn, wenn du davon ausgehen kannst, dass du 2 absolut gleiche(nur unterschiedlich gedrehte) objekte auf dem bild hast.Hauptproblem an der sache ist, dass normalerweise ein objekt aus mehr einer textur besteht, und man somit vor einem weiteren problem der sortierung steht:wenn die sortierung einen sinn haben soll,muss man "durcheinander rendern", dh wenn du 5 soldaten hast, die aus jeweils 3 texturen bestehen,musst du vom ersten soldaten die textur nr1 rendern, dann vom 2. soldaten textur nr1, dann vom 3...4...5.. dann die nächste textur setzen und wieder durch alle 5 soldaten durch...usw.
am ende stellt sich heraus, dass 2 der 5 soldaten unnötig gezeichnet wurden, da die anderen 3 soldaten sie vollständig verdecken. das konnte die graka aber nicht wissen, da die soldaten nicht von vorne nach hinten komplett gezeichnet wurden, und konnte somit kein culling durchführen, dh an den pixeln an denen die 2 hinteren soldaten standen haben wir einen unnötigen overdraw.wenn du das hier gelesen hast: hör besser nicht auf mich, ich bin absolut unwissend und werd gleich von der gemeinschaft wieder kollektiv überstimmt
-
TGGC schrieb:
rapso schrieb:
H.L.T.O schrieb:
Damit meine ich eigentlich das Sammeln der Vertices vor dem rendern. verwende DirectX.
wie soll das gehen? die sind doch in vertexbuffer drinne? ansonsten würdest du ja bei jedem frame den buffer locken müssen um vertices reinzustecken.
TGGC schrieb:
Verschiedene unabhängige Objekte in den gleichen VB zu tun, bringt IMHO keinen Vorteil.
Bye, TGGC \-/
doch das bringt es
Und welchen?
Bye, TGGC \-/
peformance
für weitere fragen hierhin
rapso->greets();
-
H.L.T.O schrieb:
rapso schrieb:
wie soll das gehen? die sind doch in vertexbuffer drinne? ansonsten würdest du ja bei jedem frame den buffer locken müssen um vertices reinzustecken.
Nein das passiert am Anfang. Also beim Laden bzw zuweisen der Textur kann der Objectmanager erkenne zu welchen Skin das Objekt gehört und es in den Buffer für diesen Skin reinschieben.
Aber wie gesagt wer sagt das alle Objekte die selbe Worldmatrix verwenden. Es geht ja darum den Aufrug der DrawPrimitive-Methode so gering wie möglich zu halten. Und das geht ja nicht weil ich die Matrix setzen muss, das Objekt rendern und danach die Matirx für das zweite Objekt ect...
Wie gesagt das würde aus meiner Sicht nur Sinn bei statischen Objekten machen. z.B. einer Landschaft.
wenn du eh jedes objekt einzeln rendern mußt, dann steck sie auch ruhig immer in einen eigenen buffer.
wonach du sortieren solltest hängt ganz extrem davon ab was du renderst. wenn du z.b. sehr wenige und lange pixelshader hast, dann kannst du nach der z-tiefe sortieren und von vorn nach hinten zeichnen. gegenüber von randommässigen zeichnen kannst du so locker 3fache geschwindigkeit herausbekommen. (siehe doom3)
wenn du viele verschiedene materialien hast (besonders shader), dann bringt es viel einen renderstatemanager/-guard zu coden, der könnte 10%performance locker raushollen (beachte, dabei wäre es nicht nötig nach materialien zu sortieren), oder du sortierst nach materialien, das bringt dann einiges mehr (zu beiden dingen gibt es im dx sdk ein sample)
wenn du extrem viele und kleine objekte hast, dann gibt es sehr viele lösungswege das zu lösen. einer wäre z.b. dass du viele in einen buffer steckst und einen speziellen vertexshader hast, der in einem matrixarray indiziert, dazu müßtest du jedem vertex abspeichern welche matrix er nutzen soll und natürlich müßtest du mehrere matrizen in die consts speichern. (würde man z.b. bei einem rts mit vielen kleinen einheiten sehr gut machen können)
wenn dein problem darin liegt, dass jedes objekt eine eigene texture hat, dann sollte man mehrere texturen in eine texturepage/textureatlas einfügen und entweder den objekten ein UV set geben mit welchem sie direkt aus der page referenzieren oder mittels shader (vielleicht über die ID die schon für die wolrdmatrizen benutzt wird) die UV coordinaten errechnen. (ala HL2)
aber optimieren solltest du erst am ende, wenn deine engine läuft. wenn sie gut konstruiert ist, dann ist es einfach sie später dahingehend zu erweitern dass es schnell läuft.
1. ist es schwerer mit einem optimierten code zu debugen und zu arbeiten (da unflexibler)
2. kann es sein dass er komplett neu geschrieben werden muss und dann ist die optimierarbeit umsonst gewesen (ala unrealengine1-rasterizer, der wurde 7mal neu geschrieben)
3. vielleicht optimierst du an einer ganz falschen stelle oder für einen ganz falschen fall der eventuell sogar das gegenteil von dem ist wofür die engine benutzt wird.rapso->greets();
-
wenn du eh jedes objekt einzeln rendern mußt, dann steck sie auch ruhig immer in einen eigenen buffer.
sicher? wär mir um ehrlich zu sein neu.
gibts dafür gründe?
-
wenn du eh jedes objekt einzeln rendern mußt, dann steck sie auch ruhig immer in einen eigenen buffer.
Na wie jetzt, eben meintest du noch das Gegenteil. Wegen der "Performance".
Bye, TGGC \-/
-
otze schrieb:
wenn du eh jedes objekt einzeln rendern mußt, dann steck sie auch ruhig immer in einen eigenen buffer.
sicher? wär mir um ehrlich zu sein neu.
gibts dafür gründe?ja, dann lässt du dx für dich den speicher managen und wenn du nur beim laden einmal nen riesen buffer vollstopfst, dann wird das meißte wohl nicht benutzt in einem frame. wozu dann alles im grakaspeicher halten müssen? wenn du dort stattdessen von dx texturen drinne hast, hast du mehr davon.
oder zeichnest du immer alle objekte?TGGC schrieb:
wenn du eh jedes objekt einzeln rendern mußt, dann steck sie auch ruhig immer in einen eigenen buffer.
Na wie jetzt, eben meintest du noch das Gegenteil. Wegen der "Performance".
Bye, TGGC \-/rapso schrieb:
...aber nur wenn man es richtig macht.
gott lass es hirn und augen regnen.
rapso->greets();
-
rapso schrieb:
...aber optimieren solltest du erst am ende, wenn deine engine läuft
Ich will richtig anfangen. Nicht das ich die Engine x-mal umprogrammieren muss.
Ich lasse mir eure Vorschläge und Meinungen durch den Kopf gehen. Danke.
-
richtig anfangen bedeutet ein projekt erst zuende zu coden und am ende optimieren und zwar nur an den stellen an denen es nötig ist. und wenn du richtig codest mußt du wenig neu coden und erweiterst nur.
so wie du das jetzt machst, ist es so als ob du jeden ziegel erst streichst und dann einbaust, anstat erst das haus zu bauen und am ende zu streichen.
rapso->greets();
-
rapso schrieb:
TGGC schrieb:
wenn du eh jedes objekt einzeln rendern mußt, dann steck sie auch ruhig immer in einen eigenen buffer.
Na wie jetzt, eben meintest du noch das Gegenteil. Wegen der "Performance".
Bye, TGGC \-/rapso schrieb:
...aber nur wenn man es richtig macht.
gott lass es hirn und augen regnen.
rapso->greets();
Also ist dein Vorschlag, es falsch zu machen?
Bye, TGGC \-/
-
TGGC schrieb:
rapso schrieb:
TGGC schrieb:
wenn du eh jedes objekt einzeln rendern mußt, dann steck sie auch ruhig immer in einen eigenen buffer.
Na wie jetzt, eben meintest du noch das Gegenteil. Wegen der "Performance".
Bye, TGGC \-/rapso schrieb:
...aber nur wenn man es richtig macht.
gott lass es hirn und augen regnen.
rapso->greets();
Also ist dein Vorschlag, es falsch zu machen?
Bye, TGGC \-/
welch redundante frage.
punkt 5 anwendenrapso->greets();
-
rapso schrieb:
richtig anfangen bedeutet ein projekt erst zuende zu coden und am ende optimieren und zwar nur an den stellen an denen es nötig ist. und wenn du richtig codest mußt du wenig neu coden und erweiterst nur.
so wie du das jetzt machst, ist es so als ob du jeden ziegel erst streichst und dann einbaust, anstat erst das haus zu bauen und am ende zu streichen.
rapso->greets();
Besteht nicht der größte Teil der Entwicklung aus Planung?
-
H.L.T.O schrieb:
rapso schrieb:
richtig anfangen bedeutet ein projekt erst zuende zu coden und am ende optimieren und zwar nur an den stellen an denen es nötig ist. und wenn du richtig codest mußt du wenig neu coden und erweiterst nur.
so wie du das jetzt machst, ist es so als ob du jeden ziegel erst streichst und dann einbaust, anstat erst das haus zu bauen und am ende zu streichen.
rapso->greets();
Besteht nicht der größte Teil der Entwicklung aus Planung?
jup,
planung, durchführung, optimierung
wenn du es in der richtigen reihenfolge haben möchtest
rapso->greets();
-
Wer bestimmt eigentlich "richtig"??
-
Sgt. Nukem schrieb:
Wer bestimmt eigentlich "richtig"??
die erfahrung die die leute durch eigens erlitene fehler bekommen haben
me2
rapso->greets();
-
otze schrieb:
kann es sein, dass jeder programmierer am ...
Ja duch hast recht mit Multitexturen. Aber ich denke mir das so.
Die Engine basiert auf Objekten und ihrer Haut(Skin) Man kann ein Skin definieren. Ein Skin besteht aus seinem Material und einer oder mehreren Texturen. Und zu einm Objekt gehört immer ein Skin.
Womit auch das Problem mit Multitexurierung beseitigt sein sollte.
Also kann ich zu einem Skin bis zu 8 Texturen zuweisen. Da fällt mir auf ich müsse ja noch ein Textur und ein Materialmanager programmieren das verhindert das die selbe Textur oder das selbe Material merhfach vorkommt.
Naja. schau ma mal.
-
am einfachsten ist das, wenn man sich dafür ein template machst. bei mir ist das auch immer weiter gewachsen, shader,materials,textures,entities,meshes... und jede resource hatte einen manager. nun hab ich nur ein template das als manager genutzt wird und es ist sehr viel weniger wartungsaufwand und zudem gibt es keine copy&paste fehler
rapso->greets();
-
rapso schrieb:
am einfachsten ist das, wenn man sich dafür ein template machst. bei mir ist das auch immer weiter gewachsen, shader,materials,textures,entities,meshes... und jede resource hatte einen manager. nun hab ich nur ein template das als manager genutzt wird und es ist sehr viel weniger wartungsaufwand und zudem gibt es keine copy&paste fehler
rapso->greets();
Und kann man mit deiner Engine schon was anfangen