如何使用Three.js制作3D月球与星空效果

目录

  • [1. 基本设置](#1. 基本设置)
  • [2. 创建星空效果](#2. 创建星空效果)
  • [3. 创建月球模型](#3. 创建月球模型)
  • [4. 添加中文3D文字](#4. 添加中文3D文字)
  • [5. 光照与相机配置](#5. 光照与相机配置)
  • [6. 动画与控制](#6. 动画与控制)
  • [7. 响应式布局](#7. 响应式布局)
  • [8. 结语](#8. 结语)

在本文中,我们将一起学习如何利用Three.js实现一个3D月球与星空的效果,并添加一些有趣的元素,比如中文3D文字和互动功能。Three.js是一个强大的JavaScript库,它简化了WebGL的使用,使得在网页上进行3D图形渲染变得更加容易。我们将逐步分析代码,帮助大家理解实现原理。

实现效果展示:

1. 基本设置

首先,我们需要引入Three.js的核心库及相关组件:

javascript 复制代码
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/loaders/FontLoader.js"></script>

这三行代码分别引入了Three.js核心库、OrbitControls(用于控制相机旋转)和FontLoader(用于加载字体)。

接下来,我们初始化一个Three.js场景、相机和渲染器:

javascript 复制代码
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

scene:场景对象,所有的3D物体都会添加到这个场景中。

camera:透视相机,用来观察场景。

renderer:WebGL渲染器,用来将场景渲染到网页上。

2. 创建星空效果

我们使用BufferGeometry和PointsMaterial来创建一个星空背景,利用随机生成的点来模拟远处的星星:

javascript 复制代码
function createStarField() {
    const starsGeometry = new THREE.BufferGeometry();
    const starCount = 5000;
    const positions = new Float32Array(starCount * 3);
    
    for(let i = 0; i < starCount * 3; i += 3) {
        positions[i] = (Math.random() - 0.5) * 2000; // X
        positions[i+1] = (Math.random() - 0.5) * 2000; // Y
        positions[i+2] = (Math.random() - 0.5) * 2000; // Z
    }
    
    starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    
    const starsMaterial = new THREE.PointsMaterial({
        color: 0xFFFFFF,
        size: 1.2,
        transparent: true,
        opacity: 0.8,
        sizeAttenuation: true,
        alphaTest: 0.5,
        map: createCircleTexture()
    });
    
    const starField = new THREE.Points(starsGeometry, starsMaterial);
    scene.add(starField);
}
createStarField();

BufferGeometry:用于高效地存储大量的点数据。

PointsMaterial:点的材质,通过设置透明度和大小来实现星星的效果。

createCircleTexture():创建一个简单的白色圆形纹理,用来表示星星。

3. 创建月球模型

为了让效果更加真实,我们还加载了月球的纹理,并将其应用到一个3D球体上,形成真实感的月球:

javascript 复制代码
const textureLoader = new THREE.TextureLoader();
const moonTexture = textureLoader.load('https://threejs.org/examples/textures/planets/moon_1024.jpg');
const moonGeometry = new THREE.SphereGeometry(2, 64, 64);
const moonMaterial = new THREE.MeshStandardMaterial({
    map: moonTexture,
    roughness: 0.8,
    metalness: 0.2
});
const moon = new THREE.Mesh(moonGeometry, moonMaterial);
scene.add(moon);

TextureLoader:加载月球的纹理图。

SphereGeometry:创建一个球形几何体,用作月球的基础模型。

MeshStandardMaterial:创建一个标准材质,提供更真实的光照效果。

4. 添加中文3D文字

通过FontLoader,我们可以加载中文字体并创建3D文字:

javascript 复制代码
const fontLoader = new THREE.FontLoader();
fontLoader.load('gongfannufangti_Regular.json', function(font) {
    const textGeometry = new THREE.TextGeometry('海上明月共潮生', {
        font: font,
        size: 0.8,
        height: 0.2,
        curveSegments: 12,
        bevelEnabled: true,
        bevelThickness: 0.03,
        bevelSize: 0.02,
        bevelOffset: 0,
        bevelSegments: 5
    });

    textGeometry.computeBoundingBox();
    const textWidth = textGeometry.boundingBox.max.x - textGeometry.boundingBox.min.x;

    const textMaterial = new THREE.MeshPhongMaterial({
        color: 0xfffff0,
        specular: 0x111111,
        shininess: 100
    });

    const textMesh = new THREE.Mesh(textGeometry, textMaterial);
    textMesh.position.set(-textWidth / 2, 3, 0);
    scene.add(textMesh);
}, undefined, function(err) {
    console.error('在线字体加载失败,请尝试备用方案');
});

5. 光照与相机配置

为了让场景更具真实感,我们添加了环境光和定向光照:

javascript 复制代码
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);

AmbientLight:提供均匀的全局光照,不会投射阴影。

DirectionalLight:模拟太阳光的定向光照,能投射阴影并增强场景的光照效果。

6. 动画与控制

通过OrbitControls,我们可以实现相机的旋转和平移功能,使得用户可以自由探索这个3D场景:

javascript 复制代码
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;

autoRotate功能允许场景自动旋转,提升交互体验。

7. 响应式布局

为了让网页在不同设备上适配,我们添加了窗口大小变化时的适应性调整:

javascript 复制代码
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});

这样,无论是手机还是电脑,都能获得最佳的显示效果。

8. 结语

通过本文的介绍,我们成功地使用Three.js创建了一个3D月球与星空的效果,并结合了中文3D文字和相机控制等互动功能。你可以根据自己的需求进一步扩展和修改这个项目,比如添加更多星体、调整光照效果、使用自定义的字体等。任何问题欢迎在评论区交流和分享。完整源码在同名知识星球可下载。

相关推荐
candyTong1 天前
一觉醒来,大模型就帮我排查完页面性能问题
前端·javascript·架构
玩嵌入式的菜鸡1 天前
网页访问单片机设备---基于mqtt
前端·javascript·css
前端一小卒1 天前
我用 Claude Code 的 Superpowers 技能链写了个服务,部署前差点把服务器搞炸
前端·javascript·后端
Dxy12393102161 天前
HTML中的Canvas入门:从零开始绘制图形世界
html
滑雪的企鹅.1 天前
HTML头部元信息避坑指南大纲
前端·html
浔川python社1 天前
HTML头部元信息避坑指南技术文章大纲
前端·html
豹哥学前端1 天前
用猜数字游戏,一口气掌握 JavaScript 核心知识点(附完整代码)
前端·javascript
忆往wu前1 天前
从0到1一步步拆解搭建,梳理一个 Vue3 简易图书后台全开发流程
前端·javascript·vue.js
shao9185161 天前
第3章(2)——使用Gradio JavaScript Client
javascript·node.js·cdn·gradio·job·events·playcode
光影少年1 天前
大屏页面,一次多个请求,请求加密导致 点击 全局时间选择器 时出现卡顿咋解决(面板收起会延迟1~2秒)
前端·javascript·vue.js·学习·前端框架·echarts·reactjs