three.js中如何创建和修改:环境光,平行光,点光源,聚光灯以及灯光辅助线等参数信息

614 阅读2分钟

前言

本篇继续给大家分享一下在three.js中,环境光(AmbientLight),平行光(DirectionalLight),点光源(PointLight),聚光灯(SpotLight)在项目中如何去使用

首先在上一篇 Three.js加载外部glb,fbx,gltf,obj,stl模型文件 的文章基础上

新加入一个创建灯光的函数 createLight 方法

	// 创建光源
	createLight() {
		// 创建环境光
		this.ambientLight = new THREE.AmbientLight('#fff', .8)
          this.ambientLight.visible = true
		this.scene.add(this.ambientLight)

		// 创建平行光
		this.directionalLight = new THREE.DirectionalLight('#1E90FF', 1)
		this.directionalLight.position.set(-1.44, 2.2, 1)
		this.directionalLight.castShadow = true
		this.directionalLight.visible = false
		this.scene.add(this.directionalLight)
		// 创建平行光辅助线
		this.directionalLightHelper = new THREE.DirectionalLightHelper(this.directionalLight, .5)
		this.directionalLightHelper.visible = false
		this.scene.add(this.directionalLightHelper)

		// 创建点光源
		this.pointLight = new THREE.PointLight(0xff0000, 1, 100)
		this.pointLight.visible = false
		this.scene.add(this.pointLight)
		// 创建点光源辅助线
		this.pointLightHelper = new THREE.PointLightHelper(this.pointLight, .5)
		this.pointLightHelper.visible = false
		this.scene.add(this.pointLightHelper)

		//  创建聚光灯
		this.spotLight = new THREE.SpotLight('#323636', 440);
		this.spotLight.visible = false
		this.spotLight.map = new THREE.TextureLoader().load(require('@/assets/image/model-bg-1.jpg'));
		this.spotLight.decay = 2;
		this.spotLight.shadow.mapSize.width = 1920;
		this.spotLight.shadow.mapSize.height = 1080;
		this.spotLight.shadow.camera.near = 1;
		this.spotLight.shadow.camera.far = 10;
		this.scene.add(this.spotLight);
                
		//创建聚光灯辅助线
		this.spotLightHelper = new THREE.SpotLightHelper(this.spotLight);
		this.spotLightHelper.visible = false
		this.scene.add(this.spotLightHelper)

		// 创建一个光源平面
		const geometry = new THREE.PlaneGeometry(4, 4);
		var groundMaterial = new THREE.MeshStandardMaterial({ color: '#939393' });
		this.planeGeometry = new THREE.Mesh(geometry, groundMaterial);
		this.planeGeometry.rotation.x = -Math.PI / 2
		this.planeGeometry.position.set(0, -.59, 0)
		// 让地面接收阴影
		this.planeGeometry.receiveShadow = true;
		this.planeGeometry.visible = true
		this.scene.add(this.planeGeometry);
	}

如何去动态的修改灯光和辅助线的参数信息?

一.首先根据对应的灯光配置添加不同的四个函数方法:
  1. 修改环境光参数方法:onSetModelAmbientLight
  2. 修改平行光参数方法:onSetModelDirectionalLight
  3. 修改点光源参数方法:onSetModelPointLight
  4. 修改聚光灯参数方法:onSetModelSpotLight
import { lightPosition } from '@/utils/utilityFunction'
// 设置环境光
function onSetModelAmbientLight({ ambientLight, ambientLightColor, ambientLightIntensity }) {
	this.ambientLight.visible = ambientLight
	this.ambientLight.intensity = ambientLightIntensity
	this.ambientLight.color.set(ambientLightColor)
}

// 设置平行光
function onSetModelDirectionalLight(config) {
	const { directionaShadow, directionalHorizontal, directionalVertical, directionalSistance, directionalLight, directionalLightColor, directionalLightIntensity, directionalLightHelper } = config

	this.directionalLight.visible = directionalLight
	this.directionalLightHelper.visible = directionalLightHelper && directionalLight
	this.directionalLight.intensity = directionalLightIntensity
	this.directionalLight.castShadow = directionaShadow
	this.directionalLight.color.set(directionalLightColor)
	const { x, y, z } = lightPosition(directionalHorizontal, directionalVertical, directionalSistance)
	this.directionalLight.position.set(x, y, z)
	this.directionalLightHelper.update()
}

