当前位置: 首页 > news >正文

Three的lod技术

 1、资源:https://sbcode.net/threejs/lod/

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module'
import { GUI } from 'dat.gui'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import TWEEN from '@tweenjs/tween.js'const scene = new THREE.Scene()
scene.background = new THREE.Color(0x87ceeb)const light = new THREE.DirectionalLight(0xffffff, 10)
light.position.set(100, 100, 100)
light.castShadow = true
light.shadow.mapSize.width = 4096
light.shadow.mapSize.height = 4096
light.shadow.camera.near = 0.5
light.shadow.camera.far = 500
light.shadow.camera.left = -500
light.shadow.camera.right = 500
light.shadow.camera.top = 500
light.shadow.camera.bottom = -500
scene.add(light)// const helper = new THREE.CameraHelper(light.shadow.camera);
// scene.add(helper);const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000
)
camera.position.set(4, 5, 7)const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
document.body.appendChild(renderer.domElement)const controls = new OrbitControls(camera, renderer.domElement)
controls.dampingFactor = 0.05
controls.enableDamping = true
controls.screenSpacePanning = falseconst raycaster = new THREE.Raycaster()
const sceneMeshes = new Array()const material = new THREE.MeshPhongMaterial({ color: 0x567d46 })
const planeGeometry = new THREE.PlaneGeometry(1, 1)
planeGeometry.scale(500, 500, 1)
const planeMesh = new THREE.Mesh(planeGeometry, material)
planeMesh.rotateX(-Math.PI / 2)
planeMesh.receiveShadow = true
scene.add(planeMesh)
sceneMeshes.push(planeMesh)let childObjectCount = 2 //how many child meshes are in the tree model. The trunk and leaves are different meshes
const treeCount = 1200 //this many trees are drawn
let treeCounter = 0const positions = new Array()
for (let i = 0; i < treeCount; i++) {positions.push({x: Math.random() * 400 - 200,y: 0,z: Math.random() * 400 - 200,})
}
const scales = new Array()
for (let i = 0; i < treeCount; i++) {scales.push({x: Math.random() * 2 + 1,y: Math.random() * 5 + 1,z: Math.random() * 2 + 1,})
}const treesTypes = ['saplingTree', 'birchTreeWithLeaves', 'tree1WithLeaves']
treesTypes.forEach((treeType) => {let treeHighDetail = new THREE.Object3D()let treeMediumDetail = new THREE.Object3D()let treeLowDetail = new THREE.Object3D()const glTFLoader = new GLTFLoader()glTFLoader.load('models/' + treeType + '_high.glb', (gltf) => {for (let j = 0; j < childObjectCount; j++) {const geometry = (gltf.scene.children[0].children[j] as THREE.Mesh).geometrytreeHighDetail.add(new THREE.Mesh(geometry,(gltf.scene.children[0].children[j] as THREE.Mesh).material))}treeHighDetail.traverse(function (child) {if ((<THREE.Mesh>child).isMesh) {child.castShadow = true}})glTFLoader.load('models/' + treeType + '_medium.glb', (gltf) => {for (let j = 0; j < childObjectCount; j++) {const geometry = (gltf.scene.children[0].children[j] as THREE.Mesh).geometrytreeMediumDetail.add(new THREE.Mesh(geometry,(gltf.scene.children[0].children[j] as THREE.Mesh).material))}treeMediumDetail.traverse(function (child) {if ((<THREE.Mesh>child).isMesh) {child.castShadow = true}})glTFLoader.load('models/' + treeType + '_low.glb', (gltf) => {for (let j = 0; j < childObjectCount; j++) {const geometry = (gltf.scene.children[0].children[j] as THREE.Mesh).geometrytreeLowDetail.add(new THREE.Mesh(geometry,(gltf.scene.children[0].children[j] as THREE.Mesh).material))}treeLowDetail.traverse(function (child) {if ((<THREE.Mesh>child).isMesh) {child.castShadow = true}})for (let i = 0; i < treeCount / treesTypes.length; i++) {const lod = new THREE.LOD()let mesh = treeHighDetail.clone()mesh.scale.copy(scales[treeCounter])lod.addLevel(mesh, 5)mesh = treeMediumDetail.clone()mesh.scale.copy(scales[treeCounter])lod.addLevel(mesh, 10)mesh = treeLowDetail.clone()mesh.scale.copy(scales[treeCounter])lod.addLevel(mesh, 30)lod.position.copy(positions[treeCounter])scene.add(lod)treeCounter++}})})})
})window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeightcamera.updateProjectionMatrix()renderer.setSize(window.innerWidth, window.innerHeight)render()
}renderer.domElement.addEventListener('dblclick', onDoubleClick, false)
function onDoubleClick(event: MouseEvent) {const mouse = {x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1,}raycaster.setFromCamera(mouse, camera)const intersects = raycaster.intersectObjects(sceneMeshes, false)if (intersects.length > 0) {const p = intersects[0].pointnew TWEEN.Tween(controls.target).to({x: p.x,y: p.y,z: p.z,},500).easing(TWEEN.Easing.Cubic.Out).start()}
}const stats = new Stats()
document.body.appendChild(stats.dom)var data = {color: light.color.getHex(),shadowMapSizeWidth: 4096,shadowMapSizeHeight: 4096,mapsEnabled: true,
}
const gui = new GUI()
const lightFolder = gui.addFolder('THREE.Light')
lightFolder.addColor(data, 'color').onChange(() => {light.color.setHex(Number(data.color.toString().replace('#', '0x')))
})
lightFolder.add(light, 'intensity', 0, 20, 0.01)
lightFolder.open()const directionalLightFolder = gui.addFolder('THREE.DirectionalLight')
directionalLightFolder.add(light.shadow.camera, 'left', -500, 1, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'right', 1, 500, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'top', 1, 500, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'bottom', -500, -1, 1).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'near', 0.1, 500).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(light.shadow.camera, 'far', 0.1, 500).onChange(() => light.shadow.camera.updateProjectionMatrix())
directionalLightFolder.add(data, 'shadowMapSizeWidth', [256, 512, 1024, 2048, 4096]).onChange(() => updateShadowMapSize())
directionalLightFolder.add(data, 'shadowMapSizeHeight', [256, 512, 1024, 2048, 4096]).onChange(() => updateShadowMapSize())
directionalLightFolder.add(light.position, 'x', -50, 50, 0.01)
directionalLightFolder.add(light.position, 'y', -50, 50, 0.01)
directionalLightFolder.add(light.position, 'z', -50, 50, 0.01)
directionalLightFolder.open()function updateShadowMapSize() {light.shadow.mapSize.width = data.shadowMapSizeWidthlight.shadow.mapSize.height = data.shadowMapSizeHeight;(light.shadow.map as any) = null
}function animate() {requestAnimationFrame(animate)controls.update()TWEEN.update()//helper.update()render()stats.update()
}function render() {renderer.render(scene, camera)
}animate()

