Three.js中的灯光API使用
1.环境光(AmbientLight)2.平行光(directionalLight)3.PointLight(点光源) 4.聚光灯(SpotLight)5.材质平面(PlaneGeometry)用于接收(平行光和聚光灯的光源)
首页在上一篇 Three.js加载外部glb,fbx,gltf,obj 模型文件 的文章基础上新加入一个创建 灯光的函数 createLight 方法
// 创建光源
createLight() {
// 创建环境光
this.ambientLight = new THREE.AmbientLight('#fff', .8)
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 = false
this.scene.add(this.planeGeometry);
}
完整的代码
import * as THREE from 'three' //导入整个 three.js核心库
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
// 定义一个 class类
class renderModel {
constructor(selector) {
this.container = document.querySelector(selector)
// 相机
this.camera
// 场景
this.scene
//渲染器
this.renderer
// 控制器
this.controls
// 模型
this.model
//文件加载器类型
this.fileLoaderMap = {
'glb': new GLTFLoader(),
'fbx': new FBXLoader(),
'gltf': new GLTFLoader(),
'obj': new OBJLoader(),
}
// 环境光
this.ambientLight
//平行光
this.directionalLight
// 平行光辅助线
this.directionalLightHelper
// 点光源
this.pointLight
//点光源辅助线
this.pointLightHelper
//聚光灯
this.spotLight
//聚光灯辅助线
this.spotLightHelper
//模型平面
this.planeGeometry
}
// 初始化加载模型方法
init(){
return new Promise(async (reslove, reject) => {
//初始化场景
this.initScene()
//初始化相机
this.initCamera()
//初始化渲染器
this.initRender()
// 创建灯光
this.createLight()
// 添加物体模型 TODO:初始化时需要默认一个 filePath:'threeFile/glb/glb-3.glb' 放在 vue项目中的public/threeFile文件下
const load = await this.setModel({ filePath: 'threeFile/glb/glb-3.glb', fileType: 'glb',scale:0.5})
//监听场景大小改变,跳转渲染尺寸
window.addEventListener("resize", this.onWindowResize.bind(this))
//场景渲染
this.sceneAnimation()
reslove(load)
})
}
//创建场景
initScene() {
this.scene = new THREE.Scene()
//创建一个球体 用于映射全景图
const sphereBufferGeometry = new THREE.SphereGeometry(40, 32, 16);
sphereBufferGeometry.scale(-1, -1, -1);
const material = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(require('@/assets/image/view-1.png'))
});
//设置场景全景图
this.viewMesh = new THREE.Mesh(sphereBufferGeometry, material);
//添加场景
this.scene.add(this.viewMesh);
}
// 创建相机
initCamera() {
const { clientHeight, clientWidth } = this.container
this.camera = new THREE.PerspectiveCamera(45, clientWidth / clientHeight, 0.25, 100)
}
// 创建渲染器
initRender() {
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }) //设置抗锯齿
//设置屏幕像素比
this.renderer.setPixelRatio(window.devicePixelRatio)
//渲染的尺寸大小
const { clientHeight, clientWidth } = this.container
this.renderer.setSize(clientWidth, clientHeight)
//色调映射
this.renderer.toneMapping = THREE.ACESFilmicToneMapping
//曝光
this.renderer.toneMappingExposure = 3
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
this.container.appendChild(this.renderer.domElement)
}
// 使用动画器不断更新场景
sceneAnimation() {
this.renderer.setAnimationLoop(this.render.bind(this))
}
//渲染场景
render(){
this.renderer.render(this.scene, this.camera)
}
//加载模型
setModel({ filePath, fileType, scale, position }) {
return new Promise((resolve, reject) => {
const loader = this.fileLoaderMap[fileType]
loader.load(filePath, (result) => {
//加载不同类型的文件
switch (fileType) {
case 'glb':
this.model = result.scene
break;
case 'fbx':
this.model = result
break;
case 'gltf':
this.model = result.scene
break;
case 'obj':
this.model = result
break;
default:
break;
}
// 设置模型大小
if (scale) {
this.model.scale.set(scale, scale, scale);
}
// 设置模型位置
if (position) {
const { x, y, z } = position
this.model.position.set(x, y, z)
}
// 设置相机位置
this.camera.position.set(0, 2, 6)
// 设置相机坐标系
this.camera.lookAt(0, 0, 0)
// 将模型添加到场景中去
this.scene.add(this.model)
resolve(true)
}, () => {
}, (err) => {
console.log(err)
reject()
})
})
}
// 创建光源
createLight() {
// 创建环境光
this.ambientLight = new THREE.AmbientLight('#fff', .8)
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);
let 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 = false
this.scene.add(this.planeGeometry);
}
}
完整的代码可参考:https://gitee.com/ZHANG_6666/Three.js3D
界面效果: