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

【技术调研】三维(4)-ThreeJs阴影投射、光线投射及案例

阴影投射

阴影是灯光经过物体后产生的,几个关键的设置:

  • 灯光属性设置:.castShadow : Boolean 。此属性设置为 true 灯光将投射阴影。注意:这样做的代价比较高,需要通过调整让阴影看起来正确。 查看 DirectionalLightShadow 了解详细信息。 默认值为 false
  • 物体属性设置:
    • .castShadow : Boolean 对象是否被渲染到阴影贴图中。默认值为false
    • .receiveShadow : Boolean 材质是否接收阴影。默认值为false
  • 渲染器设置:.shadowMap : enabled: 如果设置开启,允许在场景中使用阴影贴图。默认是 false

阴影投射动画案例

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>My first three.js app</title><style>body {margin: 0;}</style>
</head><body><script type="module">import * as THREE from "three";import { OrbitControls } from 'three/addons/controls/OrbitControls.js';const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000);camera.position.set(0, 50, 100);camera.lookAt(0, 0, 0);const renderer = new THREE.WebGLRenderer({antialias: true})renderer.setSize(window.innerWidth, window.innerHeight);renderer.shadowMap.enabled = true;renderer.shadowMapType = THREE.PCFSoftShadowMap;document.body.appendChild(renderer.domElement);//创建坐标格辅助对象// const gridHelper = new THREE.GridHelper(100,20,0xffffff );// scene.add( gridHelper );/***  创建地面*/const geometry2 = new THREE.PlaneGeometry(100, 100);const material2 = new THREE.MeshStandardMaterial({ color: 0xffffff });const plane = new THREE.Mesh(geometry2, material2);plane.rotation.x = -Math.PI / 2;plane.receiveShadow = true;scene.add(plane);//旋转/***  创建一个立方体*/const geometry = new THREE.BoxGeometry(10, 10, 10);const textureLoader = new THREE.TextureLoader();const texture = textureLoader.load('./img/Banner.png');const material = new THREE.MeshStandardMaterial({ map: texture });const cube = new THREE.Mesh(geometry,material);cube.position.set(0, 5, 0);cube.castShadow = true;scene.add(cube);/*** 灯光*///环境光const ambientLight = new THREE.AmbientLight(0x404040); // 柔和的白光scene.add(ambientLight);// 平行光const directionLight = new THREE.DirectionalLight(0xffffff, 1);directionLight.castShadow = true;//让阴影更清晰directionLight.shadow.mapSize.width = 2048;directionLight.shadow.mapSize.height = 2048;//不设置以下内容看不见directionLight.shadow.camera.left = -100;directionLight.shadow.camera.right = 100;directionLight.shadow.camera.top = 100;directionLight.shadow.camera.bottom = -100;directionLight.position.set(150, 20, 0);const directionalLightHelper = new THREE.DirectionalLightHelper(directionLight, 5);scene.add(directionLight, directionalLightHelper);// 点光源const pointLight = new THREE.PointLight( 0xffffff, 500 );const pointLightHelper = new THREE.PointLightHelper(pointLight,1);pointLight.castShadow = true;pointLight.position.set( 10, 10, 0 );scene.add( pointLight,pointLightHelper );/*** 用于查看投射相机*/// const cam = directionLight.shadow.camera;// const cameraHelper = new THREE.CameraHelper(cam);// scene.add(cameraHelper);// cameraHelper.visible = true;const controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;let angle = 0;const animete = () => {angle += 0.01;pointLight.position.set(10*Math.cos(angle),pointLight.position.y,10*Math.sin(angle));requestAnimationFrame(animete);renderer.render(scene, camera);};animete();</script>
</body></html>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

光线投射

RayCaster可以向特定方向投射光线,并测试哪些对象与其相交。光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。

应用场景:

  1. 测试相机前方是否有一堵墙(障碍)
  2. 光线是否击中目标
  3. 当鼠标移动时测试是否有物体位于光标下方,以此模拟鼠标事件
  4. 当物体朝向特定某处时提示信息

光线投射动画

1.动态的三个小球使用了一个固定方向的光线投射,被光线穿透会变绿色。

