12.Three.js纹理动画与动效墙案例

news2024/11/28 16:48:15

12.Three.js纹理动画与动效墙案例

在Three.js的数字孪生场景应用中,我们通常会使用到一些动画渲染效果,如动效墙,飞线、雷达等等,今天主要了解一下其中一种动画渲染效果:纹理动画。下面实现以下动效墙效果(警戒墙动画)。根据该案例的实现思路还可以实现很多种动画效果。

在这里插入图片描述

1.纹理贴图和纹理动画

首先了解一下Three.js纹理贴图相关的类 Texture,构造函数如下:

Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace )

该api用于是一个纹理贴图对象,可以将其应用到一个表面,或者作为反射/折射贴图。

一般通过TextureLoader方式加载和创建:

const texture = new THREE.TextureLoader().load( "textures/water.jpg" );
texture.wrapS = THREE.RepeatWrapping; //水平方向重复包裹
texture.wrapT = THREE.RepeatWrapping; //垂直方向重复包裹
texture.repeat.set( 4, 4 );

参数说明:

wrapS:这个值定义了纹理贴图在水平方向上将如何包裹

wrapT:这个值定义了纹理贴图在垂直方向上将如何包裹

方法说明:

texture.repeat.set( 4, 4 ): 设定在水平、垂直方向上的重复次数

在我们给网格模型设置材质的时候,除了可以设置通用的基础材质或者兰伯特材质,还可以加上我们的纹理贴图,为网格模型套上”皮肤“

let texture;
    function initObject() {
      const geometry = new THREE.PlaneGeometry(600, 100 );

      texture = new THREE.TextureLoader().load( "./img/warning.png" );
      texture.repeat.set( 5, 1 );
      // 设置.wrapS也就是U方向,纹理映射模式(包裹模式)
      texture.wrapS = THREE.RepeatWrapping;//对应offste.x偏移
      // 设置.wrapT也就是V方向,纹理映射模式
      texture.wrapT = THREE.RepeatWrapping;//对应offste.y偏移

      let material = new THREE.MeshBasicMaterial({
        map: texture,
        color: "#FFFFFF", 
        side: THREE.DoubleSide,
        transparent:true
      });

      let mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      mesh.rotateX(Math.PI/2);
      scene.add(mesh);
    }

在这里插入图片描述

2.纹理对象.offset属性

纹理对象Texture的.offset的功能是偏移贴图在Mesh上位置,本质上相当于修改了UV顶点坐标。

texture.offset.x +=0.5;//纹理U方向偏移
texture.offset.y +=0.5;//纹理V方向偏移

该属性结合渲染循环,动态的修改uv坐标就可以实现uv动画了

// 渲染循环
function render() {
    texture.offset.x +=0.001;//设置纹理动画:偏移量根据纹理和动画需要,设置合适的值
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
render();

3.基于平面几何体的动效墙效果代码

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <title>Three框架</title>
  <script src="../three.js-master/build/three.js"></script>
  <script src="../three.js-master/examples/js/controls/OrbitControls.js"></script>
  <script src="../three.js-master/examples/js/loaders/GLTFLoader.js"></script>
  <script src="../three.js-master/examples/js/loaders/OBJLoader.js"></script>
  <script src="../three.js-master/examples/js/loaders/MTLLoader.js"></script>
  <style type="text/css">
    body {
      margin: 0;
      padding: 0;
      overflow-y: hidden;
      overflow-x: hidden;
    }

    div#webgl {
      width: 100vw;
      height: 100vh;
    }
  </style>
  <script>
    var renderer;
    function initThree() {
      let dom = document.getElementById("webgl");
      width = dom.clientWidth;
      height = dom.clientHeight;
      renderer = new THREE.WebGLRenderer({
        antialias: true,
      });
      renderer.setSize(width, height);
      dom.appendChild(renderer.domElement);
      renderer.setClearColor("#ffffff", 1.0);
    }

    var camera;
    function initCamera() {
      camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
      // camera = new THREE.OrthographicCamera( width/-2, width/2, height/2, height/-2, 1, 10000 );
      camera.position.x = 0;
      camera.position.y = 1000;
      camera.position.z = 0;
      camera.up.x = 0;
      camera.up.y = 0;
      camera.up.z = 1;
      camera.lookAt({
        x: 0,
        y: 0,
        z: 0,
      });
    }

    var scene;
    function initScene() {
      scene = new THREE.Scene();
    }

    var light;
    function initLight() {
      light = new THREE.DirectionalLight(0xffffff, 1.0);
      light.position.set(100, 100, 200);
      scene.add(light);
    }

    let texture;
    function initObject() {
      const geometry = new THREE.PlaneGeometry(600, 100 );

      texture = new THREE.TextureLoader().load( "./img/warning.png" );
      texture.repeat.set( 5, 1 );
      // 设置.wrapS也就是U方向,纹理映射模式(包裹模式)
      texture.wrapS = THREE.RepeatWrapping;//对应offste.x偏移
      // 设置.wrapT也就是V方向,纹理映射模式
      texture.wrapT = THREE.RepeatWrapping;//对应offste.y偏移

      let material = new THREE.MeshBasicMaterial({
        map: texture,
        color: "#FFFFFF", 
        side: THREE.DoubleSide,
        transparent:true
      });

      let mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      mesh.rotateX(Math.PI/2);
      scene.add(mesh);
    }

    function threeStart() {
      initThree(); //初始化Three.js渲染器等初始操作
      initCamera(); //初始化相机
      initScene(); //初始化场景
      initLight(); //初始化灯光
      initControls(); //初始化控制器
      initObject(); //初始化渲染物体
      initAxesHelper();
      render(); //执行渲染
    }

    function initAxesHelper() {
      // AxesHelper:辅助观察的坐标系(红x、绿y、蓝z)
      const axesHelper = new THREE.AxesHelper(1500);
      scene.add(axesHelper);
    }

    function initControls() {
      // 设置相机控件轨道控制器OrbitControls
      const controls = new THREE.OrbitControls(camera, renderer.domElement);
      // 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
      controls.addEventListener("change", function () {
        renderer.render(scene, camera); //执行渲染操作
      }); //监听鼠标、键盘事件
    }

    function render() {
      // texture.offset.x -=0.01;//设置纹理动画:偏移量根据纹理和动画需要,设置合适的值
      renderer.render(scene, camera);
      requestAnimationFrame(render);
    }
  </script>
