webgl_framebuffer_texture

ThreeJS 官方案例学习(webgl_framebuffer_texture)

1.效果图

在这里插入图片描述

2.源码

<template>
	<div>
		<div id="container">
		</div>
		<div id="selection">
			<div></div>
		</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 * as GeometryUtils from 'three/examples/jsm/utils/GeometryUtils.js';
const dpr = window.devicePixelRatio;

const textureSize = 128 * dpr;
export default {
	data() {
		return {
			container: null, //界面需要渲染的容器
			scene: null,	// 场景对象
			camera: null, //相机对象(透视相机)
			renderer: null, //渲染器对象
			controller: null,	// 相机控件对象
			stats: null,// 性能监听器
			mixer: null,//动画混合器
			clock: new THREE.Clock(),// 创建一个clock对象,用于跟踪时间
			vector: new THREE.Vector2(),//用于计算复制部分帧数据的起始位置
			color: new THREE.Color(),//Color颜色对象,方便后续使用
			offset: 0,//颜色偏移度
			line: null,//线模型
			sprite: null,//点精灵材质
			texture: null,//帧缓冲纹理
			cameraOrtho: null,//正交相机
			sceneOrtho: null,//
		};
	},
	mounted() {
		this.init()
		this.animate()  //如果引入了模型并存在动画,可在模型引入成功后加载动画
		window.addEventListener("resize", this.onWindowSize)
	},
	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.setScene()
			this.setCamera()
			this.setRenderer()
			this.addHelper()
			this.setController()
			this.setPMREMGenerator()
			this.setLight()
			this.setGltfLoader()
			// this.addStatus()
		},
		/**
		 * @description 创建场景
		 */
		setScene() {
			// 创建场景对象Scene
			this.scene = new THREE.Scene()
			// 设置场景背景
			// this.scene.background = new THREE.Color(0xbfe3dd);

			this.sceneOrtho = new THREE.Scene();
		},
		/**
		 * @description 创建相机
		*/
		setCamera() {
			// 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度
			this.camera = new THREE.PerspectiveCamera(70, this.container.clientWidth / this.container.clientHeight, 1, 1000)
			// 设置相机位置
			this.camera.position.set(0, 0, 20)
			// 设置摄像头宽高比例
			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)

			// 添加正交相机
			this.cameraOrtho = new THREE.OrthographicCamera(- this.container.clientWidth / 2, this.container.clientWidth / 2, this.container.clientHeight / 2, - this.container.clientHeight / 2, 1, 10);
			this.cameraOrtho.position.z = 10;
		},
		/**
		 * @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.renderer.autoClear = false;
			// 将渲染器添加到页面
			this.container.appendChild(this.renderer.domElement);
		},
		/**
		 * @description 添加创建控制器
		 */
		setController() {
			// 为什么要绑定 selection 对象(可能selection的css层级最高,需要绑定它才能移动模型)
			this.controller = new OrbitControls(this.camera, document.getElementById('selection'));
			// 绑定这个也可以运行 this.renderer.domElement,但是要降低 selection 的层级,但是降低了就看不到白色边框了,需要另外除了白色边框
			// 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; //阻尼惯性有多大
		},
		/**
		 * @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, 100);
			// 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 添加创建模型
		*/
		setGltfLoader() {
			// 添加线模型
			const points = GeometryUtils.gosper(8)
			const geometry = new THREE.BufferGeometry()
			const positionAttribute = new THREE.Float32BufferAttribute(points, 3)
			geometry.setAttribute('position', positionAttribute)
			geometry.center()

			const colorAttribute = new THREE.BufferAttribute(new Float32Array(positionAttribute.array.length), 3)
			colorAttribute.setUsage(THREE.DynamicDrawUsage);
			geometry.setAttribute('color', colorAttribute);
			const material = new THREE.LineBasicMaterial({ vertexColors: true });// 使用点设置的颜色,使用点设置的颜色
			this.line = new THREE.Line(geometry, material)
			this.line.scale.setScalar(0.05)
			this.scene.add(this.line)
			//实例化一个framebuffer纹理
			this.texture = new THREE.FramebufferTexture(textureSize, textureSize);//(这个类只能与 WebGLRenderer.copyFramebufferToTexture() 结合使用)
			const spriteMaterial = new THREE.SpriteMaterial({ map: this.texture });
			//创建Sprite平面
			this.sprite = new THREE.Sprite(spriteMaterial);
			this.sprite.scale.set(textureSize, textureSize, 1);
			this.sceneOrtho.add(this.sprite)
			this.updateSpritePosition()
			this.updateColors(colorAttribute);
		},
		/**
		* @description 更新Sprite位置
		*/
		updateSpritePosition() {
			const halfWidth = this.container.clientWidth / 2;
			const halfHeight = this.container.clientHeight / 2;
			const halfImageWidth = textureSize / 2;
			const halfImageHeight = textureSize / 2;
			this.sprite.position.set(- halfWidth + halfImageWidth, halfHeight - halfImageHeight, 1);
		},
		/**
		* @description 模型颜色更新
		*/
		updateColors(colorAttribute) {
			const l = colorAttribute.count;
			for (let i = 0; i < l; i++) {
				const h = ((this.offset + i) % l) / l;
				this.color.setHSL(h, 1, 0.5);
				colorAttribute.setX(i, this.color.r);
				colorAttribute.setY(i, this.color.g);
				colorAttribute.setZ(i, this.color.b);
			}
			colorAttribute.needsUpdate = true;
			// 颜色循环速度(偏离量)
			this.offset -= 10;
		},
		/**
		 * @description 监听屏幕的大小改变,修改渲染器的宽高,相机的比例
		*/
		// 窗口变化
		onWindowSize() {
			// 更新摄像头
			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)

			// 更新cameraOrtho
			const width = this.container.clientWidth;
			const height = this.container.clientHeight;
			this.cameraOrtho.left = - width / 2;
			this.cameraOrtho.right = width / 2;
			this.cameraOrtho.top = height / 2;
			this.cameraOrtho.bottom = - height / 2;
			this.cameraOrtho.updateProjectionMatrix();
			this.updateSpritePosition()
		},
		/**
		* @description 动画执行函数
		*/
		animate() {
			// 引擎自动更新渲染器
			requestAnimationFrame(this.animate);
			//update()函数内会执行camera.lookAt(x, y, z)
			this.controller.update();
			// 更新性能监听器
			// this.stats.update();

			// 模型颜色更新
			const colorAttribute = this.line.geometry.getAttribute('color');
			this.updateColors(colorAttribute);
			//场景渲染
			this.renderer.clear();
			// 重新渲染场景
			this.renderer.render(this.scene, this.camera);
			// 计算复制部分帧数据的起始位置
			this.vector.x = (this.container.clientWidth * dpr / 2) - (textureSize / 2);
			this.vector.y = (this.container.clientHeight * dpr / 2) - (textureSize / 2);
			//复制渲染帧的一部分到framebuffer纹理
			this.renderer.copyFramebufferToTexture(this.vector, this.texture);
			this.renderer.clearDepth();
			this.renderer.render(this.sceneOrtho, this.cameraOrtho);

		},
	},
};
</script>
<style>
#container {
	position: absolute;
	width: 100%;
	height: 100%;
}

