Three.js遮罩多场景穿梭过渡

请添加图片描述
仓库

思路:

渲染一个遮罩 亮的区域为需要显示另一个场景的区域
在靠近门时完全渲染一个场景 在穿过门的同时切换场景关系

if (this.Doors.length) {
	// 材质变为黑色 除了“门”
    toggleRoughnessMaterial("black");
	// 设置RenderTarget保存结果
	renderer.setRenderTarget(doorsRenderTarget);
	// 渲染
	render(this.helper.scene, this.helper.camera);
	// 获取“门”的区域是否占满全屏
    const region = this.getDoorRegion(fullWidth - 1, fullHeight - 1);

    if (region == 1) {
	    // 当前的方式
        const curr = moebiusPass.reversalTag;
 		// 切换对应渲染方式
        moebiusPass.reversal = curr == "1" ? "2" : "1";
    }
	// 验证时候穿过门 并切换场景
    PassedDoor();
	// 重置RenderTarget
	renderer.setRenderTarget(null);
	// 材质切换回来
	scene.toggleRoughnessMaterial("default");
	// 隐藏“门”
    this.Doors.forEach((obj: any) => (obj.visible = false));
}

获取穿梭门的渲染范围在屏幕中的占比

getDoorRegion(fullWidth: number, fullHeight: number) {
    // 采样颜色平均值 判断距离
    const _gl = this.helper.renderer.getContext() as WebGL2RenderingContext;
    const pixels = new Uint8Array(4 * 1 * 1);
    const count = 2;
    const ratio = 1 / (count - 1);
    let total = 0;

    // 左下角开始
    for (let i = 0; i < count; i++) {
        for (let j = 0; j < count; j++) {
            _gl.readPixels(
                fullWidth * i * ratio,
                fullHeight * j * ratio,
                1,
                1,
                _gl.RGBA,
                _gl.UNSIGNED_BYTE,
                pixels
            );
            total += pixels[0];
            total += pixels[1];
            total += pixels[2];
        }
    }

    total /= count * count * 255 * 3;

    return total;
}

判断是否穿过门和方向

const PassedDoor = () => {
   const nearDoor = this.Doors.map((door) => {
       const distance = door.position.distanceTo(this.helper.camera.position);
       door.userData.distance = distance;
       return distance;
   });

   // 找到最小的一项的索引
   const minIndex = nearDoor.reduce(
       (minIdx, currentValue, currentIndex, arr) => (currentValue < arr[minIdx] ? currentIndex : minIdx),
       0
   );

   // 最近的门
   const door = this.Doors[minIndex];

   // 离得远不进行计算
   if (door.userData.distance > 2) {
       this.dir = -1;
       this.passed = false;
       return;
   }

   cameraWorldPosition.setFromMatrixPosition(this.helper.camera.matrixWorld);

   rotationMatrix.extractRotation(door.matrixWorld);

   normal.set(0, 1, 0);
   // normal.set(0, 0, 1);
   normal.applyMatrix4(rotationMatrix);

   const doorWorldPos = door.getWorldPosition(new THREE.Vector3());

   view.subVectors(doorWorldPos, cameraWorldPosition);

   // console.log(view.normalize().dot(normal.normalize()) > 0);
   const front = +(view.normalize().dot(normal.normalize()) < 0);

   if (this.dir != -1 && this.dir != front) {
       console.log("Passed");
       moebiusPass.reversal = moebiusPass.reversal == "1" ? "mix1" : "mix2";
       moebiusPass.reversalTag = moebiusPass.reversalTag == "1" ? "2" : "1";
       moebiusPass.setITime(0);
   }

   this.dir = front;
   // console.log(this.dir);
};

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

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

相关文章

【Linux系统】为什么环境变量具有全局性?共享?写时拷贝优化?