</head>

<body onload="threeStart();">
  <div id="webgl"></div>
</body>

</html>

4.通过坐标的自定义几何体创建的动效墙效果

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <title>Three框架</title>
  <script src="../three.js-master/build/three.js"></script>
  <script src="../three.js-master/examples/js/controls/OrbitControls.js"></script>
  <script src="../three.js-master/examples/js/loaders/GLTFLoader.js"></script>
  <script src="../three.js-master/examples/js/loaders/OBJLoader.js"></script>
  <script src="../three.js-master/examples/js/loaders/MTLLoader.js"></script>
  <style type="text/css">
    body {
      margin: 0;
      padding: 0;
      overflow-y: hidden;
      overflow-x: hidden;
    }

    div#webgl {
      width: 100vw;
      height: 100vh;
    }
  </style>
  <script>
    var renderer;
    function initThree() {
      let dom = document.getElementById("webgl");
      width = dom.clientWidth;
      height = dom.clientHeight;
      renderer = new THREE.WebGLRenderer({
        antialias: true,
      });
      renderer.setSize(width, height);
      dom.appendChild(renderer.domElement);
      renderer.setClearColor("#ffffff", 1.0);
    }

    var camera;
    function initCamera() {
      camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
      // camera = new THREE.OrthographicCamera( width/-2, width/2, height/2, height/-2, 1, 10000 );
      camera.position.x = 0;
      camera.position.y = 1000;
      camera.position.z = 0;
      camera.up.x = 0;
      camera.up.y = 0;
      camera.up.z = 1;
      camera.lookAt({
        x: 0,
        y: 0,
        z: 0,
      });
    }

    var scene;
    function initScene() {
      scene = new THREE.Scene();
    }

    var light;
    function initLight() {
      light = new THREE.DirectionalLight(0xffffff, 1.0);
      light.position.set(100, 100, 200);
      scene.add(light);
    }

    let texture;
    function initObject() {
      let c = [
        100,100, //第一个点
        -100,100, //第二个点
        -100,-100,
        100,-100,
        100,100
      ]

      let posArr = [];
      let uvrr = [];
      let h = 50; //围墙拉伸高度
      for (let i = 0; i < c.length - 2; i += 2) {
        // 围墙多边形上两个点构成一个直线扫描出来一个高度为h的矩形
        // 矩形的三角形1
        posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], 0, c[i + 2], c[i + 3], h);
        // 矩形的三角形2
        posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], h, c[i], c[i + 1], h);

        // 注意顺序问题,和顶点位置坐标对应
        uvrr.push(0, 0, 1, 0, 1, 1);
        uvrr.push(0, 0, 1, 1, 0, 1);
      }
      let geometry = new THREE.BufferGeometry(); //声明一个空几何体对象
      // 设置几何体attributes属性的位置position属性
      geometry.attributes.position = new THREE.BufferAttribute(new Float32Array(posArr), 3);
      // 设置几何体attributes属性的位置uv属性
      geometry.attributes.uv = new THREE.BufferAttribute(new Float32Array(uvrr), 2);
      geometry.computeVertexNormals()


      texture = new THREE.TextureLoader().load( "./img/warning.png" );
      // texture = new THREE.TextureLoader().load( "./img/wall.png" );
      texture.repeat.set( 5, 1 );
      // 设置.wrapS也就是U方向,纹理映射模式(包裹模式)
      texture.wrapS = THREE.RepeatWrapping;//对应offste.x偏移
      // 设置.wrapT也就是V方向,纹理映射模式
      texture.wrapT = THREE.RepeatWrapping;//对应offste.y偏移

      let material = new THREE.MeshBasicMaterial({
        map: texture,
        color: "#FFFFFF", 
        side: THREE.DoubleSide,
        transparent:true
      });

      let mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      scene.add(mesh);
      mesh.rotateX(-Math.PI / 2);

    }

    function threeStart() {
      initThree(); //初始化Three.js渲染器等初始操作
      initCamera(); //初始化相机
      initScene(); //初始化场景
      initLight(); //初始化灯光
      initControls(); //初始化控制器
      initObject(); //初始化渲染物体
      // initAxesHelper();
      render(); //执行渲染
    }

    function initAxesHelper() {
      // AxesHelper:辅助观察的坐标系(红x、绿y、蓝z)
      const axesHelper = new THREE.AxesHelper(1500);
      scene.add(axesHelper);
    }

    function initControls() {
      // 设置相机控件轨道控制器OrbitControls
      const controls = new THREE.OrbitControls(camera, renderer.domElement);
      // 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
      controls.addEventListener("change", function () {
        renderer.render(scene, camera); //执行渲染操作
      }); //监听鼠标、键盘事件
    }

    function render() {
      texture.offset.x -= 0.01;//设置纹理动画:偏移量根据纹理和动画需要,设置合适的值
      renderer.render(scene, camera);
      requestAnimationFrame(render);
    }
  </script>
