3D地球可视化教程 - 第1篇:基础地球渲染系统

发布于:2025-09-09 ⋅ 阅读:(17) ⋅ 点赞:(0)

最终效果:
动图只能限制5m以内,所以画质相当低

在这里动图只能限制5m以内,所以画质相当低插入图片描述
本节完成后的效果:
在这里插入图片描述

难度: ⭐⭐☆☆☆ 初级
预计时间: 30分钟
技术栈: Vue3 + Vite + Three.js

📖 教程简介

欢迎来到3D地球可视化的完整教程系列!在这个系列中,我们将从零开始,一步步构建一个专业级的3D地球项目。本篇是系列的第一篇,我们将学习如何创建一个基础但完整的3D地球渲染系统。

🎯 本篇学习目标

  • 理解Three.js的核心概念和渲染管道
  • 掌握3D场景的基础搭建方法
  • 学会创建真实感地球渲染效果
  • 实现基础的相机控制和交互

🏆 最终效果预览

完成本篇教程后,你将获得:

  • ✅ 一个可交互的3D地球
  • ✅ 真实的地球纹理效果
  • ✅ 专业的光照系统
  • ✅ 流畅的鼠标控制

🧠 理论基础

Three.js核心概念

在开始编码之前,我们需要理解Three.js的几个核心概念:

1. 渲染三要素
// Three.js的渲染三要素
const scene = new THREE.Scene();        // 场景 - 3D世界的容器
const camera = new THREE.Camera();      // 相机 - 观察3D世界的视角  
const renderer = new THREE.Renderer();  // 渲染器 - 将3D场景绘制到屏幕
2. 物体构成
// 3D物体 = 几何体 + 材质
const geometry = new THREE.SphereGeometry(); // 几何体 - 物体的形状
const material = new THREE.Material();       // 材质 - 物体的外观
const mesh = new THREE.Mesh(geometry, material); // 网格 - 最终的3D物体
3. 地球渲染原理
  • 使用 SphereGeometry 创建球体几何
  • 通过 MeshPhongMaterial 实现光照效果
  • 加载真实的地球纹理贴图
  • 配置光源系统营造真实感

🛠️ 项目架构设计

目录结构规划

src/
├── components/
│   └── three/
│       ├── models/
│       │   ├── EarthDay/        # 地球白天渲染
│       │   ├── Lights/          # 光照系统
│       │   └── Scene/           # 场景管理
│       └── utils/
│           └── EarthController/ # 地球控制器
├── constants/
│   └── index.js                 # 常量配置
└── assets/
    └── textures/               # 纹理资源

核心类设计

  1. Scene - 场景管理器(单例模式)
  2. EarthDay - 地球渲染器
  3. Lights - 光照系统
  4. EarthController - 交互控制器

🎨 Step 1: 地球几何体创建

1.1 球体几何体

地球的形状使用Three.js的球体几何体:

// src/components/three/models/EarthDay/EarthDay.js
createGeometry() {
  // 创建球体几何体
  this.geometry = new THREE.SphereGeometry(
    EARTH_RADIUS,      // 半径: 10
    EARTH_FRAGMENTS,   // 宽度分段: 64 
    EARTH_FRAGMENTS    // 高度分段: 64
  );
}

参数解释:

  • radius: 球体半径,决定地球大小
  • widthSegments: 水平方向分段数,影响球体圆滑度
  • heightSegments: 垂直方向分段数,影响球体圆滑度

💡 技巧: 分段数越高球体越圆滑,但性能消耗也越大。64是一个平衡点。

1.2 材质系统

使用Phong材质实现真实的光照效果:

createMaterial() {
  this.material = new THREE.MeshPhongMaterial({
    // 🎨 纹理贴图
    map: this.textures.day,           // 地球表面颜色贴图
    bumpMap: this.textures.bump,      // 凹凸贴图(山脉、海沟)
    specularMap: this.textures.specular, // 镜面反射贴图(海洋反光)

    // 🎭 基础属性  
    color: new THREE.Color("#ffffff"),
    opacity: 1.0,
    transparent: true,

    // ✨ Phong光照属性
    emissive: new THREE.Color("#000000"),    // 自发光颜色
    emissiveIntensity: 0.0,                  // 自发光强度
    specular: new THREE.Color("#111111"),    // 镜面反射颜色
    shininess: 30,                           // 光泽度
    bumpScale: 12.4,                         // 凹凸强度
  });
}

材质属性详解:

  • map: 主纹理,决定地球表面的颜色
  • bumpMap: 凹凸贴图,模拟地形高低起伏
  • specularMap: 镜面贴图,控制海洋的反光效果
  • shininess: 光泽度,数值越高反光越强

💡 Step 2: 光照系统设计

2.1 光源类型分析

我们的地球使用了多种光源组合:

// src/components/three/models/Lights/Lights.js
class Lights {
  constructor(parentContainer, camera, controls, options) {
    // 🌞 方向光 - 模拟太阳光
    this.directionalLight = new THREE.DirectionalLight(
      "#ffffff",  // 白色光
      5.1         // 强度
    );
    
    // 🌙 环境光 - 模拟天空散射光
    this.ambientLight = new THREE.AmbientLight(
      "#ffffff",  // 白色光
      2.45        // 强度
    );
    
    // 🔆 点光源 - 模拟城市灯光
    this.pointLight = new THREE.PointLight(
      "#ff6600",  // 橙色光
      2.0,        // 强度
      500,        // 照射距离
      0           // 衰减系数
    );
  }
}

