Nullvektor bei GLSL-Funktionen

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
smurfer
Establishment
Beiträge: 116
Registriert: 25.02.2002, 15:55

Nullvektor bei GLSL-Funktionen

Beitrag von smurfer » 10.12.2019, 09:53

Hallo zusammen,

liefert der Nullvektor bei Funktionen wie dot oder reflect ein spezifiziertes Ergebnis, oder ist dies abhängig von der Implementierung?

Die OpenGL-Referenz für reflect schreibt:

"For a given incident vector I and surface normal N reflect returns the reflection direction calculated as I - 2.0 * dot(N, I) * N. N should be normalized in order to achieve the desired result. "

Der Nachsatz mit "N should be normalized [...] desired result." liest sich für mich zunächst wie ein Hinweis, aber auch mit nicht-normalisierten Vektor sollte das Ergebnis mathematisch korrekt berechnet werden. Für N=Nullvektor wäre nach der angegebenen Formel das Ergebnis I, dies wäre der für mich gewünschte Fall. Nur bin ich mir unsicher, ob ich nicht irgendwo eine Spezifikation übersehen habe, die bei dieser und ähnlicher Funktionen den Nullvektor verbietet.

Hintergrund des Ganzen: Ich versuche mir damit im Shader ein bedingte Verzweigung zu ersparen, da ich die Reflexion nur für bestimmte Bereiche berechnen möchte. Dort, wo keine Berechnung erfolgen soll, würde ich den Nullvektor als Normale zugrunde legen.

Beste Grüße, smurfer
Zuletzt geändert von smurfer am 11.12.2019, 09:51, insgesamt 1-mal geändert.

Benutzeravatar
Schrompf
Moderator
Beiträge: 4018
Registriert: 26.02.2009, 00:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Nullvektor bei GLSL-Funktionen

Beitrag von Schrompf » 10.12.2019, 10:25

Ich kenne die Spec nicht, aber allein aufgrund der Formel würde ich behaupten, dass ein Null-Vektor da stressfrei durchgeht und halt Null ergibt.
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.

Benutzeravatar
dot
Establishment
Beiträge: 1667
Registriert: 06.03.2004, 19:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Nullvektor bei GLSL-Funktionen

Beitrag von dot » 10.12.2019, 12:35

Der Nachsatz steht da weil die Formel nur für den Fall eines normalisierten N funktioniert. Was die Formel effektiv tut ist (\(\langle\mathrm{\mathbf n}, \mathrm{\mathbf l}\rangle\) entspricht dot(n, l)):
blub.png
\(\langle\mathrm{\mathbf n}, \mathrm{\mathbf l}\rangle\cdot\mathrm{\mathbf n}\) ergibt nur dann die Projektion von \(\mathrm{\mathbf l}\) auf \(\mathrm{\mathbf n}\), wenn \(\mathrm{\mathbf n}\) normalisiert ist…

smurfer
Establishment
Beiträge: 116
Registriert: 25.02.2002, 15:55

Re: Nullvektor bei GLSL-Funktionen

Beitrag von smurfer » 10.12.2019, 13:18

Hallo Schrompf, dot,

danke für die Antworten. Dot, danke für die unterstützende Skizze, so hatte ich es auch interpretiert: das Ergebnis ist zwar nicht das erwartete (Reflexion), aber mathematisch wird es korrekt nach Formel berechnet (und liefert nicht etwa ein undefiniertes Verhalten). Damit spricht die Formel inklusive Nebensatz für mich erstmal nicht gegen den Nullvektor, was das erwartete Resultat des Terms (bei N=Nullvektor also I) angeht.
Zuletzt geändert von smurfer am 11.12.2019, 09:51, insgesamt 1-mal geändert.

Benutzeravatar
dot
Establishment
Beiträge: 1667
Registriert: 06.03.2004, 19:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Nullvektor bei GLSL-Funktionen

Beitrag von dot » 10.12.2019, 18:24

Ja, wenn du für N den Nullvektor in die Formel einsetzt, kommt l raus… ;)

Die GLSL Spezifikation schreibt vor, dass das Ergebnis nach eben genau dieser Formel zu berechnen ist. Du kannst dich darauf verlassen, dass das Ergebnis auf diese (oder mathematisch äquivalente) Art und Weise berechnet wird. Der Nachsatz, dass N normalisiert sein muss damit das Ergebnis auch wirklich einer Reflexion entspricht, ist wohl nur da, um klar zu machen, dass reflect() den Parameter nicht implizit intern normalisieren muss…

smurfer
Establishment
Beiträge: 116
Registriert: 25.02.2002, 15:55

Re: Nullvektor bei GLSL-Funktionen

Beitrag von smurfer » 11.12.2019, 09:43

Alles klar dot, danke für die Bestätigung. Dann kann ich das beruhigt so implementieren, ohne sämtliche GPUs zu testen oder zu hoffen ;-)

Noch eine Frage am Rande dazu: Wenn ich in einem Shader eine performancekritische Operation habe, die auf mehrere Arten implementiert werden kann (wie im Beispiel oben "Verzweigung vs. Nullvektor"), kann es für mein Dafürhalten sinnvoll sein, beide Varianten zur Verfügung zu stellen und auf der Zielplattform, nach einem kurzen Performancetest, die entsprechende Variante zu wählen. Gibt es dazu übliche Vorgehensweisen, ein "best practice"? Naiv würde ich bei erstmaliger oder gewünschter Nutzung testen und im Code über eine Bedingung den potentiell geeigneteren Shader wählen.

Benutzeravatar
Schrompf
Moderator
Beiträge: 4018
Registriert: 26.02.2009, 00:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Nullvektor bei GLSL-Funktionen

Beitrag von Schrompf » 11.12.2019, 14:00

Bei irgendwas übelst komplexem könnte man darüber nachdenken. Ist aber dank der Optimierungen der Treiber, Cache-Effekten und der GPU-Asynchronität gar nicht einfach zu messen, was nun besser ist. Und ganz ehrlich: bei diesem Beispiel isses wirklich wahrhaft egal. Ein üblicher FragmentShader mit ein paar Dutzend TexSamples und ein bissl Mathe dazwischen wird auf allen Karten vergleichbar performen. Solche Mikroentscheidungen ändern einfach nix, aber Du verkomplizierst Deine Shader-Pipeline und die weitere Entwicklung drastisch.
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.

Antworten