Ist verzögertes Rendern / Shading mit OpenGL ES 2.0 möglich?


20

Ich habe dies bei StackOverflow gefragt , aber es könnte hier sinnvoller sein:

Hat jemand verzögertes Rendern / Shading unter OpenGL ES 2.0 implementiert? MRTs werden nicht unterstützt. Mit nur einem Farbpuffer kann dies also nicht auf die "übliche" Weise implementiert werden.

Insbesondere erkunde ich iPad, iPhone4 (möglicherweise iPhone 3gs) und Android. In der GLESView-App auf iPad / iPhone4 / iPhone3gs ist die GL_OES_RGB8_RGBA8-Erweiterung vorhanden, und ich habe noch nicht zu tief geschaut, aber bei 8 Bit / Kanal ist diese Idee interessant: http://www.gamedev.net/topic/ 562138-opengl-es-20-and-latent-shading /

Irgendwelche anderen Ideen? Lohnt es sich überhaupt, dies in Bezug auf die Leistung zu tun?


Ja es ist möglich.
Quazi Irfan

7
Über welche Technik (en)?
Jim Buck

Antworten:


15

Ja, es ist möglich. Besonders lohnenswert ist es jedoch nicht.

Erstens können Framebuffer-Objekte unter ES 2.0 nur in einem Image gerendert werden, es sei denn, Sie haben Zugriff auf die Erweiterung NV_draw_buffers (wie der Name schon sagt, handelt es sich nur um NVIDIA) zu einer Zeit. Um Ihre G-Puffer zu generieren, müssen Sie Ihre Szene mehrmals rendern, wodurch einer der Vorteile des verzögerten Renderns wegfällt.

Zweitens ist die Bandbreite auf mobilen Plattformen nicht die gleiche wie auf GPUs mittlerer Qualität. Und Bandbreite ist entscheidend, damit sich verzögertes Rendern (für viele Lichter) lohnt. Ohne diese Bandbreite werden die Lichtpässe in Bezug auf die Leistung wirklich wehtun.

Drittens ist PowerVR-Hardware wirklich nicht für diese Art von Dingen ausgelegt. Es optimiert das Rendern mit seiner kachelbasierten Renderhardware. Daher wäre ein verzögertes Rendern darüber hinaus weniger hilfreich als in einer herkömmlichen Scan-Konvertierungsarchitektur.


6

Das Hauptproblem ist die Füllrate. Auf mobilen GPUs ist Ihre Füllrate niedrig, sodass Sie kein zeitversetztes Shading in Echtzeit mit nativer Auflösung durchführen können.

Bei iPhone 4 und iPad 1 ist die Füllrate einfach lächerlich. Das einzige IOS-Gerät mit guter Füllrate ist das iPad 2, aber ich bezweifle, dass es genug gibt ... Unter Android verfügen nur Tegra-Geräte über die GL_NV_draw_buffers, um MRT zu verwenden, aber die Füllrate ist auch sehr niedrig. Der Mali 400 scheint die beste Füllrate zu haben. Wenn Sie weinen möchten, versuchen Sie einfach, ein Farbrechteck mit 4-maliger Vollbildauflösung zu füllen ... Viele Geräte können es nicht mit 60 fps.

Auf Desktop-GPUs haben Sie eine 10-fache (oder höhere) Füllrate als auf Mobilgeräten. Vergessen Sie nicht, dass mobile GPUs denselben Arbeitsspeicher wie die CPU verwenden und Sie keinen dedizierten Arbeitsspeicher haben.

Es gibt einige Beispiele in WebGL (dieselbe API), damit die API nicht eingeschränkt wird.


1
+1, um die Schwäche zu füllen. Ich konnte nicht einmal Gaußsche Unschärfe mit einer Auflösung von 1536 x 2048 bei 60 fps erzeugen (die Bildrate wurde sofort auf 30 fps gesenkt, selbst bei nur 4 Samples)
bobobobo

1
Ich denke, dies hängt sehr stark von den Feinheiten Ihrer Implementierung ab und davon, welche Auswirkungen dies auf die mobile Hardware hat. Zum Beispiel haben diese Jungs 2012 eine mäßig performante DoF-Unschärfe gemacht .
Ingenieur

