Threejs - 灯光?投影?? 有光的地方就会有影子
灯光
threejs中光源有很多种,但是常见的光源只有4种:
1. 环境光(AmbientLight )
环境光会对场景中的所有物品进行颜色渲染,设置成白光可以清楚的显示场景内的所有物品,同时因为是对场景中所有物品进行无差别无死角渲染,自然就没有影子,也不存在渲染颜色差。
var ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient); //将环境光添加到场景中
// 参数详解
// AmbientLight( color, intensity )
// color — 光的颜色值,十六进制,默认值为0xffffff.
// intensity — 光的强度,默认值为1.
//可以设定0.5,2,10等数值,有着不同程度的强化或者弱化
2. 点光源(pointLight)
想象一下蜡烛,就能知道什么是点光源了,近处的光芒较亮,远处暗淡,照射不到的地方直接灰暗,照射范围是一个球形范围等等。
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(3,3,3);
scene.add(pointLight);
// 参数详解
// PointLight( color, intensity, distance, decay )
// color — 光的颜色值,十六进制,默认值为0xffffff.
// intensity — 光的强度,默认值为1.
// distance — 光照距离,默认为0,表示无穷远都能照到.
// decay — 随着光的距离,强度衰减的程度,默认为1,为模拟真实效果,建议设置为2
3. 平行光 (DirectinalLight )
从某一个点照射到场景中的光即是平行光,你可以认为像太阳一样,从极远处射向场景中的光。它的特点是光具有方向性,也可以启动物体对光的反射效果,迎光的一面会显示出来,背光的一面会成黑色,所以配合环境光就能完整展示场景内容了。
var light = new THREE.DirectionalLight(0xffffff);
scene.add(light); //将光添加到场景中
// 参数详解
// DirectionalLight( color, intensity )
// color — 光的颜色值,十六进制,默认值为0xffffff.
// intensity — 光的强度,默认值为1.
4. 聚光灯 (spotLight)
主要用于展示阴影和材质反射
var spotLight = new THREE.SpotLight( 0xFFFFFF, 1, 100);
spotLight.position.set(0,4,0);
scene.add(spotLight);
// 参数详解
// SpotLight( color, intensity, distance, angle, penumbra, decay )
// color — 光的颜色值,十六进制,默认值为0xffffff.
// intensity — 光的强度,默认值为1.
// distance — 光照距离,默认为0,表示无穷远都能照到.
// angle — 圆椎体的半顶角角度,最大不超过90度,默认为最大值。
// penumbra — 光照边缘的模糊化程度,范围0-1,默认为0,不模糊
// decay — 随着光的距离,强度衰减的程度,默认为1,为模拟真实效果,建议设置为2
灯光有了,下面来看下怎么才能有阴影呢 ?
阴影
什么是阴影? 顾名思义,不就是我们现实生活中的影子吗。。。
废话不多说,直接上码:
<template>
<div ref="content"></div>
</template>
<script>
// 引入threejs
import * as THREE from "../../public/build/three";
//鼠标控制
import { OrbitControls } from "../../public/example/jsm/controls/OrbitControls.js";
export default {
components: {},
data() {
return {
// 创建一个场景
scene: null,
// 创建一个相机
camera: null,
// 创建一个渲染器
renderer: null,
// 模型对象
mesh: null,
// 平面
plane: null,
// 点光源
point: null
};
},
mounted() {
this.init();
},
methods: {
// 初始化
init() {
// 初始化容器
var content = this.$refs.content;
// 创建一个场景
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color("#000");
// 创建几何体
var geometry = new THREE.BoxBufferGeometry(10, 10, 10);
// 几何体材质对象
var material = new THREE.MeshPhongMaterial({
color: "red"
});
// 创建网格模型对象
this.mesh = new THREE.Mesh(geometry, material);
//设置几何体位置
this.mesh.position.x = 0;
this.mesh.position.y = 5;
this.mesh.position.z = 0;
this.scene.add(this.mesh);
// 创建点光源
var point = new THREE.PointLight("#FFF");
point.position.set(40, 20, 30);
this.point = point;
this.scene.add(point);
const sphereSize = 10;
const pointLightHelper = new THREE.PointLightHelper(point, sphereSize);
this.scene.add(pointLightHelper);
//创建环境光
var ambient = new THREE.AmbientLight(0x444444);
this.scene.add(ambient);
// 创建一个相机
this.camera = new THREE.PerspectiveCamera(
70,
window.innerWidth / window.innerHeight,
1,
10000
);
this.camera.position.set(-50, 50, 50);
this.camera.lookAt(0, 0, 0);
//坐标轴辅助器,X,Y,Z长度30
var axes = new THREE.AxesHelper(300);
this.scene.add(axes);
// 辅助网格
// let gridHelper = new THREE.GridHelper(100, 100);
// this.scene.add(gridHelper);
/*给物体添加光感材质*/
//普通材质MeshBasicMaterial对光源是没有反应的,所以我们要修改为对光源产生反应的MeshLambertMaterial和MeshPhongMaterial
//给平面添加材质
const planeGeometry = new THREE.PlaneGeometry(100, 100);
const planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff,
side: THREE.DoubleSide //两面 // THREE.FrontSide 、THREE.BackSide
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
//水平面旋转并且设置位置
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
this.plane = plane;
this.scene.add(plane);
// 创建渲染器
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.setClearColor(0xb9d3ff, 1);
//插入 dom 元素
content.appendChild(this.renderer.domElement);
let controls = new OrbitControls(this.camera, this.renderer.domElement);
controls.addEventListener("resize", this.render(), false);
},
render() {
this.renderer.render(this.scene, this.camera);
//告诉渲染器,我们需要阴影映射
this.renderer.shadowMap.enabled = true;
// 对每个物体进行阴影设置,接受阴影还是投射阴影
//平面是接受阴影
this.plane.receiveShadow = true;
//方块投射阴影
this.mesh.castShadow = true;
//需要给光源同样设置投射阴影
this.point.castShadow = true;
// 自动旋转动画
this.mesh.rotateY(0.01);
requestAnimationFrame(this.render);
}
}
};
</script>
<style lang="scss" scoped>
</style>
过程很简单,就是先创建一个平面,用于接受阴影。告诉渲染器,我们需要阴影映射,然后对每个物体进行阴影设置,是接受阴影还是投射阴影,接受阴影可以理解为承载阴影的,投射阴影可以理解为产生阴影,制造阴影。 (纯属个人理解,如有理解不正确的地方还请大佬能指出)
废话说的有点多,程序员都喜欢直接看代码,哈哈,不喜勿喷
下一章节我们学啥? 我还要先看看,我就是个前端小菜鸡啊,边学习边分享喽
觉得本文对你有帮助?请分享给更多人
关注==>>「前端开发爱好者」,一起提升前端技能!