| Autor |
Beitrag |
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Sa 25.06.05 17:33
Hallo zusammen!
Ich sollte einige Pixel (ca. 100) aus dem aktuellen OpenGl Framebuffer lesen. Ich befürchte, dass die Daten auf der GPU sind und die CPU keinen direkten Zugriff drauf hat.
Mit glReadPixels geht das ganze unglaublich langsam: Wenn ich pro Frame 100 Pixel über glReadPixels (100 separate Aufrufe) auslese, sinkt die Framerate von 300 auf 20...
Wie könnte man das effizient lösen? Die restlichen Daten im Framebuffer interessieren mich eigentlich nicht. Der Framebuffer wird auch nie angezeigt. Ich brauch einfach die Farben von ca. 100 vordefinierten Pixel.
Vielen Dank!
|
|
Phobeus
      
Beiträge: 1280
Linux (FC6), WinXP Pro (Box)
D6 Pers, D7 Pro, FPC 2.x
|
Verfasst: Sa 25.06.05 18:07
Also ganz spontan fällt mir keine brauchbare Alternative außer glReadPixels ein. Sollte die FPS nur von 200 auf 30 bei jedem Frame runtersacken, wäre ich da noch dankbar drüber. Bei so manchem Spiel merkt man beim machen eines Screenshoots diesen Vorgang durchaus merklich.
Die Frage, die sich mir momentan durch den Kopf geistert ist ein "wieso?" vor allem, warum nur ein Bereich, der ggf. nicht einmal angezeigt werden soll. Evtl. findet man dort eher einen besseren Ansatz. Ich fürchte aber, dass es keine Verfahren gibt, die sonderlich schneller sind... also eigentlich halte ich es für recht schnell, da ja durchaus auch eine Datenmenge bewegt wird. Wenn diese dann nur im Speicher gehalten wird, wird sich nicht mehr viel verbessern lassen. (wenn ja, möge man mich darauf hinweisen) 
_________________ "Menschen sterben nicht wenn man sie zu Grabe trägt, sondern wenn sie ihre Träume verlieren..."
|
|
delfiphan 
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Sa 25.06.05 18:23
Danke für die Antwort.
Wäre für eine einfache 2D-Kollisionserkennung. Um rauszufinden, ob Eckpunkte eines Polygons innerhalb eines anderen Polygons liegen. Aber wenn's so ist, mach ich's halt anders. Ist einfach aufwändiger zum programmieren.
|
|
Phobeus
      