1

Sie müssen sich wirklich überlegen, was das absolute Minimum ist, das Sie für einen verzögerten Renderer benötigen. Wenn Sie auf verzögertes Licht zurückgreifen, wird die Menge der Daten reduziert, die im GBuffer gespeichert werden müssen, und es ist wirklich eine Menge billiger als die Hälfte der Szene dreimal oder öfter zu rendern, um eine geringe Menge an Licht zu unterstützen.

Ich würde für das folgende GBuffer-Format gehen:

  • Verwenden Sie den Tiefenpuffer für den Beleuchtungspass erneut. Sie sind sich nicht sicher, wie weit dies auf Mobilgeräten unterstützt wird, aber es handelt sich um eine freie Tiefenstruktur.
  • Eine einzelne GBuffer-Textur, in der ich speichern würde: Normal U, Normal V, Param 0, Param 1. Die Lambert-Azimuthal-Codierung sieht für Normalen sehr gut aus und komprimiert sie in nur zwei Komponenten, die auch relativ billig zu codieren und zu decodieren sind.
  • Zwei Parameter für Beleuchtungsvariablen sind eine Menge. Sie könnten einen als Aufzählung für mehrere Beleuchtungsfunktionen verwenden, wenn die Hardware die dynamische Verzweigung gut beherrscht.

Die verzögerte Beleuchtung ähnelt dem verzögerten Rendern, mit der Ausnahme, dass Sie die Szene zweimal rendern:

  1. Rendern Sie Geometrietiefe, Normalen und Beleuchtungsparameter in den GBuffer.
  2. Lichter in den Akkumulationspuffer rendern.
  3. Rendern Sie Geometrie mit Material-Shadern und kombinieren Sie auch hier Ihre Beleuchtung. Wenn Sie es gut verstehen, Umkehroperatoren für Beleuchtungsgleichungen zu erarbeiten, können Sie mit diesem Schritt VIELE wirklich coole Dinge tun.
  4. Führen Sie alle Nachbearbeitungen durch, die Sie sich leisten können, und achten Sie darauf, die Tiefe und die normalen Texturen aus Gründen der Effizienz zu Tode zu missbrauchen.

Informationen zum Speichern der Beleuchtungsergebnisse. Ich habe es geliebt, diffuse Farbe und spiegelnde Luminanz zu speichern, so dass der Akkumulationspuffer nur eine standardmäßige 32-Bit-Farbtextur sein muss. Sie können die Spiegelfarbe abschätzen, indem Sie die Farbsättigung der diffusen Farbe berechnen und diese mit der Spiegelhelligkeit kombinieren.

Das Wichtigste ist jedoch, den Tiefenschablonenpuffer so gut wie möglich zu nutzen. Stellen Sie sicher, dass Sie keinen der Lichtcodes rendern, die nicht benötigt werden. Ich würde sogar so weit gehen, den Fragment-Shadern einige Discard-Anweisungen hinzuzufügen, die die Sichtbarkeit des Lichts unter den Anzeigebereich des Geräts senken (1e-3 ist normalerweise ein sicherer Grenzwert).


discardist wirklich sehr, sehr schlecht für kachelbasierte Pipelines, die von vielen / den meisten mobilen GPUs verwendet werden.
Ingenieur

1

Erwägen Sie eine verzögerte Beleuchtung. Kurz gesagt, die verzögerte Beleuchtung ist eine Technik, bei der eine reduzierte Version der verzögerten Schattierung verwendet wird, um eine Lightmap für den Bildschirmbereich zu berechnen. In einem zweiten Durchgang wird die Geometrie unter Verwendung der Screenspace-Lightmap als Beleuchtungsinformation erneut gerendert.

Diese Technik wird verwendet, um die Größe des G-Puffers zu reduzieren, da weniger Attribute benötigt werden. Sie haben auch den Vorteil, dass der G-Buffer und die Screenspace-Lightmap eine geringere Auflösung als der Bildschirm haben können.

