three.js基础案例day09——物体剪切clipping

今日份案例是物体剪切。主要是创建一个plane(类似于刀),将物体切掉一部分。具体效果如下(实际物体是圆环扭结,切了两刀后的效果):

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

注:其实今天案例中的物体的和昨天案例中的物体是一样的

 1. 创建圆环扭结和平面

  // torus 圆环扭结几何体
  let geomery = new THREE.TorusKnotGeometry(1, 0.2, 200, 20)
  torusMaterial = new THREE.MeshBasicMaterial({
    color: 0xff0000,
    // 设置物体的正背面都渲染
    side: THREE.DoubleSide,
  })
  torusKnot = new THREE.Mesh(geomery, torusMaterial)
  torusKnot.position.y = 2
  scene.add(torusKnot)

  // ground
  geomery = new THREE.BoxGeometry(10, 0.15, 10)
  let 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

  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

  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
}

4.剪切物体

  // 创建一条线用来剪切圆环扭结 第一个属性是剪切线,第二个属性是到原点的距离
  const plane = new THREE.Plane(new THREE.Vector3(1, 0, 0), 0.5)
  const plane2 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 1)
  // localclipping
  torusMaterial.clippingPlanes = [plane, plane2]
  // 设置阴影也要跟着变化
  torusMaterial.clipShadows = true
  renderer.localClippingEnabled = true

注:在材质的时候设置了side,浏览器默认渲染物体的正面,背面不显示,设置THREE.DoubleSide后,物体会双面都显示。

全部代码:

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

<script setup lang="ts">
import { checkboxGroupEmits } from 'element-plus';
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { ref, onMounted } from 'vue'
let width, height
let scene, camera, renderer, controls
let spotLight, dirLight, torusKnot, ground
let torusMaterial
const elementRef = ref(null)
onMounted(() => {
  const element = elementRef.value
  width = element.offsetWidth
  height = element.offsetHeight
  initScene()
  initLights()
  initMeshes()
  enableShadow()
  initCameraHelper()
  enableCliping()
  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(10, 5, 10)
  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(1, 0.2, 200, 20)
  torusMaterial = new THREE.MeshBasicMaterial({
    color: 0xff0000,
    // 设置物体的正背面都渲染
    side: THREE.DoubleSide,
  })
  torusKnot = new THREE.Mesh(geomery, torusMaterial)
  torusKnot.position.y = 2
  scene.add(torusKnot)

  // ground
  geomery = new THREE.BoxGeometry(10, 0.15, 10)
  let 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

  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

  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
}
function enableCliping() {
  // 创建一条线用来剪切圆环扭结
  const plane = new THREE.Plane(new THREE.Vector3(1, 0, 0), 0.5)
  const plane2 = new THREE.Plane(new THREE.Vector3(-1, 0, 0), 1)
  // localclipping
  torusMaterial.clippingPlanes = [plane, plane2]
  // 设置阴影也要跟着变化
  torusMaterial.clipShadows = true
  renderer.localClippingEnabled = true

  //globalClipping 这个效果是renderer剪切
  // renderer.clippingPlanes = [plane]
}
function render() {
  requestAnimationFrame(render)
  controls.update()
  renderer.render(scene, camera)
}
</script>

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

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
three.js 中,可以使用 clip planes(剪裁平面)来实现消隐效果。剪裁平面允许你定义一个几何体的可见部分,而将其他部分剪裁掉。这种方法常用于显示复杂场景中的局部视图。 要使用剪裁平面,首先需要创建一个 THREE.Plane 对象来定义剪裁平面的位置和方向。然后,通过将剪裁平面添加到你想要剪裁的对象的剪裁列表中实现消隐效果。 下面是一个简单的示例代码,演示如何使用剪裁平面消隐一个立方体的一部分: ```javascript // 创建场景、相机和渲染器 var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 创建立方体 var geometry = new THREE.BoxGeometry(1, 1, 1); var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); var cube = new THREE.Mesh(geometry, material); scene.add(cube); // 创建剪裁平面 var plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); // 剪裁平面位于 y=0 的位置,法线方向朝上 var planes = [plane]; // 将剪裁平面添加到剪裁列表中 // 将剪裁列表应用于立方体 cube.userData.clippingPlanes = planes; cube.userData.clipIntersection = true; cube.userData.clipShadows = true; // 渲染场景 function render() { requestAnimationFrame(render); renderer.render(scene, camera); } render(); ``` 在这个示例中,我们将一个剪裁平面添加到立方体的剪裁列表中,并设置一些相关属性。通过这样做,立方体将只显示剪裁平面上方的部分。 你可以根据具体需求调整剪裁平面的位置、方向和其他属性,以实现不同的消隐效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值