bolajiev Claude Sonnet 4.6 commited on
Commit ·
101b0c3
1
Parent(s): 3b7d66c
Fix env map not reaching MeshPhysicalMaterial; auto-bloom for neon
Browse filesThree root causes fixed:
1. Chrome/gold/glass rendered black because scene.environment alone doesn't
always propagate to MeshPhysicalMaterial. Added explicit scene.traverse()
after __OBJECTS__ to force material.envMap = _envTex + needsUpdate on every
mesh — the same pattern Three.js recommends when mixing manual and auto env.
2. Added explicit envMapIntensity to preset materials (chrome: 2.0, glass: 1.5,
gold: 1.0) so the IBL strength is locked regardless of any global override.
3. Neon emissiveIntensity bumped 2→3; compile_html now auto-enables bloom
(strength ≥ 1.5) whenever any scene object uses preset: neon, so flat emissive
always reads as glowing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- compiler.py +21 -5
compiler.py
CHANGED
|
@@ -85,23 +85,25 @@ def _preset_mat_js(node) -> str | None:
|
|
| 85 |
if preset == "gold":
|
| 86 |
c = col if has_custom else _col_str("#ffd700")
|
| 87 |
return (f"new THREE.MeshPhysicalMaterial({{ color: {c}, "
|
| 88 |
-
f"metalness: 1.0, roughness: 0.25, clearcoat: 1.0, clearcoatRoughness: 0.1
|
|
|
|
| 89 |
|
| 90 |
if preset == "chrome":
|
| 91 |
c = col if has_custom else _col_str("#ffffff")
|
| 92 |
return (f"new THREE.MeshPhysicalMaterial({{ color: {c}, "
|
| 93 |
-
f"metalness: 1.0, roughness: 0.05, clearcoat: 1.0, clearcoatRoughness: 0.05
|
|
|
|
| 94 |
|
| 95 |
if preset == "glass":
|
| 96 |
return (f"new THREE.MeshPhysicalMaterial({{ color: {col}, "
|
| 97 |
f"metalness: 0.0, roughness: 0.05, "
|
| 98 |
f"transmission: 1.0, thickness: 0.5, ior: 1.5, "
|
| 99 |
-
f"transparent: true, opacity: 1.0 }})")
|
| 100 |
|
| 101 |
if preset == "neon":
|
| 102 |
return (f"new THREE.MeshStandardMaterial({{ "
|
| 103 |
f"color: new THREE.Color('#000000'), "
|
| 104 |
-
f"emissive: {col}, emissiveIntensity:
|
| 105 |
|
| 106 |
if preset == "matte":
|
| 107 |
return (f"new THREE.MeshStandardMaterial({{ color: {col}, "
|
|
@@ -502,7 +504,8 @@ TEMPLATE = """<!DOCTYPE html>
|
|
| 502 |
|
| 503 |
// ---- environment map: gives metals/glass real reflections ----
|
| 504 |
const pmrem = new THREE.PMREMGenerator(renderer);
|
| 505 |
-
|
|
|
|
| 506 |
pmrem.dispose();
|
| 507 |
|
| 508 |
const controls = new OrbitControls(camera, renderer.domElement);
|
|
@@ -520,6 +523,14 @@ TEMPLATE = """<!DOCTYPE html>
|
|
| 520 |
// ---- objects ----
|
| 521 |
__OBJECTS__
|
| 522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 523 |
// ---- shadow casting on every mesh ----
|
| 524 |
if (__USE_SHADOWS__) {
|
| 525 |
group.traverse(o => { if (o.isMesh) { o.castShadow = true; o.receiveShadow = true; } });
|
|
@@ -594,6 +605,11 @@ def compile_html(
|
|
| 594 |
lighting: str = "studio",
|
| 595 |
shadows: bool = True,
|
| 596 |
) -> str:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 597 |
html = TEMPLATE
|
| 598 |
html = html.replace("__BG__", scene.background)
|
| 599 |
html = html.replace("__PRESET_LIGHTS__", _preset_lights_js(lighting, shadows))
|
|
|
|
| 85 |
if preset == "gold":
|
| 86 |
c = col if has_custom else _col_str("#ffd700")
|
| 87 |
return (f"new THREE.MeshPhysicalMaterial({{ color: {c}, "
|
| 88 |
+
f"metalness: 1.0, roughness: 0.25, clearcoat: 1.0, clearcoatRoughness: 0.1, "
|
| 89 |
+
f"envMapIntensity: 1.0 }})")
|
| 90 |
|
| 91 |
if preset == "chrome":
|
| 92 |
c = col if has_custom else _col_str("#ffffff")
|
| 93 |
return (f"new THREE.MeshPhysicalMaterial({{ color: {c}, "
|
| 94 |
+
f"metalness: 1.0, roughness: 0.05, clearcoat: 1.0, clearcoatRoughness: 0.05, "
|
| 95 |
+
f"envMapIntensity: 2.0 }})")
|
| 96 |
|
| 97 |
if preset == "glass":
|
| 98 |
return (f"new THREE.MeshPhysicalMaterial({{ color: {col}, "
|
| 99 |
f"metalness: 0.0, roughness: 0.05, "
|
| 100 |
f"transmission: 1.0, thickness: 0.5, ior: 1.5, "
|
| 101 |
+
f"transparent: true, opacity: 1.0, envMapIntensity: 1.5 }})")
|
| 102 |
|
| 103 |
if preset == "neon":
|
| 104 |
return (f"new THREE.MeshStandardMaterial({{ "
|
| 105 |
f"color: new THREE.Color('#000000'), "
|
| 106 |
+
f"emissive: {col}, emissiveIntensity: 3.0 }})")
|
| 107 |
|
| 108 |
if preset == "matte":
|
| 109 |
return (f"new THREE.MeshStandardMaterial({{ color: {col}, "
|
|
|
|
| 504 |
|
| 505 |
// ---- environment map: gives metals/glass real reflections ----
|
| 506 |
const pmrem = new THREE.PMREMGenerator(renderer);
|
| 507 |
+
const _envTex = pmrem.fromScene(new RoomEnvironment(), 0.04).texture;
|
| 508 |
+
scene.environment = _envTex;
|
| 509 |
pmrem.dispose();
|
| 510 |
|
| 511 |
const controls = new OrbitControls(camera, renderer.domElement);
|
|
|
|
| 523 |
// ---- objects ----
|
| 524 |
__OBJECTS__
|
| 525 |
|
| 526 |
+
// ---- force env map on every material (MeshPhysicalMaterial needs explicit assignment) ----
|
| 527 |
+
scene.traverse(o => {
|
| 528 |
+
if (o.isMesh && o.material) {
|
| 529 |
+
o.material.envMap = _envTex;
|
| 530 |
+
o.material.needsUpdate = true;
|
| 531 |
+
}
|
| 532 |
+
});
|
| 533 |
+
|
| 534 |
// ---- shadow casting on every mesh ----
|
| 535 |
if (__USE_SHADOWS__) {
|
| 536 |
group.traverse(o => { if (o.isMesh) { o.castShadow = true; o.receiveShadow = true; } });
|
|
|
|
| 605 |
lighting: str = "studio",
|
| 606 |
shadows: bool = True,
|
| 607 |
) -> str:
|
| 608 |
+
# auto-enable bloom when any leaf object uses the neon preset
|
| 609 |
+
if any(getattr(n, "preset", None) == "neon" for n in _flatten(scene.objects)):
|
| 610 |
+
glow = True
|
| 611 |
+
glow_strength = max(float(glow_strength), 1.5)
|
| 612 |
+
|
| 613 |
html = TEMPLATE
|
| 614 |
html = html.replace("__BG__", scene.background)
|
| 615 |
html = html.replace("__PRESET_LIGHTS__", _preset_lights_js(lighting, shadows))
|