Beiträge: 1280
Linux (FC6), WinXP Pro (Box)
D6 Pers, D7 Pro, FPC 2.x
|
Verfasst: Sa 25.06.05 21:53
Na,na,na, na... was höre ich den da. Also Kollisionserkennungen über glReadPixels klingen wirklich nicht wie Sinn und Zwecker dieser Funktion. Hole mir aus der Apotheke ja auch kein Medikament, damit ich den Beipackzettel benutzen kann um den Grill anzuzünden  Kollisionserkennungen sind definitiv einfacher, schneller und effizienter zu realisieren. Alles was Du auf dem Bildschirm bringst hat ja schließlich auch eine bekannte Position mit der man ermitteln kann, ob etwas mit etwas anderem kollidiert. Im Falle der Maus gäbe es die Möglichkeit dies über eine Selektion zu machen. Ich vermute mal, dass der Hintergrund für den "Pixelversuch" ist, dass ein sehr genauer Kollisionsbereich vorhanden sein soll. In diesem Fall würde ich dennoch eher zu Bounding Boxes bzw Bound Spheres greifen. Setzt man mehre davon ein erreicht man Ergebnisse die für den Menschen nicht mehr als ungenau wahrgenommen werden können.
Auch gibt es einige Extensions (keine Ahnung, ob noch wirklich zeitgemäß) mit denen man prüfen kann, wieviele pixel eines Objektes sichtbar sind ( www.delphigl.com/scr...n_query&action=2 Kurze Beschreibung). Vermutlich aber auch eher nur dann zu gebrauchen, wenn es darum geht irgendwelche Flares realistisch auf den Bildschirm zu zauberen. Dazu fällt mir dann höchstens noch FastGeo ein ( www.partow.net/projects/fastgeo/index.html). Habe es mir noch nicht näher angesehen, allerdings sollte diese Lib helfen, wenn es um sehr komplexe Kollisionen geht. Das Darstellen via OpenGL sollte damit auch leicht sein.
Eine Kollision auf Basis der Pixelerkennung ist aber in jedem Fall, der Denkbar schlechteste Weg.
_________________ "Menschen sterben nicht wenn man sie zu Grabe trägt, sondern wenn sie ihre Träume verlieren..."
|
|
delfiphan 
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Sa 25.06.05 23:04
Nun so schlecht ist es nicht. Es gibt (IIRC) auch neue Papers, die diesen Weg sogar für 3D-Kollisionserkennung vorschlagen. Jedoch ist dann die Software-gerenderte Version schneller, da eben diese Pixelkopiererei sehr langsam ist. AABB, usw. kenn ich natürlich schon. Die beste Methode ist wohl wenn man OOBs verwendet, habe aber keinen Bock das zu programmieren. Aber ich möcht in meinem eigenen Thread eigentlich auch gar keine Methoden vorstellen, die es in der Literatur gibt.
Ich wollte eigentlich bloss wissen, ob das Lesen eines einzigen Pixels auch wirklich so langsam ist. Offenbar ist das der Fall...
Mir geht es vor allem darum, nicht viel programmieren zu müssten. Ich möchte eigentlich damit meine Physik-Engine testen. Die Engine läuft in 3D; zu Testzwecken reicht mir aber eigentlich 2D (vorerst). Eine Library benützen möcht ich eigentlich auch nicht (Einarbeitung/Inkompatibilität der Datentypen/Sollte auch für nicht-konvexe Polygone gehn/Dazu brauch ich noch die Normalen an den Kontaktpunkten/etc.).
Hab jetzt einen anderen Quick&Dirty Weg gefunden. Das reicht mal sicher für Testzwecke.
Vielen Dank nochmals.
|
|
Phobeus
      
Beiträge: 1280
Linux (FC6), WinXP Pro (Box)
D6 Pers, D7 Pro, FPC 2.x
|
Verfasst: Sa 25.06.05 23:24
Also diese Papers würden mich wirklich interessieren. Ich habe keinerlei Erklärung warum man einen solchen Weg wählen sollte. Immerhin schleifen wir einen riesigen Datenwulst quer von Grafikkarte durch Hauptspeicher, vergleichen dann vermutlich mit der langsamen CPU diese. Um sowas zu machen muss es schon einen mächtig guten Grund geben... zumindest wenn die Alternative aus ein paar Fliesskomma-Berechnungen, die selbst aufm C64 noch laufen täten.
_________________ "Menschen sterben nicht wenn man sie zu Grabe trägt, sondern wenn sie ihre Träume verlieren..."
|
|
delfiphan 
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Sa 25.06.05 23:50
z.B.: Naga Govindaraju et al: Efficient Inter- and Intra-Object Collision Culling using Graphics Hardware ( gamma.cs.unc.edu/QCULLIDE/QCULLIDE.pdf).
(Ist eines aus einer Referenzliste. Könnte falsch liegen. Ich les es jetzt nicht durch um das zu verifizieren)
Kollisionserkennung ist nicht so einfach wie es du schilderst. Oft hat man Tausende von Elemente/Dreiecke. "Ein paar Fliesskommaberechnungen" reichen da nicht, vor allem wenn das Objekt nicht konvex ist. Die Komplexität der Brute-Force-Methode ist O(n^2). Um das auf O(n) runterzubringen braucht es schlaue Algorithmen... Am besten ist es, wenn man sich eine Hierarchie baut, zuerst das ganze Objekt als ganze betrachten (z.B. Konvexe Hülle), dann das halbe Objekt, dann 1/4, usw. So kann man schnell sehr viele Dreiecke ausschliessen, ohne die jemals berührt zu haben. Jedoch muss man bei einer Bewegung des Objektes die gesamte Hierarchie updaten, usw.. Bei deformierbaren Objekten geht das natürlich auch nicht. Da kann der Weg über die GPU sehr nützlich sein, da diese sehr viele Dreiecke sehr schnell verarbeiten kann.
|
|
Phobeus
      