2.静态的三个小球,使用的是鼠标+相机方向进行光线投射,鼠标点击时触发。即鼠标点击会变黄色。

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>My first three.js app</title><style>body {margin: 0;}</style></head><body><script type="module">import * as THREE from "three";import {OrbitControls} from 'three/addons/controls/OrbitControls.js';const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000);camera.position.set(0, 5, 5);camera.lookAt(0, 0, 0);const renderer = new THREE.WebGLRenderer({antialias: true})renderer.setSize(window.innerWidth, window.innerHeight);renderer.shadowMap.enabled = true;renderer.shadowMapType = THREE.PCFSoftShadowMap;document.body.appendChild(renderer.domElement);/***  创建地面*/const geometry2 = new THREE.PlaneGeometry(100, 100);const material2 = new THREE.MeshStandardMaterial({color: 0xffffff});const plane = new THREE.Mesh(geometry2, material2);//旋转plane.rotation.x = -Math.PI / 2;plane.receiveShadow = true;plane.position.y = -5;scene.add(plane);/*** 球1*/const sphere1 = new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32),new THREE.MeshBasicMaterial({color: 0xff0000}))sphere1.position.x = -2const sphere2 = new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32),new THREE.MeshBasicMaterial({color: 0xff0000}))const sphere3 = new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32),new THREE.MeshBasicMaterial({color: 0xff0000}))sphere3.position.x = 2;scene.add(sphere1, sphere2, sphere3)const sphere4 = new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32),new THREE.MeshBasicMaterial({color: 0xff0000}))sphere4.position.x = -2sphere4.position.z = -5const sphere5 = new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32),new THREE.MeshBasicMaterial({color: 0xff0000}))sphere5.position.z = -5const sphere6 = new THREE.Mesh(new THREE.SphereGeometry(0.5, 32, 32),new THREE.MeshBasicMaterial({color: 0xff0000}))sphere6.position.x = 2;sphere6.position.z = -5scene.add(sphere4, sphere5, sphere6)/*** 灯光*///环境光const ambientLight = new THREE.AmbientLight(0x404040); // 柔和的白光scene.add(ambientLight);/*** 创建光线投射*/const raycaster = new THREE.Raycaster()//射线原点const rayOrigin = new THREE.Vector3(-3, 0, 0)//射线方向const rayDirection = new THREE.Vector3(10, 0, 0)//将该向量的方向设置为和原向量相同,但是其长度rayDirection.normalize()raycaster.set(rayOrigin, rayDirection)// 检测和射线相交的物体。const intersect = raycaster.intersectObject(sphere1)console.log(intersect)// 检测和射线相交的一组物体。const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3])console.log(intersects)console.log(raycaster)/*** 创建用于鼠标控制的光线投射*/const raycaster2 = new THREE.Raycaster();const objectsToTests = [sphere4, sphere5, sphere6];/*** 获取鼠标位置,转换为x,y形成射线原点*/const mouse = new THREE.Vector2();window.addEventListener("mousedown", (event) => {mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;//设置后会根据鼠标和相机 进行光线投射console.log(camera.position);raycaster2.setFromCamera(mouse, camera);console.log(raycaster2);console.log(mouse);const intersectObjects = raycaster2.intersectObjects(objectsToTests);console.log(intersectObjects);for (const object of objectsToTests) {object.material.color.set(0xff0000);}for (const intersect of intersectObjects) {intersect.object.material.color.set(0xFFFF00)}})const controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;const clock = new THREE.Clock()const animete = () => {const elapsedTime = clock.getElapsedTime();sphere1.position.y = Math.sin(elapsedTime * 0.3) * 1.5sphere2.position.y = Math.sin(elapsedTime * 0.7) * 1.5sphere3.position.y = Math.sin(elapsedTime * 1.4) * 1.5const objectsToTests = [sphere1, sphere2, sphere3]const intersectObjects = raycaster.intersectObjects(objectsToTests)for (const object of objectsToTests) {object.material.color.set(0xff0000)}for (const intersect of intersectObjects) {intersect.object.material.color.set(0x008000)}controls.update()requestAnimationFrame(animete);renderer.render(scene, camera);};animete();</script></body></html>

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Day26_0.1基础学习MATLAB学习小技巧总结(26)——数据插值
  • 基于双向RRT算法的三维空间最优路线规划matlab仿真
  • 热点数据更新优化
  • 【Unity实战】SO反序列化正确姿势
  • 每天五分钟深度学习PyTorch:不同的神经网络层设置不同的学习率
  • 三、Kubernetes中的控制器的使用
  • 响应式CSS 媒体查询——WEB开发系列39
  • 安卓framework美化手势导航侧滑返回UI
  • 使用CUBE_MX实现STM32 DMA 功能(存储器到存储器)
  • 打开VSCod安装“PHP Intelephense”或“PHP Server”PHP扩展
  • 通过SQL语句判断奇偶数的几种方法
  • QXml 使用方法
  • 物联网之ESP32与微信小程序实现指示灯、转向灯
  • FloodFill算法(DFS+BFS)【上】
  • NLP基础及其代码-tokenizer
  • [PHP内核探索]PHP中的哈希表
  • 77. Combinations
  • CentOS6 编译安装 redis-3.2.3
  • fetch 从初识到应用
  • gcc介绍及安装
  • java2019面试题北京
  • js 实现textarea输入字数提示
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • sublime配置文件
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • vue的全局变量和全局拦截请求器
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 第2章 网络文档
  • 浅谈web中前端模板引擎的使用
  • 巧用 TypeScript (一)
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 原生 js 实现移动端 Touch 滑动反弹
  • 自动记录MySQL慢查询快照脚本
  • 阿里云服务器如何修改远程端口?
  • ​插件化DPI在商用WIFI中的价值
  • #Linux(帮助手册)
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (1)(1.9) MSP (version 4.2)
  • (6)添加vue-cookie
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (java)关于Thread的挂起和恢复
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (计算机网络)物理层
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (新)网络工程师考点串讲与真题详解
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)3D模板阴影原理