schnelle mehrfache Animationen
-
moinmoin in die runde,
ich benutzte vc++6 und opengl und habe eine eigenen klasse für milkshape-modell-animationen (skeletal) geschrieben, die auch wunderbar funktioniert.
bei meiner planung zu einem spiel bin ich noch an einem problem hängen geblieben:
in den meisten spielen sind viele animierte objekte gleichzeitig sichtbar und im sichtfeld. die skeletale animation dauert aber auch relativ lange. meine frage zielt in das problem, wie man zeit sparen kann, um die framerate hochzuhalten, aber viele objekte sich auf dem bildschirm bewegen.
bei einem testmodel, bestehend aus ca 250 vertiece, ca 550 dreiecken und ca 12 bones ist mein neuer rechner (3,2GH und x800pro) schon bei 100 einzeln animierten objekten überfordert (fps: 12). bei serious sam bspw sind zeitweise mehr als 100 objekte gleichzeitig auf dem screen.
mein erster ansatz wäre es ein model für alle gleichartigen objekte zu laden, pro frame einmal zu animieren und mehrmals zu zeichnen. das ganze hat aber den nachteil, dass alle gleichen objekte gleichzeitig beim laufen ihr bein heben würden. das sieht ja verständlicherweise total blöde aus, also müssten doch eigentlich alle objekte einzeln animiert werden, welches aber wiederum viel zeit kostet. an meinem code kann ich kaum noch was optimieren, leider...
gibt es da eine alternative?? ich freu mich über eure ideen. ich kann doch nicht der erste sein, der vor diesem problem steht und in der forensuche und bei google hab ich nichts gefunden.
heimschmiede
-
zunächst solltest du untersuchen, was deinen rechner wirklich überfordert - ist es die skelettbasierte animation oder das rendern von 100 modellen
was kostet das Rendern aller modelle?
wieviel zeit nimmt die Animation in Anspruch?
-
jau, danke schon mal für den hinweis. hatte den test auch mal vorgehabt, is aber irgendwie in vergessenheit geraten.
aber dein gedanke is schon ganz richtig.
100 einzeln animierte Objekte: (Zeiterfassung in Millisekunden)
animieren und malen: 78 ms
nur animieren: 0-1 ms
nur malen: 78 msalso Zeitfresser ist das malen.
aber wie ist es möglich, dass neuere Spiele Szenarien besitzen mit mehreren Tausend Dreiecken in einem Sichtfeld und das ganze flüssig läuft?
Gibt es da Methoden, den Mal-Prozess zu beschleunigen ? (ich meine nicht die Techniken, wie Frustum-Culling & co...)
ich mein ein animiertes model lässt sich ja nicht in eine display-list von ogl packen, weil sich ja vertieces bewegen.heimschmiede
-
verschiedene Detail Stuffen - Für Modelle die weit Weg sind reicht es, wenn sie nur mit halber oder noch weniger Polygonen gerendert werden - es ist unsinnig eine Objekt mit 1000 Polygonen zu rendern, wenn es nur 10 * 10 Pixel groß ist
-
ich mein ein animiertes model lässt sich ja nicht in eine display-list von ogl packen
Da gibts schon Möglichkeit wie man sowas besser macht - vielleicht mit Vertex Shadern arbeiten - ich weiß es nicht - aber da gibts möglichkeiten

-
danke, ich werd mir mal deine tipps reinpfeifen und schaun, obs für meine zwecke ausreicht.
edit: hast du evetuell auch ein paar gute tuts zum thema vertex-shader ? wenn man sich in was neues reinsteigert, dann weiß man vorher kaum, ob das tut auch gut is

heimschmiede
-
bin mir nicht 100% ob vertex-shader die beste Lösung ist - hab damit keine Erfahrung - aber bin sicher hier gibt es jemanden der das weiß