</head>

<body onload="threeStart();">
  <div id="webgl"></div>
</body>

</html>

视频地址:https://www.bilibili.com/video/BV1K7BRYeEyq/

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

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

相关文章

SJYP 24冬季系列 FROZEN CHARISMA发布

近日&#xff0c;女装品牌SJYP 2024年冬季系列——FROZEN CHARISMA已正式发布&#xff0c;展现了更加干练的法式风格。此次新品发布不仅延续了SJYP一贯的强烈设计风格和个性时尚&#xff0c;更融入了法式风情的干练元素&#xff0c;为消费者带来了一场视觉与穿着的双重盛宴。  …

无人机产业发展如何?如何进行产业分析?

▶无人机产业发展现状&#xff1a;高速增长 1.市场规模和增长趋势&#xff1a; 全球无人机市场规模在2021年约为256亿美元&#xff0c;同比增长14%。中国民用无人机市场规模在2021年达到869.12亿元&#xff0c;显示出市场的快速增长。 预计到2029年&#xff0c;中国无人机市…

<项目代码>YOLOv8 红绿灯识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

DVWA靶场——File Inclusion

File Inclusion&#xff08;文件包含&#xff09;漏洞 指攻击者通过恶意构造输入&#xff0c;利用应用程序错误的文件包含机制&#xff0c;导致程序包含并执行未经授权的本地或远程文件。这类漏洞广泛存在于Web应用程序中&#xff0c;尤其是在那些允许用户提供文件路径或URL的地…

Ubuntu下用Docker部署群晖系统---Virtual DSM --zerotier实现连接

Ubuntu下用Docker部署群晖系统—Virtual DSM --zerotier实现连接 1. Docker 安装 安装最新docker curl -fsSL get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo docker run hello-world2.docker-compose 安装 sudo pip install docker-compose测试安装是否成功…

神经网络(系统性学习四):深度学习——卷积神经网络(CNN)

相关文章&#xff1a; 神经网络中常用的激活函数神经网络&#xff08;系统性学习一&#xff09;&#xff1a;入门篇神经网络&#xff08;系统性学习二&#xff09;&#xff1a;单层神经网络&#xff08;感知机&#xff09;神经网络&#xff08;系统性学习三&#xff09;&#…

数据结构C语言描述5(图文结合)--队列,数组、链式、优先队列的实现

前言 这个专栏将会用纯C实现常用的数据结构和简单的算法&#xff1b;有C基础即可跟着学习&#xff0c;代码均可运行&#xff1b;准备考研的也可跟着写&#xff0c;个人感觉&#xff0c;如果时间充裕&#xff0c;手写一遍比看书、刷题管用很多&#xff0c;这也是本人采用纯C语言…

打开windows 的字符映射表

快捷键 win R 打开资源管理器 输入: charmap 点击确定

