Three.js材质纹理扩散过渡

在这里插入图片描述

Three.js材质纹理扩散过渡

import * as THREE from "three";
import { ThreeHelper } from "@/src/ThreeHelper";
import { LoadGLTF, MethodBaseSceneSet } from "@/src/ThreeHelper/decorators";
import { MainScreen } from "@/src/components/Three/Canvas";
import { Injectable } from "@/src/ThreeHelper/decorators/DI";
import type { GUI } from "dat.gui";
import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader";
import EventMesh from "@/src/ThreeHelper/decorators/EventMesh";
import { noise } from "@/src/ThreeHelper/addons/perlinNoise";
import { gsap } from "gsap";

@Injectable
export class Main extends MainScreen {
    static instance: Main;
    clock = new THREE.Clock();
    iTime = { value: 0 };
    iProgress = { value: 0.15 };
    startPoint = { value: new THREE.Vector3(-0.02, 0.2, 0.7) };
    // 初始贴图
    matcap = {
        value: this.helper.loadTexture("/public/textures/5E5855_C6C4CD_C89B67_8F8E98-512px.png"),
    };
    matcap2 = {
        value: this.helper.loadTexture("/public/textures/B6B8B1_994A24_315C81_927963-512px.png"),
    };
    textures = [
        this.helper.loadTexture("/public/textures/1A2461_3D70DB_2C3C8F_2C6CAC-512px.png"),
        this.helper.loadTexture("/public/textures/1B1B1B_999999_575757_747474-512px.png"),
        this.helper.loadTexture("/public/textures/3E2335_D36A1B_8E4A2E_2842A5-512px.png"),
        this.helper.loadTexture("/public/textures/3F3A2F_91D0A5_7D876A_94977B-512px.png"),
        this.helper.loadTexture("/public/textures/48270F_C4723B_9B5728_7B431B-512px.png"),
        this.helper.loadTexture("/public/textures/4C462E_6D876C_9AAC8F_9AABA6-512px.png"),
        this.helper.loadTexture("/public/textures/4F5246_8C8D84_7B7C74_131611-512px.png"),
        this.helper.loadTexture("/public/textures/5E5855_C6C4CD_C89B67_8F8E98-512px.png"),
        this.helper.loadTexture("/public/textures/B6B8B1_994A24_315C81_927963-512px.png"),
        this.helper.loadTexture("/public/textures/C7C7D7_4C4E5A_818393_6C6C74-512px.png"),
    ];
    play?: (swap: boolean) => void;
    playing = false;

    constructor(private helper: ThreeHelper) {
        super(helper);
        helper.main = this;
        Main.instance = this;

        this.init();
    }

    @MethodBaseSceneSet({
        addAxis: false,
        cameraPosition: new THREE.Vector3(0, 0, 2.7),
        cameraTarget: new THREE.Vector3(0, 0, 0),
        useRoomLight: true,
        near: 0.1,
        far: 800,
    })
    init() {
        const { helper } = this;

        this.loadModel();
    }

    @EventMesh.OnMouseDown(Main)
    click(result: typeof EventMesh.RayInfo) {
        // console.log(this.helper.gui.__controllers[1].name())
        // this.helper.gui?.__controllers[1].fire()
        if (!this.playing && result && result.point) {
            this.startPoint.value.copy(result.point);
            this.play && this.play(true);
        }
    }

