之前有讲过使用天空盒子来绘制天空效果,简单的讲就是做一个正方体将整个场景包含在里面,正方体的六个面用贴图无缝衔接上,然后渲染出天空的效果。
这节讲用threejs自带的Sky组件实现天空效果,这样不仅省的自己去找图片,而且会加上太阳的效果,显得更逼真和漂亮,上一篇文章绘制了大海,这这个Sky就基于海面上创建天空效果,如果需要前面的代码可以参照这篇文章Threejs绘制海面效果。
首先我们在开头引入Sky组件:
import * as THREE from 'three'
import {OrbitControls} from "three/addons/controls/OrbitControls";
import { Water } from 'three/examples/jsm/objects/Water.js';
import { Sky } from 'three/examples/jsm/objects/Sky'
接着在新建一个方法用于渲染天空和太阳,这的天空实际上还是使用的天空盒子,要做个很大的盒子,把整个场景装进去,然后渲染起来类似天空的效果,其次在天空中添加一个太阳的效果,使用Sky的一些属性给太阳的周围添加一些晕轮效果,可以设置太阳浑浊度,散射等,属性的作用我已经在代码中做了详细的注释,大家可以修改他们的值来尝试。
initSky(){
let sky = new Sky();
sky.scale.setScalar( 45000 );//太阳盒子的大小,要把整个场景包含进去
scene.add( sky );
const effectController = {
turbidity: 10,//浑浊度
rayleigh: 3,//阳光散射,黄昏效果的程度
mieCoefficient: 0.005,//太阳对比度,清晰度
mieDirectionalG: 0.7,
elevation: 2,//太阳高度
azimuth: 180,//太阳水平方向位置
exposure: this.renderer.toneMappingExposure //光线昏暗程度
};
let sun = new THREE.Vector3();
const uniforms = sky.material.uniforms;
uniforms[ 'turbidity' ].value = effectController.turbidity;
uniforms[ 'rayleigh' ].value = effectController.rayleigh;
uniforms[ 'mieCoefficient' ].value = effectController.mieCoefficient;
uniforms[ 'mieDirectionalG' ].value = effectController.mieDirectionalG;
const phi = THREE.MathUtils.degToRad( 90 - effectController.elevation );
const theta = THREE.MathUtils.degToRad( effectController.azimuth );
sun.setFromSphericalCoords( 1, phi, theta );
uniforms[ 'sunPosition' ].value.copy( sun );
this.renderer.toneMappingExposure = effectController.exposure;
this.renderer.render( scene, this.camera );
},
最终,在场景中的展示如图所示:个人觉得还是很nice的,可以通过之前制作动画效果的课程,实现太阳的升起和落下,