three.js基础案例day08——shadowMapviewer

今日份案例是阴影图查看器。主要技术:光源、阴影和阴影图查看器的引入和使用。具体效果如下:

 首先需要搭建基础环境,场景、相机、渲染器、控制器。不清楚的可以查看three.js基础案例day01。

 1. 添加圆环扭结几何体、立方体和平面

  // torus 扭结几何体
  let geomery = new THREE.TorusKnotGeometry(25, 8, 200, 20)
  let material = new THREE.MeshPhongMaterial({
    color: 0xff0000,
    shininess: 150,
    specular: 0x222222,
  })
  torusKnot = new THREE.Mesh(geomery, material)
  torusKnot.scale.multiplyScalar(1 / 18)
  torusKnot.position.y = 3
  scene.add(torusKnot)

  // cube
  geomery = new THREE.BoxGeometry(3, 3, 3)
  cube = new THREE.Mesh(geomery, material)
  cube.position.set(9, 3, 9)
  scene.add(cube)

  // ground
  geomery = new THREE.BoxGeometry(10, 0.15, 10)
  material = new THREE.MeshPhongMaterial({
    color: 0xa0adaf,
    shininess: 150,
    specular: 0x111111,
  })
  ground = new THREE.Mesh(geomery, material)
  ground.scale.multiplyScalar(3)
  scene.add(ground)

2.添加聚光灯和平行光

  spotLight = new THREE.SpotLight(0xffffff)
  spotLight.name = 'Spot light'
  spotLight.angle = Math.PI / 5
  spotLight.penumbra - 0.3
  spotLight.position.set(10, 10, 5)
  scene.add(spotLight)

  dirLight = new THREE.DirectionalLight(0xffffff, 1)
  dirLight.name = 'Dir light'
  dirLight.position.set(0, 10, 0)
  scene.add(dirLight)

3.设置参数 使物体产生阴影

  renderer.shadowMap.enabled = true
  renderer.shadowMap.type = THREE.BasicShadowMap

  spotLight.castShadow = true
  dirLight.castShadow = true

  torusKnot.castShadow = true
  torusKnot.receiveShadow = true

  cube.castShadow = true
  cube.receiveShadow = true

  ground.castShadow = false
  ground.receiveShadow = true

4.创建相机辅助器并将其添加到场景中

注:线框显示的其实的可视化聚光灯和方向灯的阴影相机,并设置了近远裁剪面,阴影贴图大小和视场的边界

  // 近裁剪面的距离
  spotLight.shadow.camera.near = 8
  // 远裁剪面的距离
  spotLight.shadow.camera.far = 30
  // 阴影贴图的大小
  spotLight.shadow.mapSize.width = 1024
  spotLight.shadow.mapSize.height = 1024
  scene.add(new THREE.CameraHelper(spotLight.shadow.camera))

  dirLight.shadow.camera.near = 1
  dirLight.shadow.camera.far = 10
  // 边界
  dirLight.shadow.camera.right = 15
  dirLight.shadow.camera.left = -15
  dirLight.shadow.camera.top = 15
  dirLight.shadow.camera.bottom = -15
  scene.add(new THREE.CameraHelper(dirLight.shadow.camera))

5. 物体运动起来

  // clock最开始有设置 clock = new THREE.Clock()
  // 帧时间
  const delta = clock.getDelta()

  torusKnot.rotation.x += 0.25 * delta
  torusKnot.rotation.y += 2 * delta
  torusKnot.rotation.z += 1 * delta

  cube.rotation.x += 0.25 * delta
  cube.rotation.y += 2 * delta
  cube.rotation.z += 1 * delta

6.引入阴影图查看器并使用

function resizeShadowMapViewer() {
  const size = width * 0.15
  dirLightShadowMapViewer.position.x = 10
  dirLightShadowMapViewer.position.y = 10
  dirLightShadowMapViewer.size.width = size
  dirLightShadowMapViewer.size.height = size
  dirLightShadowMapViewer.update()

  // 使用.set() 会自动调用.update()
  spotLightShadowMapViewer.size.set(size, size)
  spotLightShadowMapViewer.position.set(size + 20, 10)
}
// 需要在render中调用
function render() {
  dirLightShadowMapViewer.render(renderer)
  spotLightShadowMapViewer.render(renderer)
}

全部代码

<template>
  <div id="threeId" ref="elementRef"></div>
</template>

<script setup lang="ts">
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { ShadowMapViewer } from 'three/examples/jsm/utils/ShadowMapViewer.js'
import { ref, onMounted } from 'vue'
let width, height
let scene, camera, renderer, controls
let spotLight, dirLight, torusKnot, cube, ground
let dirLightShadowMapViewer, spotLightShadowMapViewer
let clock = new THREE.Clock()
const elementRef = ref(null)
onMounted(() => {
  const element = elementRef.value
  width = element.offsetWidth
  height = element.offsetHeight
  initScene()
  initLights()
  initMeshes()
  enableShadow()
  initCameraHelper()
  initShadowMapViewer()
  render()
})
function initScene() {
  // 初始化场景: 创建场景,相机,物体,渲染器
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x808080)
  camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000)
  camera.position.set(20, 10, 20)
  scene.add(camera)
  // 三维坐标
