webgl_framebuffer_texture

news2024/11/24 22:31:38

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>

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

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

相关文章

嵌入式Linux系统编程 — 2.3 标准I/O库:格式化I/O

目录 1 格式化I/O简介 2 格式化输出 2.1 格式化输出函数简介 2.2 格式控制字符串 format 2.3 示例程序 3 格式化输入 3.1 格式化输入简介 3.2 格式控制字符串 format 3.3 示例程序 1 格式化I/O简介 在先前示例代码中&#xff0c;经常使用库函数 printf() 来输出程序中…

操作系统教材第6版——个人笔记6

3.3.4 页面调度 页面调度 当主存空间已满而又需要装入新页时&#xff0c;页式虚拟存储管理必须按照一定的算法把已在主存的一些页调出去 #主存满加新&#xff0c;把已在主存一些页调出选择淘汰页的工作称为页面调度 选择淘汰页的算法称为页面调度算法 页面调度算法设计不当&a…

【递归、搜索与回溯】递归、搜索与回溯准备+递归主题

递归、搜索与回溯准备递归主题 1.递归2.搜索3.回溯与剪枝4.汉诺塔问题5.合并两个有序链表6.反转链表7.两两交换链表中的节点8.Pow(x, n)-快速幂&#xff08;medium&#xff09; 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你…

解决Windows Hosts 文件因为权限无法修改的问题

如何修改 Windows Hosts 文件并添加域名映射 在日常工作中&#xff0c;可能需要修改 Windows 的 hosts 文件&#xff0c;以将特定的域名映射到指定的 IP 地址。本文介绍三种方法来完成这一任务&#xff1a;直接手动编辑 hosts 文件&#xff0c;使用批处理文件自动完成任务&…

哈默纳科Harmonic谐波减速机应用领域有哪些

在制造设备中&#xff0c;精确控制速度与位置的需求日益凸显&#xff0c;这为谐波减速机的广泛应用提供了广阔的舞台。哈默纳科Harmonic谐波减速机以结构紧凑、高精度、高刚度、高可靠性、便于安装维护等优势&#xff0c;在工业机器人和自动化系统中发挥着举足轻重的作用。 一、…

如何调用地方天地图?

我们在《如何申请自己的专属天地图&#xff1f;》一文中&#xff0c;为大家分享了如果申请专属天地图&#xff0c;并在水经微图&#xff08;以下简称“微图”&#xff09;中加载的具体方法。 于是&#xff0c;就有朋友问如何调地方用天地图。 现在&#xff0c;我们就以四川地…

六位一线AI工程师总结大模型应用摸爬滚打一年的心得,网友:全程高能!

六位一线AI工程师和创业者&#xff0c;把在大模型应用开发上摸爬滚打一整年的心得&#xff0c;全&#xff01;分&#xff01;享&#xff01;了&#xff01; &#xff08;奇怪的六一儿童节大礼包出现了&#xff09; 这篇干货长文&#xff0c;一时间成为开发者社区热议的话题。…

2024年几款优秀的SQL IDE优缺点分析

SQL 工具在数据库管理、查询优化和数据分析中扮演着重要角色。 以下是常见的 SQL 工具及其优缺点。 1. SQLynx 优点&#xff1a; 智能代码补全和建议&#xff1a;采用AI技术提供高级代码补全、智能建议和自动错误检测&#xff0c;大幅提高编写和调试SQL查询的效率。跨平台和…

蓝桥杯物联网竞赛_STM32L071_19_输出方波信号(PWM)

国赛考了一个方波&#xff0c;第一次考这个&#xff0c;连个示波器都没有 CUBMX配置&#xff1a; 按上述配置刚好是32MHZ / 32 / 100 10KHZ 理论&#xff1a; 频率&#xff1a;就是一秒钟能产生多少个脉冲&#xff0c;如下图: 这算是一个脉冲&#xff0c;1KHZ说明一秒钟产生…

源码发布Quantlab4.2,Deap因子挖掘|gplearn做不到的咱们也能做。(代码+数据)

原创文章第552篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 又到了星球发布代码的日子&#xff1a; 更新说明&#xff1a;1、Deap做因子挖掘的框架使用。值得说明的是&#xff0c;源码级别&#xff0c;并非产品级&#xff0c;不能指望输入一堆…

降噪是什么意思?视频如何降噪?一文了解全部

在视频制作的过程中&#xff0c;我们经常会遇到噪音问题&#xff0c;这些噪音可能来自拍摄环境、录制设备或其他源头。然而&#xff0c;对于初学者来说&#xff0c;降噪是什么意思&#xff0c;以及如何有效地在视频中进行降噪可能是一些疑惑的问题。本文将深入解释降噪的概念&a…

Mat的lambda方式像素高效遍历(C++11)

Mat的lambda方式像素高效遍历&#xff08;C11&#xff09; 文章目录 Mat的lambda方式像素高效遍历&#xff08;C11&#xff09;前言一、Mat的lambda方式像素高效遍历二、代码实现总结 前言 图像遍历是图像处理中的经典操作&#xff0c;快速高效的进行像素遍历对性能的提升至关…

[AI OpenAI] 提取GPT-4中的概念

总结&#xff1a; 研究人员采用新的可扩展方法&#xff0c;将GPT-4的内部表示分解为1600万个通常可解释的模式&#xff0c;这些模式被称为“特征”&#xff0c;目的是提高语言模型的透明度和可解释性。通过使用稀疏自编码器&#xff0c;研究人员能够识别与特定概念相关的特征&…

《今日科技》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《今日科技》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊 问&#xff1a;《今日科技》是什么级别的&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;浙江省科学技术厅 主办单位&#xff1a;浙江省…

免费分享一套SpringBoot+Vue校园论坛(微博)系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue校园论坛(微博)系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue校园论坛(微博)系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue校园论坛(微博)系统 Java毕业设计…

Cesium401 (Unauthorized)https://api.cesium.com/v1/assets/2/endpoint未授权问题

目录 前言1.原因分析2.解决问题1.禁用默认的imageryProvider2.禁用图层切换3.移除所有默认图层4.使用自己的地形(可选) 3.最终解决方案4.总结 前言 在初始化Cesium的Viewer以后&#xff0c;Viewer会自动去访问Cesium官网的资源&#xff0c;如果访问不到官网的资源&#xff0c;就…

parseInt函数

貌似遇到问题了&#xff0c;在Java中&#xff0c;parseInt方法是java.lang.Integer类的一个静态方法&#xff0c;它用来将字符串转换为基本数据类型int。如果字符串不能被解析为有效的整数&#xff0c;parseInt会抛出一个NumberFormatException。 原来是取整串转换&#xff0c;…

Lab_ Exploiting an API endpoint using documentation

https://portswigger.net/web-security/learning-paths/api-testing/ 开局一个页面 打开代理和burp&#xff0c;查看功能点&#xff0c;然后看HTTPhistory 然后使用题目已知的账号去登录一下 My account 登录 然后发现 /api 路径 那么我们访问一下 URL/api &#xff0c;发现…

宋仕强论道 之 AI(人工智能)

《宋仕强论道 之 AI&#xff08;人工智能&#xff09;如何赋能新质生产力》于6月3日由新华瞭望网首发后&#xff0c;被环球科技新闻网等多家媒体转载&#xff1b;随后又分别以《宋仕强论道 之 AI如何赋能新质生产力》《宋仕强&#xff1a;AI赋能新质生产力的理论探索与实践路径…

有关大学的搜题软件?六个不限次的公众号和软件分享啦 #其他#职场发展

有些同学虽然喜欢刷题&#xff0c;但是如果参考答案遗失、找不到参考答案&#xff0c;导致做好的题目无法校对&#xff0c;就会比较烦恼了。不过不用担心&#xff0c;今天就给大家分享一些超好用的搜题工具 1.彩虹搜题 这是个老公众号了 它不仅可以查到大学题目&#xff0c;…