方向光DirectionalLight使用
- 一、方向光介绍
- 二、如何使用方向光
-
- 1.创建方向光
- 2.方向光的属性
-
- 2.1颜色-color
- 2.2是否可见-visible
- 2.3强度-intensity
- 2.4目标-target
- 2.5位置-position
- 2.6是否产生阴影-castShadow
- 2.7投影远点-shadow.camera.far
- 2.8投影近点-shadow.camera.near
- 2.9投影上边界-shadow.camera.top
- 2.10投影下边界-shadow.camera.bottom
- 2.11投影左边界-shadow.camera.left
- 2.12投影右边界-shadow.camera.right
- 2.13shadow.mapSize.width 和 shadow.mapSize.height
- 三、demo效果
- 四、demo代码
一、方向光介绍
方向光发出的所有光线都是平行的,可以认为是距离很远的光源,例如遥远的太阳光就是方向光,方向光不像聚焦光那样距离目标越远越暗淡,被方向光照射的整个区域收到的光照强度都一样
二、如何使用方向光
1.创建方向光
创建一个简单的方向光,通过new THREE.DirectionalLight(color)
语句就可以创建一个指定颜色的方向光,然后将它添加到场景中就可以了
var directionalLight = new THREE.DirectionalLight(0x0c0c0c) // 创建方向光
scene.add(directionalLight ) // 将方向光添加到场景
2.方向光的属性
2.1颜色-color
color属性继承自基类Light,color属性的类型是Color,所以color属性的值需要通过颜色对象THREE.Color()来创建
2.2是否可见-visible
visible属性继承自基类Object3D,使用很简单,该属性时布尔类型,取值true或false
2.3强度-intensity
intensity属性是用来设置聚光灯的强度,默认值是1,如果设置成0那什么也看不到,该值越大,点光源看起来越亮
2.4目标-target
target属性用来决定光照的方向,一般会指向一个对象
2.5位置-position
position属性表示光源的发光位置,该属性继承自基类Object3D,positon属性的类是Vector3
2.6是否产生阴影-castShadow
castShadow属性是用来控制光源是否产生阴影,取值为true或false
2.7投影远点-shadow.camera.far
表示到距离光源的哪一个位置可以生成阴影
2.8投影近点-shadow.camera.near
表示距离光源的哪一个位置开始生成阴影
2.9投影上边界-shadow.camera.top
2.10投影下边界-shadow.camera.bottom
2.11投影左边界-shadow.camera.left
2.12投影右边界-shadow.camera.right
2.13shadow.mapSize.width 和 shadow.mapSize.height
阴影映射宽度和阴影映射高度。决定了有多少像素用来生成阴影。当阴影具有锯齿状边缘或看起来不光滑时,可以增加这个值。在场景渲染之后无法更改,默认值都为512
三、demo效果
如上图,该示例支持以下功能
- 可以控制方向光是否显示
- 调整方向光颜色
- 调整方向光的位置
- 调整方向光的强度
- 调整聚光灯的照射目标,即光照方向
- 调整聚光灯是否产生阴影
四、demo代码
<template><div><div id="container"></div><div class="controls-box"><section><el-row><el-checkbox v-model="lightProperties.visible">是否展示方向光</el-checkbox></el-row><el-row><el-col :span="8" class="label-col"><label> 方向光颜色</label></el-col><el-col :span="16"><div @click="inputClick"><el-input :value="lightProperties.color"></el-input></div><div v-show="isShowColors" class="color-select-layer"><sketch-picker v-model="lightProperties.color" @input="colorChange"></sketch-picker></div></el-col></el-row><el-row><div v-for="(item,key) in lightProperties" :key="key"><div v-if="item&&item.name!=undefined"><el-col :span="8"><span class="vertice-span">{
{item.name}}</span></el-col><el-col :span="13"><el-slider v-model="item.value" :min="item.min" :max="item.max" :step="item.step" :format-tooltip="formatTooltip"></el-slider></el-col><el-col :span="3"><span class="vertice-span">{
{item.value}}</span></el-col></div></div></el-row><el-row><el-col :span="8" class="label-col"><label>target</label></el-col><el-col :span="16"><el-select v-model="lightProperties.target" placeholder="请选择"><el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option></el-select></el-col></el-row><el-row><el-checkbox v-model="lightProperties.castShadow">是否产生阴影</el-checkbox></el-row></section></div></div>
</template><script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { Sketch } from 'vue-color'
export default {components: {'sketch-picker': Sketch},data () {return {options: [{value: 'cube',label: 'cube'},{value: 'sphere',label: 'sphere'},{value: 'plane',label: 'plane'}],lightProperties: {positionX: {name: 'positionX',value: 15,min: -40,max: 40,step: 1},positionY: {name: 'positionY',value: 40,min: -60,max: 100,step: 1},positionZ: {name: 'positionZ',value: 35,min: -40,max: 40,step: 1},intensity: {name: 'intensity',value: 3.1,min: 0,max: 5,step: 0.1},color: '#fafafa',visible: true,target: 'sphere',castShadow: true},isShowColors: false,lightHelper: null,shadowCameraHelper: null,cube: null,sphere: null,plane: null,ambientLight: null,directionalLight: null,camera: null,scene: null,renderer: null,controls: null}},mounted () {this.init()},methods: {formatTooltip (val) {return val},inputClick () {this.isShowColors = !this.isShowColors},colorChange (val) {this.lightProperties.color = val.hex},// 初始化init () {this.createScene() // 创建场景this.createMesh() // 创建网格模型this.createCubeAndSphere() // 创建方块和球this.createLight() // 创建光源this.createCamera() // 创建相机this.createRender() // 创建渲染器this.createControls() // 创建控件对象this.render() // 渲染},// 创建场景createScene () {this.scene = new THREE.Scene()},// 创建网格模型createMesh () {const planeGeometry = new THREE.PlaneGeometry(200, 100) // 创建一个平面对象PlaneGeometryconst planeMaterial = new THREE.MeshLambertMaterial({color: 0x409fee}) // 材质对象Materialthis.plane = new THREE.Mesh(planeGeometry, planeMaterial)this.plane.receiveShadow = true// 设置平面位置this.plane.rotation.x = -0.5 * Math.PIthis.plane.position.set(15, 0, 0)// 平面对象添加到场景中this.scene.add(this.plane)},// 创建方块和球createCubeAndSphere () {const geom = new THREE.BoxGeometry(4, 4, 4) // 创建几何对象geomconst material = new THREE.MeshLambertMaterial({ color: 0xff0000 }) // 创建材质对象materialthis.cube = new THREE.Mesh(geom, material) // 创建网格对象cubethis.cube.castShadow = truethis.cube.position.set(25, 6, 10)this.scene.add(this.cube) // 将网格对象添加到场景const sphereGeometry = new THREE.SphereGeometry(4, 26, 20) // 创建几何对象sphereGeometryconst sphereMaterial = new THREE.MeshLambertMaterial({ color: 0x7777ff }) // 创建材质对象sphereMaterialthis.sphere = new THREE.Mesh(sphereGeometry, sphereMaterial) // 创建网格对象spherethis.sphere.castShadow = truethis.sphere.position.set(25, 5, -5)this.scene.add(this.sphere) // 将网格对象添加到场景},// 创建光源createLight () {// 环境光this.ambientLight = new THREE.AmbientLight(0xffffff, 0.1) // 创建环境光this.scene.add(this.ambientLight) // 将环境光添加到场景this.directionalLight = new THREE.DirectionalLight(0xffffff) // 创建方向光this.directionalLight.position.set(15, 40, 35) // 设置方向光源位置this.directionalLight.castShadow = truethis.directionalLight.shadow.mapSize.width = 1024this.directionalLight.shadow.mapSize.height = 1024// 方向光投影近点、远点更新this.directionalLight.shadow.camera.near = 2this.directionalLight.shadow.camera.far = 100// 方向光投影边界更新this.directionalLight.shadow.camera.top = 8this.directionalLight.shadow.camera.bottom = -8this.directionalLight.shadow.camera.left = -8this.directionalLight.shadow.camera.right = 8this.scene.add(this.directionalLight)// 创建辅助工具this.lightHelper = new THREE.DirectionalLightHelper(this.directionalLight)this.scene.add(this.lightHelper)this.shadowCameraHelper = new THREE.CameraHelper(this.directionalLight.shadow.camera)this.scene.add(this.shadowCameraHelper)this.scene.add(new THREE.AxesHelper(20))},// 创建相机createCamera () {const element = document.getElementById('container')const width = element.clientWidth // 窗口宽度const height = element.clientHeight // 窗口高度const k = width / height // 窗口宽高比// PerspectiveCamera( fov, aspect, near, far )this.camera = new THREE.PerspectiveCamera(35, k, 0.1, 1000)this.camera.position.set(165, 38, -10) // 设置相机位置this.camera.lookAt(new THREE.Vector3(10, 0, 0)) // 设置相机方向this.scene.add(this.camera)},// 创建渲染器createRender () {const element = document.getElementById('container')this.renderer = new THREE.WebGLRenderer()this.renderer.setSize(element.clientWidth, element.clientHeight) // 设置渲染区域尺寸this.renderer.shadowMap.enabled = true // 显示阴影this.renderer.setClearColor(0x3f3f3f, 1) // 设置背景颜色element.appendChild(this.renderer.domElement)},// 更新属性updateFun () {// 方向光颜色更新this.directionalLight.color = new THREE.Color(this.lightProperties.color)// 方向光强度更新this.directionalLight.intensity = this.lightProperties.intensity.value// 方向光位置更新this.directionalLight.position.set(this.lightProperties.positionX.value,this.lightProperties.positionY.value,this.lightProperties.positionZ.value)// 更新targetif (this.lightProperties.target === 'sphere') {this.directionalLight.target = this.sphere} else if (this.lightProperties.target === 'plane') {this.directionalLight.target = this.plane} else {this.directionalLight.target = this.cube}// 方向光是否可见更新this.directionalLight.visible = this.lightProperties.visible// 是否产生阴影this.directionalLight.castShadow = this.lightProperties.castShadow// 更新辅助工具this.lightHelper.update()this.shadowCameraHelper.update()},render () {this.updateFun()this.renderer.render(this.scene, this.camera)requestAnimationFrame(this.render)},// 创建控件对象createControls () {this.controls = new OrbitControls(this.camera, this.renderer.domElement)this.controls.target.copy(this.plane.position)}}
}
</script><style>
#container {position: absolute;width: 100%;height: 100%;
}
.controls-box {position: absolute;right: 5px;top: 5px;width: 300px;padding: 10px;background-color: #fff;border: 1px solid #c3c3c3;
}
.label-col {padding: 8px 5px;
}
.color-select-layer {position: relative;left: -20px;padding: 15px 0;
}
.vertice-span {line-height: 38px;padding: 0 2px 0 10px;
}
</style>