2.2 光照效果原理

方向光 (DirectionalLight):

  • 模拟太阳光,平行光线
  • 产生明确的明暗对比
  • 支持阴影投射

环境光 (AmbientLight):

  • 模拟天空散射光
  • 均匀照亮所有物体
  • 避免过暗的阴影区域

点光源 (PointLight):

  • 模拟城市灯光效果
  • 从一个点向四周发散
  • 可设置衰减距离

🎬 Step 3: 场景管理系统

3.1 单例模式设计

场景管理器使用单例模式,确保全局唯一:

// src/components/three/models/Scene/Scene.js
class Scene {
  static instance = null;

  constructor(container, options) {
    // 防止多实例
    if (Scene.instance) {
      return Scene.instance;
    }
    
    Scene.instance = this;
    this.init();
  }

  static getInstance() {
    return Scene.instance;
  }
}

3.2 组件组织结构

使用分组管理不同类型的组件:

init() {
  // 🌍 地球主组
  this.earthGroup = new THREE.Group();
  
  // 💡 灯光子组 (固定位置,不随地球旋转)
  this.lightsGroup = new THREE.Group();
  this.earthGroup.add(this.lightsGroup);
  
  // 🌐 元素子组 (跟随地球旋转)
  this.elementsGroup = new THREE.Group();
  this.earthGroup.add(this.elementsGroup);
  
  this.scene.add(this.earthGroup);
}

🎮 Step 4: 交互控制系统

4.1 自定义控制器

项目使用自定义的地球控制器替代标准的OrbitControls:

// src/components/three/utils/EarthMouseController.js
class EarthMouseController {
  constructor(camera, renderer, earthGroup, elementsGroup, scene) {
    this.camera = camera;
    this.renderer = renderer;
    this.earthGroup = earthGroup;        // 整个地球组
    this.elementsGroup = elementsGroup;  // 只旋转元素组
    
    this.setupEventListeners();
  }

  setupEventListeners() {
    // 鼠标事件监听
    this.renderer.domElement.addEventListener('mousedown', this.onMouseDown);
    this.renderer.domElement.addEventListener('mousemove', this.onMouseMove);
    this.renderer.domElement.addEventListener('mouseup', this.onMouseUp);
    this.renderer.domElement.addEventListener('wheel', this.onWheel);
  }
}

4.2 旋转逻辑分离

设计亮点: 灯光固定,只旋转地球元素

onMouseMove(event) {
  if (this.isMouseDown) {
    const deltaX = event.clientX - this.mouse.x;
    const deltaY = event.clientY - this.mouse.y;
    
    // 🌍 只旋转元素组,灯光保持固定
    this.elementsGroup.rotation.y += deltaX * 0.005;
    this.elementsGroup.rotation.x += deltaY * 0.005;
    
    // 💡 灯光组不旋转,保持照射方向
  }
}

🖼️ Step 5: 纹理系统实现

5.1 纹理加载策略

async loadTextures() {
  const textureLoader = new THREE.TextureLoader();
  
  // 并行加载多张纹理
  const [dayTexture, bumpTexture, specularTexture] = await Promise.all([
    this.loadTexture(textureLoader, './textures/earth-day.jpg'),
    this.loadTexture(textureLoader, './textures/earth-bump.jpg'),
    this.loadTexture(textureLoader, './textures/earth-specular.jpg'),
  ]);

  // 设置纹理属性
  dayTexture.colorSpace = THREE.SRGBColorSpace;     // 颜色空间
  dayTexture.anisotropy = renderer.capabilities.getMaxAnisotropy(); // 各向异性过滤
}

5.2 纹理类型说明

  • Day Texture: 地球表面的彩色贴图
  • Bump Map: 黑白高度图,模拟地形起伏
  • Specular Map: 控制反光强度,海洋更亮,陆地更暗

🎯 Step 6: 完整实现代码

6.1 主要的实现要点

让我们看看当前的核心实现:

  1. 地球几何体创建
  2. Phong材质配置
  3. 多光源照明
  4. 纹理系统
  5. 交互控制

🎯 关键参数配置

// src/constants/index.js
export const EARTH_RADIUS = 20;        // 地球半径
export const EARTH_FRAGMENTS = 64;     // 球体分段数
export const AUTO_ROTATE_SPEED = 0.03; // 自动旋转速度

// 纹理路径配置
export const PATHS = {
  earthMap: "./img/earth-day.jpg",      // 地球白天贴图
  bumpMap: "./img/bump-map.webp",       // 凹凸贴图
  specularMap: "./img/specular-map.webp", // 镜面贴图
};

🚀 运行和测试

启动项目

npm run dev

测试功能

在浏览器中你应该看到:

  • ✅ 一个完整的3D地球
  • ✅ 真实的地球纹理
  • ✅ 鼠标拖拽旋转功能
  • ✅ 滚轮缩放功能

📊 性能优化要点

1. 纹理优化

  • 使用WebP格式减少文件大小
  • 设置合适的anisotropy值
  • 启用纹理预加载

2. 几何体优化

  • 64分段是性能和质量的平衡点
  • 避免过高的分段数
  • 复用几何体实例

✅ 已掌握的技能:

  1. Three.js基础概念
  2. 地球几何体创建
  3. Phong材质系统
  4. 多光源照明
  5. 纹理贴图系统
  6. 交互控制系统

🎯 下一篇预告

第2篇:夜晚纹理与昼夜过渡效果



网站公告

今日签到

点亮在社区的每一天
去签到