EPS生成垂直模型闪退

问题描述 EPS在生成垂直模型时闪退。 解决办法在这里插入图片描述 原DSM文件和DOM文件分别在单独文件夹中。 将这几个文件统一放在一个文件夹中&#xff0c;并且注意路径不要太复杂。 成功运行&#xff0c;文件大时&#xff0c;处理会非常缓慢。

4——单页面应用程序,vue-cli脚手架

单页面应用程序(英文名:Single Page Application)简称 SPA,顾名 思义,指的是一个 Web 网站中只有唯一的一个 HTML 页面,所有的功能与交互都在这唯一的一个页面内完成。 1、脚手架 ① 什么是脚手架 vue-cli 是 Vue.js 开发的标准工具&#xff61;它简化了程序员基于 webpack …

嵌入式Qt使用ffmpeg视频开发记录

在此记录一下Qt下视频应用开发的自学历程&#xff0c;可供初学者参考和避雷。 了解常用音频格式yuv420p、h264等了解QML&#xff0c;了解QVideoOutput类的使用&#xff0c;实现播放yuv420p流参考ffmpeg官方例程&#xff0c;调用解码器实现h264解码播放 不需要手动分帧。ffmpeg…

kmeans 最佳聚类个数 | 轮廓系数(越大越好)

轮廓系数越大&#xff0c;表示簇内实例之间紧凑&#xff0c;簇间距离大&#xff0c;这正是聚类的标准概念。 簇内的样本应该尽可能相似。不同簇之间应该尽可能不相似。 目的&#xff1a;鸢尾花数据进行kmeans聚类&#xff0c;最佳聚类个数是多少&#xff1f; plot(iris[,1:4…

【大数据学习 | Spark-Core】详解Spark的Shuffle阶段

1. shuffle前言 对spark任务划分阶段&#xff0c;遇到宽依赖会断开&#xff0c;所以在stage 与 stage 之间会产生shuffle&#xff0c;大多数Spark作业的性能主要就是消耗在了shuffle环节&#xff0c;因为该环节包含了大量的磁盘IO、序列化、网络数据传输等操作。 负责shuffle…

Ubuntu20.04安装kalibr

文章目录 环境配置安装wxPython下载编译测试报错1问题描述问题分析问题解决 参考 环境配置 Ubuntu20.04&#xff0c;python3.8.10&#xff0c;boost自带的1.71 sudo apt update sudo apt-get install python3-setuptools python3-rosinstall ipython3 libeigen3-dev libboost…

转录组数据挖掘(生物技能树)(第11节)下游分析

转录组数据挖掘&#xff08;生物技能树&#xff09;&#xff08;第11节&#xff09; 文章目录 R语言复习转录组数据差异分析差异分析的输入数据操作过程示例一&#xff1a;示例二&#xff1a;示例三&#xff1a;此代码只适用于人的样本 R语言复习 #### 读取 ####dat read.deli…

排序学习整理(1)

1.排序的概念及运用 1.1概念 排序&#xff1a;所谓排序&#xff0c;就是使⼀串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作&#xff0c;以便更容易查找、组织或分析数据。 1.2运用 购物筛选排序 院校排名 1.3常见排序算法 2.实…

洛谷刷题之p1631

序列合并 题目入口 题目描述 有两个长度为 N N N 的单调不降序列 A , B A,B A,B&#xff0c;在 A , B A,B A,B 中各取一个数相加可以得到 N 2 N^2 N2 个和&#xff0c;求这 N 2 N^2 N2 个和中最小的 N N N 个。 输入格式 第一行一个正整数 N N N&#xff1b; 第二…

【漏洞复现】CVE-2022-24697

漏洞信息 NVD - CVE-2022-24697 Kylin’s cube designer function has a command injection vulnerability when overwriting system parameters in the configuration overwrites menu. RCE can be implemented by closing the single quotation marks around the parameter…

非常简单实用的前后端分离项目-仓库管理系统(Springboot+Vue)part 2

七、创建前端项目 你下载了nodejs吗&#xff1f;从cn官网下载&#xff1a;http://nodejs.cn/download/&#xff0c;或者从一个国外org网站下载&#xff0c;选择自己想要的版本https://nodejs.org/download/release/&#xff0c;双击下载好的安装文件&#xff0c;选择安装路径安…

应急响应靶机——Windows近源攻击

载入虚拟机&#xff0c;开启虚拟机&#xff0c;点击“解题.exe”&#xff1a; &#xff08;账户密码&#xff1a;Administrator/zgsf2024&#xff09; 1、攻击者的外网IP地址 2、攻击者的内网跳板IP地址 3、攻击者使用的限速软件的md5大写 4、攻击者的后门md5大写 5、攻击…