2、效果

 

http://www.lryc.cn/news/253119.html

相关文章:

  • Git配置
  • 阻抗控制下机器人接触刚性环境振荡不稳定进行阻抗调节
  • 【鸿蒙应用ArkTS开发系列】-自定义底部菜单列表弹窗
  • yolov8添加ca注意力机制
  • linux java后台启动的几种方式
  • selinux-policy-default(2:2.20231119-2)软件包内容详细介绍(5)
  • 代码随想录二刷 |栈与队列 |理论基础
  • java--接口概述
  • 出海风潮:中国母婴品牌征服国际市场的机遇与挑战!
  • 一文读懂MongoDB的知识点(3),惊呆面试官。
  • ssm的“魅力”西安宣传网站(有报告)。Javaee项目。
  • 怎么让SecureCRT不自动断开连接
  • 介绍几种Go语言开发的IDE
  • 1、设计模式简介(7大原则,3大类)
  • 华为鲲鹏+银河麒麟V10编译FreeSWITCH1.10.9
  • CFS三层靶机内网渗透
  • 软件分享--智能照片识别分类软件
  • Leetcode—409.最长回文串【简单】
  • 计算机网络入侵检测技术研究
  • 深入学习锁--Synchronized各种使用方法
  • pycharm中绘制一个3D曲线
  • 人工智能_AI服务器安装清华开源_CHATGLM大语言模型_GLM-6B安装部署_人工智能工作笔记0092
  • 用户反馈组件实现(Vue3+ElementPlus)含图片拖拽上传
  • K8S部署nginx并且使用NFS存储数据
  • Homework 3: Higher-Order Functions, Self Reference, Recursion, Tree Recursion
  • (C++)有效三角形的个数--双指针法
  • 11.30BST理解,AVL树操作,定义;快速幂,二分求矩阵幂(未完)
  • 深入理解Java核心技术:Java工程师的实用干货笔记
  • 大学里面转专业介绍
  • MySQL_1. mysql数据库介绍