webgl_effects_stereo

news2024/9/19 10:36:03

ThreeJS 官方案例学习(webgl_effects_stereo)

1.效果图

在这里插入图片描述

2.源码

<template>
	<div>
		<div id="container"></div>
	</div>
</template>
<script>
import * as THREE from 'three';
// 导入控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 引入房间环境,创建一个室内环境
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
// 导入性能监视器
import Stats from 'three/examples/jsm/libs/stats.module.js';
// 导入gltf载入库、模型加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
// 引入模型解压器
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
//GUI界面
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import gsap from 'gsap';
//双屏渲染插件
import { StereoEffect } from 'three/examples/jsm/effects/StereoEffect.js';


//创建环境贴图(全景图)
const path = '/textures/cube/Park3Med/'
const format = '.jpg'
const urls = [
	path + 'px' + format, path + 'nx' + format,
	path + 'py' + format, path + 'ny' + format,
	path + 'pz' + format, path + 'nz' + format
]
const textureCube = new THREE.CubeTextureLoader().load(urls);
export default {
	data() {
		return {
			container: null, //界面需要渲染的容器
			scene: null,	// 场景对象
			camera: null, //相机对象
			renderer: null, //渲染器对象
			controller: null,	// 相机控件对象
			stats: null,// 性能监听器
			mixer: null,//动画混合器
			model: null,//导入的模型
			clock: new THREE.Clock(),// 创建一个clock对象,用于跟踪时间
			spheres: [],//小球集合
			// 鼠标移动位置
			mouseX: 0,
			mouseY: 0,
			// 窗口位移
			windowHalfX: 0,
			windowHalfY: 0,
			effect: null,//3D渲染对象
		};
	},
	mounted() {
		this.init()
		this.animate()  //如果引入了模型并存在动画,可在模型引入成功后加载动画
		window.addEventListener("resize", this.onWindowSize)
		window.addEventListener('mousemove', this.onDocumentMouseMove);
	},
	beforeUnmount() {
		console.log('beforeUnmount===============');
		// 组件销毁时置空
		this.container = null
		this.scene = null
		this.camera = null
		this.renderer = null
		this.controller = null
		this.stats = null
		this.mixer = null
		this.model = null//导入的模型
	},
	methods: {
		/**
		* @description 初始化
		 */
		init() {
			this.container = document.getElementById('container')
			this.windowHalfX = this.container.clientWidth / 2;
			this.windowHalfY = this.container.clientHeight / 2;
			this.setScene()
			this.setCamera()
			this.setRenderer()
			this.setEffect()
			this.setController()
			this.addHelper()
			this.setPMREMGenerator()
			this.setLight()
			this.setMesh()
			this.addStatus()
		},
		/**
		 * @description 创建场景
		 */
		setScene() {
			// 创建场景对象Scene
			this.scene = new THREE.Scene()
			// 设置场景背景
			// this.scene.background = new THREE.Color(0xbfe3dd);
			this.scene.background = textureCube;
		},
		/**
		 * @description 创建相机
		*/
		setCamera() {
			// 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度
			this.camera = new THREE.PerspectiveCamera(60, this.container.clientWidth / this.container.clientHeight, 1, 100000)
			// 设置相机位置
			this.camera.position.set(0, 0, 3200)
			// 设置摄像头宽高比例
			this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
			// 设置摄像头投影矩阵
			this.camera.updateProjectionMatrix();
			// 设置相机视线方向
			this.camera.lookAt(new THREE.Vector3(0, 0, 0))// 0, 0, 0 this.scene.position
			// 将相机加入场景
			this.scene.add(this.camera)
		},
		/**
		 * @description 创建渲染器
		 */
		setRenderer() {
			// 初始化渲染器
			this.renderer = new THREE.WebGLRenderer({
				antialias: true,// 设置抗锯齿
				logarithmicDepthBuffer: true,  // 是否使用对数深度缓存
			})
			// 设置渲染器宽高
			this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
			// 设置渲染器的像素比
			this.renderer.setPixelRatio(window.devicePixelRatio);
			// 是否需要对对象排序
			// this.renderer.sortObjects = false;
			// 将渲染器添加到页面
			this.container.appendChild(this.renderer.domElement);
		},
		/**
		* @description 创建双屏渲染器
		*/
		setEffect() {
			// 初始化渲染器
			this.effect = new StereoEffect(this.renderer)
			// 设置渲染器宽高
			this.effect.setSize(this.container.clientWidth, this.container.clientHeight);
		},

		/**
		 * @description 添加创建控制器
		 */
		setController() {
			this.controller = new OrbitControls(this.camera, this.renderer.domElement);
			// 控制缩放范围
			// this.controller.minDistance = 1;
			// this.controller.maxDistance = 5;
			//是否开启右键拖拽
			// this.controller.enablePan = false;
			// 阻尼(惯性)
			this.controller.enableDamping = true; //启用阻尼(惯性)
			this.controller.dampingFactor = 0.04; //阻尼惯性有多大
			// this.controller.autoRotate = true; //自动围绕目标旋转
			// this.controller.minAzimuthAngle = -Math.PI / 3; //能够水平旋转的角度下限。如果设置,其有效值范围为[-2 * Math.PI,2 * Math.PI],且旋转角度的上限和下限差值小于2 * Math.PI。默认值为无穷大。
			// this.controller.maxAzimuthAngle = Math.PI / 3;//水平旋转的角度上限,其有效值范围为[-2 * Math.PI,2 * Math.PI],默认值为无穷大
			// this.controller.minPolarAngle = 1; //能够垂直旋转的角度的下限,范围是0到Math.PI,其默认值为0。
			// this.controller.maxPolarAngle = Math.PI - 0.1; //能够垂直旋转的角度的上限,范围是0到Math.PI,其默认值为Math.PI。
			// 修改相机的lookAt是不会影响THREE.OrbitControls的target的
			// 由于设置了控制器,因此只能改变控制器的target以改变相机的lookAt方向
			// this.controller.target.set(0, 0.5, 0); //控制器的焦点
		},
		/**
		 * @description 创建辅助坐标轴
		 */
		addHelper() {
			// 模拟相机视锥体的辅助对象
			let helper = new THREE.CameraHelper(this.camera);
			// this.scene.add(helper);
			//创建辅助坐标轴、轴辅助 (每一个轴的长度)
			let axisHelper = new THREE.AxesHelper(150);  // 红线是X轴,绿线是Y轴,蓝线是Z轴
			this.scene.add(axisHelper)
			// 坐标格辅助对象
			let gridHelper = new THREE.GridHelper(100, 30, 0x2C2C2C, 0x888888);
			this.scene.add(gridHelper);
		},
		/**
		 * @description 给场景添加环境光效果
		 */
		setPMREMGenerator() {
			// 预过滤的Mipmapped辐射环境贴图
			const pmremGenerator = new THREE.PMREMGenerator(this.renderer);
			this.scene.environment = pmremGenerator.fromScene(new RoomEnvironment(this.renderer), 0.04).texture;
		},
		/**
		 * @description 设置光源
		 */
		setLight() {
			// 环境光
			const ambientLight = new THREE.AmbientLight(0x404040, 4);
			// this.scene.add(ambientLight);
			// 平行光
			const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
			// this.scene.add(directionalLight);
			// 点光源 - 照模型
			const test = new THREE.PointLight("#ffffff", 10, 2);
			// test.position.set(0, 0, 0);
			// this.scene.add(test);
			//点光源 - 辅助对象
			const testHelperMap = new THREE.PointLightHelper(test);
			// this.scene.add(testHelperMap);
		},
		/**
		 * @description 创建性能监听器
		*/
		addStatus() {
			// 创建一个性能监听器
			this.stats = new Stats();
			// 将性能监听器添加到容器中
			this.container.appendChild(this.stats.dom);
		},
		/**
		* @description 添加创建模型
		*/
		setMesh() {
			// 创建模型
			// THREE.js 中环境贴图的映射模式有哪些?
			// THREE.CubeReflectionMapping:该映射模式将环境贴图作为一个立方体贴图,将六个面分别映射到对应的立方体面上,以模拟立方体环境映射和反射效果。
			// THREE.CubeRefractionMapping:该映射模式与 THREE.CubeReflectionMapping 类似,但是它模拟的是折射效果,即将环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。
			// THREE.EquirectangularReflectionMapping:该映射模式将环境贴图作为一个全景图片,将图片映射到球体或半球体上,以模拟球形环境映射和反射效果。
			// THREE.EquirectangularRefractionMapping:该映射模式与 THREE.EquirectangularReflectionMapping 类似,但是模拟的是折射效果,即将环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。
			// THREE.SphericalReflectionMapping:该映射模式将环境贴图映射到一个球形贴图上,以模拟球形环境映射和反射效果。与 THREE.EquirectangularReflectionMapping 相比,该映射模式需要使用一个球形贴图,因此对图像质量的要求较高,但可以实现更加真实的球形反射效果。

			textureCube.mapping = THREE.CubeRefractionMapping;//图像将如何应用到物体(对象)上

			const geometry = new THREE.SphereGeometry(100, 32, 16);
			const material = new THREE.MeshBasicMaterial({
				color: 0xffffff,
				envMap: textureCube,//环境贴图
				refractionRatio: 0.95,//空气的折射率(IOR)(约为1)除以材质的折射率。它与环境映射模式THREE.CubeRefractionMapping 一起使用
			})
			// 随机生成500个小球
			for (let i = 0; i < 500; i++) {
				const mesh = new THREE.Mesh(geometry, material)
				mesh.position.x = Math.random() * 10000 - 5000//[-5,5]
				mesh.position.y = Math.random() * 10000 - 5000
				mesh.position.z = Math.random() * 10000 - 5000
				mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 3 + 1//[1,4]
				this.scene.add(mesh)
				this.spheres.push(mesh)
			}
		},
		/**
		 * @description 监听屏幕的大小改变,修改渲染器的宽高,相机的比例
		*/
		// 窗口变化
		onWindowSize() {
			this.windowHalfX = this.container.clientWidth / 2;
			this.windowHalfY = this.container.clientHeight / 2;
			// 更新摄像头
			this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
			// 更新摄像机的投影矩阵
			this.camera.updateProjectionMatrix();
			//更新渲染器
			// this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
			// 设置渲染器的像素比
			// this.renderer.setPixelRatio(window.devicePixelRatio)
			// 更新3D渲染器
			this.effect.setSize(this.container.clientWidth, this.container.clientHeight);
		},
		/**
		* @description 监听 mousemove 窗口事件
		*/
		onDocumentMouseMove(event) {
			this.mouseX = (event.clientX - this.windowHalfX) * 10;
			this.mouseY = (event.clientY - this.windowHalfY) * 10;
		},
		/**
		* @description 动画执行函数
		*/
		animate() {
			// camera聚焦
			const timer = 0.0001 * Date.now();
			this.camera.position.x += (this.mouseX - this.camera.position.x) * .05;
			this.camera.position.y += (- this.mouseY - this.camera.position.y) * .05;
			this.camera.lookAt(this.scene.position);

			// 小球位置随机
			for (let i = 0; i < this.spheres.length; i++) {
				const sphere = this.spheres[i];
				sphere.position.x = 5000 * Math.cos(timer + i);
				sphere.position.y = 5000 * Math.sin(timer + i * 1.1);
			}

			const delta = this.clock.getDelta();
			// mixer 动画更新
			if (this.mixer) {
				this.mixer.update(delta);
			}
			// 引擎自动更新渲染器
			requestAnimationFrame(this.animate);
			//update()函数内会执行camera.lookAt(x, y, z)
			this.controller.update(delta);
			// 更新性能监听器
			this.stats.update();
			// 重新渲染场景
			// this.renderer.render(this.scene, this.camera);
			this.effect.render(this.scene, this.camera);
		},
	},
};
</script>
<style>
#container {
	position: absolute;
	width: 100%;
	height: 100%;
}
</style>

