somethinglikegames.de

Kategorien


Tags

Opacity

Nach meinem ersten Artikel zum Thema Blending-Modes hat mich das Thema irgendwie nicht mehr losgelassen, sodass ich ins zugehörige Kaninchenbau gezogen wurde. Um meine Erlebnisse auf der Reise zurück in die Realität zu verarbeiten, habe ich einen “allmächtigen” 😉 Knoten für’s Blenden von Ebenen erstellt. Dieser enthält 47 verschiedene Blending-Modes für Graustufen und RGB(A) und drei zusätzliche Blending-Modes speziell für NormalMaps. Damit man aber nicht den Überblick über die Funktionsweise der verschiedenen Blending-Modes verliert, soll der restliche Artikel als Nachschlagewerk dienen.

Über UberBlend

Ich habe den Knoten UberBlend getauft, da mir bislang keine so vollständige Sammlung an Blending-Modes begegnet ist. Sind so viele Blending-Modes wirklich notwendig? Wahrscheinlich nicht, aber warum sollte man sie nicht ausprobieren, um so bessere Resultate erzielen zu können. Mein Ziel ist es, so die Wahrscheinlichkeit für “Happy Accidents” zu erhöhen.

Es gibt UberBlend in verschiedenen Versionen. Einmal als All-in-One-Knoten “UberBlend” und einmal aufgeteilt in “UberBlend Grayscale”, “UberBlend Color” und “UberBlend Normals”. Der Grund hierfür ist, dass eigene Knoten in Adobe Substance 3D Designer gewissen Beschränkungen unterliegen und ich daher mit der All-in-One-Lösung leider nicht die beste Benutzererfahrung bieten kann. Die Einschränkung ist dabei, dass man manuell zwischen Graustufen und Farbe wählen muss, da ich leider keine Möglichkeit gefunden habe, wie man bei eigenen Knoten den Komfort des integrierten Blend-Knotens übernimmt, bei dem sich der Farbmodus nach dem Hintergrundeingang richtet. Dies hat zur Folge, dass man beim Wechsel zwischen Grayscale und Color zwei zusätzliche Eingänge bekommen kann, wenn man die Eingänge des vorher ausgewählten Farbmodus bereits angebunden hatte.

Welche Funktionalitäten bietet UberBlend generell:

  • 47 verschiedene allgemeine Blending-Modes; genauere Details findet ihr im nächsten Abschnitt
  • 3 spezielle Blending-Modes für NormalMaps
  • “Advanced” Modus für RGB(A)-Eingaben, in welchem pro Farbkanal Einstellungen vorgenommen werden können
  • Gewohnte Funktionalitäten des integrierten Blend-Knotens, wie Unterstützung von Eingabemasken, Einstellen der Deckkraft, …

Aktuell plane ich, auch noch Versionen von UberBlend zu erstellen, die sich mit Substance 3D Painter und Photoshop nutzen lassen. Da beide ihre eigenen Hürden mit sich bringen, werden diese Versionen dann gesondert erscheinen.

Für alle Ungeduldigen: Hier geht es zum Download

Blending-Modes

Die folgende Tabelle soll einen Vergleich der verschiedenen Blending-Modes ermöglichen:

  • In der Spalte Helligkeit sieht man das Blend-Resultat der beiden bekannten Graustufen-Gradienten, wobei der horizontale Gradient als Hintergrund und der vertikale Gradient als Vordergrund agiert.
  • In der Spalte Helligkeitsunterschied sieht man die Helligkeitsveränderungen zwischen dem Blendresultat und dem ursprünglichen Hintergrund. Aufhellungen sind rötlich und Abdunkelungen sind bläulich eingefärbt. Grünliche Bereiche haben entsprechend kaum bis keine Veränderungen.
  • Die Tabelle ist alphabetisch sortiert. Sollte jemand eine Idee für eine bessere Sortierung haben, gerne bei mir melden.