    @LoadGLTF("/public/models/猴头.glb")
    // @LoadGLTF("/public/models/猴头细分x4.glb")
    loadModel(gltf?: GLTF) {
        if (gltf) {
            // this.helper.add(gltf.scene);
            // EventMesh.setIntersectObjects(gltf.scene.children);
            gltf.scene.traverse((obj) => {
                if (obj.type == "Mesh") {
                    const meshTemp = obj as THREE.Mesh;

                    const material = new THREE.ShaderMaterial({
                        uniforms: {
                            matcap: this.matcap,
                            matcap2: this.matcap2,
                            startPoint: this.startPoint,
                            iProgress: this.iProgress,
                            iTime: this.iTime,
                        },
                        side: THREE.DoubleSide,
                        defines: { PI: Math.PI },
                        vertexShader: /* glsl */ `
                            varying vec2 vUv;
                            varying vec3 vNormal;
                            varying vec3 vPosition;
                            varying vec3 vViewPosition;
                            attribute float aRandom;
                            attribute vec3 aCenter;
                            uniform float iProgress;
                            uniform vec3 startPoint;

                            #include <common>

                            mat4 rotation3d(vec3 axis, float angle) {
                                axis = normalize(axis);
                                float s = sin(angle);
                                float c = cos(angle);
                                float oc = 1.0 - c;
                              
                                return mat4(
                                  oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,
                                  oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,
                                  oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,
                                  0.0,                                0.0,                                0.0,                                1.0
                                );
                            }

                            void main() {
                                vUv = uv;

                                vNormal = normalMatrix * normalize( normal );

                                vPosition = position;

                                vec3 transform = position - aCenter;


                                float distancePoint = distance( startPoint, position );

                                float percent = iProgress * 4.;
                                
                                float diff = percent - distancePoint;

                                distancePoint = diff * 1.;
                                
                                distancePoint = clamp( distancePoint, 0., 1.);

                                // float intensity = smoothstep( 0., iProgress * 4.,distancePoint);
                                float intensity = distancePoint;

                                // mat4 rotation = rotation3d(vec3(normal), PI * 2. * intensity);
                                mat4 rotation = rotation3d(vec3(normal), PI * 2. * intensity);

                                transform += ((( normal * intensity ) * position * (1.0 - intensity))) / 2.;
                                transform = (rotation * vec4(transform,1.)).xyz;
                                // transform = (rotation * vec4(transform,1.)).xyz;

                                transform += aCenter;

                                vec4 modelPosition = modelMatrix * vec4(transform, 1.0);

                                vec4 modelViewPosition = viewMatrix * modelPosition;

                                gl_Position = projectionMatrix * modelViewPosition;

                                vViewPosition =  - modelViewPosition.xyz;
                            }
                        `,
                        fragmentShader: /* glsl */ `
                            varying vec3 vNormal;
                            varying vec2 vUv;
                            varying vec3 vPosition;
                            varying vec3 vViewPosition;

                            uniform float iTime;
                            uniform float iProgress;
                            uniform vec3 startPoint;
                            uniform sampler2D matcap;
                            uniform sampler2D matcap2;

                            ${noise}

                            void main() {

                                vec3 viewDir = normalize( vViewPosition );
                                vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );
                                vec3 y = cross( viewDir, x );
                                vec2 uv = vec2( dot( x, vNormal ), dot( y, vNormal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks

                                float noiseVal = noise(vPosition * 20.);

                                float distancePoint = distance( startPoint, vPosition );

                                //TODO 受物体的体积影响
                                float intensity = smoothstep( 0., iProgress * 4.,distancePoint);
                                
                                vec3 matcapColor = texture2D(matcap,uv).rgb;
                                vec3 matcapColor2 = texture2D(matcap2,uv).rgb;

                                float range = (1.0 - intensity) * pow( intensity, (iProgress + 2.) * 8.) * 100.;
                                range = (range * noiseVal * 3.) + pow(intensity,4.);

                                // matcapColor = vec3(range);

                                range = clamp(range,0.,1.);
                                // range = smoothstep(0.,1.,range);

                                matcapColor = mix(matcapColor2,matcapColor,range);
                                // matcapColor *= vec3((noiseVal) * intensity);

                                gl_FragColor = vec4(matcapColor, 1.0);
                            }
                        `,
                    });

                    /**
                     * tip: 几何体去掉indexed 点的数量会增加数倍 不再计算共用顶点
                     */
                    // const geometry = meshTemp.geometry;
                    const geometry = meshTemp.geometry.toNonIndexed();
                    const mesh = new THREE.Mesh(geometry, material);

                    this.setAttribute(geometry);

                    this.helper.add(mesh);
                    EventMesh.setIntersectObjects([mesh]);
                }
            });
        }
    }

    setAttribute(geometry: THREE.BufferGeometry) {
        const position = geometry.attributes.position.array;
        const length = geometry.attributes.position.count;

        const randoms = new Float32Array(length);
        const centers = new Float32Array(length * 3);

        for (let index = 0; index < length; index += 3) {
            const random = Math.random() * 1;

            randoms[index] = random;
            randoms[index + 1] = random;
            randoms[index + 2] = random;

            const i3 = index * 3;

            const x = position[i3];
            const y = position[i3 + 1];
            const z = position[i3 + 2];

            const x1 = position[i3 + 3];
            const y1 = position[i3 + 4];
            const z1 = position[i3 + 5];

            const x2 = position[i3 + 6];
            const y2 = position[i3 + 7];
            const z2 = position[i3 + 8];

            const center = new THREE.Vector3(x + x1 + x2, y + y1 + y2, z + z1 + z2).divideScalar(3);

            centers.set([center.x, center.y, center.z], index * 3);
            centers.set([center.x, center.y, center.z], (index + 1) * 3);
            centers.set([center.x, center.y, center.z], (index + 2) * 3);
        }

        geometry.setAttribute("aRandom", new THREE.BufferAttribute(randoms, 1));
        geometry.setAttribute("aCenter", new THREE.BufferAttribute(centers, 3));
    }

