vlambda博客
学习文章列表

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>// 引入threejsimport * 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>

过程很简单,就是先创建一个平面,用于接受阴影。告诉渲染器,我们需要阴影映射,然后对每个物体进行阴影设置,是接受阴影还是投射阴影,接受阴影可以理解为承载阴影的,投射阴影可以理解为产生阴影,制造阴影。 (纯属个人理解,如有理解不正确的地方还请大佬能指出)


废话说的有点多,程序员都喜欢直接看代码,哈哈,不喜勿喷

下一章节我们学啥? 我还要先看看,我就是个前端小菜鸡啊,边学习边分享喽



觉得本文对你有帮助?请分享给更多人

关注==>>「前端开发爱好者」,一起提升前端技能!