环境变量表具有全局性的原因&#xff1a; 环境变量表之所以具有全局性的特征&#xff0c;主要是因为它们是在进程上下文中维护的&#xff0c;并且在大多数操作系统中&#xff0c;当一个进程创建另一个进程&#xff08;即父进程创建子进程&#xff09;时&#xff0c;子进程会继承…

网站建设前需要搞清楚哪些问题

网站建设前需要搞清楚的问题涉及多个方面&#xff0c;以下是一些关键问题的概述&#xff1a; 明确目标和目的 企业宣传与品牌塑造&#xff1a;网站是企业展示形象、传播品牌的重要窗口。通过精心设计的网站界面和内容布局&#xff0c;可以向潜在客户传递企业的价值观、文化理念…

iOS AVAudioSession 详解【音乐播放器的配置】

前言 在 iOS 音频开发中&#xff0c;AVAudioSession 是至关重要的工具&#xff0c;它控制着应用的音频行为&#xff0c;包括播放、录音、后台支持和音频中断处理等。对于音乐播放器等音频需求强烈的应用&#xff0c;设计一个合理的 AVAudioSession 管理体系不仅能保证音频播放…

[JAVAEE] 多线程的案例(三) - 线程池

目录 一. 什么是线程池 二. 线程池的作用 三. java提供的线程池类 四. ThreadPoolExecutor的构造方法及参数理解 1. int corePoolSize: 核心线程数. 2. int maximumPoolSize: 最大线程数 核心线程数 非核心线程数 3. int keepAliveTime:非核心线程允许空闲的最大时间. …

网络通信与并发编程(六)线程、进程池与线程池

线程、进程池与线程池 文章目录 线程、进程池与线程池一、线程二、线程的相关操作2.1创建线程的两种方式2.2线程的其他操作2.3死锁现象和递归锁2.4条件2.5定时器2.6 队列与堆栈 三、进程池与线程池 一、线程 线程是指cpu上实际执行计算的单位&#xff0c;而进程是将计算所需资…

Leetcode刷题笔记12

HJ1 字符串最后一个单词的长度 字符串最后一个单词的长度_牛客题霸_牛客网 这里可以使用rfind()&#xff0c;rfind()函数从字符串的末尾向前查找第一个空格的位置。这个空格将是最后一个单词和前面的单词的分隔符。首先使用getline读取字符串&#xff0c;然后用rfind找到最后一…

class 36 二叉树高频题目 - 上 (不含有树形dp)

1. BFS 的两种方式 如下图, 是一个二叉树. 我们需要按照层的方式来遍历这棵树. 1.1 使用 JDK 自带的类实现(链表实现, 经典 BFS) 首先我们实现一个队列, 这个队列从头进, 从尾出.然后将根节点放入其中, 然后将放入的节点弹出,然后继续验证弹出的节点有没有左孩子, 若是有, 将…

便捷之选:微信小程序驱动的停车场管理系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

跨境支付,哪些国产数据库能接得住?

最近有一个非常重大的事件&#xff0c;那就是10月22日-24日的金砖国家会议。金砖国家领导人第十六次会晤是金砖国家进一步凝聚共识、以实际行动推动“全球南方”共同发展进步的重要机遇。 酝酿已久的金砖跨境支付体系&#xff0c;也在这次峰会中正式推出。金砖国家的支付系统一…

国内大语言模型哪家更好用?

大家好&#xff0c;我是袁庭新。 过去一年&#xff0c;AI大语言模型在爆发式增长&#xff0c;呈现百家争鸣之态。国内外相关厂商积极布局&#xff0c;并相继推出自家研发的智能化产品。 我在工作中已习惯借助AI来辅助完成些编码、创作、文生图等任务&#xff0c;甚至对它们产…

【计网】从零开始认识IP协议 --- 认识网络层,认识IP报头结构

从零开始认识IP协议 1 网络层协议1.1 初步认识IP协议1.2 初步理解IP地址 2 IP协议报头3 初步理解网段划分 1 网络层协议 1.1 初步认识IP协议 我们已经熟悉了传输层中的UDP和TCP协议&#xff0c;接下来我们来接触网络层的协议&#xff1a; 网络层在计算机网络中的意义主要体现…