.lookAt(x, y, z)
			this.controller.update(delta);
			// 更新性能监听器
			this.stats.update();
			// 重新渲染场景
			// this.renderer.render(this.scene, this.camera);
			this.effect.render(this.scene, this.camera);
		},
	},
};
</script>
<style>
#container {
	position: absolute;
	width: 100%;
	height: 100%;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1794371.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

锐捷校园网自助服务系统 login_judge.jsf 任意文件读取漏洞复现(XVE-2024-2116)

0x01 产品简介 锐捷校园网自助服务系统是锐捷网络推出的一款面向学校和校园网络管理的解决方案。该系统旨在提供便捷的网络自助服务,使学生、教职员工和网络管理员能够更好地管理和利用校园网络资源。 0x02 漏洞概述 校园网自助服务系统/selfservice/selfservice/module/sc…

Linux Kernel nf_tables 本地权限提升漏洞(CVE-2024-1086)

文章目录 前言声明一、netfilter介绍二、漏洞成因三、漏洞危害四、影响范围五、漏洞复现六、修复方案临时解决方案升级修复方案 前言 2024年1月&#xff0c;各Linux发行版官方发布漏洞公告&#xff0c;修复了一个 netfilter:nf_tables 模块中的释放后重用漏洞&#xff08;CVE-…

