GLSL Matrix / Inverse Multiplikationsgenauigkeit

8

Ich versuche, mit der GPU für eine Stoffsimulation zu arbeiten und habe Probleme mit der Hardware. Ich benutze Threejs als Rahmen, aber ich glaube, das ist nicht relevant für das Problem, das ich habe.

Im Grunde lade ich eine Matrix und eine Umkehrung dieser Matrix ein, um Punkte von lokalen Koordinaten in Welt zu transformieren, mache einige Berechnungen in Weltkoordinaten (wie Kollisionserkennung) und transformiere sie dann wieder in Lokal. Das funktioniert gut auf meinem Laptop, wenn ich Fließkomma-Texturen verwende, aber ich bemerkte auf meinem Handy einige bizarre Artefakte:

richtig:

falsch:

Nach einigen Debugging habe ich es auf zwei Probleme beschränkt. Beide beziehen sich auf die Dezimalgenauigkeit. Das Kollabieren der Vertices aufgrund von Constraints (und Präzisionsproblemen während der Constraints) und das Verlieren der Genauigkeit bei Verwendung der Matrixmultiplikation und der Inversen.

Der Grund, warum ich glaube, dass das Problem mit der Präzision zusammenhängt, ist, dass wenn ich eine Fließkomma-Textur verwende, es auf meinem Computer funktioniert, aber wenn ich einen halben Float benutze, habe ich dieselben Probleme. Mein Telefon unterstützt Floating-Point-Texturen. Das ist einer der Gründe, warum ich verwirrt bin, warum das auf meinem Handy passiert. Ich habe das Problem eingegrenzt, so dass die gesamte Stoffsimulation deaktiviert ist, und wenn ich die Anwendung mit Halb-Float-Texturen auf meinem Computer laufe, ohne Gravitation, aber mit der Transformation und umgekehrt flimmert die Ebenen-Art auf seltsame Weise

Wenn die Umwandlung und die Umkehrung deaktiviert sind, sieht es normal aus.

Ich habe keine Ideen, wie ich mit diesem Problem umgehen soll oder ob ich sogar den richtigen Weg eingeschlagen habe. Ich glaube, dass Halb-Float-Texturen eine begrenzte Dezimal-Genauigkeit haben, aber ich verstehe nicht, warum dies meine Probleme verursachen würde, da es nur die Ausgabe des Shaders beeinflussen sollte, nicht die Mathe, die im Shader läuft.

Der Code für den Shader sieht folgendermaßen aus:

%Vor%     
Luple 29.12.2017, 16:42
quelle

1 Antwort

1

Um sicherzustellen, dass Ihr Shader hochpräzise Variablen für Gleitkommaberechnungen erstellt, sollten Sie Folgendes am Anfang des Vertex-Shaders hinzufügen:

%Vor%

Und im Fragment-Shader sollten Gleitkomma-Variablendeklarationen wie folgt deklariert werden:

%Vor%

Gleitkommafehler werden vergrößert, wenn Sie Werte in Ihren Berechnungen verwenden, die das Ergebnis von vorherigen Berechnungen sind, die als Gleitkommazahlen gespeichert sind. Ansonsten bekannt als Zwischenwerte.

Um diese Fehler zu minimieren, sollten Sie die Anzahl der im Shader ausgeführten Zwischenberechnungen begrenzen. Sie können beispielsweise die Berechnungen für newUV vollständig erweitern:

%Vor%

Sie können die Berechnung für totalDisplacement auch schrittweise vollständig erweitern, indem Sie zuerst offsetX wie folgt ersetzen:

%Vor%

Ersetzen Sie nun jede Variable dx und percent in obiges:

%Vor%

Sie können nun sehen, dass die Gleichung noch weiter erweitert werden kann, indem Sie in difference wie folgt ersetzen:

%Vor%

An dieser Stelle können Sie etwas Algebra machen, um einige Variablen zu vereinfachen und zu löschen (Division durch distance ). Durch Vereinfachung der obigen Gleichung erhalten wir nun folgendes:

%Vor%

Schließlich können wir die Formel für targetDistance wie folgt ersetzen:

%Vor%

Und jeweils für die anderen Koordinaten:

%Vor%

Und natürlich können Sie weitermachen, d. h. indem Sie den Wert für posOld , posOld2 und newPos ersetzen.

Beachten Sie, dass wir bis jetzt die Notwendigkeit beseitigt haben, 5 der Zwischenwerte in float-Variablen zu speichern. Auch durch die Vereinfachung der Gleichung (Division durch distance ) wird die Variable distance nur einmal in der Berechnung verwendet. Vergleichen Sie dies mit der ursprünglichen Implementierung, distance wird verwendet, um difference und percent zu berechnen. Wenn Sie alles in einer Gleichung kombinieren, können Sie die Häufigkeit, mit der derselbe Gleitkommawert verwendet wird, vereinfachen und reduzieren. Daher reduziert sich auch der gesamte Gleitkommafehler. Der Kompromiss hier ist, dass die resultierende Gleichung weniger menschlich lesbar ist.

Wenn Sie neugierig sind, können Sie auch die Genauigkeit für einen bestimmten Shader-Compiler überprüfen, indem Sie glGetShaderPrecisionFormat :

aufrufen %Vor%

Wenn Sie das Ergebnis für den Desktop und mobile Version Ihrer Anwendung, können Sie den Unterschied in der Genauigkeit vergleichen für die zwei Versionen.

    
sparkplug 08.01.2018, 08:22
quelle

Tags und Links