且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Threejs - 灯光?投影?? 有光的地方就会有影子

更新时间:2022-08-12 21:59:47

灯光

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>

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


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

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