Beiträge: 1280
Linux (FC6), WinXP Pro (Box)
D6 Pers, D7 Pro, FPC 2.x
|
Verfasst: So 26.06.05 08:42
Also in seinem Artikel sehe ich zumindest nichts zu glReadPixrls. Schaut aber interessant aus und werde es mir mal bei Zeit zu gemüte führen. Was Du begreifen mußt ist, dass dein angestrebter Weg alles andere als über die GPU geht. Du liesst eine Datenmenge (ca 2 MB) in den Hauptspeicher und gehst diesen dann mit der CPU durch. Und was komplexe Kollisionen angehst, so nennst Du ja bereits die Lösung. Erst grobe Schritte und dann immer feiner werden. Auch bei kommerziellen Titeln wird um ein Objekt nur eine einfache Spehre hängen und dann wenn wirklich eine Kollision droht beginnt man diese zu zerteilen und verschiedene Hitzones zu überprüfen. Würde man wirklich komplexe Abfragen haben würde sich der Einsatz eines Baumes sicherlich lohnen. Das schlägt zwar auch alles auf die CPU, allerdings ist immer noch weitaus weniger Aufwand als die von Dir angestrebte Lösung und ist immer noch viel exakter.
Wie soll den eine Farberkennung in der Praxis aussehen? Der Co-Designer eines Spiels entscheidet sich die Fussbodentextur nun statt schwar doch grau zu machen und schon funktioniert der Algorithemus nicht mehr?
Bei Bewegung muss nichts aktualisiert werden. Alle Positionen sind weiterhin bekannt und die zur Ausgabe verwendete Ausrichtung ergibt dann den Rest. Schwerer wird es in der Tat mit Objekten, die sich verformen und alles andere als "eckig" sind. Doch ernsthaft. Wofür brauchst Du eine solch exakte Kollisionserkennung? Wenn Du nicht gerade damit an deiner Diplomarbeit arbeitest, sondern diese "nur" für ein Projekt brauchst, wird eine herkömmliche Erkennung ´a la "min/max"-Bounce ihren Dienst bereits prima erfüllen. Den gerade im 3D-Bereich wird auch heute (und muss IMAO auch) immer noch mit Nährungs und Schätzverfahren gearbeitet werden, die allesamt einen durchaus realistisches Ergebnis bieten können.
//edit: Das Verfahren was in dem PDF beschrieben wird scheint wohl in Richtung der NV-Extension zu gehen, die ich Dir oben genannt habe. Ich bezweifel zwar, dass diese im großen stil angewendet wirklich gute Ergebnisse liefern wird, aber vielleicht solltest Du Dir das einmal näher ansehen bzw. deren ARB-Nachfolger.
_________________ "Menschen sterben nicht wenn man sie zu Grabe trägt, sondern wenn sie ihre Träume verlieren..."
|
|
delfiphan 
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 26.06.05 09:51
Vielen Dank für deine Antworten. Wie gesagt, ich weiss schon, was es für Möglichkeiten gibt  Es ging mir lediglich darum, in 10 Minuten eine Kollisionserkennung zu schreiben, welche nicht Brute-Force ist, und auch für nicht-konvexe Polygone funktioniert, ohne dass ich dieses aufteilen muss.
Wenn du Bounding Spheres nimmst musst du bei Bewegung nichts updaten. Wenn du aber AABBs oder z.B. die konvexe Hülle nimmst, musst du diese alle updaten/mitdrehen, wenn sich das Objekt dreht. Mein (alter) Weg geht sehr wohl über die GPU: Ich lasse die Sache von der GPU zeichnen (Polygone verdreht/verschoben zeichnen). Das geht einiger schneller als von Hand und über Canvas.Polygon. Nur ist eben dieser Informationsaustausch der "Bottleneck"...
Wenn man in einer quasi "Gratisoperation" Pixels auslesen könnte, könnte man in 2O(n) Schritten eine (recht gute, aber nicht exakte) Kollisionserkennung durchführen: Einmal vorwärtsrendern (natürlich ohne Textur), einmal rückwärtsrendern (verkehrte Reihenfolge), Eckpunkte auslesen, Farbinformationen auswerten. => Ist sehr einfach zu implementieren, geht für sehr allgemeine Objekte, und ist erst noch sehr schnell (ausser eben...).
Also, ich mag jetzt nicht noch lange über Kollisionserkennung diskutieren. Wollte ja lediglich wissen, ob man vielleicht einzelne Pixel schnell auslesen kann, denn glReadPixels ist ja für mehrere Pixel gedacht und sehr langsam. 
|
|
Phobeus
      
