mana-godot-materie
Oberflächen für die Godot-Flotte: `Materie.fuer(mesh, &"fels")` — der Aufrufer sagt, WAS eine Fläche ist, nicht wie sie texturiert wird. Entstanden aus einer Zählung: im Haus setzen 814 Materialien eine Rauheits-ZAHL und genau sechs eine Rauheits-KARTE. Der Mangel ist nicht zu wenig Bilder, sondern dass jede Fläche überall gleich glänzt.
Kopie mit Wächter
Kopiert statt verlinkt, damit das Projekt nach einem frischen Klon aufgeht. Ein Wächter im Prüflauf meldet, wenn die Kopie hinter der Quelle zurückbleibt.
./tools/kit-abgleich.sh holen
Landet unter modules/materie/ im Projekt.
Drei ähnliche Namen, drei verschiedene Dinge
Sie werden verwechselt, und deshalb stehen sie hier nebeneinander:
| Ort | was es ist |
|---|---|
libs/mana-godot-materie |
die Godot-API: Materie.fuer(mesh, &"fels") |
libs/materialien |
der CC0-Rohbestand (ambientCG) und sein Host texturen.mana.how |
material.mana.how |
das Register aller selbst gemachten Materialien des Vereins |
Kurz: materialien liefert die Pixel, materie legt sie auf ein Mesh,
material.mana.how führt Buch über das, was wir selbst gemacht haben.
Der Befund, gezählt
Am 2026-09-10 im Haus: 1 111 StandardMaterial3D.new() in 530 Dateien und
59 Apps.
| gesetzt | Anzahl |
|---|---|
albedo_color |
1 017 |
roughness — eine Zahl |
814 |
albedo_texture |
211 |
normal_texture |
76 |
roughness_texture |
6 |
Sechs Rauheitskarten im ganzen Haus. Nicht zu wenig Bilder also, sondern jede Fläche glänzt überall gleich — und daran erkennt das Auge Plastik, egal wie gut die Farbe ist.
Der Pilot: steinbruch
Eine Funktion getauscht, Gelaende.material():
- var m := StandardMaterial3D.new()
- m.vertex_color_use_as_albedo = true
- m.roughness = 0.96
- m.specular_mode = BaseMaterial3D.SPECULAR_DISABLED
- return m
+ return Materie.koerper(&"fels", true)
Die 11 m hohe Bruchwand hatte vorher keine Oberfläche: Vertexfarbe, eine Rauheitszahl, Glanz abgeschaltet. Nachher trägt sie Schichtung und gebrochenen Glanz — und ihre Farbmischung aus Fels, Schutt und Kies ist unverändert.
Was die Probe gefunden hat, weil sie sich Bilder hinlegt
Bis zum 2026-09-11 lag im Wegwerf-Projekt der Probe kein einziges Foto. Damit lief jeder Aufruf über die gerechnete Fassung, und der ganze Foto-Weg war ungeprüft. Aufgefallen ist es nicht beim Lesen, sondern an zwei Mutationen, die durchschlüpften — weil der Code, den sie kaputt machten, gar nicht ausgeführt wurde. Eine Prüfung, die ein Stück Code nie betritt, ist keine Prüfung.
Seither legt die Probe auch absichtlich kaputte Karten hin: eine Bilddatei
plus eine .import, die auf eine .ctex zeigt, die es nicht gibt — der
Zustand nach einem frischen git clone. Gemessen: ResourceLoader.exists()
sagt true, load() gibt null. Ohne Rückfall wäre die Folge die
schlimmstmögliche: der Foto-Weg wird gewählt, alle Karten kommen leer zurück,
die gerechnete Fassung läuft nicht — und die Fläche hat am Ende weder Foto noch
Rauschen. Ein stiller Totalausfall, der aussieht, als bringe das Kit nichts.
Die Naturböden — und warum der Katalog vor dem Holen kommt
Am 13. September kamen Erde, Sand, Schnee und Waldboden dazu: die letzte echte Lücke im CC0-Bestand, denn eine Waldwelt ohne Erdboden ist der erste Mangel, der auffällt. Drei Materialien, drei verschiedene Antworten — und genau deshalb war der Blick auf das Katalogblatt vor dem Ausliefern die richtige Reihenfolge:
| Quelle | warum | |
|---|---|---|
sand |
Foto | echte Windrippeln; gerechnet ein vager Fleck |
schnee |
gerechnet | das Foto ist eine strukturlose weisse Fläche |
erde, waldboden |
Foto | echtes Korn, Nadeln und Rindenstücke |
Die Entscheidung steht als vorzug im Katalog und nicht bloss in einem
Commit-Text: schnee hat ein Bild im Spiegel und läuft trotzdem gerechnet.
Der Holen-Lauf überspringt solche Einträge — nur der Katalog holt sie, denn
ein verworfenes Foto, das man nicht sehen kann, ist eine Behauptung statt
eines Belegs.
Der Nebenfund war grösser als die Aufgabe
Beim Nachschlagen der echten Kachelmasse: elf von 22 waren geschätzt und
daneben, zwei um das Dreifache — Wood066/Wood067 1,2 → 0,40 m,
Fabric061 1,0 → 0,40 m, Grass001 2,0 → 1,40, Bark014 0,8 → 1,20.
Sie kommen jetzt aus ambientCGs dimensionX, und das Manifest sagt mit
kachel_gemessen, welche Zahl gemessen und welche geraten ist. Eine Zahl,
der man das nicht ansieht, wird beim nächsten Mal wieder für gemessen
gehalten.
Der Fehler war im Katalogbild zu sehen, bevor ihn jemand gemessen hatte — und dasselbe Bild hat anschliessend die erste, zu schnelle Erklärung dafür wieder umgeworfen (siehe die Bildunterschrift zu Holz).
Eine Korrektur an dieser Seite
Hier stand bis zum 12. September, texturen.mana.how sei mit 404 ausgefallen
und der Katalog habe deshalb gegen einen lokalen Bestand laufen müssen. Das
war falsch. Der Host läuft: /healthz gibt 200, /Bark014/color.jpg gibt
200, und holen.sh holt 18 Dateien in einem Zug.
Getestet worden war / — das gibt korrekt 404, weil der Host kein
Verzeichnislisting ausliefert — und zwei Pfade, die es nie gab. Die Karten
liegen flach unter der Wurzel: {host}/{bild}/{karte}.jpg.
🛑 Eine Adresse, die 404 gibt, ist kein Befund über den Host, sondern einer über die Adresse. Der Satz steht hier, weil die Falschmeldung öffentlich war und eine stille Löschung sie nur unsichtbar machte, nicht ungeschehen.
64 Bilder aus dem Katalog
-
Fels, gerechnet — 0 Bytes, keine Datei im Projekt. Plausibel, und genau deshalb die ehrliche Rückfallebene: dieselbe API, derselbe Name, kein Sonderweg in der App.
-
Fels, mit Foto — derselbe Aufruf. Was sich unterscheidet, ist nur, was im Projekt liegt. Der Katalog läuft deshalb ZWEIMAL und nicht über einen Schalter: ein `gerechnet()`-Schalter wäre ein zweiter Weg neben dem echten, und das Bild zeigte dann den Schalter statt den Bestand.
-
Ziegel, gerechnet. Eine Rauschfunktion kann eine Farbe und eine Körnung, aber keinen Verband — und ein Ziegel ohne Fugen ist ein roter Ball.
-
Ziegel mit Foto. Hier sieht man, wofür der `MeshVertrag` da ist: die Kachel sitzt in Metern, nicht in UV-Einheiten. Ohne diese Angabe ist jede Kachelzahl geraten.
-
Holz, gerechnet — die Maserung ist eine Richtung, kein Bild.
-
Holz mit Foto — und der Spiegelstreif der Sonne darin ist das, was diese Seite zweimal falsch erklärt hat. Erst hiess es „offene Frage zur Rauheitskarte", dann „das Kachelmass war dreifach zu gross". Das Mass war falsch (1,2 m statt der gemessenen 0,40 m, korrigiert) — nur blieb der Lack auch danach. Gemessen ist es die Quelle selbst: Wood067 trägt eine ORM-Rauheit von 0,33 gegen den Katalogwert 0,78. Das Foto ist der Sache treu, es ist eine lackierte Diele.
-
Gras, gerechnet.
-
Gras mit Foto — und hier gewinnt die linke Hälfte. Ein Foto mit Halm-Auflösung ist aus 20 m wegmipgemappt, bevor man es sieht; die gerechnete Fassung hat weiche Streifen, die sich als Grasnarbe lesen. An weiler mit vier Abzügen nebeneinander gemessen, die 6,4 MB Grass001 sind daraufhin wieder aus der App geflogen.
-
Sand mit Foto — und hier ist es umgekehrt: echte Windrippeln, die die gerechnete Fassung nicht hat. Sand lebt im Streiflicht, nicht in der Farbe; das war vorhergesagt und hat sich bestätigt.
-
Schnee, gerechnet — und so wird er ausgeliefert, obwohl ein Foto im Spiegel liegt. Weiche Mulden, blauer Schatten.
-
Schnee mit Foto: eine strukturlose weisse Fläche (Albedo 0,95 ± 0,02 — das ist Papier). Der Grund geht nicht weg: Schnee lebt von Selbststreuung unter der Oberfläche, und `StandardMaterial3D` kann kein Subsurface. Der Katalog trägt diese Entscheidung als `vorzug: &"gerechnet"` — sonst stünde sie nur in einem Commit-Text, und der nächste Holen-Lauf lieferte die schlechtere Fassung aus.
-
Waldboden mit Foto — Nadeln und Rindenstücke einzeln erkennbar. Er steht neben `erde` (dichtem Humus), weil das zwei Dinge sind. 🔴 Und er zeigt einen Mangel: auf grossen Böden wird die Normalkarte stark verkleinert, und der Glanz auf ihren Bümpchen aliast zu Funkeln. Gemessen, nicht vermutet — derselbe Abzug ohne Normalkarte hat kein Funkeln.
Und der Rest des Katalogs
52 Bilder, so benannt, wie der Katalog sie rendert. Ohne Legende — geschrieben wird eine erst, wenn jemand am Bild etwas gesehen hat.
-
materie beton
-
materie beton gerechnet
-
materie beton glatt
-
materie beton glatt gerechnet
-
materie eisen
-
materie eisen gerechnet
-
materie erde
-
materie erde gerechnet
-
materie fels dunkel
-
materie fels dunkel gerechnet
-
materie fels hell
-
materie fels hell gerechnet
-
materie filz
-
materie filz gerechnet
-
materie fliese
-
materie fliese gerechnet
-
materie gras trocken
-
materie gras trocken gerechnet
-
materie holz diele
-
materie holz diele gerechnet
-
materie holz rund
-
materie holz rund gerechnet
-
materie karton
-
materie karton gerechnet
-
materie kies
-
materie kies gerechnet
-
materie kork
-
materie kork gerechnet
-
materie kupfer
-
materie kupfer gerechnet
-
materie messing
-
materie messing gerechnet
-
materie papier
-
materie papier gerechnet
-
materie pflaster
-
materie pflaster gerechnet
-
materie putz
-
materie putz gerechnet
-
materie rinde
-
materie rinde gerechnet
-
materie sand gerechnet
-
materie stoff
-
materie stoff gerechnet
-
materie strasse
-
materie strasse gerechnet
-
materie stroh
-
materie stroh gerechnet
-
materie styropor
-
materie styropor gerechnet
-
materie teppich
-
materie teppich gerechnet
-
materie waldboden gerechnet
Woraus er besteht
materie.gd- Die API, vier Türen: `fuer(mesh, kennung)` wählt den Weg selbst, `koerper()` für Vollkörper ohne Abwicklung, `flaeche()` für Abgewickeltes, `bake()` für ein fertiges Bild wie einen Kartendruck. Dazu drei Auflösungsstufen — 512 · 1k · 2k — denn Grösse ist im Baum egal, im Grafikspeicher nicht: bei 25 Materialien ist das der Unterschied zwischen 105 MB und 420 MB, also zwischen „läuft überall" und „läuft auf dem Entwicklungsrechner".
katalog.gd- Der Bestand: 32 Oberflächen mit Kachelgrösse in Metern, Grundfarbe, Rauheit und Metall — eine Wahrheit je Material, an einer Stelle. **Jeder Eintrag muss ohne Bild auskommen.** Das ist kein Vorbehalt, sondern der Grund, warum ein Kit für Kistli UND für die Weltapps gelten kann: Props dürfen keine Bild-Texturen tragen, Weltflächen brauchen sie.
quellen/rauschen.gd- Die gerechnete Fassung — 0 Bytes, keine Datei, dieselben Namen. Sie ist kein Notnagel: wer nichts holt, bekommt dieselbe API und keinen Sonderweg in der App. **Ihre Grenze ist gemessen und steht im Kit**: die gerechnete Normalkarte trägt bei Fels fast nichts bei (Streuung 0,1863 gegen 0,1867 ohne sie), und stärker gestellt zeigt sie ein *benennbares* Flechtenmuster — eine gerechnete Struktur, die man benennen kann, sieht schlechter aus als gar keine.
quellen/bild.gd- Der Foto-Weg. Karten aus dem CC0-Bestand (ambientCG), ORM in glTF-Ordnung gepackt — Verdeckung, Rauheit und Metall in den drei Kanälen EINER Textur. Das spart zwei Abtastungen je Pixel, und triplanar zählt das dreifach, weil dort jede Karte dreimal abgetastet wird.
vertrag/mesh_vertrag.gd- Wo der Weg fällt: am Mesh, nicht am Aufrufer. Fünf der sieben Welt-Generatoren erzeugen gar keine UVs — auf ihnen kann eine Kachel nur triplanar sitzen, und für Vollkörper ist das auch die bessere Wahl: zwanzig gestreute Felsen teilen sich in Weltkoordinaten eine durchgehende Gesteinsstruktur, statt zwanzigmal dieselbe Kachel an derselben Stelle zu zeigen. Ein Generator erfüllt seine ganze Pflicht mit einer Zeile: `MeshVertrag.auskunft_setzen(mesh, &"zylindrisch", 0.9)`.
holen.sh- Holt die CC0-Karten **einmal beim Bauen, nie zur Laufzeit** — eine App, die beim Start ins Netz greift, ist offline kaputt. Und es ist freiwillig: ohne es funktioniert alles, es sieht nur anders aus.
katalog.sh- Fotografiert den ganzen Bestand: je Oberfläche ein Blatt, links gerechnet, rechts fotografisch, beide mit nahem Körper und Boden bis 40 m. **Die anderen Haus-Kataloge stellen ein Ding auf eine Bühne — hier gibt es nichts hinzustellen.** Die Frage dieses Kits ist der Vergleich selbst: gewinnt das Foto oder die gerechnete Fassung? Sie 32-mal einzeln in einer App zu stellen, wäre der teure Weg.
9 Projekte benutzen ihn
Gezählt, nicht behauptet: pnpm bausteine durchsucht jede
App im Baum nach Klassennamen des Bausteins und nach vendorierten
Kopien. Ein Baustein ohne Abnehmer wäre keiner, sondern eine
Bibliothek auf Vorrat. Stand: 2026-09-15.
- bauernhaus
- burg
- hofrain
- immertal
- muehle
- riedhaus
- steinbruch
- sternwarte
- weiler
Wem er gehört, was ihn prüft
- Lizenz
- MIT — Bausteine sind permissiv lizenziert, Anwendungen AGPL-3.0. Ein Baustein, der ansteckt, wäre keiner.
- Träger
- Der Verein
- Gebiet
- oberflaechen —
- Wache
-
probe/lauf.sh— prüft ihn headless. - Katalog
-
kit_katalog.gd— rendert seine Bauteile als Bilder.
🛑 Kein Link ins Repository: die Kit-Repos liegen auf der eigenen Forge und sind noch nicht öffentlich. Ein Link, der 404 antwortet, wäre schlechter als keiner.
Was er verkörpert
-
OffenheitCode und Mittelverwendung öffentlich.
-
LanglebigkeitBewährte Stacks, gute Doku.
-
AchtsamkeitKeine Engagement-Tricks.
Was offen ist
- Sieben der 32 Oberflächen haben keine CC0-Karten und bleiben gerechnet. Bei Karton und Papier ist das gemessene Absicht; **Metall (eisen, kupfer, messing) gerechnet ist der schwächste Fall**, weil dort gerade die Reflexion die Arbeit tut.
- Normalkarten **funkeln in der Ferne** — auf grossen Böden wird die Karte verkleinert, und der Glanz auf ihren Bümpchen aliast. Bekanntes Problem (Specular-Aliasing), bekannte Lösung (Normalkarte über die Entfernung ausblenden), nicht gebaut.
- Der Foto-Weg ist **systematisch glänzender** als der gerechnete: Wood067 0,33 gegen Katalog 0,78, Rock051 0,56 gegen 0,92, Grass001 0,54 gegen 0,95. Welche der beiden Zahlen recht hat, ist je Material verschieden und nicht entschieden.
- **17 der 29 Kachelmasse sind geschätzt.** ambientCG gibt für sie keine Grösse an; das Manifest sagt mit `kachel_gemessen`, welche. Elf waren vorher falsch geschätzt, zwei um das Dreifache.
- Nichts davon lief auf einer Brille. Ein 2K-Satz kostet rund 17 MB Grafikspeicher je Material; der Regler dafür ist bewusst NICHT an `QualityBudget` gekoppelt, damit ein Kistli nicht das ganze Weltkit vendorieren muss — den Wirt kostet das eine Zeile.
Ein Gebiet je Baustein
Die Trennung nach Fachgebiet ist der Grund, warum es fünf Repos sind und nicht eines.