3D Viewer — Technical Guide

S7 Implementation Reference — Multi-layer glass, environment mapping, and shadow enhancements

1. Overview

The 3D viewer renders realistic window previews using Three.js r0.160.0. S7 added four enhancements to make glass rendering physically accurate:

Environment Map

RoomEnvironment PMREM provides soft, realistic reflections on glass and frame surfaces.

Multi-Layer Glass

Parses composition strings into stacked glass layers with metallic spacer bars.

Shadow Enhancement

Stronger floor shadow (0.25 opacity) plus radial-gradient contact shadow blob.

Material Catalog

12 glass material types with physically-based optical properties (IOR, transmission, roughness).

File: src/js/3d-engine.js (1415 lines) — single file, all changes within WindowRenderer class.

2. Environment Map

Three.js MeshPhysicalMaterial with transmission needs an environment map for realistic refraction and reflection. Without it, glass appears flat.

How It Works

RoomEnvironment (Three.js addon) | v PMREMGenerator.fromScene(roomEnv, sigma=0.04) | v scene.environment = cubemap texture | v All MeshPhysicalMaterial auto-reflect this environment

The sigma = 0.04 parameter produces slightly blurred reflections — premium and soft rather than mirror-sharp.

Performance: Runs once at init (~16ms). Zero per-frame cost. Safe on mobile.

3. Multi-Layer Glass Rendering

Real insulating glass units (IGU) have 2–3 glass panes separated by gas-filled gaps with metallic spacer bars.

Layer Stack Visualization

Double pane: "4LowE-16Ag-4Float" Exterior Interior | [4mm LowE] [spacer] 16mm Ag [spacer] [4mm Float] | | blue-green metal (empty) metal neutral | Triple pane: "331LowE-10Ag-4F-12Ag-4LowE" | [7mm LowE] [sp] 10mm [sp] [4mm Float] [sp] 12mm [sp] [4mm LowE] |

Visual Scale

Real glass is 4mm thick — invisible at window scale. A visual scale factor of 3.0 is applied:

Real ThicknessVisual ThicknessElement
4 mm12 mm (0.012m)Glass layer
16 mm48 mm (0.048m)Argon gap
24 mm total72 mm totalFull stack

Spacer Bars

TypeColorMaterial
Standard spacer 0x888888 Silver aluminium (metalness 0.9)
Warm Edge (we) 0x333333 Dark composite (better thermal insulation)

4. Composition String Parser

parseGlassComposition(str) converts WinArhi catalog strings into structured data.

Algorithm

  1. Strip suffix (we) or (Ag, we) → set warmEdge flag
  2. Split on - delimiter
  3. Classify each segment:
    • Gap: purely numeric, ≤24mm, optional Ag/Aer suffix
    • Layer: leading digits = thickness, rest = material name
    • Laminate: digits >20 and ≥3 chars (e.g. 331 = 3+3+1 = 7mm)
  4. Return { layers, gaps, warmEdge }

Tested Patterns

InputLayersGapsNotes
4LowE-16Ag-4Float4mm LowE + 4mm Float16mm ArgonStandard double
331-12Aer-331Sablat7mm Float + 7mm Sablat12mm AirLaminate + frosted
4LowE-14Ag-4R. Clear4mm LowE + 4mm Clear14mm ArgonDot/space in name
331LowE-10Ag-4F-12Ag-4LowE7mm + 4mm + 4mm10mm + 12mm AgTriple pane
4LowE-16Ag-4Float (we)4mm + 4mm16mm AgWarm Edge = dark spacers
6Float6mm FloatnoneSingle pane
Edge case: Purely numeric segments >24 are treated as laminate codes, not gaps. Real gaps are always ≤24mm.

5. Glass Material Catalog

Each glass layer gets a MeshPhysicalMaterial with physically-based properties. Materials are cached in materialCache.

TypeColorTransmissionRoughnessVisual
LowE 0x88ccdd 0.900.0Blue-green tint
Float / Clear 0xeeeeff 0.920.0Neutral transparent
Planitherm 0x99ccdd 0.880.0Premium blue
Sablat (frosted) 0xdddddd 0.400.8Diffuse white
Krizet 0xdddddd 0.500.6Textured pattern
Securizat 0x99aacc 0.880.0Tempered blue
Screen 0xaabbaa 0.300.1Solar control green
Bronze 0xcc9966 0.350.05Reflective warm
Oglinda (mirror) 0xcccccc 0.100.0Near-opaque
Lacobel 0x334455 0.050.1Painted back
Ornament 0xdddddd 0.550.7Decorative rough

All materials: ior: 1.52, DoubleSide, polygonOffset: true, clearcoat: 1 (frosted types → 0.2).

6. Shadow System

Floor Shadow

ShadowMaterial opacity increased 0.1 → 0.25 for a more pronounced ground shadow.

Contact Shadow

Canvas 128x128px radial gradient: 0% rgba(0,0,0, 0.18) ← dark center 50% rgba(0,0,0, 0.08) ← fade 100% rgba(0,0,0, 0.00) ← transparent edge PlaneGeometry(2.5 x 1.0) + MultiplyBlending Y = -1.49 (1cm above floor, prevents z-fighting) Dynamically scaled: width*1.2, height*0.3

7. Performance & Mobile

MetricValueNotes
Triangles per panel (double)~722 layers + 4 spacers
Triangles per panel (triple)~1323 layers + 8 spacers
4-panel triple window~528Negligible
Environment mapOne-time ~16msNot per-frame
Material cacheSharedSame type reused across panels
Pixel ratio cap2.0Prevents 4K overdraw

Mobile Fallback

Touch devices with viewport < 768px: multi-layer glass disabled, falls back to single PlaneGeometry.

this._useSimpleGlass = ('ontouchstart' in window && window.innerWidth < 768);
Environment map still applies on mobile — only multi-layer geometry is skipped. Reflections remain realistic.

8. Public API Reference

MethodPurpose
updateWindow(config)Rebuild with new config. If glazingDef.composition exists, triggers multi-layer.
toggleWireframe()Toggles wireframe on all materials including cached glass layers.
toggleCrossSection()Profile cross-section view.
fitToView()Auto-positions camera. Also resizes contact shadow.
dispose()Cleans up all GPU resources.

Config Object

renderer.updateWindow({
    width: 1.2,              // meters
    height: 1.4,
    panels: 2,
    openings: ['obd', 'ds'],
    glazingDef: {
        id: '24mm, 4LowE-16Ag-4Float',
        composition: '4LowE-16Ag-4Float',  // triggers multi-layer
        type: 'double',                      // 'single' skips it
        thickness: 24                        // mm, fallback material
    },
    colorDef: { hex: '#FFFFFF', tip: 'solid' },
    handleColor: '#C0C0C0'
});

9. Testing Checklist

#TestExpected Result
1Select double LowE glassTwo glass layers visible in profile view
2Check spacer barsSilver metallic bars at gap edges
3Select warm edge (we)Spacer bars change to dark grey
4Select triple pane3 layers + 2 sets of spacers
5Select Sablat (frosted)Visible roughness on glass
6Check reflectionsSoft environment reflections on glass
7Check floor shadowDarker shadow + contact shadow blob
8Resize window configContact shadow resizes
9Mobile viewport (<768px)Falls back to flat PlaneGeometry
10Toggle wireframeAll glass layers show wireframe
11Change glass repeatedlyNo console errors (disposal correct)
12Double-click to open panelMulti-layer glass animates with sash