仓库地址

laddish/threejs-build-earth
https://gitee.com/laddish/threejs-build-earth

预览地址

https://static-c4ab0b87-5a60-4e43-9cfc-1979c6de3ecd.bspapp.com/

效果图

鼠标可以控制地球
地球, 云层和背景星系都会移动
左上角显示渲染的帧数图片.png

主要思路

没什么难点, 最难的估计就是地球的贴图和云层贴图 背景贴图///笑死
地球云层星系都是创建了一个球体 然后引入材质贴图

主要代码

threejs中的几个重要的部分

scene 场景

camera 相机

light 光线

renderer 渲染器

缺一不可

注释写的很清楚 每一步干啥写的都很清楚

  1. import "./style.css";
  2. import * as THREE from "three";
  3. //引入轨道控制
  4. import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
  5. import Stats from "three/examples/jsm/libs/stats.module";
  6. import * as dat from "dat.gui";
  7. const stats = Stats();
  8. document.body.appendChild(stats.dom)
  9. // Debug
  10. const gui = new dat.GUI();
  11. // 加载材质
  12. const loader = new THREE.TextureLoader();
  13. //加载earth贴图 放置在static目录下
  14. const texture = loader.load("texture/earthmap1k.jpg");
  15. //加载肿块
  16. const bumpMap = loader.load("texture/earthbump.jpg");
  17. // 加载云朵材质
  18. const cloudMap = loader.load("texture/earthCloud.png");
  19. // 加载星星材质
  20. const starMap = loader.load("texture/galaxy.png");
  21. // Canvas 至少需要 场景 渲染器 和 照相机 缺一不可
  22. // canvas 元素 是渲染器的渲染范围
  23. const canvas = document.querySelector("canvas.webgl");
  24. // Scene 场景
  25. const scene = new THREE.Scene();
  26. // Objects 创建几何球体 半径范围 宽度 高度
  27. const geometry = new THREE.SphereBufferGeometry(0.7, 32, 32);
  28. // Materials 创建材料
  29. const material = new THREE.MeshPhongMaterial({
  30. roughness: 1, //粗糙度
  31. metalness: 0,
  32. // 也可以使用
  33. // map:THREE.ImageUtils.loadTexture(),
  34. map: texture,
  35. bumpMap,
  36. bumpScale: 1,
  37. });
  38. //设置材料的颜色
  39. // material.color = new THREE.Color(0x00ff00);
  40. // Mesh 创建网孔球体
  41. const sphere = new THREE.Mesh(geometry, material);
  42. //把球体添加到场景中
  43. scene.add(sphere);
  44. //创建云朵球体 更大点
  45. const cloudGeometry = new THREE.SphereBufferGeometry(0.75, 32, 32);
  46. // Materials 创建材料
  47. const cloudMaterial = new THREE.MeshPhongMaterial({
  48. map: cloudMap,
  49. transparent:true, //设置为透明
  50. });
  51. // Mesh 创建网孔球体
  52. const cloudMesh = new THREE.Mesh(cloudGeometry, cloudMaterial);
  53. //把球体添加到场景中
  54. scene.add(cloudMesh);
  55. //创建星星球体 更大点 可能超出视野
  56. const starGeometry = new THREE.SphereBufferGeometry(80, 64, 64);
  57. // Materials 创建基础材料 没有光线
  58. const starMaterial = new THREE.MeshBasicMaterial({
  59. map: starMap,
  60. transparent:true, //设置为透明
  61. side: THREE.BackSide
  62. });
  63. // Mesh 创建网孔球体
  64. const starMesh = new THREE.Mesh(starGeometry, starMaterial);
  65. //把球体添加到场景中
  66. scene.add(starMesh);
  67. // Lights 光线 需要光线才能看到
  68. //创建环境光
  69. const ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
  70. //创建点光源
  71. const pointLight = new THREE.PointLight(0xffffff, 1);
  72. // 点光源必须要设置放置位置
  73. pointLight.position.x = 2;
  74. pointLight.position.y = 3;
  75. pointLight.position.z = 4;
  76. //为场景添加光线
  77. scene.add(ambientLight);
  78. scene.add(pointLight);
  79. /**
  80. * Sizes
  81. */
  82. const sizes = {
  83. width: window.innerWidth,
  84. height: window.innerHeight,
  85. };
  86. //监听window的resize事件
  87. //更新camera的长宽比
  88. //更新renderer的大小
  89. window.addEventListener("resize", () => {
  90. // Update sizes
  91. sizes.width = window.innerWidth;
  92. sizes.height = window.innerHeight;
  93. // Update camera
  94. camera.aspect = sizes.width / sizes.height;
  95. camera.updateProjectionMatrix();
  96. // Update renderer
  97. renderer.setSize(sizes.width, sizes.height);
  98. renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  99. });
  100. /**
  101. * Camera 照相机 创建透视摄影
  102. * fov 你想要看到的视角有多大多宽 一般为60
  103. * aspect 这个场景的长宽比
  104. * near 0.1
  105. * far 1000
  106. */
  107. // Base camera
  108. const camera = new THREE.PerspectiveCamera(
  109. 75,
  110. sizes.width / sizes.height,
  111. 0.1,
  112. 100
  113. );
  114. // position 照相机的放置位置
  115. camera.position.x = 0;
  116. camera.position.y = 0;
  117. camera.position.z = 2;
  118. scene.add(camera);
  119. // Controls 创建轨道控制器 接收参数 为相机 和 canvas元素
  120. const controls = new OrbitControls(camera, canvas);
  121. controls.enableDamping = true;
  122. /**
  123. * Renderer 渲染器
  124. */
  125. const renderer = new THREE.WebGLRenderer({
  126. canvas: canvas,
  127. antialias: true, //开启抗锯齿(antialiased)渲染
  128. });
  129. //设置渲染器的大小
  130. renderer.setSize(sizes.width, sizes.height);
  131. //设置渲染器的像素值
  132. renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  133. //渲染前自动清理
  134. renderer.autoClear = false;
  135. //设置清理颜色
  136. renderer.setClearColor(0x000000, 0);
  137. /**
  138. * Animate
  139. */
  140. const clock = new THREE.Clock();
  141. const tick = () => {
  142. const elapsedTime = clock.getElapsedTime();
  143. // Update objects 旋转球体的y轴
  144. sphere.rotation.y = -0.11 * elapsedTime;
  145. cloudMesh.rotation.y = -0.061 * elapsedTime;
  146. starMesh.rotation.y = -0.18 * elapsedTime;
  147. cloudMesh.rotation.x = -0.061 * elapsedTime;
  148. starMesh.rotation.x = -0.18 * elapsedTime;
  149. cloudMesh.rotation.z = -0.051 * elapsedTime;
  150. starMesh.rotation.z = -0.18 * elapsedTime;
  151. // Update Orbital Controls 更新轨道控制器 可以使用鼠标控制
  152. controls.update();
  153. // Render 渲染要在最后才能渲染
  154. renderer.render(scene, camera);
  155. stats.update()
  156. // Call tick again on the next frame
  157. window.requestAnimationFrame(tick);
  158. };
  159. tick();

克隆

  1. yarn add
  2. yarn dev