企业数据挖掘建模平台极简建模流程

泰迪智能科技企业数据挖掘建模平台是企业自主研发&#xff0c;面向企业级用户的快速数据处理构建模型工具。平台底层算法基于R语言、Python、Spark等引擎&#xff0c;使用JAVA语言开发&#xff0c;采用 B/S 结构&#xff0c;用户无需下载客户端&#xff0c;可直接通过浏览器进…

Makefile:2:*** missing separator. Stop.

中文意思是说缺少分隔符。 解决办法如下 出现这种错误的原因: 在编辑makefile 时有些行没有前面没有按下tab键。举例&#xff1a;另外需要注意的是&#xff0c;如果你是使用vscode编辑&#xff0c;注意在vscode里面编辑的tab有可能也出现问题。建议使用vim编辑一下Makefile &a…

Word2021中的The Mathtype DLL cannot be found问题解决(office 16+mathtype7+非初次安装)

问题描述&#xff0c;我的问题发生在word中无法使用自定义功能区中的mathtype 我的环境是&#xff1a;W11Word2021mathtype7 因为我是第二次安装mathtype7&#xff0c;所以我怀疑是因为没有卸载干净&#xff0c;于是我参考了下面这篇文章的做法 参考文章 1.首先重新卸载当前的…

QT:QML中使用Loader加载界面