-
Das Problem wird auch nicht das malen sein, denn da ist sicher noch etwaws mehr drin. Das Problem wird der übliche Transport über den AGp Bus sein ...
Du transformierst nicht zufällig in Software und lädts dann das Modell auf die Grafikkarte ?Du könntest nämlich das Modell auf die Grafikkarte laden und dann vor dem Zeichnen für jedes Körperteil Matrizen festlegen die alles richtig bewegen ..
Sorry, grad keine Zeit!
-
Du könntest nämlich das Modell auf die Grafikkarte laden und dann vor dem Zeichnen für jedes Körperteil Matrizen festlegen die alles richtig bewegen ..
Sorry, grad keine Zeit!also über Vetexshader???
-
ich vermute bei so extrem kleinen polygonmengen <1mio dass jedes vertex einzeln zur graka geschoben eird mit zig aufrufenß

rapso->greets();
-
Vertexwahn schrieb:
Du könntest nämlich das Modell auf die Grafikkarte laden und dann vor dem Zeichnen für jedes Körperteil Matrizen festlegen die alles richtig bewegen ..
Sorry, grad keine Zeit!also über Vetexshader???
er hat nichts von vs gesagt. er meint wohl die schon in der fixfunc existierende möglichkeit.
-
ich transformiere die models in meiner software, also ausgeführt auf der CPU. ich erstelle finale Matrizen für jeden bone . ich multipliziere die vertieces mit der finalen Matrix, die in der animations-funktion erstellt wird und schiebe die vertieces mit glVertex3f in die graka.
eine kleine zusatzinfo vieleicht: das model ist vollständig texturiert mit 2 texturen.
wie würde ich denn vorher das model in die graka schieben können? oder mit vertex-shadern (hab mich mal reingelesen, n leckeres thema
) ?
während der animation ändern sich ja alle finale matrizen für die animation, dann wäre das das einzige, was über den agp laufen muss.
hatte aber nicht toms-hardware einen bericht gehabt, dass eigentlich heut zu tage nicht einmal der agp-8mal in spielen ausgenutzt wird?
(http://www.tomshardware.de/graphic/20040425/pci-express-02.html)
und bei 100 modellen fällt folgender aufwand an: ca 25000 Vertieces und 55000 dreiecken -> 165000 Aufrufe der Funktion glVertex3f.
ich werd gleich mal testen, in wie weit die texturen den speed beeinflussen.
ich hab auch schon mal häufiger was von Vertexbuffern gehört und gelesen, hab mich aber noch nicht mit befasst, könnten die evtl weiterhelfen ??
heimschmiede
-
ich hab mir das model mal ohne texturen und materials anzeigen lassen und es ist nur minimal schneller (von 12FPS auf 13FPS)
ich habe mir nochmal gedanken über den agp-bus gemacht. wenn agb-8x einen datentransfer von abgerundet 2100 MByte/s schafft, dann kann man ja die benötigte zeit errechnen, wie lange es dauert die daten zu senden.
165.000 Aufrufe der funktion glVertex3f -> übertragung von 3 floats (jeweils 4byte lang). also erzeuge ich einen traffic von 1.980.000 Bytes (165000*3*4). das sind ca 1,888 MBytes.
benötigte zeit der übertragung: 1,888 MBytes / 2100MBytes/s = ~ 0,9 ms
dann muss man noch bedenken, dass protokoll-traffic dabei erzeugt wird. aber summa sumarum dürfte das nicht mehr als 2-3 Millisekunden dauern bei allen AGP-8x-Karten.also helfen in dem problem den draw-prozess zu beschleuningen nur die vertex-shader weiter? wie beschleuningt ihr eure spiele oder grafikanwendungen ??
heimschmiede
-
Das böse OGL hat wieder mal zugeschlagen. So viele glVertex3f sind nun mal lahm, lahm, lahm.
Bye, TGGC (Das Jahr des Helden)
-
Hi,
Auf der Seite www.nvidia.com findest du unter der Sparte Developer einige Präsentationen in denen unter anderem erklärt wird, wie du vertex-shader für bone-animationen bzw. key-frame interpolationen nutzen kannst (Wirklich viele Präsentationen!!!!).
Falls die FrameRate doch mal an der animation hängt bietet sich auch folgende Lösung an: Benutze deine Animations-Klasse nur um etwa alle 0.05 sec einen Keyframe zu berechnen und dann die GrKa(Vertexshader) um zwischen den letzten Keyframes zu interpolieren. Damit hängst du zwar minimal in der Zeit hinterher, hast aber einige Vorteile wie z.B.:
-Solltest du gezwungen sein ein einzelnes Modell mehrfach in einem Frame zu rendern (um z.B. coole Lichteffekte o.ä. zu erreichen) muß die GaKa einen weniger aufwändigen Shader beackern -> mehr fps.
-Natürlich wird die CPU weniger durch animationen belastet usw.
-Die Effektivität der Vertexbuffer (falls du welche einbaust) wird erhöht falls du die Bone-Animation auf der CPU ausführst (da du sie nicht jeden Frame neu beschreiben mußt) - Führst du alles auf der GraKa aus zieht dieses Argument natürlich nicht
.
.
.
Natürlich ist es außerdem wichtig wirklich nur die Objekte zu animieren und zu zeichnen die sichtbar sind...
-
also, ich werde mal schaun, wie weit ich es gebrauchen werde. ich denke mir mal, dass die kombination aus vertexbuffer + vertexshader + animationsberechnung auf der CPU die sinnvollste variante wäre. ich errechne also auf der CPU die finalen Matrizen und schiebe sie dann auf die graka, wo dann der vertexshader die matrizen empfängt, sich die vertices aus dem vertexbuffer holt und richtig rendert. ist es denn möglich speicherplatz auf dem graka-ram zu reservieren (für die finalen Matrizen) ?
und eine weitere Frage zu den vertex-shadern: ist es für das Programmieren egal, welche version der shader installiert ist? und von welchem Hersteller die graka ist? (ATI, nVidia) ?? oder muss ich mehrere versionen schreiben, sodass es auf ATI- und nVidia-Karten läuft ?
heimschmiede
-
Shader sind ein sehr sehr interessantes aber auch hoch komplexes Thema.
Ich würde es für dein Vorhaben nicht benutzen. Es ist mit Kanonen auf Spatzen geschossen. Und Animationen gab es auch schon bevor es VertexShader gab !
Lern erstmal noch ein bisschen den richtigen Umgang mit OpenGL, da kann man noch eine ganze Menge herausholen !
Hier mein Vorschlag den ich neulich nicht zuende schreiben konnte, da ich nun weiss das du über Software Transformierst.
Jede T&L Karte kann auf Hardware transformieren. Also alle Karten die so momentan im Umlauf sind halt.
Deshalb ein Vorschlag.
1. Lies dir was an wie du ganze Arrays an Vertices auf einmal an die Grafikkarte schicken kannst. Transformiere immernoch in Software und schicke dann alle Daten GESAMMELT im Array an die Gk (pro Modell).
Dies sollte dir einen ersten Eindruck geben wieviel die ganzen FunktionCalls zu glVertex3f gekostet haben als du jedes Vertex einzeln hochgeladen hast. (Diese Funktionen sind eigentlich nur für kleine Demos zum testen etc... nicht als praktikable Lösung gedacht)Danach verwirf das alles und unterteile dein Modell in alle Beweglichen Teile und lege einen VertexBuffer auf der Grafikkarte für jedes dieser Teile an.
Also hast du dann Arm, Torso, Fuss, Hand, Kopf, etc... auf der Grafikkarte liegen.Dann gehst du durch die Liste deiner "virtuellen" Modells und errechnest die Animationsmatrix für das entsprechende Körperteil(so wie bisher in Software auch)
Nur das du jetzt nicht in Software deine Vertices mit der Matrix multiplizierst sondern die TransformationsMatrix direkt an OpenGL auf die Grafikkarte schickst. Dann Renderst du den Körperteil.
Dies machst du einfach für alle Körperteile aller Models.
Dadurch wird die Matrixmultiplikation jedes einzelnen Vertex auf der Grafikkarte ausgeführt was natürlich viel viel schneller ist. Ausserdem musst du (siehe AGP) nicht jedesmal deine VertexDaten auf die Grafikkarte schicken(diese liegen dort untransformiert im Speicher) sondern nur die Transformationsbeschreibungen (Matrizen) für die einzelnen Körperteile. Und dies spart ordentlich Overhead über den AGP.
Diese Variante lässt sich noch um einiges Optimieren indem du TeilTransformationen (Position des Modells, Arm bewegt auch Hand etc...) behälts und die letzte Transformationsmatrix auf der GK nur mit der neuen Mutliplizierst.3. Diese Variante ist dann nur wenn du alles vorher gut gemacht hast und es dir immernoch zu langsam seien sollte(was ich nicht recht glaube
)
Du kannst versuchen die BewegungsMatrizen auf dem Shader zu berechnen, so das du diese Berechnung auch von der Software auf die Hardware verlagerst. Ich weiss nicht genau wie dies funktioniert. Ich nehme an die setzt einige Werte für deine Vertices im Buffer auf feste Vectoren(wie der Arm gedreht werden kann, etc...) und schreibst dir dann einen Shader der durch Shaderparameter weiss an welcher Stelle der Animation das Modell gerade sein soll und daraus die Matrizen berechnet.
Dadurch hast du dann nur noch ein paar Shadervariablen pro Model und Frame(bzw. Animationsabschnitt(muss nicht jedes Frame sein(->gilt auch für die anderen Varianten)) die über den AGP gehen müssen. Ausserdem sind dann sämtliche Berechnungen auf der Harfware, wofür sie schliesslich da ist.K, hoffe ich hab nicht zu viel scheisse geredet, hab mich verdammt lange nicht mit Grafik beschäftigt.
-
das hört sich doch schon sehr gut an. aber wie wird das dann wiederum in ogl realisiert?
1. wie sende ich ein ganzes Paket von Vertices rüber? ich kenn nur glVertex3fv und der verlangt nur einen Vertex in nem array.
2. wie lasse ich in ogl die Transformationsmtrix auf der graka errechnen ohne den in 3 angesprochenen VertexShader zu benutzen?
3. alles im shader arbeiten lassen, das wird noch ein heiden spaß
und nochmal die weitere Frage zu den vertex-shadern (damit sie nicht untergeht): ist es für das Programmieren egal, welche version der shader installiert ist? (änderungen der versionen sind logisch, sind sie aber auch abwärtskompatibel?) und von welchem Hersteller die graka ist? (ATI, nVidia) ?? oder muss ich mehrere versionen schreiben, sodass es auf ATI- und nVidia-Karten läuft ?
heimschmiede
-
Ob ati oder nvidia ist egal, solange die karte die entsprechende shader version unterstütz. Die Karten unterstützen auch immer ältere Shader. (Die Shader werden kompiliert und dann vom Prozessor der Karte ausgeführt. Da diese Prozessoren normalerweise immer umfangreichere Operationen unterstützen ist die Abwärtskompatibilität so weit ich das sehe eigentlich fast garantiert).Die Transformations - matrizen kannst du dir nicht auf der GraKa berechnen lassen (wäre zumindest nicht sinnvoll, da du die Berechnung dann für jeden vertex wieder ausführen müßtest). Die Transformationen der vertices bei gegebenen Matrizen auf der GraKa auszuführen ist hingegen sehr sinnvoll, da deren Prozessor für solche Rechnungen optimiert ist.
Zu Punkt 2 von Chaos Angle
Diese Unterteilung ist nur dann sinnvoll, wenn du kein skinning benutzt, d.h. wenn deine vertices nicht von mehreren bones beeinflußt werden. Falls du dich trotzdem dafür entscheidest wäre es etwas schneller, wenn du dein gesamtes modell in einem vertex-buffer schreibst und dir nur die offsets der jeweiligen Teile merkst. -> Dadurch mußt du den Buffer seltener wechseln.Auf der folgenden Seite findest du einige Methoden, wie du deine Dreiecke schneller auf die Karte bekommst.
-
zu finale matrizen-multiplikation der vertices auf der graka. ich meine das genau so, wie das gesagt hast mac_bu. nur die matrix-vektor-multiplikation auf der graka. aber wie mache ich diese finale multiplikation auf der graka? das dürfte doch nur mit nem vertex-shader funzen, oder? und wie bekomme ich dann die finale matrix auf die graka? (Quelltext)
die nehes kenne ich größten teils, aber der nutzt ja auch hauptsächlich die Funktion glVertex3fv. ansonsten verwendet er vertex-buffer. bei welchem tut siehst du, wo er nen vertex-array am stück rüber zieht??
heimschmiede