    @ThreeHelper.InjectAnimation(Main)
    animation() {
        const delta = this.clock.getDelta();
        this.iTime.value += delta / 7;
    }

    @ThreeHelper.AddGUI(Main)
    createEnvTexture(gui: GUI) {
        const progressBar = gui.add(this.iProgress, "value", 0, 1).step(0.001);

        const play = (swap = true) => {
            this.iProgress.value = 0;
            this.playing = true;

            gsap.to(this.iProgress, {
                value: 1,
                duration: 1.5,
                onUpdate: () => {
                    progressBar.updateDisplay();
                },
                onComplete: () => {
                    this.playing = false;
                    if (swap) {
                        const temp = this.matcap.value;
                        this.matcap.value = this.matcap2.value;
                        this.matcap2.value = temp;
                        this.iProgress.value = 0;
                    }
                },
            });
        };

        this.play = play;

        gui.addFunction(() => play(true)).name("play");

        this.textures.forEach((texture, index) => {
            gui.addFunction(() => {
                if (!this.playing) {
                    this.matcap.value = this.matcap2.value;
                    this.matcap2.value = texture;
                    play(false);
                }
            }).name("texture:" + (index + 1));
        });
    }

    clickImage(url: string) {
        if (!this.playing) {
            const t = this.textures.find((t) => t.image.src == url);
            if (t) {
                this.matcap.value = this.matcap2.value;
                this.matcap2.value = t;
                this.play && this.play(false);
            }
        }
    }
}

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

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

相关文章

apache-tomcat-6.0.44.exe Win10

apache-tomcat-6.0.44.exe Win10

赫布定律 | 机器学习 / 反向传播 / 经验 / 习惯

注&#xff1a;本文为 “赫布定律” 相关文章合辑。 未整理。 赫布定律 Hebb‘s law 馥墨轩 2021 年 03 月 13 日 00:03 1 赫布集合的基本定义 唐纳德・赫布&#xff08;Donald Hebb&#xff09;在 1949 年出版了《行为的组织》&#xff08;The Organization of Behavior&a…

uni-app实现小程序、H5图片轮播预览、双指缩放、双击放大、单击还原、滑动切换功能

前言 这次的标题有点长&#xff0c;主要是想要表述的功能点有点多&#xff1b; 简单做一下需求描述 产品要求在商品详情页的头部轮播图部分&#xff0c;可以单击预览大图&#xff0c;同时在预览界面可以双指放大缩小图片并且可以移动查看图片&#xff0c;双击放大&#xff0…

杭州乘云联合信通院发布《云计算智能化可观测性能力成熟度模型》

原文地址&#xff1a;杭州乘云联合中国信通院等单位正式发布《云计算智能化可观测性能力成熟度模型》标准 2024年12月3日&#xff0c;由全球数字经济大会组委会主办、中国信通院承办的 2024全球数字经济大会 云AI计算创新发展大会&#xff08;2024 Cloud AI Compute Ignite&…

第6章图6.21-6.27-《分析模式》原图和UML图对比

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集

如何在谷歌浏览器中设置广告屏蔽

在数字时代&#xff0c;网络广告无处不在&#xff0c;虽然它们为网站提供了收入来源&#xff0c;但有时也会干扰我们的浏览体验。如果你正在寻找一种方法来减少这些干扰&#xff0c;那么在谷歌浏览器中设置广告屏蔽是一个不错的选择。本文将指导你完成这一过程&#xff0c;并简…

认识网络互联设备(二)

交换机 功能&#xff1a; &#xff08;1&#xff09;通过支持并行通信&#xff0c;提高交换机的信息吞吐量&#xff1b; &#xff08;2&#xff09;将传统的一个大局域网上的用户分若干工作组&#xff0c;每个端口连接一台设备或者连接一个工作组&#xff0c;有效的解决了拥塞情…

数据可视化-2. 条形图

目录 1. 条形图适用场景分析 1.1 比较不同类别的数据 1.2 展示数据分布 1.3 强调特定数据点 1.4 展示时间序列数据的对比 1.5 数据可视化教育 1.6 特定领域的应用 2. 条形图局限性 3. 条形图图代码实现 3.1 Python 源代码 3.2 条形图效果&#xff08;网页显示&#…

AMBA-CHI协议详解(十二)