//   const axesHelper = new THREE.AxesHelper(40)
//   scene.add(axesHelper)
  // antialias:是否执行抗锯齿
  renderer = new THREE.WebGLRenderer({ antialias: true })
  // 设备像素比
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setSize(width, height)
  elementRef.value.appendChild(renderer.domElement)
  controls = new OrbitControls(camera, renderer.domElement)
}
function initLights() {
  scene.add(new THREE.AmbientLight(0x404040))

  spotLight = new THREE.SpotLight(0xffffff)
  spotLight.name = 'Spot light'
  spotLight.angle = Math.PI / 5
  spotLight.penumbra - 0.3
  spotLight.position.set(10, 10, 5)
  scene.add(spotLight)

  dirLight = new THREE.DirectionalLight(0xffffff, 1)
  dirLight.name = 'Dir light'
  dirLight.position.set(0, 10, 0)
  scene.add(dirLight)
}
function initMeshes() {
  // torus
  let geomery = new THREE.TorusKnotGeometry(25, 8, 200, 20)
  let material = new THREE.MeshPhongMaterial({
    color: 0xff0000,
    shininess: 150,
    specular: 0x222222,
  })
  torusKnot = new THREE.Mesh(geomery, material)
  torusKnot.scale.multiplyScalar(1 / 18)
  torusKnot.position.y = 3
  scene.add(torusKnot)

  // cube
  geomery = new THREE.BoxGeometry(3, 3, 3)
  cube = new THREE.Mesh(geomery, material)
  cube.position.set(9, 3, 9)
  scene.add(cube)

  // ground
  geomery = new THREE.BoxGeometry(10, 0.15, 10)
  material = new THREE.MeshPhongMaterial({
    color: 0xa0adaf,
    shininess: 150,
    specular: 0x111111,
  })
  ground = new THREE.Mesh(geomery, material)
  ground.scale.multiplyScalar(3)
  scene.add(ground)
}
function enableShadow() {
  renderer.shadowMap.enabled = true
  renderer.shadowMap.type = THREE.BasicShadowMap

  spotLight.castShadow = true
  dirLight.castShadow = true

  torusKnot.castShadow = true
  torusKnot.receiveShadow = true

  cube.castShadow = true
  cube.receiveShadow = true

  ground.castShadow = false
  ground.receiveShadow = true
}
function initCameraHelper() {
  // 近裁剪面的距离
  spotLight.shadow.camera.near = 8
  // 远裁剪面的距离
  spotLight.shadow.camera.far = 30
  // 阴影贴图的大小
  spotLight.shadow.mapSize.width = 1024
  spotLight.shadow.mapSize.height = 1024
  scene.add(new THREE.CameraHelper(spotLight.shadow.camera))

  dirLight.shadow.camera.near = 1
  dirLight.shadow.camera.far = 10
  // 边界
  dirLight.shadow.camera.right = 15
  dirLight.shadow.camera.left = -15
  dirLight.shadow.camera.top = 15
  dirLight.shadow.camera.bottom = -15
  scene.add(new THREE.CameraHelper(dirLight.shadow.camera))
}
function initShadowMapViewer() {
  dirLightShadowMapViewer = new ShadowMapViewer(dirLight)
  spotLightShadowMapViewer = new ShadowMapViewer(spotLight)
  resizeShadowMapViewer()
}
function resizeShadowMapViewer() {
  const size = width * 0.15
  dirLightShadowMapViewer.position.x = 10
  dirLightShadowMapViewer.position.y = 10
  dirLightShadowMapViewer.size.width = size
  dirLightShadowMapViewer.size.height = size
  dirLightShadowMapViewer.update()

  // 使用.set() 会自动调用.update()
  spotLightShadowMapViewer.size.set(size, size)
  spotLightShadowMapViewer.position.set(size + 20, 10)
}
function render() {
  requestAnimationFrame(render)
  const delta = clock.getDelta()
  controls.update()
  renderer.render(scene, camera)

  torusKnot.rotation.x += 0.25 * delta
  torusKnot.rotation.y += 2 * delta
  torusKnot.rotation.z += 1 * delta

  cube.rotation.x += 0.25 * delta
  cube.rotation.y += 2 * delta
  cube.rotation.z += 1 * delta

  dirLightShadowMapViewer.render(renderer)
  spotLightShadowMapViewer.render(renderer)
}
</script>

<style scoped>
#threeId {
  width: 100%;
  height: 100%;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值