webgl_effects_stereo

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.mfbz.cn/a/687326.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【乐吾乐2D可视化组态编辑器】实时数据,数据绑定

什么是绑定变量&#xff1f; 绑定变量是指把图元的一个属性与设备数据点关联的一个过程。【注意】只是建立一个数据模型的关联&#xff0c;数据源后面设置。 乐吾乐2D可视化组态编辑器地址&#xff1a;https://2d.le5le.com/ 为什么不直接设置数据源&#xff1f; 方便批量…

AWS-生产级微服务部署架构分享

使用AWS搭建云上应用 名词解释 AWS ECR&#xff1a;AWS ECR 容器存储库&#xff0c;按项目名创建容器仓库&#xff0c;一个项目对应一个仓库&#xff0c;目前是由Jenkins构建镜像远程push到AWS ECR。 **AWS ECS&#xff1a;Amazon Elastic Container Service (ECS) &#xf…

物理安全防护如何创新强化信息安全体系?

物理安全防护是信息安全体系的重要组成部分&#xff0c;它通过保护实体设施、设备和介质等&#xff0c;防止未授权访问、破坏、盗窃等行为&#xff0c;从而为信息系统提供基础的安全保障。要创新强化信息安全体系中的物理安全防护&#xff0c;可以从以下几个方面着手&#xff1…

AI查重与降重:科研人员的新型助手

论文写作低效&#xff1f;试试这四款AI论文工具和降重技术&#xff01;-笔灵 副本 在科研领域&#xff0c;AI写作工具如同新一代的科研利器&#xff0c;它们能够极大提高文献查阅、思路整理和表达优化的效率&#xff0c;本质上促进了科研工作的进步。AI写作工具不仅快速获取并…

k8s AIOps

k8s AIOps 主要介绍下k8sgpt 官站 github 介绍 k8sgpt 是一个用于扫描Kubernetes集群、诊断和分级问题的工具。它以简单的英语呈现问题&#xff0c;并将站点可靠性工程&#xff08;SRE&#xff09;的经验编码到其分析器中。通过AI丰富问题的解释&#xff0c;k8sgpt帮助提取最…

面试题react03

React事件机制&#xff1a; React的事件机制可以分为两个部分&#xff1a;事件的触发和事件的处理。事件的触发&#xff1a;在React中&#xff0c;事件可以通过用户与组件进行交互而触发&#xff0c;如点击、鼠标移动、键盘输入等。当用户与组件进行交互时&#xff0c;浏览器会…

mysql 8 linux7,8安装教程

选择自己对应的linux版本 cat /etc/os-release //查看自己linux系统版本 1.mysql下载地址 MySQL :: Download MySQL Community Server (Archived Versions) 拉到下面找到 选择自己linux指定的版本&#xff0c;否则会很麻烦 cat /etc/os-release //查看系统版本 2.查…

为什么给网站安装SSL证书之后还是有被提示不安全?

分为两种情况一种是安装了付费证书之后还是显示无效&#xff0c;另一种是安装了免费SSL证书的。 付费SSL证书&#xff1a;直接找厂商帮助解决遇到的问题&#xff0c;一般都是有专业的客服来对接这些的。 免费SSL证书&#xff1a;出现这种情况的原因会有很多。因为免费SSL证书的…

代码随想录-二叉树 | 101对称二叉树

代码随想录-二叉树 | 101对称二叉树 LeetCode 101-对称二叉树解题思路代码难点总结 LeetCode 101-对称二叉树 题目链接 代码随想录 题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 解题思路 判断&#xff1a; 同时遍历并比较根节点的左、右子树。…

服务器数据恢复—强制上线raid5阵列离线硬盘导致raid不可用的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌2850服务器中有一组由6块SCSI硬盘组建的raid5磁盘阵列&#xff0c;linux操作系统ext3文件系统。 服务器故障&#xff1a; 服务器运行过程中突然瘫痪。服务器管理员检查阵列后发现raid5阵列中有两块硬盘离线&#xff0c;将其中一块硬盘进行…

3、前端本地环境搭建

前端本地环境搭建 安装node [node下载地址] https://nodejs.org/en/download/prebuilt-installer 选择LTS的版本进行下载 下载后直接双击点击&#xff0c;选择自己想要安装到的目录一直点下一步即可&#xff08;建议不要安装到c盘&#xff09; 安装完成后配置环境变量&am…

JSON 无法序列化

JSON 无法序列化通常出现在尝试将某些类型的数据转换为 JSON 字符串时&#xff0c;这些数据类型可能包含不可序列化的内容。 JSON 序列化器通常无法处理特定类型的数据&#xff0c;例如日期时间对象、自定义类实例等。在将数据转换为 JSON 字符串之前&#xff0c;确保所有数据都…

PHP线上文具商城设计与实现-计算机毕业设计源码65198

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对线上文具商城 等问题&#xff0c;对线上文具…

Python 和 Java 实现云计算的最终年项目

1、问题背景 目前&#xff0c;我正在进行我的最终年项目&#xff0c;计划用 Python 编写一个云计算系统&#xff0c;而云客户端将由我的团队成员使用 Java 来编写。这个云客户端将具有一个带有标签的界面&#xff0c;并提供文本编辑器、媒体播放器、几个基于 Java 的小游戏以及…

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048 2024/6/7 13:59 1、背光部分&#xff1a;&backlight { pwms <&pwm2 0 25000 0>; status "okay"; }; &pwm2 { status "okay&…

5、搭建前端项目

5.1 使用vite vue搭建 win r 打开终端 切换到你想要搭建的盘 npm init vitelatest跟着以下步骤取名即可 cd fullStackBlognpm installnpm run dev默认在 http://localhost:5173/ 下启动了 5.2 用vscode打开项目并安装需要的插件 1、删除多余的 HelloWorld.vue 文件 2、安装…

linux驱动学习(七)之混杂设备

需要板子一起学习的可以这里购买&#xff08;含资料&#xff09;&#xff1a;点击跳转 一、混杂设备 混杂设备也叫杂项设备&#xff0c;是对普通的字符设备(struct cdev)的一种封装,设计目的就是为了简化字符设备驱动设计的流程。具有以下特点&#xff1a; 1) 主设备号为10&a…

你工作中最推荐的 C/C++ 程序库有哪些,为什么?

我主要做计算力学&#xff0c;说说平时用的一些c库1、前处理划网格用netgen&#xff0c;非结构网格功能强大&#xff0c;有可执行的软件和供调用的库&#xff0c;使用方便。 刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&…

1898java疫情防控管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 疫情防控管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了java设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发…

【JMeter接口测试工具】第一节.JMeter简介和安装【入门篇】

文章目录 前言一、JMeter简介 1.1 JMeter基本介绍 1.2 JMeter优缺点二、JMeter安装 2.1 JMeter安装步骤 2.2 JMeter环境配置三、项目介绍 3.1 项目简介 3.2 API接口清单总结 前言 一、JMeter简介 1.1 JMeter基本介绍 JMeter 是 Apache 组织使用…