
Work
Prompt
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>iPhone 13 Pro Max - High Fidelity 3D</title> <style> body { margin: 0; overflow: hidden; background-color: #050505; color: white; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; } #ui-container { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); text-align: center; pointer-events: none; z-index: 10; } h1 { margin: 0; font-size: 24px; font-weight: 600; letter-spacing: 1px; } p { margin: 5px 0 0 0; font-size: 14px; opacity: 0.6; } #loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 20px; font-weight: 500; transition: opacity 0.5s ease; } .color-picker { position: absolute; top: 30px; right: 30px; display: flex; gap: 15px; pointer-events: auto; } .color-btn { width: 30px; height: 30px; border-radius: 50%; cursor: pointer; border: 2px solid transparent; transition: transform 0.2s, border-color 0.2s; } .color-btn:hover { transform: scale(1.1); } .color-btn.active { border-color: white; } </style> </head> <body> <div id="loading">Loading Engine...</div> <div id="ui-container"> <h1>iPhone 13 Pro Max</h1> <p>Interactive 3D Model</p> </div> <div class="color-picker"> <!-- Sierra Blue --> <div class="color-btn" style="background: #9bb5ce;" data-color="sierra" title="Sierra Blue"></div> <!-- Graphite --> <div class="color-btn active" style="background: #5c5b57;" data-color="graphite" title="Graphite"></div> <!-- Silver --> <div class="color-btn" style="background: #f1f2ed;" data-color="silver" title="Silver"></div> <!-- Gold --> <div class="color-btn" style="background: #fae7cf;" data-color="gold" title="Gold"></div> </div> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.160.0/build/three.module.js", "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js'; import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js'; // Scene Setup const scene = new THREE.Scene(); // Add a subtle radial gradient background scene.background = new THREE.Color(0x050505); scene.fog = new THREE.FogExp2(0x050505, 0.015); const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100); camera.position.set(0, 0, 25); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.2; document.body.appendChild(renderer.domElement); const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.minDistance = 10; controls.maxDistance = 40; // Environment Lighting (CRITICAL for realism) const pmremGenerator = new THREE.PMREMGenerator(renderer); scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture; RectAreaLightUniformsLib.init(); // Add dramatic lighting const rectLight1 = new THREE.RectAreaLight(0xffffff, 2.5, 10, 20); rectLight1.position.set(-8, 5, 10); rectLight1.lookAt(0, 0, 0); scene.add(rectLight1); const rectLight2 = new THREE.RectAreaLight(0xe0eaff, 2.0, 10, 20); rectLight2.position.set(8, -5, -10); rectLight2.lookAt(0, 0, 0); scene.add(rectLight2); // --- IPHONE CONSTRUCTION --- // const W = 7.81; const H = 16.08; const R = 1.3; const D = 0.72; const phoneGroup = new THREE.Group(); scene.add(phoneGroup); // Colors configurations const phoneColors = { sierra: { frame: 0x829cbd, back: 0x9bb5ce, bump: 0x7a96b5 }, graphite: { frame: 0x444444, back: 0x333333, bump: 0x222222 }, silver: { frame: 0xdddddd, back: 0xf1f2ed, bump: 0xe0e2dc }, gold: { frame: 0xd4af37, back: 0xfae7cf, bump: 0xd4af37 } }; let currentColor = phoneColors.graphite; // Materials const matDark = new THREE.MeshStandardMaterial({ color: 0x111111, roughness: 0.9 }); const matMetal = new THREE.MeshPhysicalMaterial({ color: currentColor.frame, metalness: 1.0, roughness: 0.1, clearcoat: 0.3, clearcoatRoughness: 0.1 }); const matBack = new THREE.MeshPhysicalMaterial({ color: currentColor.back, metalness: 0.2, roughness: 0.7, clearcoat: 0.0, // iPhone Pro backs are matte frosted glass, not clearcoated clearcoatRoughness: 0.0 }); const matBump = new THREE.MeshPhysicalMaterial({ color: currentColor.bump, metalness: 0.1, roughness: 0.05, // The bump itself is glossy polished glass transmission: 0.5, thickness: 0.15, clearcoat: 1.0 }); const matLens = new THREE.MeshPhysicalMaterial({ color: 0x010101, metalness: 1.0, roughness: 0.0, clearcoat: 1.0, iridescence: 1.5, // Creates beautiful purple/green camera lens anti-reflective coating look iridescenceIOR: 1.3 }); // Helper shape builder function createRoundedShape(width, height, radius) { const shape = new THREE.Shape(); const x = -width / 2, y = -height / 2; shape.moveTo(x, y + radius); shape.lineTo(x, y + height - radius); shape.quadraticCurveTo(x, y + height, x + radius, y + height); shape.lineTo(x + width - radius, y + height); shape.quadraticCurveTo(x + width, y + height, x + width, y + height - radius); shape.lineTo(x + width, y + radius); shape.quadraticCurveTo(x + width, y, x + width - radius, y); shape.lineTo(x + radius, y); shape.quadraticCurveTo(x, y, x, y + radius); return shape; } // 1. FRAME const shape = createRoundedShape(W, H, R); const frameExtrudeSettings = { depth: D, bevelEnabled: true, bevelThickness: 0.05, bevelSize: 0.04, bevelSegments: 16, curveSegments: 32 }; const frameGeom = new THREE.ExtrudeGeometry(shape, frameExtrudeSettings); frameGeom.computeVertexNormals(); frameGeom.center(); const frame = new THREE.Mesh(frameGeom, [matDark, matMetal]); phoneGroup.add(frame); // Buttons const btnGeom = new THREE.BoxGeometry(0.1, 2.0, 0.2); const powerBtn = new THREE.Mesh(btnGeom, matMetal); powerBtn.position.set(W/2 + 0.03, 2.5, 0); // Right side, slightly up phoneGroup.add(powerBtn); const volGeom = new THREE.BoxGeometry(0.1, 1.2, 0.2); const volUp = new THREE.Mesh(volGeom, matMetal); volUp.position.set(-W/2 - 0.03, 3.2, 0); // Left side, up phoneGroup.add(volUp); const volDown = new THREE.Mesh(volGeom, matMetal); volDown.position.set(-W/2 - 0.03, 1.8, 0); // Left side, below volume up phoneGroup.add(volDown); const muteGeom = new THREE.BoxGeometry(0.1, 0.6, 0.15); const muteBtn = new THREE.Mesh(muteGeom, matMetal); muteBtn.position.set(-W/2 - 0.03, 4.5, 0); // Left side, above volume up phoneGroup.add(muteBtn); // Bottom Details (Charging port, Screws, Speakers) const bottomGroup = new THREE.Group(); bottomGroup.position.set(0, -H/2 - 0.01, 0); phoneGroup.add(bottomGroup); const portGeom = new THREE.BoxGeometry(0.9, 0.2, 0.25); const port = new THREE.Mesh(portGeom, new THREE.MeshBasicMaterial({color: 0x000000})); bottomGroup.add(port); const portInnerGeom = new THREE.BoxGeometry(0.7, 0.05, 0.1); const portInner = new THREE.Mesh(portInnerGeom, new THREE.MeshStandardMaterial({color: 0xaaaaaa, metalness: 1.0})); portInner.position.y = -0.05; bottomGroup.add(portInner); // Pentalobe Screws const screwGeom = new THREE.CylinderGeometry(0.08, 0.08, 0.05, 16); const screwMat = new THREE.MeshStandardMaterial({color: 0x555555, metalness: 0.9, roughness: 0.4}); const screw1 = new THREE.Mesh(screwGeom, screwMat); screw1.rotation.x = Math.PI / 2; screw1.position.set(-0.8, 0, 0); bottomGroup.add(screw1); const screw2 = new THREE.Mesh(screwGeom, screwMat); screw2.rotation.x = Math.PI / 2; screw2.position.set(0.8, 0, 0); bottomGroup.add(screw2); // Speaker holes (3 on left, 5 on right) const holeGeom = new THREE.CylinderGeometry(0.06, 0.06, 0.1, 12); const holeMat = new THREE.MeshBasicMaterial({color: 0x000000}); for(let i=0; i<3; i++) { const h = new THREE.Mesh(holeGeom, holeMat); h.rotation.x = Math.PI / 2; h.position.set(-1.2 - i*0.25, 0, 0); bottomGroup.add(h); } for(let i=0; i<5; i++) { const h = new THREE.Mesh(holeGeom, holeMat); h.rotation.x = Math.PI / 2; h.position.set(1.2 + i*0.25, 0, 0); bottomGroup.add(h); } const faceZ = (D / 2) + 0.03; // Accounting for bevelThickness // 2. BACK GLASS const backShape = createRoundedShape(W - 0.04, H - 0.04, R - 0.02); const backGeom = new THREE.ShapeGeometry(backShape); const backGlass = new THREE.Mesh(backGeom, matBack); backGlass.position.z = -faceZ - 0.005; backGlass.rotation.y = Math.PI; // Face backwards phoneGroup.add(backGlass); // Apple Logo (Canvas Texture) const logoCanvas = document.createElement('canvas'); logoCanvas.width = 256; logoCanvas.height = 256; const ctxL = logoCanvas.getContext('2d'); ctxL.fillStyle = 'rgba(255,255,255,1)';
A system prompt was added to support web rendering