目录 一.介绍 二.实现 三.效果展示 四.代码 一.介绍 在QML中使用Loader加载界面&#xff0c;可以带来诸多好处&#xff0c;如提高应用程序的启动速度、动态地改变界面内容、根据条件加载不同的组件、更有效地使用内存以及帮助分割应用逻辑等。 1.延迟加载&#xff1a;QML…

【WRF理论第四期】namelist.wps文件详述

WRF理论第四期&#xff1a;namelist.wps文件详述 1 namelist.wps 的主要部分1 &share2 &geogrid3 &ungrib4 &metgrid示例 namelist.wps 文件参考 namelist.wps 文件是 WRF Preprocessing System (WPS) 的关键配置文件&#xff0c;用于设置地理数据和气象数据预…

c语言练习:POJ 1003 宿醉(HangOver)

为什么写这篇文章 作为一名计算机相关方向的学生&#xff0c;本人的代码能力却十分差劲&#xff0c;这不能不让人万分羞愧。于是&#xff0c;决定从此好好学代码&#xff0c;每天坚持刷题。而C语言是计算机程序语言的基础&#xff0c;遂决定从c语言开始&#xff0c;提高自身编…

以hive metastore报错举例,远程调试hadoop服务

项目场景&#xff1a; CDH集群CM切换hive元数据库报错&#xff1a; com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server.at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at…

UML静态图-类图

概述 静态图包含类图、对象图和包图的主要目的是在系统详细设计阶段&#xff0c;帮助系统设计人员以一种可视化的方式来理解系统的内部结构和代码结构&#xff0c;包括类的细节、类的属性和操作、类的依赖关系和调用关系、类的包和包的依赖关系。 一、类图的表示法 类图(Cla…