Blending ModeHelligkeitHelligkeitsunterschied
Arctan\(p_\text{new} = 2\pi * \text{arctan}(\frac{p_\text{bg}}{p_\text{fg}})\)
Helligkeitsveränderungen von ArctanHelligkeitsunterschiede von Arctan
Average\(p_\text{new} = \frac{p_\text{fg} + p_\text{bg}}{2}\)
Helligkeitsveränderungen von AverageHelligkeitsunterschiede von Average
Bleach\(p_\text{new} = (1 - p_\text{fg}) + (1 - p_\text{bg}) - 1\)
Helligkeitsveränderungen von BleachHelligkeitsunterschiede von Bleach
Bright\(p_\text{new} = 1 - \text{Dark}(1 - p_\text{fg}, 1 - p_\text{bg})\)
Helligkeitsveränderungen von BrightHelligkeitsunterschiede von Bright
Burn\(p_\text{new} = 1 - \frac{1 - p_\text{fg}}{p_\text{bg}}\)
Helligkeitsveränderungen von BurnHelligkeitsunterschiede von Burn
Burn (Reverse)\(p_\text{new} = 1 - \frac{1 - p_\text{bg}}{p_\text{fg}}\)
Helligkeitsveränderungen von Burn (Reverse)Helligkeitsunterschiede von Burn (Reverse)
Burn (Soft)\(p_\text{new} = \begin{cases} \frac{1}{2} * \frac{p_\text{fg}}{1 - p_\text{bg}} & p_\text{bg} + p_\text{fg} \lt 1 \\\\1 - (\frac{1}{2} * \frac{1 - p_\text{bg}}{p_\text{fg}}) & \text{sonst}\end{cases} \)
Helligkeitsveränderungen von Burn (Soft)Helligkeitsunterschiede von Burn (Soft)
Dark\(p_\text{new} = p_\text{bg}p_\text{fg} + p_\text{fg} - p_\text{fg}^2 \)
Helligkeitsveränderungen von DarkHelligkeitsunterschiede von Dark
Darken / Min\(p_\text{new} = \text{Min}(p_\text{bg}, p_\text{fg})\)
Helligkeitsveränderungen von Darken / MinHelligkeitsunterschiede von Darken / Min
Darken (Illusions.hu)\(p_\text{new} = \log_2(1 + \frac{\frac{p_\text{bg}}{1- p_\text{fg}}}{8})\)
Helligkeitsveränderungen von Darken (Illusions.hu)Helligkeitsunterschiede von Darken (Illusions.hu)
Difference\(p_\text{new} = |p_\text{bg} - p_\text{fg}|\)
Helligkeitsveränderungen von DifferenceHelligkeitsunterschiede von Difference
Divide\(p_\text{new} = \frac{p_\text{bg}}{p_\text{fg}}\)
Helligkeitsveränderungen von DivideHelligkeitsunterschiede von Divide
Dodge\(p_\text{new} = \frac{p_\text{bg}}{1 - p_\text{fg}}\)
Helligkeitsveränderungen von DodgeHelligkeitsunterschiede von Dodge
Dodge (Linear) / Add\(p_\text{new} = p_\text{bg} + p_\text{fg}\)
Helligkeitsveränderungen von Dodge (Linear) / AddHelligkeitsunterschiede von Dodge (Linear) / Add
Dodge (Reverse)\(p_\text{new} = \frac{p_\text{fg}}{1 - p_\text{bg}}\)
Helligkeitsveränderungen von Dodge (Reverse)Helligkeitsunterschiede von Dodge (Reverse)
Dodge (Soft)\(p_\text{new} = \begin{cases} \frac{1}{2} * \frac{p_\text{bg}}{1 - p_\text{fg}} & p_\text{bg} + p_\text{fg} \lt 1 \\\\1 - (\frac{1}{2} * \frac{1 - p_\text{fg}}{p_\text{bg}}) & \text{sonst}\end{cases} \)
Helligkeitsveränderungen von Dodge (Soft)Helligkeitsunterschiede von Dodge (Soft)
Exclusion\(p_\text{new} = p_\text{bg} + p_\text{fg} - 2 p_\text{bg} p_\text{fg}\)
Helligkeitsveränderungen von ExclusionHelligkeitsunterschiede von Exclusion
Freeze\(p_\text{new} = 1 - (1 - p_\text{bg}) \frac{1 - p_\text{bg}}{p_\text{fg}}\)
Helligkeitsveränderungen von FreezeHelligkeitsunterschiede von Freeze
Gamma (Bright)\(p_\text{new} = 1 - (1 - p_\text{bg}) ^ \frac{1}{1 - p_\text{fg}}\)
Helligkeitsveränderungen von Gamma (Bright)Helligkeitsunterschiede von Gamma (Bright)
Gamma (Dark)\(p_\text{new} = p_\text{bg} ^ \frac{1}{p_\text{fg}}\)
Helligkeitsveränderungen von Gamma (Dark)Helligkeitsunterschiede von Gamma (Dark)
Gamma (Light)\(p_\text{new} = p_\text{bg} ^ {p_\text{fg}}\)
Helligkeitsveränderungen von Gamma (Light)Helligkeitsunterschiede von Gamma (Light)
Geometric Mean\(p_\text{new} = \sqrt{p_\text{bg} p_\text{bg}}\)
Helligkeitsveränderungen von Geometric MeanHelligkeitsunterschiede von Geometric Mean
Glow\(p_\text{new} = \frac{p_\text{fg} p_\text{fg}}{p_\text{bg}}\)
Helligkeitsveränderungen von GlowHelligkeitsunterschiede von Glow
Grain (Extract)\(p_\text{new} = p_\text{bg} + (1 - p_\text{fg}) - \frac{1}{2}\)
Helligkeitsveränderungen von Grain (Extract)Helligkeitsunterschiede von Grain (Extract)
Grain (Merge)\(p_\text{new} = p_\text{bg} + p_\text{fg} - \frac{1}{2}\)
Helligkeitsveränderungen von Grain (Merge)Helligkeitsunterschiede von Grain (Merge)
Heat\(p_\text{new} = 1 - (1 - p_\text{fg}) \frac{1 - p_\text{fg}}{p_\text{bg}}\)
Helligkeitsveränderungen von HeatHelligkeitsunterschiede von Heat
Lighten / Max\(p_\text{new} = \text{Max}(p_\text{bg}, p_\text{fg})\)
Helligkeitsveränderungen von Lighten / MaxHelligkeitsunterschiede von Lighten / Max
Light (Hard)\(p_\text{new} = \begin{cases} 2 p_\text{bg} p_\text{fg} & p_\text{fg} \lt \frac{1}{2} \\\\1 - (2 * (1 - p_\text{fg})(1 - p_\text{bg})) & \text{sonst}\end{cases} \)
Helligkeitsveränderungen von Light (Hard)Helligkeitsunterschiede von Light (Hard)
Lighten (Illusions.hu)\(p_\text{new} = 1 - \text{Darken (Illusions.hu)}(1 - p_\text{fg}, 1 - p_\text{bg})\)
Helligkeitsveränderungen von Lighten (Illusions.hu)Helligkeitsunterschiede von Lighten (Illusions.hu)
Light (Linear) / Add Sub\(p_\text{new} = p_\text{bg} + ((p_\text{fg} - \frac{1}{2}) * 2)\)
Helligkeitsveränderungen von Light (Linear) / Add SubHelligkeitsunterschiede von Light (Linear) / Add Sub
Light (Pin)\(p_\text{new} = \begin{cases} \text{Min}(p_\text{bg}, 2 p_\text{fg}) & p_\text{fg} \lt \frac{1}{2} \\\\\text{Max}(p_\text{bg}, 2 p_\text{fg} - 1) & \text{sonst}\end{cases}\)
Helligkeitsveränderungen von Light (Pin)Helligkeitsunterschiede von Light (Pin)
Light (Vivid)\(p_\text{new} = \begin{cases} \text{Burn}(p_\text{bg}, 2 p_\text{fg}) & p_\text{fg} \lt \frac{1}{2} \\\\\text{Dodge}(p_\text{bg}, 2 p_\text{fg} - 1) & \text{sonst}\end{cases}\)
Helligkeitsveränderungen von Light (Vivid)Helligkeitsunterschiede von Light (Vivid)
Multiply\(p_\text{new} = p_\text{bg} * p_\text{fg}\)
Helligkeitsveränderungen von MultiplyHelligkeitsunterschiede von Multiply
Negation\(p_\text{new} = 1 - |(1 - p_\text{bg}) - p_\text{fg}|\)
Helligkeitsveränderungen von NegationHelligkeitsunterschiede von Negation
Overlay\(p_\text{new} = \begin{cases} 2 p_\text{bg} p_\text{fg} & p_\text{bg} \lt \frac{1}{2} \\\\1 - (2 (1 - p_\text{bg}) (1 - p_\text{fg})) & \text{sonst}\end{cases}\)
Helligkeitsveränderungen von OverlayHelligkeitsunterschiede von Overlay
Parallel\(p_\text{new} = \frac{2}{\frac{1}{p_\text{bg}}+\frac{1}{p_\text{fg}}}\)
Helligkeitsveränderungen von ParallelHelligkeitsunterschiede von Parallel
Phoenix\(p_\text{new} = \text{Min}( p_\text{bg}, p_\text{fg}) + (1 - \text{Max}(p_\text{bg}, p_\text{fg}))\)
Helligkeitsveränderungen von PhoenixHelligkeitsunterschiede von Phoenix
Reflect\(p_\text{new} = \frac{p_\text{bg} ^ 2}{1 - p_\text{fg}}\)
Helligkeitsveränderungen von ReflectHelligkeitsunterschiede von Reflect
Screen\(p_\text{new} = p_\text{bg} + p_\text{fg} - p_\text{bg} * p_\text{fg}\)
Helligkeitsveränderungen von ScreenHelligkeitsunterschiede von Screen
Shadow\(p_\text{new} = 1 - ((1 - p_\text{bg}) p_\text{fg}) + \sqrt{1 - p_\text{fg}} \)
Helligkeitsveränderungen von ShadowHelligkeitsunterschiede von Shadow
Softlight (PS, DS)\(p_\text{new} = \begin{cases} 2 p_\text{bg} p_\text{fg} + p_\text{bg}^2 (1 - 2 p_\text{fg}) & p_\text{fg} \lt 0.5 \\\sqrt{p_\text{bg}} (2 p_\text{fg} - 1) + 2 p_\text{bg} (1 - p_\text{fg}) & \text{sonst}\end{cases}\)
Helligkeitsveränderungen von Softlight (PS, DS)Helligkeitsunterschiede von Softlight (PS, DS)
Softlight (Illusions.hu)\(p_\text{new} = p_\text{bg} ^ {(2 ^ {2 (0,5 - p_\text{fg} )})}\)
Helligkeitsveränderungen von Softlight (Illusions.hu)Helligkeitsunterschiede von Softlight (Illusions.hu)
Softlight (PegTop)\(p_\text{new} = (1 - 2 p_\text{fg}) * p_\text{bg} ^ 2 + 2 p_\text{bg} p_\text{fg} \)
Helligkeitsveränderungen von Softlight (PegTop)Helligkeitsunterschiede von Softlight (PegTop)
Subtract\(p_\text{new} = p_\text{bg} - p_\text{fg}\)
Helligkeitsveränderungen von SubtractHelligkeitsunterschiede von Subtract

Auch wenn Blending von NormalMaps innerhalb von Substance 3D Designer nur selten vorkommt, dachte ich mir, dass es vielleicht trotzdem nicht schaden kann, darauf spezialisierte Blending Modes zu integrieren. Aus diesem Grund bin ich dem wirklich ausführlichen und interessanten Artikel Blending in Detail gefolgt und habe die drei “besten” Blending Modes transferiert, also Whiteout-Blending, UDN-Blending und Reoriented-Normal-Mapping.

Als Testobjekte müssen die folgenden zwei NormalMaps herhalten:

Basis / Background

Basis / Background

Detail / Foreground

Detail / Foreground

Ich habe lange Zeit darüber nachgedacht, wie ich die jeweiligen NormalMap-Berechnungen ebenfalls als Formel schreiben kann. Ich hoffe, ich habe eine verständliche Art und Weise gefunden. Die shaderorientierte Variante findet man im verlinkten Artikel Blending in Detail.

Blending ModeFormelErgebnis
UDN\(\begin{align*} \vec{p_\text{bg}} &= \vec{p_\text{bg}} * 2 - 1 \\ \vec{p_\text{fg}} &= \vec{p_\text{fg}} * 2 - 1 \\ \vec{r} &= \begin{pmatrix} \vec{p_\text{bg}}_x + \vec{p_\text{fg}}_x \\ \vec{p_\text{bg}}_y + \vec{p_\text{fg}}_y \\ \vec{p_\text{bg}}_z \end{pmatrix} \\ \vec{p_\text{new}} &= \frac{\vec{r}}{|\vec{r}|} * \frac{1}{2} + \frac{1}{2} \end{align*} \)UDN
Whiteout\(\begin{align*} \vec{p_\text{bg}} &= \vec{p_\text{bg}} * 2 - 1 \\ \vec{p_\text{fg}} &= \vec{p_\text{fg}} * 2 - 1 \\ \vec{r} &= \begin{pmatrix} \vec{p_\text{bg}}_x + \vec{p_\text{fg}}_x \\ \vec{p_\text{bg}}_y + \vec{p_\text{fg}}_y \\ \vec{p_\text{bg}}_z * \vec{p_\text{fg}}_z \end{pmatrix} \\ \vec{p_\text{new}} &= \frac{\vec{r}}{|\vec{r}|} * \frac{1}{2} + \frac{1}{2} \end{align*} \)Whiteout
Reoriented Normal Mapping\(\begin{align*} \vec{p_\text{bg}} &= \vec{p_\text{bg}} * \begin{pmatrix} 2 \\ 2 \\ 2 \end{pmatrix} + \begin{pmatrix} -1 \\ -1 \\ 0 \end{pmatrix}\\ \vec{p_\text{fg}} &= \vec{p_\text{fg}} * \begin{pmatrix} -2 \\ -2 \\ 2 \end{pmatrix} + \begin{pmatrix} 1 \\ 1 \\ -1 \end{pmatrix}\\ \vec{r} &= \vec{p_\text{bg}} * (\vec{p_\text{bg}} \cdot \vec{p_\text{fg}}) - \vec{p_\text{fg}} * \vec{p_\text{bg}}_z \\ \vec{p_\text{new}} &= \frac{\vec{r}}{|\vec{r}|} * \frac{1}{2} + \frac{1}{2} \end{align*} \)Reoriented Normal Mapping

So, bevor nun wirklich der Download kommt, noch ein direkter Vergleich zwischen den Blending Modes der NormalMaps, da die Ergebnisse nur bei direktem Hinsehen Unterschiede aufzeigen.

Vergleich der NormalMap Blending Modes

Vergleich der NormalMap Blending Modes

UberBlend Download

Ich stelle das SBSAR von UberBlend allen Interessierten kostenlos unter der CC0 1.0 zur Verfügung.

Ihr dürft damit also eigentlich alles Legale tun, solange ihr mich nicht für etwaige Fehler verantwortlich macht. Solltet ihr Fehler finden, würde ich mich aber dennoch freuen, wenn ihr sie mir mitteilt, damit ich sie korrigieren kann 😉

Weitere Lektüre

Natürlich bin ich nicht von ganz allein auf all diese Erkenntnisse gekommen. Freundlicherweise gibt es Menschen, die viele der Informationen bereits gut aufbereitet haben, sodass ich sie als Quellen nutzen konnte. Falls ihr also mehr über das Thema erfahren wollt, könnt ihr gerne die folgenden Seiten besuchen: