Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>3D Cube with Sun Flare</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <style> | |
| .hidden { display: none; } | |
| </style> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/objects/Lensflare.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/GLTFLoader.min.js"></script> | |
| <style> | |
| body { | |
| margin: 0; | |
| overflow: hidden; | |
| font-family: 'Inter', sans-serif; | |
| } | |
| canvas { | |
| display: block; | |
| } | |
| #info { | |
| position: absolute; | |
| bottom: 20px; | |
| width: 100%; | |
| text-align: center; | |
| color: white; | |
| background-color: rgba(0,0,0,0.5); | |
| padding: 10px; | |
| border-radius: 8px; | |
| max-width: 500px; | |
| margin: 0 auto; | |
| left: 0; | |
| right: 0; | |
| } | |
| #loading { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: rgba(0,0,0,0.8); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| color: white; | |
| font-size: 24px; | |
| z-index: 1000; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900"> | |
| <div id="loading">Loading 3D scene...</div> | |
| <div id="info" class="hidden"> | |
| <p>Click and drag to rotate view</p> | |
| <p>Scroll to zoom in/out</p> | |
| </div> | |
| <div id="editor" class="fixed top-4 right-4 bg-gray-800 bg-opacity-90 p-4 rounded-lg text-white w-64"> | |
| <h2 class="text-xl font-bold mb-4">Scene Editor</h2> | |
| <div class="mb-4"> | |
| <label class="block mb-2">Background Color</label> | |
| <input type="color" id="bgColor" value="#87CEEB" class="w-full"> | |
| </div> | |
| <div class="mb-4"> | |
| <label class="block mb-2">Model Rotation Speed</label> | |
| <input type="range" id="rotationSpeed" min="0" max="0.1" step="0.001" value="0.005" class="w-full"> | |
| </div> | |
| <div class="mb-4"> | |
| <label class="block mb-2">Sun Intensity</label> | |
| <input type="range" id="sunIntensity" min="0" max="3" step="0.1" value="1.5" class="w-full"> | |
| </div> | |
| <div class="mb-4"> | |
| <label class="block mb-2">Ambient Light</label> | |
| <input type="range" id="ambientIntensity" min="0" max="2" step="0.1" value="0.8" class="w-full"> | |
| </div> | |
| <button id="randomize" class="bg-blue-600 hover:bg-blue-700 px-4 py-2 rounded w-full">Randomize</button> | |
| </div> | |
| <script> | |
| // Wait for everything to load | |
| window.addEventListener('load', init); | |
| // Global variables for editor | |
| let model, scene, sunLight, ambientLight; | |
| let rotationSpeed = 0.005; | |
| function init() { | |
| // Hide loading screen | |
| document.getElementById('loading').style.display = 'none'; | |
| document.getElementById('info').classList.remove('hidden'); | |
| // Scene setup | |
| const scene = new THREE.Scene(); | |
| scene.background = new THREE.Color(0x87CEEB); // Sky blue skybox | |
| scene.fog = new THREE.FogExp2(0x87CEEB, 0.005); // Less dense fog | |
| // Camera setup | |
| const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
| camera.position.set(5, 5, 5); | |
| // Renderer setup | |
| const renderer = new THREE.WebGLRenderer({ | |
| antialias: true, | |
| powerPreference: "high-performance" | |
| }); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| renderer.shadowMap.enabled = true; | |
| renderer.shadowMap.type = THREE.PCFSoftShadowMap; | |
| renderer.outputEncoding = THREE.sRGBEncoding; | |
| renderer.toneMapping = THREE.ACESFilmicToneMapping; | |
| renderer.toneMappingExposure = 1.0; | |
| renderer.physicallyCorrectLights = true; | |
| document.body.appendChild(renderer.domElement); | |
| // Controls | |
| const controls = new THREE.OrbitControls(camera, renderer.domElement); | |
| controls.enableDamping = true; | |
| controls.dampingFactor = 0.05; | |
| // Available sample models from KhronosGroup/glTF-Sample-Models: | |
| // - Duck: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Duck/glTF/Duck.gltf | |
| // - 2CylinderEngine: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/2CylinderEngine/glTF/2CylinderEngine.gltf | |
| // - Avocado: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Avocado/glTF/Avocado.gltf | |
| // - BarramundiFish: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BarramundiFish/glTF/BarramundiFish.gltf | |
| // - BrainStem: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BrainStem/glTF/BrainStem.gltf | |
| // - Buggy: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Buggy/glTF/Buggy.gltf | |
| // - CesiumMan: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMan/glTF/CesiumMan.gltf | |
| // - Corset: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Corset/glTF/Corset.gltf | |
| // - FlightHelmet: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/FlightHelmet/glTF/FlightHelmet.gltf | |
| // - Lantern: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Lantern/glTF/Lantern.gltf | |
| // - MosquitoInAmber: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/MosquitoInAmber/glTF/MosquitoInAmber.gltf | |
| // - WaterBottle: https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/WaterBottle/glTF/WaterBottle.gltf | |
| const loader = new THREE.GLTFLoader(); | |
| loader.load( | |
| 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Avocado/glTF/Avocado.gltf', | |
| (gltf) => { | |
| const model = gltf.scene; | |
| model.scale.set(0.5, 0.5, 0.5); | |
| model.position.set(0, 0, 0); | |
| model.rotation.y = Math.PI; | |
| model.traverse((child) => { | |
| if (child.isMesh) { | |
| child.castShadow = true; | |
| child.receiveShadow = true; | |
| } | |
| }); | |
| scene.add(model); | |
| // Animation loop | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| // Rotate model slightly | |
| model.rotation.y += rotationSpeed; | |
| // Update controls | |
| controls.update(); | |
| // Render | |
| renderer.render(scene, camera); | |
| } | |
| animate(); | |
| }, | |
| undefined, | |
| (error) => { | |
| console.error('Error loading model:', error); | |
| // Fallback to simple geometry if model fails | |
| const geometry = new THREE.ConeGeometry(1, 2, 4); | |
| const material = new THREE.MeshStandardMaterial({ color: 0x00ffff }); | |
| const cone = new THREE.Mesh(geometry, material); | |
| scene.add(cone); | |
| } | |
| ); | |
| // Ambient light matching skybox | |
| const ambientLight = new THREE.AmbientLight(0xffffff, 0.8); | |
| scene.add(ambientLight); | |
| // Sun light (directional) | |
| const sunLight = new THREE.DirectionalLight(0xffffcc, 1.5); | |
| sunLight.position.set(10, 15, 10); | |
| sunLight.castShadow = true; | |
| sunLight.shadow.mapSize.width = 4096; | |
| sunLight.shadow.mapSize.height = 4096; | |
| sunLight.shadow.camera.near = 0.5; | |
| sunLight.shadow.camera.far = 50; | |
| sunLight.shadow.camera.left = -15; | |
| sunLight.shadow.camera.right = 15; | |
| sunLight.shadow.camera.top = 15; | |
| sunLight.shadow.camera.bottom = -15; | |
| sunLight.shadow.bias = -0.0001; | |
| scene.add(sunLight); | |
| // Fill light | |
| const fillLight = new THREE.DirectionalLight(0xccffff, 0.5); | |
| fillLight.position.set(-10, 10, -10); | |
| scene.add(fillLight); | |
| // Back light | |
| const backLight = new THREE.DirectionalLight(0xffffff, 0.3); | |
| backLight.position.set(0, 5, -15); | |
| scene.add(backLight); | |
| // Lens flare effect | |
| const textureLoader = new THREE.TextureLoader(); | |
| const textureFlare0 = textureLoader.load('https://threejs.org/examples/textures/lensflare/lensflare0.png'); | |
| const textureFlare3 = textureLoader.load('https://threejs.org/examples/textures/lensflare/lensflare3.png'); | |
| const lensflare = new THREE.Lensflare(); | |
| lensflare.addElement(new THREE.LensflareElement(textureFlare0, 700, 0, sunLight.color)); | |
| lensflare.addElement(new THREE.LensflareElement(textureFlare3, 60, 0.6)); | |
| lensflare.addElement(new THREE.LensflareElement(textureFlare3, 70, 0.7)); | |
| lensflare.addElement(new THREE.LensflareElement(textureFlare3, 120, 0.9)); | |
| lensflare.addElement(new THREE.LensflareElement(textureFlare3, 70, 1)); | |
| sunLight.add(lensflare); | |
| // Window resize handler | |
| window.addEventListener('resize', () => { | |
| camera.aspect = window.innerWidth / window.innerHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| }); | |
| // Editor controls | |
| document.getElementById('bgColor').addEventListener('input', (e) => { | |
| scene.background = new THREE.Color(e.target.value); | |
| }); | |
| document.getElementById('rotationSpeed').addEventListener('input', (e) => { | |
| rotationSpeed = parseFloat(e.target.value); | |
| }); | |
| document.getElementById('sunIntensity').addEventListener('input', (e) => { | |
| sunLight.intensity = parseFloat(e.target.value); | |
| }); | |
| document.getElementById('ambientIntensity').addEventListener('input', (e) => { | |
| ambientLight.intensity = parseFloat(e.target.value); | |
| }); | |
| document.getElementById('randomize').addEventListener('click', () => { | |
| // Random colors | |
| scene.background = new THREE.Color(Math.random() * 0xffffff); | |
| sunLight.color.setHSL(Math.random(), 0.7, 0.5); | |
| ambientLight.color.setHSL(Math.random(), 0.2, 0.8); | |
| // Random rotation speed | |
| rotationSpeed = Math.random() * 0.1; | |
| document.getElementById('rotationSpeed').value = rotationSpeed; | |
| // Random intensities | |
| sunLight.intensity = Math.random() * 3; | |
| ambientLight.intensity = Math.random() * 2; | |
| document.getElementById('sunIntensity').value = sunLight.intensity; | |
| document.getElementById('ambientIntensity').value = ambientLight.intensity; | |
| }); | |
| } | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=iCoderX/webgame-engine" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |