Created
February 13, 2026 22:23
-
-
Save lpenguin/e847a4a46eb1af486aa8e3affb187861 to your computer and use it in GitHub Desktop.
Ghibli-style 3D Diorama Prototype (Three.js)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Ghibli Diorama Prototype</title> | |
| <style> | |
| body { margin: 0; overflow: hidden; background: #FFF4E0; font-family: sans-serif; } | |
| #info { position: absolute; top: 10px; width: 100%; text-align: center; color: #6D6875; pointer-events: none; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="info">Ghibli Diorama Prototype<br>Hold to rotate • Scroll to zoom</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'; | |
| // --- SCENE SETUP --- | |
| const scene = new THREE.Scene(); | |
| scene.background = new THREE.Color(0xFFF4E0); // Warm sky | |
| const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
| camera.position.set(10, 8, 10); | |
| const renderer = new THREE.WebGLRenderer({ antialias: true }); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| renderer.shadowMap.enabled = true; | |
| renderer.shadowMap.type = THREE.SoftShadowMap; | |
| document.body.appendChild(renderer.domElement); | |
| const controls = new OrbitControls(camera, renderer.domElement); | |
| controls.enableDamping = true; | |
| // --- LIGHTING (Golden Hour) --- | |
| const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); | |
| scene.add(ambientLight); | |
| const sunLight = new THREE.DirectionalLight(0xffe4b5, 1.5); | |
| sunLight.position.set(10, 20, 10); | |
| sunLight.castShadow = true; | |
| sunLight.shadow.mapSize.width = 1024; | |
| sunLight.shadow.mapSize.height = 1024; | |
| scene.add(sunLight); | |
| // --- GROUND --- | |
| const groundGeo = new THREE.CylinderGeometry(8, 8, 0.5, 6); // Hexagonal base | |
| const groundMat = new THREE.MeshStandardMaterial({ color: 0x9DBE94, roughness: 0.8 }); | |
| const ground = new THREE.Mesh(groundGeo, groundMat); | |
| ground.receiveShadow = true; | |
| scene.add(ground); | |
| // --- HELPER FUNCTIONS --- | |
| function createTree(x, z) { | |
| const group = new THREE.Group(); | |
| // Trunk | |
| const trunkGeo = new THREE.CylinderGeometry(0.3, 0.5, 4, 8); | |
| const trunkMat = new THREE.MeshStandardMaterial({ color: 0x6D6875 }); | |
| const trunk = new THREE.Mesh(trunkGeo, trunkMat); | |
| trunk.position.y = 2; | |
| trunk.castShadow = true; | |
| group.add(trunk); | |
| // Foliage (Cloud style) | |
| const foliageMat = new THREE.MeshStandardMaterial({ color: 0x52796F, roughness: 1 }); | |
| const sphereGeo = new THREE.SphereGeometry(1.5, 16, 16); | |
| const mainCloud = new THREE.Mesh(sphereGeo, foliageMat); | |
| mainCloud.position.y = 4.5; | |
| mainCloud.scale.set(1.5, 1, 1.5); | |
| mainCloud.castShadow = true; | |
| group.add(mainCloud); | |
| for(let i=0; i<3; i++) { | |
| const cloud = new THREE.Mesh(sphereGeo, new THREE.MeshStandardMaterial({ color: 0x84A59D })); | |
| cloud.position.set(Math.random()-0.5, 4 + Math.random(), Math.random()-0.5); | |
| cloud.position.multiplyScalar(2); | |
| cloud.scale.set(0.8, 0.8, 0.8); | |
| cloud.castShadow = true; | |
| group.add(cloud); | |
| } | |
| group.position.set(x, 0, z); | |
| scene.add(group); | |
| } | |
| function createBush(x, z) { | |
| const group = new THREE.Group(); | |
| const bushMat = new THREE.MeshStandardMaterial({ color: 0x4F6F52 }); | |
| const bushGeo = new THREE.SphereGeometry(0.8, 12, 12); | |
| const bush = new THREE.Mesh(bushGeo, bushMat); | |
| bush.position.y = 0.4; | |
| bush.castShadow = true; | |
| group.add(bush); | |
| // Berries/Roses | |
| const berryGeo = new THREE.SphereGeometry(0.15, 8, 8); | |
| const berryMat = new THREE.MeshStandardMaterial({ color: 0xE5989B }); | |
| for(let i=0; i<8; i++) { | |
| const berry = new THREE.Mesh(berryGeo, berryMat); | |
| const angle = Math.random() * Math.PI * 2; | |
| const r = 0.7; | |
| berry.position.set(Math.cos(angle)*r, 0.5 + Math.random()*0.5, Math.sin(angle)*r); | |
| group.add(berry); | |
| } | |
| group.position.set(x, 0, z); | |
| scene.add(group); | |
| } | |
| // --- POPULATE SCENE --- | |
| createTree(-3, -2); | |
| createTree(4, 3); | |
| for(let i=0; i<10; i++) { | |
| const angle = Math.random() * Math.PI * 2; | |
| const r = 3 + Math.random() * 3; | |
| createBush(Math.cos(angle)*r, Math.sin(angle)*r); | |
| } | |
| // --- ANIMATION RECTIVITY --- | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| // Subtle breathing effect for foliage | |
| scene.traverse((object) => { | |
| if (object.isMesh && object.geometry.type === 'SphereGeometry' && object.position.y > 1) { | |
| object.scale.x += Math.sin(Date.now() * 0.002) * 0.0001; | |
| object.scale.y += Math.sin(Date.now() * 0.002) * 0.0001; | |
| } | |
| }); | |
| controls.update(); | |
| renderer.render(scene, camera); | |
| } | |
| window.addEventListener('resize', () => { | |
| camera.aspect = window.innerWidth / window.innerHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| }); | |
| animate(); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment