OpenGL-Vertex-Attribute - Normalisierung

8

Leider habe ich gesucht und keine endgültige Antwort gefunden.

Wann würden Sie die Scheitelpunktdaten in OpenGL mit dem folgenden Befehl normalisieren:

glVertexAttribPointer(index, size, type, normalize, stride, pointer);

Dh wann würde normalize == GL_TRUE; In welchen Situationen und warum sollten Sie die GPU die Berechnungen durchführen lassen, anstatt sie vorzuverarbeiten? Alle Beispiele, die ich jemals gesehen habe, haben dies auf GL_FALSE gesetzt; und ich persönlich kann keine Verwendung dafür sehen. Aber Khronos sind nicht dumm, also muss es für etwas Nützliches (und wahrscheinlich Gemeinsames) da sein.

verzögert kaviar
quelle

Antworten:

9

Der Parameter "normalisiert" wirkt sich auf die Verwendung von Festpunktwerten aus.

In diesem Dokument heißt es im Parameter "Gibt an, ob Festkomma-Datenwerte beim Zugriff normalisiert (GL_TRUE) oder direkt als Festkomma-Werte (GL_FALSE) konvertiert werden sollen."

Ferner dieses eine states „Für glVertexAttribPointer wird auf GL_TRUE wenn normalisiert gesetzt ist , zeigt es , dass in einem Integer - Format gespeicherten Werte auf den Bereich abgebildet wird [-1,1] (für vorzeichenbehaftete Werte) oder [0,1] ( für vorzeichenlose Werte), wenn auf sie zugegriffen und in Gleitkomma konvertiert wird. Andernfalls werden Werte ohne Normalisierung direkt in Gleitkommazahlen konvertiert. "

Zusammenfassend lässt sich sagen, dass Sie sich nicht darum kümmern müssen, wenn Sie keine Festpunktwerte verwenden. Wenn Sie dies tun, steuert dieses Flag, ob (zum Beispiel) der Bytewert 128 0,5 oder 128,0 sein soll.

Jari Komppa
quelle
3
Dies beantwortet die Frage nicht wirklich, ich habe bereits verstanden, was es tut, aber ich wollte wissen, wann es tatsächlich auf eine "gemeinsame" Implementierung anwendbar ist.
Verlangsamte
2
Ich bin mir ziemlich sicher, dass es damals relevant war, als viele mobile Anwendungen hauptsächlich Festkomma-Mathematik verwendeten und Gleitkomma-Mathematik nicht berühren wollten. Eine andere Möglichkeit besteht darin, dass Sie manchmal Daten kompakter speichern möchten, z. B. in Bytes, wenn die Genauigkeit ausreicht, und OpenGL die Bytes in den Bereich 0..1 konvertieren lassen.
Jari Komppa
Es ist immer noch relevant. Denken Sie zum Beispiel an UV-Koordinaten. Möglicherweise möchten Sie keinen Speicherplatz verschwenden und als float2 speichern. Speichern Sie ihn stattdessen als Optimierung unter 2 uint8 und setzen Sie das Normalisierungsflag so, dass Sie im Bereich [0, 1] anstelle von [0, 256] den Wert erhalten Programm.
nichtig
Wird 128 0,5 oder 128/255 = etwas höher?
Riv
11

Dies ist eine alte Frage, aber die aktuelle Antwort erklärt nicht wirklich, wofür Sie sie verwenden würden.

Es geht darum, Platz zu sparen. Und mit Scheitelpunktattributen kann weniger Speicherplatz eine höhere Leistung bedeuten (wenn Sie an die Scheitelpunktübertragung gebunden sind).

Farben benötigen normalerweise nicht viel mehr als 8 Bit pro Komponente. Manchmal benötigen Sie 16-Bit, wenn es sich um einen HDR-Lichtwert handelt oder so. Für Oberflächeneigenschaften (was die meisten Scheitelpunktattribute sind) sind 8 Bit in Ordnung. Vorzeichenlose normalisierte Bytes sind also ein gutes Scheitelpunktformat.

