讨论

使用Three.js实现逼真的3D地球模拟

来自 Wikiprompt,自由的提示词百科全书

Paul Couvert

2025年7月10日

使用Three.js实现逼真的3D地球模拟 一个用于生成交互式3D地球模拟的详细提示,包含昼夜纹理、云层、星空和轨道控制,全部集成在单个HTML文件中。

提示词内容收藏

🌐
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Earth - Photorealistic 3D Simulation</title> <style> body { margin: 0; overflow: hidden; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } #info { position: absolute; top: 20px; left: 20px; color: white; background: rgba(0,0,0,0.6); padding: 10px 18px; border-radius: 30px; pointer-events: none; font-size: 14px; letter-spacing: 1px; backdrop-filter: blur(4px); border: 1px solid rgba(255,255,255,0.2); z-index: 100; } #controls-hint { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,0.7); background: rgba(0,0,0,0.4); padding: 8px 16px; border-radius: 20px; font-size: 13px; backdrop-filter: blur(4px); border: 1px solid rgba(255,255,255,0.15); pointer-events: none; z-index: 100; } </style> </head> <body> <div id="info">🌍 EARTH · DAY/NIGHT · CLOUDS · STARS</div> <div id="controls-hint">🖱️ Drag to rotate · Scroll to zoom · Right-drag to pan</div> <!-- Three.js core and OrbitControls --> <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.js"></script> <script> (function() { // --- Initialize Scene, Camera, Renderer --- const scene = new THREE.Scene(); scene.background = new THREE.Color(0x050510); // deep space base const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.set(0, 0.5, 3.2); // slightly elevated for better view const renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: false }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // softer shadows renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.2; document.body.appendChild(renderer.domElement); // --- Controls --- const controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.rotateSpeed = 0.8; controls.zoomSpeed = 1.2; controls.panSpeed = 0.8; controls.minDistance = 1.5; controls.maxDistance = 8.0; controls.enablePan = true; controls.target.set(0, 0, 0); // --- Lighting --- // Ambient light to softly illuminate the dark side (prevents pure black) const ambientLight = new THREE.AmbientLight(0x404060); // subtle blue-ish scene.add(ambientLight); // Main directional light (sun) const sunLight = new THREE.DirectionalLight(0xfff5e6, 2.0); sunLight.position.set(5, 2, 5); // from a diagonal angle sunLight.castShadow = true; sunLight.receiveShadow = true; // Shadow settings for better quality sunLight.shadow.mapSize.width = 1024; sunLight.shadow.mapSize.height = 1024; const d = 3; sunLight.shadow.camera.left = -d; sunLight.shadow.camera.right = d; sunLight.shadow.camera.top = d; sunLight.shadow.camera.bottom = -d; sunLight.shadow.camera.near = 1; sunLight.shadow.camera.far = 10; sunLight.shadow.bias = -0.0005; scene.add(sunLight); // Optional fill light from opposite side to slightly reveal night side details const fillLight = new THREE.DirectionalLight(0x446688, 0.15); fillLight.position.set(-3, 0, -3); scene.add(fillLight); // --- Helper: Create Earth Group --- const earthGroup = new THREE.Group(); scene.add(earthGroup); // --- 1. Earth Sphere (Day/Night textures + specular) --- // Load textures using TextureLoader const loader = new THREE.TextureLoader(); // Use high-quality textures from Three.js examples repository (public domain / free) const dayTexture = loader.load('https://threejs.org/examples/textures/planets/earth_atmos_2048.jpg'); const nightTexture = loader.load('https://threejs.org/examples/textures/planets/earth_lights_2048.png'); const specularMap = loader.load('https://threejs.org/examples/textures/planets/earth_specular_2048.jpg'); const normalMap = loader.load('https://threejs.org/examples/textures/planets/earth_normal_2048.jpg'); const cloudTexture = loader.load('https://threejs.org/examples/textures/planets/earth_clouds_1024.png'); // Earth material with day/night blending via custom shader? // For simplicity and high quality, we use MeshPhongMaterial with emissive map for night lights. // But to get both day and night in one material, we can use a custom shader or use two meshes. // Better approach: Use a MeshPhongMaterial with emissiveMap for night lights, and map for day. // However, standard material doesn't blend day/night dynamically. // We'll create two overlapping spheres: one for day (lit) and one for night (emissive) with blending. // But to keep it clean and still show city lights on night side, we use a custom ShaderMaterial. // Given time, I'll implement a custom shader that blends day and night based on light direction. // This gives the most realistic effect. // --- Custom Shader Material for Earth (Day/Night/Specular) --- const earthVertexShader = ` varying vec3 vNormal; varying vec3 vWorldPosition; varying vec2 vUv; void main() { vUv = uv; vNormal = normalize(normalMatrix * normal); vec4 worldPosition = modelMatrix * vec4(position, 1.0); vWorldPosition = worldPosition.xyz; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const earthFragmentShader = ` uniform sampler2D dayMap; uniform sampler2D nightMap; uniform sampler2D specularMap; uniform sampler2D normalMap; // not used in shader but kept for completeness uniform vec3 sunDirection; // in world space uniform vec3 ambientColor; varying vec3 vNormal; varying vec3 vWorldPosition; varying vec2 vUv; void main() { vec3 normal = normalize(vNormal); vec3 lightDir = normalize(sunDirection); // Diffuse lighting factor (dot product) float diff = max(dot(normal, lightDir), 0.0); // Day color vec3 dayColor = texture2D(dayMap, vUv).rgb; // Night color (city lights) vec3 nightColor = texture2D(nightMap, vUv).rgb; // Specular map (ocean highlights) float specularIntensity = texture2D(specularMap, vUv).r; // Blinn-Phong specular highlight vec3 viewDir = normalize(cameraPosition - vWorldPosition); vec3 halfDir = normalize(lightDir + viewDir); float spec = pow(max(dot(normal, halfDir), 0.0), 32.0) * specularIntensity * 1.5; // Blend day and night: night shows when diff is low, but also add a small ambient float nightFactor = smoothstep(0.1, 0.35, 1.0 - diff); // night appears when diff < 0.3 // Add a bit of ambient to day side vec3 ambient = ambientColor * dayColor * 0.1; // Final color = day * diff + night * nightFactor + spec + ambient vec3 color = dayColor * diff + nightColor * nightFactor * 1.2 + vec3(spec) + ambient; // Tone mapping (simple Reinhard) for better dynamic range color = color / (color + vec3(1.0)); gl_FragColor = vec4(color, 1.0); } `; const earthMaterial = new THREE.ShaderMaterial({ uniforms: { dayMap: { value: dayTexture }, nightMap: { value: nightTexture }, specularMap: { value: specularMap }, normalMap: { value: normalMap }, sunDirection: { value: sunLight.position.clone().normalize() }, ambientColor: { value: new THREE.Color(0x202030) } }, vertexShader: earthVertexShader, fragmentShader: earthFragmentShader, lights: false, // we handle lighting manually shininess: 0 // not used }); // Create Earth mesh const earthGeometry = new THREE.SphereGeometry(1.0, 64, 64); const earthMesh = new THREE.Mesh(earthGeometry, earthMaterial); earthMesh.castShadow = true; earthMesh.receiveShadow = true; earthGroup.add(earthMesh); // --- 2. Cloud Layer (semi-transparent, rotating independently) --- const cloudMaterial = new THREE.MeshPhongMaterial({ map: cloudTexture, transparent: true, opacity: 0.45, depthWrite: false, blending: THREE.AdditiveBlending, // makes clouds glow slightly side: THREE.DoubleSide }); const cloudGeometry = new THREE.SphereGeometry(1.01, 64, 64); const cloudMesh = new THREE.Mesh(cloudGeometry, cloudMaterial); cloudMesh.castShadow = false; cloudMesh.receiveShadow = false; earthGroup.add(cloudMesh); // --- 3. Starfield Background (sphere with star texture) --- // Generate a star texture procedurally for high quality const starCanvas = document.createElement('canvas'); starCanvas.width = 1024; starCanvas.height = 1024; const ctx = starCanvas.getContext('2d'); ctx.fillStyle = '#050510'; ctx.fillRect(0, 0, 1024, 1024); // Draw random stars (white, some with slight blue/yellow tint) for (let i = 0; i < 4000; i++) { const x = Math.random() * 1024; const y = Math.random() * 1024; const size = Math.random() * 1.8 + 0.2; const brightness = Math.random() * 0.8 + 0.2; const color = `rgba(255, 255, 255, ${brightness})`; ctx.beginPath(); ctx.arc(x, y, size, 0, 2 * Math.PI); ctx.fillStyle = color; ctx.fill(); // occasional colored star if (Math.random() > 0.98) { ctx.beginPath(); ctx.arc(x, y, size * 1.5, 0, 2 * Math.PI); ctx.fillStyle = `rgba(180, 220, 255, ${brightness * 0.8})`; ctx.fill(); } } const starTexture = new THREE.CanvasTexture(starCanvas); starTexture.wrapS = THREE.RepeatWrapping; starTexture.wrapT = THREE.ClampToEdgeWrapping; const starMaterial = new THREE.MeshBasicMaterial({ map: starTexture, side: THREE.BackSide, transparent: false, depthWrite: false }); const starSphere = new THREE.Mesh(new THREE.SphereGeometry(20, 32, 32), starMaterial); scene.add(starSphere); // --- 4. Add a subtle glow effect (optional) via a point light? Not necessary. // --- Animation Loop --- let clock = new THREE.Clock(); function animate() { const delta = clock.getDelta(); const elapsedTime = performance.now() * 0.001; // seconds // Rotate Earth and clouds at different speeds earthMesh.rotation.y += 0.0008; // slow rotation cloudMesh.rotation.y += 0.0012; // clouds move faster // Update sun direction uniform (if light moves, but we keep it static) // For realism, we could rotate the light, but we keep it fixed. // Update controls controls.update(); // Render renderer.render(scene, camera); requestAnimationFrame(animate); } animate(); // --- Handle Window Resize --- window.addEventListener('resize', onWindowResize, false); function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } // --- Update sunDirection uniform if needed (not necessary for static light) --- // But we can update it in case we want to move light later. // For now, it's set. // --- Add a subtle rim light or atmosphere effect? // Could add a glow sphere, but not necessary for this demo. // --- Optional: Add a small sun sphere for visual reference (not needed) --- // --- Ensure textures are loaded and then update uniforms if needed --- // All textures are loaded via loader, but we can set the sun direction again after load. // Since we use the same direction, it's fine. // --- Add a very subtle specular highlight on the night side? Not needed. // --- Final touch: adjust renderer shadow settings --- renderer.shadowMap.type = THREE.PCFSoftShadowMap; // --- Log to console for confirmation --- console.log('Earth simulation started. Enjoy!'); })(); </script> </body> </html>

登录以查看完整提示词

继续使用:

登录即表示你同意我们的 使用条款 隐私政策

用法

此提示词专为 coding 设计。复制上方内容并粘贴到你常用的 AI 工具中。

为获得最佳效果,可将占位符(方括号或大写字母标示)替换为你的具体需求。

参考资料

分类:coding| twitter| three-js| webgl

讨论