← 3D
Fix it in Prompt · 3D

PBR-Textur aus einem Foto

Ein Foto einer Oberfläche rein, eine nahtlos kachelbare PBR-Textur mit neun Maps raus. Läuft lokal, kostet nichts, benutzt kein Non-Commercial-Modell.

2048 px, kachelbar 9 Maps ab 8 GB VRAM MIT · kommerziell nutzbar
↓ Workflow herunterladen (.json)

Kein Formular, kein Newsletter, keine Anmeldung. Datei laden und per Drag & Drop in ComfyUI ziehen.

Vorher lesen. Die Height Map wird aus der Helligkeit des Fotos abgeleitet. Das stimmt nur bei Materialien, bei denen dunkel auch tief bedeutet — Putz, Beton, Ziegel, Rinde, Stoff. Bei Kies, Terrazzo oder buntem Mosaik ist dunkel nur dunkel, und das Relief wird falsch. Details im Abschnitt Grenzen.

PBR-Textur auf Ebene, Fels und Kugel unter Streiflicht
Die neun Maps im Blender-Testaufbau unter Streiflicht: dieselbe Textur auf Ebene, unregelmäßigem Mesh und Kugel. Streiflicht ist die ehrlichste Prüfung — es zeigt sofort, ob Normal und Height zusammenpassen oder gegeneinander arbeiten.

Was herauskommt

Neun PNGs, alle in der Zielauflösung, alle nach ComfyUI/output/pbr/.

MapDateiFarbraumInhalt
Base ColorbasecolorsRGBGrundfarbe ohne Beleuchtung, farblich ans Foto angeglichen
RoughnessroughnessNon-ColorMaterialschätzung von Marigold, Rotkanal, kontrastangehoben
MetallicmetallicNon-ColorKonstante, standardmäßig schwarz. Weiße Variante liegt bypassed daneben
HeightheightNon-ColorLuminanz der Kachel, hochpassgefiltert
Normal GLnormal_glNon-ColorSobel aus der Height, Grün nach oben — Blender, Cinema 4D, Maya, Godot
Normal DXnormal_dxNon-ColorDasselbe mit gespiegeltem Grünkanal — Unreal, Unity
AOaoNon-ColorCavity-Näherung aus der Height
ORMmaterial_ORMNon-ColorR = AO, G = Roughness, B = Metallic, fertig gepackt
TileabletileablesRGBDas kachelbare Quellbild selbst — Ausgangspunkt für eigene Nachbearbeitung

Voraussetzungen

Hardware. Ab 8 GB VRAM, eine RTX 2080 Super reicht. Ein Durchlauf bei 2048 px dauert dort ein paar Minuten, der Löwenanteil davon entfällt auf die Nahtreparatur mit SDXL.

Vier Node-Pakete

PaketAutorLizenz
ComfyUI-MarigoldkijaiApache 2.0
ComfyUI-KJNodeskijaiGPL-3.0
ComfyUI_LayerStylechflame163MIT
ComfyUI_cspnodescerspenseApache 2.0

Zwei Modelle

ModellOrdnerLizenzBeschaffung
sd_xl_base_1.0models/checkpoints/CreativeML Open RAIL++-Mmanuell ablegen
marigold-iid-appearance-v1-1models/diffusers/Open RAIL++-Mlädt beim ersten Lauf selbst

Bekannte Stolperstelle. ColorMatch aus den KJNodes ist als deprecated markiert und taucht in der Node-Suche nicht mehr auf. Geladen wird es weiterhin — der Workflow funktioniert. Wer den Node selbst neu setzt, nimmt ColorMatchV2.

Wie es funktioniert

Der Workflow besteht aus vier Blöcken. Die vier farbigen Gruppen im Graphen sind so geschnitten, dass jede genau ein Subgraph wird, falls du das aufräumen willst.

Der Kern, den man verstanden haben sollte. Die KI-Stufen haben feste Arbeitsauflösungen: Marigold rechnet bei 768 px, SDXL bei 1024 px. Daran lässt sich nichts drehen. Die Schärfe der fertigen Textur kommt deshalb nicht aus einem Modell, sondern direkt aus dem Foto — die Modelle liefern nur die grobe Schicht, das Detail wird per Frequenztrennung aus dem Original zurückgeholt. Einzige Ausnahme ist die Naht: dort existiert kein Original mehr, deshalb wird genau dieses schmale Band neu gerechnet. Praktische Folge: die Qualität des Fotos ist die Obergrenze, nicht die Zahl im Auflösungsfeld.

Die Normal Map wird gerechnet, nicht geschätzt. Sie entsteht per Sobel-Gradient aus der Height, bei voller Auflösung — kein Modell, keine 768-px-Grenze. Marigold Normals ist bewusst nicht im Workflow: das schätzt Szenennormalen, und eine frontal fotografierte Fläche ergibt dabei ein flaches Lavendelfeld. Korrekt, aber für Texturarbeit nutzlos.

Bedienung

  1. Workflow-JSON per Drag & Drop in ComfyUI ziehen. Fehlende Nodes über den Manager nachinstallieren, ComfyUI neu starten.
  2. In 1. Load Photo das Foto wählen. Frontal aufgenommen, diffus beleuchtet, keine harten Schlagschatten, keine Objekte im Bild. Nicht quadratische Fotos werden mittig beschnitten — lieber vorher selbst zuschneiden.
  3. Zielauflösung in 2. Target Resolution prüfen. Standard ist 2048.
  4. Run. Dann bei 3. Check the tile und 4. Tiling test 2x2 hinsehen, bevor du weitermachst. Der 2×2-Test ist die eigentliche Prüfung: wenn dort im Kreuz eine Linie oder ein Materialbruch steht, stimmt die Naht nicht.
  5. Die neun Maps liegen in ComfyUI/output/pbr/.

Die Regler, die etwas bewirken

ReglerNodeStandardWirkung
denoiseSample the seam0.70Wie frei SDXL die Naht neu malt. Bei 1.0 erfindet der Sampler Material, das nicht zum Foto passt; unter 0.5 überlebt die Naht.
stepsSample the seam25Qualität gegen Rechenzeit der Nahtreparatur
width / heightVertical / Horizontal bar160Breite des reparierten Bandes, bei 2048 rund 8 %. Zu schmal: die Naht bleibt sichtbar. Zu breit: du wirfst Fotodetail weg. Wird der Wert geändert, müssen die beiden MaskComposite-Offsets mit: (Auflösung − Balkenbreite) / 2.
strengthMatch colour to photo0.75Wie stark das Albedo farblich ans Foto gezogen wird
blend_factorDetail from photo0.40Schärfe: wie viel Fotodetail ins Albedo zurückkommt
blend_factorDarken0.25Helligkeit des Albedo
blend_factorHigh-pass contrast0.55Wie ausgeprägt das Relief liest. Der Node High-pass darüber lässt sich mit Ctrl+B bypassen — dann bekommst du die rohe Height zum Vergleich.
normal_intensityNormal from Height / Normal DX0.60Tiefe der Normal Map. Höher bei flachen Oberflächen, niedriger wenn das Ergebnis geprägt aussieht.
blend_factorAO from cavity0.50AO-Stärke. 0.0 ergibt eine weiße Map, also praktisch kein AO.

Stapelverarbeitung. Der Node BATCH in der Eingangsgruppe ist bypassed. Mit Ctrl+B einschalten, den absoluten Ordnerpfad in directory_path eintragen und den IMAGE-Ausgang auf 2. Target Resolution ziehen — das ersetzt die Verbindung von 1. Load Photo. image_index per Rechtsklick auf increment stellen und so oft in die Queue legen, wie du Fotos hast. Alle Sätze landen im selben Ordner mit fortlaufender Nummer, also selbst mitzählen, welche neun Dateien zusammengehören.

Auflösung ändern

Standard ist 2048 × 2048. Bleib bei Zweierpotenzen — 1024, 2048, 4096. Game-Engines bauen Mipmap-Ketten und Blockkompression darum herum; 3072 funktioniert, ergibt aber keine saubere Mip-Kette und streamt schlecht. Für die meiste Indie-Arbeit ist 2048 die richtige Wahl: 4096 vervierfacht den Speicher für Detail, das auf Spieldistanz niemand sieht.

Es reicht nicht, eine Zahl zu ändern. Diese Felder müssen zusammenpassen:

Feld20484096
2. Target Resolution20484096
Offset by half edge (shift_x/y)10242048
Mask base, Breite / Höhe20484096
Vertical bar, Höhe20484096
Horizontal bar, Breite20484096
Add vertical bar x9441968
Add horizontal bar y9441968
Back to target resolution20484096
Upscale Albedo / Roughness20484096
Back to target (Hochpass)20484096
EmptyImage ×3 (Metallic, AO)20484096

Die beiden MaskComposite-Offsets ergeben sich aus (Auflösung − Balkenbreite) / 2. Stimmt der Offset nicht, sitzt die Naht nicht in der Mitte und das Kacheln bricht. Und: geh nicht über die Auflösung deines Quellfotos hinaus — darüber erfindest du Pixel, die nie da waren.

In Blender, Unreal und Cinema 4D

Farbräume, überall gleich. basecolor ist sRGB. Alles andere ist Non-Color, Raw beziehungsweise Linear. Das ist der Fehler Nummer eins: eine Roughness in sRGB sieht falsch aus und niemand weiß warum.

Blender

normal_gl in einen Normal Map-Node, dessen Ausgang in den Normal-Eingang des Principled BSDF. Willst du Normal und Height kombinieren, kommt zuerst der Normal-Map-Node, sein Ausgang geht in den Normal-Eingang eines Bump-Nodes, und die Height in dessen Height-Eingang — nur diese Reihenfolge addiert beide, statt dass eines das andere überschreibt. Bump-Stärke klein halten. Echtes Displacement braucht Subdivision und Werte um 0.01–0.05. Für unregelmäßige Meshes ohne saubere UVs ist Box Projection der schnellste Weg.

Unreal

normal_dx nehmen, nicht normal_gl — sonst kippt das Licht in den Vertiefungen auf die falsche Seite. Beim ORM-Import sRGB abwählen und die Kompression auf Masks stellen. Im Material die drei Kanäle trennen: R → Ambient Occlusion, G → Roughness, B → Metallic. Base Color bleibt sRGB.

Cinema 4D

normal_gl, wie in Blender. In Redshift und im Standard-Renderer alles außer Base Color auf Raw stellen. Height läuft als Displacement mit Subdivision oder, wenn es billig sein soll, als Bump. Das ORM wird hier meist nicht gebraucht — nimm die Einzelmaps, sie liegen ohnehin daneben.

Querverweis. Das Umrechnen von Normal GL nach DX und das Packen von ORM erledigt der Utility-Workflow unreal_prep (Smart Utilities). Für diesen Workflow brauchst du ihn nicht — beides passiert hier schon. Er ist für Maps aus anderen Quellen: Scans, gekaufte Sets, Substance-Exporte.

Grenzen

Der Workflow erzeugt brauchbare Texturen, keine perfekten. Was er nicht kann, steht hier und nicht im Kleingedruckten:

Kugel mit Terrazzo-Textur unter Streiflicht
Genau dieser Fall: Die dunklen Steine sitzen in Wirklichkeit bündig in der Matrix, die Height liest sie als Vertiefungen. Unter Streiflicht sieht das plausibel aus und ist trotzdem falsch. Bei solchen Materialien lohnt es sich, die Height von Hand nachzuziehen oder auf Bump zu verzichten.

Lizenz

Kein Bestandteil dieses Workflows steht unter einer Non-Commercial-Lizenz. Die erzeugten Texturen gehören dir.

BestandteilLizenzKommerziell
Workflow-JSON (Laser Studios)MITja
ComfyUI-MarigoldApache 2.0ja
ComfyUI-KJNodesGPL-3.0ja — die Nutzung ist frei; wer den Node-Code verändert weitergibt, gibt ihn unter GPL weiter
ComfyUI_LayerStyleMITja
ComfyUI_cspnodesApache 2.0ja
sd_xl_base_1.0CreativeML Open RAIL++-Mja, mit den Einsatzbeschränkungen im Anhang der Lizenz
marigold-iid-appearance-v1-1Open RAIL++-Mja, mit den Einsatzbeschränkungen im Anhang der Lizenz

Die beiden RAIL-Lizenzen erlauben kommerzielle Nutzung ausdrücklich, verbieten aber bestimmte Einsatzzwecke. Wer Texturen für ein kommerzielles Spiel oder eine Visualisierung baut, ist davon nicht betroffen. Lies die Anhänge trotzdem einmal — das ist eine Seite.

↓ Workflow herunterladen (.json)