// 设置点光源
function onSetModelPointLight(config) {
	const { pointHorizontal, pointVertical, pointSistance, pointLight, pointLightColor, pointLightIntensity, pointLightHelper } = config
        
	this.pointLight.visible = pointLight
	this.pointLightHelper.visible = pointLight && pointLightHelper
	this.pointLight.intensity = pointLightIntensity
	this.pointLight.color.set(pointLightColor)
	const { x, y, z } = lightPosition(pointHorizontal, pointVertical, pointSistance)
	this.pointLight.position.set(x, y, z)
	this.pointLightHelper.update()
}

// 设置聚光灯
function onSetModelSpotLight(config) {
	const { spotDistance, spotCastShadow, spotLightHelper, spotFocus, spotPenumbra, spotAngle, spotLight, spotLightColor, spotLightIntensity, spotHorizontal, spotVertical, spotSistance } = config

	this.spotLight.visible = spotLight
	this.spotLightHelper.visible = spotLight && spotLightHelper
	this.spotLight.intensity = spotLightIntensity
	this.spotLight.angle = spotAngle
	this.spotLight.penumbra = spotPenumbra
	this.spotLight.shadow.focus = spotFocus
	this.spotLight.castShadow = spotCastShadow
	this.spotLight.distance = spotDistance
	this.spotLight.color.set(spotLightColor)
	const { x, y, z } = lightPosition(spotHorizontal, spotVertical, spotSistance)
	this.spotLight.position.set(x, y, z)
	this.spotLightHelper.update()

}
二.封装一个修改灯光位置(position)的方法 lightPosition
/**
 * 计算光源垂直和水平方向的定位
 *
 * @param {Number} horizontal 水平方向值
 * @param {Number} vertical  垂直方向值
 * @param {Number} distance  光源距离
 * @return {x , y , z}  返回光源坐标轴位置
 */
export function lightPosition(horizontal, vertical, distance) {
	const x = distance * Math.sin(horizontal) * Math.cos(vertical);
	const y = distance * Math.sin(vertical);
	const z = distance * Math.cos(horizontal) * Math.cos(vertical);
	return {x,y,z}
}
三.在页面中去使用
<script setup>
import { reactive, computed } from "vue";
const store = useMeshEditStore();

const config = reactive({
  //光源平面
  planeGeometry: false,
  planeColor: "#000000",
  planeWidth: 7,
  planeHeight: 7,
  //环境光
  ambientLight: true,
  ambientLightColor: "#fff",
  ambientLightIntensity: 0.8,
  //平行光
  directionalLight: false,
  directionalLightHelper: true,
  directionalLightColor: "#fff",
  directionalLightIntensity: 5,
  directionalHorizontal: -1.26,
  directionalVertical: -3.85,
  directionalSistance: 2.98,
  directionaShadow: true,
  //点光源
  pointLight: false,
  pointLightHelper: true,
  pointLightColor: "#1E90FF",
  pointLightIntensity: 10,
  pointHorizontal: -4.21,
  pointVertical: -4.1,
  pointSistance: 2.53,
  //聚光灯
  spotLight: false,
  spotLightColor: "#00BABD",
  spotLightIntensity: 900,
  spotHorizontal: -3.49,
  spotVertical: -4.37,
  spotSistance: 4.09,
  spotAngle: 0.5,
  spotPenumbra: 1,
  spotFocus: 1,
  spotCastShadow: true,
  spotLightHelper: true,
  spotDistance: 20
});

const state = reactive({
  modelApi: computed(() => store.modelApi)
});

// 设置环境光
const onChangeAmbientLight = () => {
  state.modelApi.onSetModelAmbientLight(config);
};


// 设置平行光
const onChangeDirectionalLight = () => {
  if (config.directionalLight) {
    config.planeGeometry = true;
    state.modelApi.onSetModelPlaneGeometry(config);
  }
  state.modelApi.onSetModelDirectionalLight(config);
};

// 设置点光源
const onChangePointLight = () => {
  state.modelApi.onSetModelPointLight(config);
};


// 设置聚光灯
const onChangeSpotLight = () => {
  if (config.spotLight) {
    config.planeGeometry = true;
    state.modelApi.onSetModelPlaneGeometry(config);
  }
  state.modelApi.onSetModelSpotLight(config);
};


<script>

完整的代码可参考:gitee.com/ZHANG_6666/…

界面效果:

image.png