Ich habe eine Anwendung, in der der Benutzer ein Bild mit Schiebereglern für Farbton, Sättigung und Helligkeit modifizieren kann. Die gesamte Bildverarbeitung erfolgt auf der GPU mithilfe von GLSL-Fragment-Shadern.
Mein Problem ist, dass RGB - & gt; HSL - & gt; RGB-Konvertierungen sind aufgrund der umfangreichen Verzweigungen auf der GPU ziemlich teuer.
Meine Frage ist, ob ich die "Farbanpassungen" der Benutzer in einen anderen Farbraum umwandeln kann, der das angepasste Bild auf der GPU effizienter berechnen kann.
Für Leichtigkeit und Sättigung können Sie YUV (eigentlich YCbCr) . Es ist einfach, von RGB und zurück zu konvertieren. Keine Verzweigung benötigt. Die Sättigung wird durch Erhöhen oder Verringern von Cr und Cb gesteuert. Leichtigkeit ist Y.
Sie erhalten etwas Ähnliches wie HSL-Farbtonmodifikation durch Drehen von Cb- und Cr-Komponenten (es ist praktisch ein 3D-Vektor), aber natürlich hängt es von Ihrer Anwendung ab, ob das ausreicht.
Bearbeiten: Eine Farbkomponente (Cb, Cr) ist ein Punkt in einer Farbebene wie oben. Wenn Sie einen zufälligen Punkt nehmen und ihn um die Mitte drehen, ändert sich das Ergebnis. Aber da der Mechanismus ein bisschen anders ist als in HSL, sind die Ergebnisse nicht genau die gleichen.
Bild ist eine öffentliche Domäne von Wikipedia.
Es ist ein Fehler anzunehmen, dass die Verzweigung in der GPU und die Verzweigung im Code dasselbe sind.
Für einfache Bedingungen gibt es überhaupt keine Verzweigungen. GPUs haben bedingte Verschiebeanweisungen, die direkt in ternäre Ausdrücke und einfache if-else-Anweisungen umgesetzt werden.
Wo Probleme auftreten, ist, wenn Sie geschachtelte Bedingungen oder mehrere bedingt abhängige Operationen haben. Dann müssen Sie überlegen, ob der GLSL-Compiler schlau genug ist, um alles in cmoves zu übersetzen. Wann immer es möglich ist, gibt der Compiler einen Code aus, der alle Zweige ausführt und das Ergebnis mit bedingten Bewegungen rekombiniert, aber das kann nicht immer geschehen.
Sie müssen wissen, wann Sie helfen können. Erraten Sie nie, wann Sie messen können - verwenden Sie AMDs GPU Shader Analyzer oder Nvidias GCG, um die Baugruppenausgabe anzuzeigen. Der Befehlssatz einer GPU ist sehr begrenzt und simpel, also haben Sie keine Angst vor dem Wort Assembly.
Hier ist ein Paar RGB / HSL-Konvertierungsfunktionen, die ich geändert habe, damit sie gut mit dem GLSL-Compiler von AMD zusammen mit der Assembly-Ausgabe funktionieren. Credit geht an Paul Bourke für den ursprünglichen C-Umwandlungscode.
%Vor%Baugruppenausgabe für diese Funktion:
%Vor%Beachten Sie, dass keine Verzweigungsanweisungen vorhanden sind. Es sind bedingte Züge, ziemlich genau so, wie ich sie geschrieben habe.
Die Hardware, die für eine bedingte Bewegung benötigt wird, ist nur ein Binärkomparator (5 Gatter pro Bit) und eine Reihe von Spuren. Sehr schnell.
Eine weitere lustige Sache ist, dass es keine Trennlinien gibt. Stattdessen verwendete der Compiler einen ungefähren reziproken und einen multiplizierten Befehl. Es tut dies auch für den sqrt-Betrieb und die meiste Zeit. Sie können die gleichen Tricks auf einer CPU mit (zum Beispiel) den Anweisungen SSE rcpps und rsqrtps ziehen.
Jetzt die umgekehrte Operation:
%Vor%(editiert 05 / Juli / 2013: Ich habe bei der Übersetzung dieser Funktion einen Fehler gemacht. Die Assembly wurde ebenfalls aktualisiert).
Baugruppenausgabe:
%Vor%Wieder keine Zweige. Yum!
Ich hatte dieselbe Frage, aber ich fand eine sehr einfache Lösung, die meinen Bedürfnissen entspricht, vielleicht ist sie auch für Sie nützlich. Die Sättigung einer Farbe ist im Grunde genommen verbreitet, ich glaube, dass dies der euklidische Abstand zwischen den RGB-Werten und ihrem Durchschnitt ist. Unabhängig davon, wenn Sie einfach den Durchschnitt des Maximums und Minimums der RGB-Werte nehmen und die Farben relativ zu diesem Drehpunkt skalieren, ist der Effekt ein sehr anständiger Anstieg (oder Rückgang) der Sättigung.
In einem Glsl-Shader würden Sie schreiben:
%Vor%Sie könnten eine 3D-Look-Up-Tabelle verwenden, um die Farbtransformation zu speichern. Die Tabelle würde durch die Benutzervariablen aktualisiert, aber es könnten einfachere Approches vorhanden sein.
Weitere Informationen finden Sie in GPU Gems 2 .
Ich glaube, dass die Konvertierung zwischen RGB und HSV / HSL ohne Verzweigung codiert werden könnte. Zum Beispiel, wie Umwandlung RGB - & gt; HSV ohne Verzweigung könnte in GLSL aussehen:
%Vor%Aber ich habe diese Lösung nicht bewertet. Es kann sein, dass ein Leistungsgewinn, den wir ohne Verzweigung gewinnen, durch Leistungsverluste der redundanten Codeausführung kompensiert werden kann. So umfangreiche Tests sind erforderlich ...
Tags und Links c c++ image-processing shader glsl