AMBA-CHI协议详解&#xff08;一&#xff09;- Introduction AMBA-CHI协议详解&#xff08;二&#xff09;- Channel fields / Read transactions AMBA-CHI协议详解&#xff08;三&#xff09;- Write transactions AMBA-CHI协议详解&#xff08;四&#xff09;- Other transac…

【MATLAB第109期】基于MATLAB的带置信区间的RSA区域敏感性分析方法,无目标函数

【MATLAB第108期】基于MATLAB的带置信区间的RSA区域敏感性分析方法&#xff0c;无目标函数 参考第64期文章【MATLAB第64期】【保姆级教程】基于MATLAB的SOBOL全局敏感性分析模型运用&#xff08;含无目标函数&#xff0c;考虑代理模型&#xff09; 创新点&#xff1a; 1、采…

《外国服务区加油站模型:功能与美观的完美结合 caotu66.com》

这个外国服务区加油站模型在设计上独具特色&#xff0c;兼具实用性和美观性。 从整体布局来看&#xff0c;加油站位于服务区的显眼位置。加油站的顶棚采用了现代风格的设计&#xff0c;顶棚的颜色主要是黄色和蓝色&#xff0c;色彩鲜明且具有辨识度。顶棚下方有多个加油柱&…

mybatis-plus超详细讲解

mybatis-plus &#xff08;简化代码神器&#xff09; 地址&#xff1a;https://mp.baomidou.com/ 目录 mybatis-plus 简介 特性 支持数据库 参与贡献 快速指南 1、创建数据库 mybatis_plus 2、导入相关的依赖 3、创建对应的文件夹 4、编写配置文件 5、编写代码 …

数据结构(顺序表)JAVA方法的介绍

前言 在 Java 中&#xff0c;集合类&#xff08;Collections&#xff09;是构建高效程序的核心组件之一&#xff0c;而 List 接口作为集合框架中的重要一员&#xff0c;是一个有序、可重复的元素集合。与 Set 接口不同&#xff0c;List 保证了元素的顺序性&#xff0c;并允许存…

泊松编辑 possion editing图像合成笔记

开源地址&#xff1a; GitHub - kono-dada/Reproduction-of-possion-image-editing 掩码必须是矩形框

【Flink-scala】DataStream编程模型之状态编程

DataStream编程模型之状态编程 参考&#xff1a; 1.【Flink-Scala】DataStream编程模型之数据源、数据转换、数据输出 2.【Flink-scala】DataStream编程模型之 窗口的划分-时间概念-窗口计算程序 3.【Flink-scala】DataStream编程模型之窗口计算-触发器-驱逐器 4.【Flink-scal…

Linux实操篇-远程登录/Vim/开机重启

目录 传送门前言一、远程登录1、概念2、ifconfig3、实战3.1、SSH&#xff08;Secure Shell&#xff09;3.2、VNC&#xff08;Virtual Network Computing&#xff09;3.3、RDP&#xff08;Remote Desktop Protocol&#xff09;3.4、Telnet&#xff08;不推荐&#xff09;3.5、FT…

【计算机网络】期末考试预习复习|上

作业讲解 物理层作业 共有4个用户进行CDMA通信。这4个用户的码片序列为&#xff1a; A: (–1 –1 –1 1 1 –1 1 1)&#xff1b;B: (–1 –1 1 –1 1 1 1 –1) C: (–1 1 –1 1 1 1 –1 –1)&#xff1b;D: (–1 1 –1 –1 –1 –1 1 –1) 现收到码片序列&#xff1a;(–1 1 –…

CTFHub-ssrf

技能树--Web--SSRF 内网访问 开启题目 尝试访问位于127.0.0.1的flag.php吧 进入环境 根据提示输入即可 127.0.0.1/flag.php 伪协议读取文件 开启题目 尝试去读取一下Web目录下的flag.php吧 进入环境&#xff0c;根据提示输入 file:///var/www/html/flag.php 鼠标右键查看…

解决PyTorch模型推理时显存占用问题的策略与优化

在将深度学习模型部署到生产环境时&#xff0c;显存占用逐渐增大是一个常见问题。这不仅可能导致性能下降&#xff0c;还可能引发内存溢出错误&#xff0c;从而影响服务的稳定性和可用性。本文旨在探讨这一问题的成因&#xff0c;并提供一系列解决方案和优化策略&#xff0c;以…

Java从入门到工作3 - 框架/工具

3.1、SpringBoot框架结构 在 Spring Boot 或微服务架构中&#xff0c;每个服务的文件目录结构通常遵循一定的约定。以下是一个常见的 Spring Boot 服务目录结构示例&#xff0c;以及各个文件和目录的简要说明&#xff1a; my-service │ ├── src │ ├── main │ │…