Three.js--》实现3d地月模型展示

目录

项目搭建

初始化three.js基础代码

创建月球模型

添加地球模型

添加模型标签


今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。

项目搭建

本案例还是借助框架书写three项目,借用vite构建工具搭建vue项目,vite这个构建工具如果有不了解的朋友,可以参考我之前对其讲解的文章:vite脚手架的搭建与使用 。搭建完成之后,用编辑器打开该项目,在终端执行 npm i 安装一下依赖,安装完成之后终端在安装 npm i three 即可。





初始化three.js基础代码

three.js开启必须用到的基础代码如下:

导入three库

import * as THREE from 'three'

初始化场景

const scene = new THREE.Scene()

初始化相机

const camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,200)
camera.position.set(10,5,20)

初始化渲染器

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth,window.innerHeight)

监听屏幕大小的改变,修改渲染器的宽高和相机的比例

window.addEventListener("resize",()=>{ 
  renderer.setSize(window.innerWidth,window.innerHeight)
  camera.aspect = window.innerWidth/window.innerHeight
  camera.updateProjectionMatrix()
})

设置渲染函数

const render = () =>{ 
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}

进行挂载

onMounted(()=>{
  render()
})

ok,写完基础代码之后,接下来开始具体的Demo实操。

创建月球模型

首先这里通过直接给画布的canvas标签添加css样式,给其一个背景图片作为背景:

canvas{
  background-image: url('../../public/images/star.jpg');
  background-size: cover;
}

然后使用TextureLoader用于加载图片纹理的工具,将图片文件加载为 Three.js 中的纹理对象,并且可以将纹理应用到场景中的任何物体上,从而实现更加生动的渲染效果。

// 创建月球
const moonGeometry = new THREE.SphereGeometry(MOON_RADIUS,16,16)
const moonMaterial = new THREE.MeshPhongMaterial({
  map: textureLoader.load('/public/textures/planets/moon_1024.jpg')
})
const moon = new THREE.Mesh(moonGeometry, moonMaterial)
moon.receiveShadow = true
moon.castShadow = true;
scene.add(moon)

创建好模型之后给场景中添加光源:

// 创建添加聚光灯光源
const dirLight = new THREE.SpotLight(0xffffff)
dirLight.position.set(0,0,10)
dirLight.intensity = 1
dirLight.castShadow = true
scene.add(dirLight)
// 添加环境光
const aLight = new THREE.AmbientLight(0xffffff)
aLight.intensity = 0.03
scene.add(aLight)

在渲染函数中通过getElapsedTime方法计算动画经过的时间或者控制动画的播放速度,来动态改变月球位置,让其绕圆周开始运动。

let clock = new THREE.Clock();
// 设置渲染函数
const render = () =>{ 
  const elapsed = clock.getElapsedTime()
  // 月球旋转
  moon.position.set(Math.sin(elapsed)*5,0,Math.cos(elapsed)*5)
  renderer.render(scene,camera)
  requestAnimationFrame(render)
}

Three.js--》实现3d地月模型展示_第1张图片

添加地球模型

这里也采用TextureLoader用于加载图片纹理的工具,将图片文件加载为 Three.js 中的纹理对象,并且可以将纹理应用到场景中的任何物体上,从而实现更加生动的渲染效果。

// 创建地球
const earthGeometry = new THREE.SphereGeometry(EARTH_RADIUS,16,16)
const earthMaterial = new THREE.MeshPhongMaterial({
  map: textureLoader.load('/public/textures/planets/earth_atmos_2048.jpg'),
  specularMap: textureLoader.load('/public/textures/planets/earth_specular_2048.jpg'),
  normalMap: textureLoader.load('/public/textures/planets/earth_normal_2048.jpg'),
})
const earth = new THREE.Mesh(earthGeometry,earthMaterial)
earth.receiveShadow = true
earth.castShadow = true
scene.add(earth)

这里依然在render渲染函数处通过getElapsedTime方法计算动画经过的时间或者控制动画的播放速度,来动态改变地球自转速度,让自转运动。

let clock = new THREE.Clock();
let oldtime = 0
// 设置渲染函数
const render = () =>{ 
  const elapsed = clock.getElapsedTime()
  // 月球旋转
  moon.position.set(Math.sin(elapsed)*5,0,Math.cos(elapsed)*5)
  // 地球自转
  let axis = new THREE.Vector3(0,1,0)
  earth.rotateOnAxis(axis, (elapsed - oldtime) * Math.PI / 10)
  oldtime = elapsed
  requestAnimationFrame(render)
}

添加模型标签

在 Three.js 中,CSS2DRenderer 是一个用于将 HTML 元素渲染成 2D 贴图,并将其添加到 Three.js 场景中的工具类。它可以帮助我们更方便地在 Three.js 场景中添加 HTML 元素,比如显示标签、文字等。CSS2DRenderer 类似于 Three.js 中的 WebGLRenderer,但是它渲染的不是 Three.js 的 3D 对象,而是 HTML 元素。

import { CSS2DRenderer} from 'three/examples/jsm/renderers/CSS2DRenderer'

// 创建标签选择器
const labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight)
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
document.body.appendChild(labelRenderer.domElement)
// 给CSS2DRenderer添加控制器
const controls1 = new OrbitControls(camera,labelRenderer.domElement)
controls1.enableDamping = true

CSS2DObject 则是可以在 Three.js 场景中创建的一个 CSS2D 元素。它类似于 Three.js 中的 Mesh,但是它表示的不是三维物体,而是一个 CSS 元素。你可以通过创建 CSS2DObject 实例,将其添加到 Three.js 的场景中,并设置其内部的 HTML 元素,从而在 Three.js 场景中显示 HTML 内容。

import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'

// 创建月球标签
const moonDiv = document.createElement('div');
moonDiv.className = 'label';
moonDiv.textContent = 'Moon';
const moonLabel = new CSS2DObject(moonDiv)
moonLabel.position.set(0, MOON_RADIUS + 0.5, 0);
moon.add(moonLabel)

// 创建地球标签
const earthDiv = document.createElement('div');
earthDiv.className = 'label';
earthDiv.textContent = 'Earch';
const eartchLabel = new CSS2DObject(earthDiv)
eartchLabel.position.set(0, EARTH_RADIUS + 0.5, 0);
earth.add(eartchLabel)

然后给出直接设置类名的样式:

Three.js--》实现3d地月模型展示_第2张图片

最后在渲染函数中加载渲染标签函数 :

Three.js--》实现3d地月模型展示_第3张图片

demo做完,给出本案例的完整代码:(获取素材也可以私信博主)


你可能感兴趣的:(#,Three.js,javascript,vue.js,3d,three.js,前端)