#selection {
	position: fixed;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	height: 100%;
	width: 100%;
	top: 0;
	z-index: 999;
}

#selection>div {
	height: 128px;
	width: 128px;
	border: 1px solid white;
}
</style>

r {
	position: absolute;
	width: 100%;
	height: 100%;
}

#selection {
	position: fixed;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	height: 100%;
	width: 100%;
	top: 0;
	z-index: 999;
}

#selection>div {
	height: 128px;
	width: 128px;
	border: 1px solid white;
}
</style>

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

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

相关文章

【sklearn】【逻辑回归1】

学习笔记来自&#xff1a; 所用的库和版本大家参考&#xff1a; Python 3.7.1Scikit-learn 0.20.1 Numpy 1.15.4, Pandas 0.23.4, Matplotlib 3.0.2, SciPy 1.1.0 1 概述 1.1 名为“回归”的分类器 在过去的四周中&#xff0c;我们接触了不少带“回归”二字的算法&#xf…

IDEA破解后的配置

以下所有操作都要求进入全局setting而不是某一个项目的setting 进入全局Setting File→close project 进入欢迎页面 低版本 然后点击Setting 关闭自动更新 不关闭有可能会破解失败 Appearance & Behavior->System Settings->Updates下取消Automatically chec…

k8s 对外服务之 Ingress(HTTPS/HTTP 代理访问 以及Nginx 进行 BasicAuth )

目录 一 Ingress HTTP 代理访问虚拟主机 &#xff08;一&#xff09;原理 &#xff08;二&#xff09;实验 1&#xff0c;准备 2&#xff0c;创建虚拟主机1资源 3&#xff0c;创建虚拟主机2资源 4&#xff0c;创建ingress资源 5&#xff0c;查看相关参数 6&#xff0…

ai写作工具哪些好用,分享4种ai智能写作软件

当我们踏入这个充满创意与无限可能的自媒体时代&#xff0c;ai写作工具就如同一盏盏闪耀的明灯&#xff0c;照亮我们的创作之路。那么&#xff0c;市面上的ai写作工具哪些好用呢&#xff1f;对于这个问题&#xff0c;今天&#xff0c;本文就带领大家一同揭开那神秘的面纱&#…

编译等底层知识

目录 一. GCC命令语句大全 二. GCC编译4个阶段 三. makefile的使用 四. CMake 五. GNU工具链开发流程图 六. Keil中的地址段 七. 静态库和动态库 一. GCC命令语句大全 -c只编译源文件&#xff0c;生成目标文件&#xff08;.o 文件&#xff09;&#xff0c;不进行链接。…

如何查询公网IP?

在互联网中&#xff0c;每个设备都有一个唯一的公网IP地址&#xff0c;用于标识设备在全球范围内的位置。查询公网IP是一个常见的需求&#xff0c;无论是用于远程访问、网络配置还是其他目的&#xff0c;了解自己的公网IP地址都是很有必要的。本文将介绍几种常见的方法来查询公…

Java并发编程中Future使用

Future类有什么用 Future类是异步思想的典型应用&#xff0c;主要用在一些需要执行耗时任务的场景&#xff0c;避免程序一直原地等待耗时任务完成&#xff0c;执行效率太低。具体来说&#xff1a;**当我们执行某一个耗时的任务时&#xff0c;可以将这个耗时任务交给一个子线程…

python3 -m http.server 检查打包前端的项目

python3 -m http.server这是 Python 提供的一个内置的简单 HTTP 服务器。当你在终端中运行 python3 -m http.server 命令时(在对应的打包目录比如dist目录)&#xff0c;Python 会启动一个 HTTP 服务器&#xff0c;它会将当前工作目录下的文件作为静态文件提供给浏览器。这个服务…

selenium非全新的方式同时启动多个浏览器又互不影响的一种实现方法,欢迎讨论!

最近在做模拟浏览器批量定时自动点击实现批量操作功能&#xff0c;主要使用selenium&#xff0c;但是发现selenium直接调用本地浏览器&#xff0c;启动的是一个全新的&#xff08;与手动打开的不一致&#xff09;&#xff0c;网站可以检测到&#xff0c;每次都要双重验证(密码登…

UnityXR Interaction Toolkit 如何使用XRHand手部识别

前言 Unity的XR Interaction Toolkit是一个强大的框架,允许开发者快速构建沉浸式的VR和AR体验。随着虚拟现实技术的发展,手部追踪成为了提升用户交互体验的关键技术之一。 本文将介绍如何在Unity中使用XR Interaction Toolkit实现手部识别功能。 准备工作 在开始之前,请…

论文阅读 A Distributional Framework for Data Valuation

本论文解决的问题 量化数据价值&#xff08;机器学习模型训练中各个数据点的贡献&#xff09; 避免数据价值受到其所处数据集的影响&#xff0c;使数据点的估值更加稳定、一致 变量假设 假设 D 表示一个在全集 Z 上的数据分布。对于监督学习问题&#xff0c;我们通常认为 Z…

RapidMiner数据挖掘4 —— 决策树

0. 序章 0.1 文本说明 所有应用程序操作的名称和编程说明都以黄色背景书写&#xff0c;问题以蓝色背景书写&#xff0c;以方便他们在文本中识别。 在整个课程中&#xff0c;请逐步遵循所有说明&#xff0c;并确保获得预期结果&#xff0c;然后再继续下一部分或问题。 通过在Ub…

Hadoop3:MapReduce源码解读之Map阶段的CombineFileInputFormat切片机制(4)

Job那块的断点代码截图省略&#xff0c;直接进入切片逻辑 参考&#xff1a;Hadoop3&#xff1a;MapReduce源码解读之Map阶段的Job任务提交流程&#xff08;1&#xff09; 6、CombineFileInputFormat原理解析 类的继承关系 与TextInputFormat切片机制的区别 框架默认的TextI…

api接口模块封装

1&#xff1a;前端封装接口 前端请求的统一封装也是为了方便前端项目的请求维护起来更加方便&#xff0c;将页面中的请求封装到js文件中&#xff0c;不同的页面需要用到相同的请求可以直接进行复用。 第一步创建一个api文件夹和js文件 第二步&#xff1a;在文件中导入axios&am…

精妙无比的App UI 风格

精妙无比的App UI 风格

springboot vue 开源 会员收银系统 (6) 收银台的搭建

前言 完整版演示 前面我们对会员系统 分类和商品的开发 完成了收银所需的基础信息 下面我们开始完成收银台的开发 简单画了一个收银的流程图大家参考下 从这张图我们可以分析一下几点 可以选择会员或散客收银选择会员使用相应的会员价结算使用会员卡则在价格基础根据卡折扣…

Day22 客户端添加IDialogService 弹窗服务

​ 本章节实现了首页点击待办事项或备忘录的时候,弹出一个对话服务窗口 当用户点击首页的“添加备忘录”或“待办事项”按钮时,系统应弹出一个对话框,以便用户执行相关的内容添加操作。下面就开始实现这个弹窗服务。 一.在Views文件夹中,再创建一个Dialog 文件夹,用于放置…

【Selenium+java环境配置】(超详细教程常见问题解决)

Seleniumjava环境配置 windows电脑环境搭建-chrome浏览器1. 下载chrome浏览器2. 查看chrome浏览器版本3. 下载chrome浏览器驱动4.配置系统环境变量PATH 验证环境是否搭建成功1. 创建java项目&#xff0c;添加pom文件中添加依赖2. 编写代码运行 常见问题&解决办法1.访问失败…

防病毒克星——白名单可信系统

白名单作为一种网络安全措施&#xff0c;其核心概念在于限制用户只能访问网络所有者定义的受信任内容。这种机制在保护系统免受恶意软件、病毒等攻击方面发挥着重要作用。然而&#xff0c;关于白名单是否可以防病毒的问题&#xff0c;实际上涉及了多个方面的考虑。 首先&#x…

【C++题解】1074 - 小青蛙回来了

问题&#xff1a;1074 - 小青蛙回来了 类型&#xff1a;需要找规律的循环 题目描述&#xff1a; 关于小青蛙爬井的故事&#xff0c;你应该早就听过了&#xff1a;井深10 尺&#xff0c;小青蛙从井底向上爬&#xff0c;每个白天向上爬 3 尺&#xff0c;每个晚上又滑下来 2 尺&…