Beiträge: 1280
Linux (FC6), WinXP Pro (Box)
D6 Pers, D7 Pro, FPC 2.x
|
Verfasst: So 26.06.05 11:13
Ja, klar. Das Rendering erfolgt über die GPU. Ich meinte auch die Kollisionserkennung und das pixelweise auslesen belastet die CPU weitaus mehr als die GPU. Das interessante ist ja gerade den Falschenhals CPU zu meiden. Die Methode mit dem Occlussion Query ist dabei evtl. eine solche, allerdings war sie auf der alten GeForce recht "langsam", zumindest im direkten Vergleich zu normalen Fließkommaberechnungen. Keine Ahnung, ob dies eventuell bei neueren Karten performanter geht. Ich kenne diese Technik von Lens Flares bei der geprüft wird, wieviel von einer Lichtquelle sichtbar ist um entsprechend die Stärke der Lens zu bestimmen.
However, wenn Du mal was zeigbares hast, was in diese Richtung funktioniert, tue Dir keinen Zwang an und terrorisiere mich mal mit ner PM 
_________________ "Menschen sterben nicht wenn man sie zu Grabe trägt, sondern wenn sie ihre Träume verlieren..."
|
|
delfiphan 
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 26.06.05 11:42
Ich brauch ja nebst der Kollisionserkennung auch noch die Normale zur nächstgelegenen Kante. Deswegen eignet sich die Pixelmethode alleine (für meine Zwecke) nicht wirklich... Ich hab jetzt einfache konvexe Bereiche vorberechnet/tabelliert und die Normalen grad mitgespeichert. Damit scheint es eigentlich recht gut zu klappen. Das Demo mit den Zahnrädern (ca. 180 Eckpunkte) läuft bei mir mit 550 Frames/Sekunde (es wird aber nur jedes 10. Frame angezeigt) bei ca. 50% CPU Auslastung inkl. Physik. Für Testzwecke reicht das völlig aus.
|
|
F34r0fTh3D4rk
      
Beiträge: 5285
Erhaltene Danke: 28
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: So 26.06.05 19:33
kannst du deine physik engine vielleicht für delphix umbauen ? physik in 2d ist ein interessanter aspekt, aber in opengl arbeite ich nicht gerne damit 
|
|
delfiphan 
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: So 26.06.05 22:18
Sollte eigentlich kein Problem sein, kenn mich einfach überhaupt nicht mit DelphiX aus. Kann man dort schnell Polygone zeichnen und auch schnell Pixel auslesen? (Viel schneller als OpenGl kann es ja aber nicht sein, weil die Geschwindigkeitsschranke hardwarebedingt ist...)
(PS: Mein Problem ist eigentlich gelöst  )
|
|
|