bolajiev Claude Sonnet 4.6 commited on
Commit
101b0c3
·
1 Parent(s): 3b7d66c

Fix env map not reaching MeshPhysicalMaterial; auto-bloom for neon

Browse files

Three 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>

Files changed (1) hide show
  1. 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: 2.0 }})")
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
- scene.environment = pmrem.fromScene(new RoomEnvironment(), 0.04).texture;
 
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))