Ich hatte einen strengen GLES 2.0-basierten Renderer implementiert (obwohl ein experimenteller) und es gelang mir, den G-Buffer auf eine RGBA-Textur zu reduzieren (ja, ich habe eine texture2D anstelle eines Renderbuffers verwendet). Es enthielt die normale Karte des Bildschirmbereichs + den Tiefenpuffer im Alphakanal (der, soweit ich mich erinnere, mit einem Logarithmus komprimiert wurde).

Die Position Attribute ( so genannte Welt hier) während der Beleuchtung Passes mit der Tatsache berechnet werden, dass in einem perspectivic Vorsprung, .xy durch geteilt wird .z , so dass:

xyfrustum=xywOrld/zwOrld

Ich habe das xy des Positionsattributs wie folgt approximiert :

xywOrld=xyfrustumzwOrld

Hinweis: Ich musste abhängig von den Einstellungen der Projektionsmatrix weitere Anpassungen vornehmen.

Bemerkenswert ist auch, dass ich die .z- Komponente der normalen Vektoren weglassen konnte, da ich .z aus .xy rekonstruieren konnte, da der normale Vektor normalisiert ist, so dass:

x2+y2+z2=1x2+y2+z2=1z2=1-(x2+y2)z=1-(x2+y2)

Mit dieser Technik konnte ich einen anderen Kanal in meinem RGBA G-Buffer freigeben und damit die spiegelnde Bildschirmkarte (oder, wenn Sie so wollen, den Glanz) speichern.


Übrigens: Mein Renderer war an keine Spiele-Engine gebunden. Es war nur eine Hallo-Welt-Demo, die Suzanne renderte.
Simon Schmidt

0

Ja, das ist absolut möglich. Die Füllrate ist kein Problem, da mobile Grafikchips für Bildschirme mit sehr hoher Auflösung ausgelegt sind. Das verzögerte Rendern hilft dabei, da Ihre Beleuchtungsberechnung unabhängig von der Komplexität der Szene ist, sodass ein Überzeichnen keine Verlangsamung verursacht. Hier ist meine Implementierung auf einem iPad der vierten Generation: http://www.youtube.com/watch?v=K4X1oF6b4V8

Wenn Sie die vierfache Leistung erzielen möchten, benötigen Sie nur die Hälfte der Auflösung der Textur, auf die Sie rendern. Bei 3D-Grafiken auf einem Retina-Bildschirm kann ich sowieso keinen Unterschied feststellen.

Mobile Grafikchips eignen sich aufgrund der Art und Weise, wie sie Render-to-Texture verarbeiten, hervorragend für verzögertes Rendern. Im Gegensatz zu PC-Grafikkarten, die normalerweise einen großen Leistungseinbruch erleiden, wenn Sie beginnen, eine Textur anstelle eines Fensterkontexts zu rendern, sind mobile Grafiken so konzipiert, dass sie keine Leistungseinbußen verursachen. So erhalten Sie die Skalierbarkeit eines verzögerten Renderers, ohne die anfängliche Leistungseinbuße, die Sie bei einer Desktop-Grafikkarte erleben.

Zum Zeitpunkt meiner Implementierung fehlte OpenGLES das Rendern für mehrere Ziele, sodass ich die Bildschirmfarbe und die Normalfarbe in separaten Durchgängen zeichnen musste. Dies kann in neueren Versionen von OpenGLES behoben werden, weiß aber nicht, ob die Lösungen noch in mobiler Consumer-Hardware verfügbar sind.


3
"Mobile Grafikchips sind aufgrund der Art und Weise, wie sie Rendering-to-Texture verarbeiten, sehr gut in der verzögerten Wiedergabe. Im Gegensatz zu PC-Grafikkarten, die in der Regel einen enormen Leistungseinbruch erleiden, wenn Sie statt in einem Fensterkontext in eine Textur rendern, sind es mobile Grafiken entwickelt, um dies ohne Leistungseinbußen zu tun. " Das ist eine große Behauptung. Haben Sie seriöse Referenzen, um diese Behauptung zu stützen?
Panda Pyjama
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.