2024年计算机、信息工程与大数据应用国际会议(CIEBDA 2024)

2024 International Conference on Computer, Information Engineering, and Big Data Applications 【1】大会信息 会议简称&#xff1a;CIEBDA 2024 大会地点&#xff1a;中国青岛 审稿通知&#xff1a;投稿后2-3日内通知 投稿邮箱&#xff1a;ciebdasub-paper.com 【2】会…

eNSP学习——配置RIP的版本兼容、定时器和协议优先级

目录 主要命令 原理概述 实验内容 实验拓扑 实验目的 实验编址 实验步骤 1、基本配置 2、配置RIP协议的版本兼容 3、配置RIP的定时器 4&#xff0e;配置RIP协议优先级 需要eNSP各种配置命令的点击链接自取&#xff1a;华为&#xff45;NSP各种设备配置命令大全PDF版…

【YOLOv8改进[CONV]】SPDConv助力YOLOv8目标检测效果 + 含全部代码和详细修改方式 + 手撕结构图

本文将使用SPDConv助力YOLOv8目标检测效果的实践,文中含全部代码、详细修改方式以及手撕结构图。助您轻松理解改进的方法。 改进前和改进后的参数对比: 目录 一 SPDConv 二 SPDConv助力YOLOv8目标检测效果 1 整体修改 ① 添加SPDConv.py文件 ② 修改ultralytics/nn/tas…

【图像处理与机器视觉】灰度变化与空间滤波

基础 空间域与变换域 空间域&#xff1a;认为是图像本身&#xff0c;对于空间域的操作就是对图像中的像素直接进行修改 变换域&#xff1a;变换系数处理&#xff0c;不直接对于图像的像素进行处理 邻域 图像中某点的邻域被认为是包含该点的小区域&#xff0c;也被称为窗口 …

ai智能写作app有分享吗?4个专业的软件!

在数字化浪潮席卷全球的今天&#xff0c;内容创作的需求日益旺盛&#xff0c;而AI智能写作app的出现&#xff0c;无疑为内容创作者们带来了一股清新的风。它们凭借强大的自然语言处理能力和海量的数据资源&#xff0c;帮助创作者们快速生成高质量、有吸引力的文章&#xff0c;让…

目标检测-AnyLabeling标注格式转换成YOLO格式

Anylabel可以极大的增加数据的标注效率&#xff0c;但是其标注格式如何能转换成YOLO标注格式&#xff0c;具体内容如下所示。 关于AnyLabeling的其它详细介绍如下链接所示 https://blog.csdn.net/u011775793/article/details/134918861 Github链接 https://github.com/vietanhd…

五大PS插件推荐,让你的设计效率翻倍!

前言 PS插件可以在繁忙的设计工作中&#xff0c;帮助设计师们快速高效地完成任务&#xff0c;是每个设计师都渴望解决的问题。这些插件不仅能够提升设计效率&#xff0c;还能让设计师的创意得到更好的展现。接下来&#xff0c;就为大家推荐五款必备的PS插件&#xff0c;让你的…

Vue3_Vuex

目录 一、安装 二、创建实例 三、main.js引入 四、组件内使用 1.查询vuex里面的数据值 2.更改vuex里面的数据值 3.调用vuex里Actions的异步请求方法 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相…

虚拟机Ubuntu扩展磁盘大小

虚拟机Ubuntu扩展磁盘大小 1. 选择硬盘,并点击扩展,如果扩展选项是灰色的,请考虑是否开机或者留有快照 2. 虚拟机Ubuntu扩展磁盘大小 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/2aea6670d42940f68d0f53c87810ac2b.png 3. 完成后开机,此时,我们的系统是还没…

DevOps后时代,构建基于价值流的平台化工程

本文来自腾讯蓝鲸智云社区用户: CanWay 平台化工程涉及双重核心意义。一方面&#xff0c;是类似利用IDE等工具提高工程师效率的平台化工程&#xff0c;如GitOps或命令行调度般便捷。然而&#xff0c;本文重点探讨的是基于价值流的平台化工程&#xff0c;尤其针对传统金融行业&a…