线段树

文章目录 1 线段树概念2 线段树操作2.1 建树2.2 区间修改2.3 区间查询2.4 练习题目 3 线段树进阶3.1 乘法线段树 * 补充&#xff1a;快读快写4 End 1 线段树概念 线段树 ( S e g m e n t T r e e ) (Segment\ Tree) (Segment Tree) 是 O I OI OI 中的常用算法。线段树是一种…

PHP-FPM 性能配置优化

4 核 8 G 服务器大约可以开启 500 个 PHP-FPM&#xff0c;极限吞吐量在 580 qps &#xff08;Query Per Second 每秒查询数&#xff09;左右。 Nginx php-fpm 是怎么工作的&#xff1f; php-fpm 全称是 PHP FastCGI Process Manager 的简称&#xff0c;从名字可得知&#xff…

基于SSM的冰淇淋在线购买网站【附源码】

基于SSM的冰淇淋在线购买网站 效果如下&#xff1a; 系统首页界面 用户登录界面 冰淇淋页面 每日秒杀页面 个人中心界面 管理员登录界面 管理员功能界面 口味管理界面 冰淇淋管理界面 每日秒杀管理界面 视频教学管理界面 研究背景 近些年&#xff0c;随着中国经济发展&#…

订购 Claude AI 的第二天 它独自完成 文字转语音 flask应用

图二里&#xff0c;删除几个无关的 chats 全程我做的工作&#xff1a;向 AI 提要求&#xff0c;copy / paste 代码&#xff0c;在venv验证运行&#xff0c;向 AI 反馈&#xff0c;总共用了3个 chats.&#xff08;图中的只有一个 Chat&#xff0c; 删掉的另外两个: Python 库安…

海外云手机实现高效的海外社交媒体营销

随着全球化的深入发展&#xff0c;越来越多的中国企业走向国际市场&#xff0c;尤其是B2B外贸企业&#xff0c;海外社交媒体营销已成为其扩大市场的重要手段。在复杂多变的海外市场环境中&#xff0c;如何有效提高营销效率并降低运营风险&#xff0c;成为了众多企业的首要任务。…

计算机网络(十二) —— 高级IO

#1024程序员节 | 征文# 目录 一&#xff0c;预备 1.1 重新理解IO 1.2 五种IO模型 1.3 非阻塞IO 二&#xff0c;select 2.1 关于select 2.2 select接口参数解释 2.3 timeval结构体和fd_set类型 2.4 socket就绪条件 2.5 select基本工作流程 2.6 简单select的服务器代…

【mysql进阶】4-8 临时表空间

临时表空间 - Temporary Tablespaces 1 什么是临时表&#xff1f; ✅ 解答问题 临时表存储的是临时数据&#xff0c;不能永久的存储数据&#xff0c;⼀般在复杂的查询或计算过程中⽤来存储过渡的中间结果&#xff0c;MySQL在执⾏查询与计算的过程中会⾃动⽣成临时表&#xff0c…

C++ 抛异常

目录 一.抛异常与运行崩溃的区别 1.运行崩溃 2.抛异常 二.抛异常机制存在的意义 1.清晰的处理错误 2.结构化的错误管理 3.跨函数传递错误信息 4.异常对象多态性 三.抛异常的使用方法 1.抛出异常 (throw) 2.捕获异常 (catch) 3.标准异常类 四.抛异常的处理机制 1.抛…

2024“源鲁杯“高校网络安全技能大赛-Misc-WP

Round 1 hide_png 题目给了一张图片&#xff0c;flag就在图片上&#xff0c;不过不太明显&#xff0c;写个python脚本处理一下 from PIL import Image ​ # 打开图像并转换为RGB模式 img Image.open("./attachments.png").convert("RGB") ​ # 获取图像…