Texturkoordinaten benötigen keine 32-Bit-Gleitkomma-Genauigkeit. Ein 16-Bit-Wert von [0, 1] ist ausreichend. Normalisierte Shorts ohne Vorzeichen sind also ein vernünftiges Vertex-Format.

Normalen benötigen niemals eine Genauigkeit von 32 Bit. Das sind Anweisungen. Normalisierte 8-Bit-Bytes mit Vorzeichen sind in der Regel etwas klein, aber normalisierte 10-Bit-Werte sind die meiste Zeit gut genug. Mit OpenGL (3.3+) können Sie sogar 10-Bit-Normalen über ein gepacktes 10/10/10/2-Bit-Format verwenden, das in einer einzelnen 32-Bit-Ganzzahl ohne Vorzeichen gespeichert ist.

Sie können sogar Spiele mit Scheitelpunktpositionen spielen, wenn Sie dringend mehr Speicher benötigen.

Ohne Normalisierung müssten Sie wertvolle Zyklen in Ihrem Shader verschwenden, indem Sie die Byteattribute durch 255,0 teilen. Warum dies tun, wenn die Hardware dies kostenlos kann?

Nicol Bolas
quelle
Eine schöne Antwort. Aber ist der Overhead der Divisions-Gleitkomma-Mathematik vergleichbar mit einer Verringerung der normalen Größe um 50%? (Dh 32bit um 16bit zu sagen); auf moderner Hardware. Zumal wir uns nicht wirklich um zu viel Speicher kümmern müssen (zumindest in meinem Fall sowieso).
Verlangsamte
1
@ Daniel: Nun, lass uns darüber nachdenken. Bei "MODERNER Hardware" beträgt der Aufwand für die Übergabe normalisierter Werte ... Null. Der Aufwand für die Division im Shader ist ... ungleich Null. Egal wie verschwindend klein es ist, es ist immer noch größer als Null. Ganz zu schweigen von den Bandbreiteneinsparungen beim Senden eines 32-Byte-Blocks mit Scheitelpunktdaten anstelle eines 64 + -Byte-Blocks. Oh, und der Shader muss nicht speziell programmiert werden. Sie können denselben Shader verwenden, um normalisierte oder Float-Werte zu verwenden. Wenn Sie die Unterteilung in den Shader einfügen, benötigen Sie jetzt neue Shader für verschiedene Größen von Scheitelpunktdaten.
Nicol Bolas
Danke für die nette Antwort. Ich werde es auf jeden Fall im Hinterkopf behalten, es ist im Moment nicht notwendig, da ich ausgerichtete Scheitelpunktdaten sende, aber wenn ich weitere Informationen hinzufüge, sind diese möglicherweise nicht gleich, und dies kann sowohl beim Caching ein großer Vorteil sein und Durchsatz.
Verlangsamte
Gibt es Strategien zum Konvertieren des normalen (derzeit in einer Folge von (3x) 32-Bit-Floats gespeicherten) in einen 32-Bit-Int (10.10.10.2)?
Verlangsamte
@ Daniel: Wenn Sie fragen, wie die Erweiterung ARB_vertex_type_2_10_10_10_rev verwendet werden soll , empfehlen wir Ihnen, die Erweiterungsspezifikation zu lesen, mit der ich gerade verlinkt habe. Wenn Sie sich fragen, wie Sie die Bitmanipulation persönlich durchführen sollen, würde ich eine Struktur im C-Stil vorschlagen, die Bitfelder enthält .
Nicol Bolas
0

Stellen Sie sich vor, Sie haben ein Netz mit hochpräzisen Normalen und ein anderes Netz mit niedrigen Normalen. Mit der Attributnormalisierung können Sie denselben Shader verwenden, aber die Normalen des zweiten Netzes in Bytes packen.

Stepan Zastupov
quelle