fix(world): Straße/Stadtfläche-Kontrast, Brückennaht, tote metalnessMap (Fix-Runde 1)
Ruling 55: asphalt_02 maß roh heller (Ø 89.5) als concrete_pavement_03 (Ø 65.9) und ließ Stadtflächen wie dunkle Flecken auf der Straße wirken. material.color kann eine Textur nur abdunkeln, also wird die Straße auf 0x999999 abgetönt statt die Stadtfläche zu verändern. Gemessen im gerenderten Bild an denselben Bildschirmregionen: Straße 93.0 -> 42.5, Stadtfläche 63.2 -> 63.0 (unverändert) — die Straße kommt jetzt deutlich dunkler heraus als die Stadtfläche, nicht nur als vorher sie selbst. Ruling 56: Brücken sind in den Daten dasselbe Straßenstück, nur über Wasser (geometry.js trennt sie einzig über roads.filter(r => r.bridge)) und bekommen jetzt asphalt_02 und denselben Farbton wie roads statt der Stadtflächentextur, damit an keinem Straße-Brücke-Übergang mehr eine Farbnaht entsteht. Neuer Test dafür (RED vor der Änderung, GREEN danach) plus ein erreichtes Brückenstück im Browser (Chunk 11_7) fotografiert. Ruling 57: metalnessMap entfernt. metalness steht fest auf 0, three multipliziert texelMetalness nur noch dazu (metalnessmap_fragment.glsl.js) und könnte das Ergebnis nie von 0 wegbewegen — reine Kosten ohne Wirkung. Ruling 58: anisotropy als optionaler Parameter von createMaterials()/loadSet() statt eines globalen Renderer-Zugriffs; main.js übergibt jetzt renderer.capabilities.getMaxAnisotropy(). Laufzeit bestätigt: alle drei Texturtypen auf allen Materialien tragen anisotropy 16 (= getMaxAnisotropy() auf diesem Gerät). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fb0d19c2e5
commit
2469d30e76
3 files changed
+35
-7
No files matched your search
+28
-6
@@ -7,13 +7,22 @@ export const TEXTURES = {
|
||||
park: "leafy_grass", // Grünflächen
|
||||
urban: "concrete_pavement_03", // versiegelte Stadtfläche
|
||||
roads: "asphalt_02",
|
||||
bridges: "concrete_pavement_03",
|
||||
// Ruling 56: eine Brücke ist in den Daten dasselbe Straßenstück, nur über Wasser
|
||||
// (geometry.js trennt sie einzig über roads.filter(r => r.bridge)) — dieselbe
|
||||
// Textur wie roads, sonst zeigt jeder Straße-Brücke-Übergang eine Farbnaht.
|
||||
bridges: "asphalt_02",
|
||||
buildings: "white_stucco",
|
||||
};
|
||||
const FALLBACK_COLORS = {
|
||||
ground: 0xa8b878, sand: 0xe8d888, park: 0x8bc34a, urban: 0xd8d8d8,
|
||||
roads: 0x505050, bridges: 0xb0b0b0, buildings: 0xe8e4dc,
|
||||
};
|
||||
// Ruling 55: asphalt_02 misst roh heller (Ø 89.5) als concrete_pavement_03 (Ø 65.9) —
|
||||
// Stadtflächen wirkten dadurch wie dunkle Flecken auf der Straße, das Straßennetz
|
||||
// verschwand optisch. material.color kann eine Textur nur abdunkeln, nie aufhellen,
|
||||
// also wird hier die hellere Straße (und die jetzt identisch texturierte Brücke)
|
||||
// abgetönt statt die Stadtfläche zu verändern.
|
||||
const ROAD_TINT = 0x999999;
|
||||
|
||||
/** Kachelbare Wellen-Normalmap, weil Poly Haven keine Wassertextur hat. */
|
||||
export function waterNormalData(size = 128) {
|
||||
@@ -34,7 +43,7 @@ export function waterNormalData(size = 128) {
|
||||
return data;
|
||||
}
|
||||
|
||||
async function loadSet(loader, slug, fallback) {
|
||||
async function loadSet(loader, slug, fallback, { tint, maxAnisotropy } = {}) {
|
||||
let map, normalMap, arm;
|
||||
try {
|
||||
[map, normalMap, arm] = await Promise.all(
|
||||
@@ -46,16 +55,29 @@ async function loadSet(loader, slug, fallback) {
|
||||
}
|
||||
for (const t of [map, normalMap, arm]) {
|
||||
t.wrapS = t.wrapT = RepeatWrapping;
|
||||
// Ruling 58: Straßen laufen flach in die Tiefe — dort flimmert Standard-
|
||||
// filterung zuerst. createMaterials() kennt den Renderer nicht selbst, daher
|
||||
// als optionaler Parameter von außen; ohne ihn bleibt three beim Standard (1).
|
||||
if (maxAnisotropy) t.anisotropy = maxAnisotropy;
|
||||
}
|
||||
map.colorSpace = SRGBColorSpace;
|
||||
// arm packt Ambient Occlusion, Rauheit und Metallgrad in R, G und B.
|
||||
return new MeshStandardMaterial({ map, normalMap, aoMap: arm, roughnessMap: arm, metalnessMap: arm, metalness: 0 });
|
||||
// arm packt Ambient Occlusion und Rauheit in R und G. metalnessMap fehlt bewusst
|
||||
// (Ruling 57): metalness steht fest auf 0, three multipliziert texelMetalness nur
|
||||
// noch dazu (metalnessmap_fragment.glsl.js) und könnte das Ergebnis nie von 0
|
||||
// wegbewegen — reine Kosten (Texturbindung, Shader-Permutation) ohne Wirkung.
|
||||
const material = new MeshStandardMaterial({ map, normalMap, aoMap: arm, roughnessMap: arm, metalness: 0 });
|
||||
// Ruling 55/56: nur der geladene Erfolgsfall bekommt die Tönung — der einfarbige
|
||||
// Ersatz oben hat schon seinen eigenen, passenden Grundton.
|
||||
if (tint) material.color.set(tint);
|
||||
return material;
|
||||
}
|
||||
|
||||
export async function createMaterials() {
|
||||
export async function createMaterials(maxAnisotropy) {
|
||||
const loader = new TextureLoader();
|
||||
const tints = { roads: ROAD_TINT, bridges: ROAD_TINT };
|
||||
const entries = await Promise.all(
|
||||
MATERIAL_KEYS.map(async (key) => [key, await loadSet(loader, TEXTURES[key], FALLBACK_COLORS[key])]),
|
||||
MATERIAL_KEYS.map(async (key) =>
|
||||
[key, await loadSet(loader, TEXTURES[key], FALLBACK_COLORS[key], { tint: tints[key], maxAnisotropy })]),
|
||||
);
|
||||
const materials = Object.fromEntries(entries);
|
||||
materials.buildings.vertexColors = true; // pastellige Tönung je Gebäude
|
||||
|
||||
Reference in new issue
Block a user