当前位置: 首页 > news >正文

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 disksfloat 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);}}}
}

相关文章:

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/compone…...

免费开源!推荐一款网页版数据库管理工具!

免费开源&#xff01;推荐一款网页版数据库管理工具&#xff01; DBGate 是一个开源的数据库管理工具&#xff0c;DBGate 的最大特点是可以 Web 访问&#xff01;&#xff0c;轻松实现一台机器部署&#xff0c;所有人使用&#xff01; 无论是 MySQL、PostgreSQL、SQLite 还是…...

生态系统NPP及碳源、碳汇模拟实践技术应用(土地利用变化、未来气候变化、空间动态模拟)

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。碳中和可以从碳排放&#xff08;碳源&#xff09;和碳固定&#xff08;碳汇&#xff09;这两个侧面来理解。陆地生态系统在全球碳循环过程中有着重要作…...

Mvc、Springmvc框架

一.Mvc&#xff1a; 1.概念&#xff1a; MVC它是一种设计理念。把程序按照指定的结构来划分: Model模型 、View视图 、Controller控制层&#xff1b; 结构图&#xff1a; 二.Springmvc: 1.概念&#xff1a; springmvc框架它是spring框架的一个分支。它是按照mvc架构思想设计…...

MATLAB2021B APP seriallist 串口通信

文章目录 前言一、项目需要二、使用步骤1.查找串口填写到查找列表2.发送函数3. 接收函数4.检测串口按钮5.选择串口号 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 项目需要&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面…...

【Python爬虫系列】_033.Scrapy_分布式爬虫

课 程 推 荐我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)教程合集 👈👈…...

2025erp系统开源免费进销存系统搭建教程/功能介绍/上线即可运营软件平台源码

系统介绍 基于ThinkPHP与LayUI构建的全方位进销存解决方案 本系统集成了采购、销售、零售、多仓库管理、财务管理等核心功能模块&#xff0c;旨在为企业提供一站式进销存管理体验。借助详尽的报表分析和灵活的设置选项&#xff0c;企业可实现精细化管理&#xff0c;提升运营效…...

Android实战经验篇-busybox小工具

Android开发系列文章请转如下链接 Android实战经验篇-系列文章 Android Display Graphics系列文章-汇总 俗话说“工欲善其事&#xff0c;必先利其器&#xff01;” 在原生Android系统中&#xff0c;提供的基础调试命令是基于toybox的。支持的命令不够全面&#xff0c;而Busy…...

上海艾一公司-运维工程师知识点备战

1.AD域控&#xff08;ActionDirectory活动目录&#xff09; ad域的作用&#xff1a;批量管理主机和用户&#xff08;所以数量要多用这个才合适&#xff09; 前置1&#xff1a;VM安装Windows镜像 2.IT资产管理 3.会议室管理...

【网络安全】Web安全基础- 第一节:web前置基础知识

目录 前言一、 中间件1.1消息中间件1.2数据库中间件1.3web服务器中间件1.4应用服务器中间件1.5远程过程调用中间件 二、源码**组成部分&#xff1a;**1、**前端&#xff08;客户端&#xff09;代码&#xff1a;**2、**后端&#xff08;服务器端&#xff09;代码**&#xff1a;3…...

数仓开发那些事_番外(2)

一闪在摸爬滚打了数年后&#xff0c;结合去年获得了个优秀员工&#xff0c;现在负责数据开发一面。 神州员工&#xff1a;一闪&#xff0c;你们还缺人不&#xff0c;不想当外包了。 一闪&#xff1a;我只负责招开发&#xff0c;实施的招聘我参与不了哇。&#xff08;所以你能…...

Linux常用指令-----下

Linux常用指令------上 Linux常用指令------中 Linux系列 文章目录 Linux系列前言一、more指令二、less指令三、head指令和tail指令四、grep指令五、zip指令和unzip指令六、tar指令1、打包压缩2. 预览3. 解压解包 前言 在上一篇博客中&#xff0c;我給大家介绍了cat指令&#…...

MySQL通过binlog日志进行数据恢复

记录一次阿里云MySQL通过binlog日志进行数据回滚 问题描述由于阿里云远程mysql没有做安全策略 所以服务器被别人远程攻击把数据库给删除&#xff0c;通过查看binlog日志可以看到进行了drop操作&#xff0c;下面将演示通过binlog日志进行数据回滚操作。 1、查询是否开始binlog …...

【AIGC】与模型对话:理解与预防ChatGPT中的常见误解

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;模型的工作原理和用户期望差异人工智能模型的基本工作原理认知上的局限与误解用户期望与模型实际能力的差距精确理解用户意图的重要性实际应用中的建议 &…...

字符2

strncpy n表示最多拷贝n个字符到目标字符串&#xff0c;当源字符串的字符个数不够时&#xff0c;就拷贝\0直至拷贝n个(源字符串不一定有\0&#xff09;&#xff0c;相对strcpy更加安全 char* strncpy (char* destination, const char* source, size_t n); strncat 当源字符串…...

25年宁德时代社招在职晋升Verify测评SHL题库:语言理解+数字推理考什么?

宁德时代的社招测评采用Verify系统&#xff0c;主要分为两大核心部分&#xff1a;语言理解和数字推理。 1. **语言理解部分**&#xff1a;包括阅读理解、逻辑填空和语句排序等题型。要求应聘者在17分钟内完成30题&#xff0c;旨在考察应聘者的阅读速度、理解准确性和逻辑性。 …...

数据转换:连接数据孤岛,释放信息价值

引言 在当今这个数据驱动的时代&#xff0c;数据转换已成为企业获取竞争优势的关键。随着数据量的爆炸性增长&#xff0c;不同来源、不同格式的数据需要被整合和转换&#xff0c;以便于分析和决策。本文将探讨数据转换的重要性、常见方法、工具以及最佳实践。 数据转换的重要…...

提升PHP技能:18个实用高级特性

掌握PHP基础知识只是第一步。 深入了解这18个强大的PHP特性&#xff0c;将显著提升您的开发效率和代码质量。 1、超越 __construct() 的魔法方法 虽然 __construct() 为大多数开发者所熟知&#xff0c;PHP 却提供了更多强大的魔术方法&#xff0c;例如&#xff1a; class Da…...

MySQL基础操作(2)

目录 1. CONCAT() 2. 3. ! 或 <> 4. IS NULL 5. IS NOT NULL 6. BETWEEN ... AND ... 7. LIKE 8. ORDER BY 9. LIMIT 10. LENGTH() 11. SUBSTR() 12. UPPER() 13. LOWER() 14. CONCAT_WS() 15. REPLACE() 16. INSTR() 17. TRIM() 18. IFNULL() 19. SY…...

Windows环境 (Ubuntu 24.04.1 LTS ) 国内镜像,用apt-get命令安装RabbitMQ

一、环境 Windows11 WSL(Ubuntu 24.04.1) 二、思路 1 用Windows中的Ubuntu安装RabbitMQ&#xff0c;贴近Linux的线上环境&#xff1b; 2 RabbitMQ用erlang语言编写的&#xff0c;先安装erlang的运行环境&#xff1b; 2 用Linux的apt-get命令安装&#xff0c;解决软件依赖…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...