Threejs&WebGPU运动残影demo

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

功能点
实例化SkinnedMesh
修改NodeMaterial着色器
节点材质系统 shader 语言 使用uniform和attribute
中合其他几篇博客中的内容
在这里插入图片描述

代码仓库
克隆后需要放到three源码同级别目录下 运行 three源码部分不在git仓库中(太大了)
使用vscode的live-server启动后访问
http://127.0.0.1:5501/demo/webgpu_skinning_instancing/webgpu_skinning_instancing.html

在这里插入图片描述

html部分

<!--
 * @Author: hongbin
 * @Date: 2024-07-30 07:48:37
 * @LastEditors: hongbin
 * @LastEditTime: 2024-08-12 22:03:13
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgpu - skinning instancing</title>
        <meta charset="utf-8" />
        <meta
            name="viewport"
            content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
        <link
            type="text/css"
            rel="stylesheet"
            href="../../three.js/examples/main.css" />
    </head>
    <body>
        <div id="info">
            <a
                href="https://threejs.org"
                target="_blank"
                rel="noopener"
                >three.js</a
            >
            webgpu - skinning instancing
        </div>

        <script type="importmap">
            {
     
     
                "imports": {
     
     
                    "three": "./three.webgpu.js",
                    "three/tsl": "./three.webgpu.js",
                    "three/addons/": "../../three.js/examples/jsm/"
                }
            }
        </script>

        <script type="module">
            import * as THREE from "three";
            import {
     
     
                pass,
                mix,
                range,
                color,
                oscSine,
                timerLocal,
                texture,
                TextureNode,
                normalLocal,
                min,
                max,
                abs,
                uniform,
                floor,
                float,
                nodeObject,
                instanceIndex,
                buffer,
                varyingProperty,
                int,
                instancedBufferAttribute,
                instancedDynamicBufferAttribute,
                vec3,
                reference,
            } from "three/tsl";

            import {
     
      GUI } from "three/addons/libs/lil-gui.module.min.js";
            import {
     
      GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
            import {
     
      OrbitControls } from "three/addons/controls/OrbitControls.js";
            import {
     
      RectAreaLightHelper } from "three/addons/helpers/RectAreaLightHelper.js";
            import {
     
      RectAreaLightTexturesLib } from "three/addons/lights/RectAreaLightTexturesLib.js";
            import TWEEN from "three/addons/libs/tween.module.js";

            let camera, scene, renderer, controls;
            let postProcessing, gui;

            let clock, delta;

            let dir = 1;

            let mixer, skinningInstanceMatrices;
            let mixer2, skinningInstanceMatrices2;
            let mixer3, skinningInstanceMatrices3;

            const tt = uniform(0, "float");
            const ttI = uniform(0, "float");

            class SkinningInstanceMatrices {
     
     
                constructor(mesh, count = 2, delay = 5,useTween = false) {
     
     
                    this.mesh = mesh;
                    this.count = count;
                    this.delay = 0.016 * delay;
                    this.time = 0;
                    this.useTween = useTween;

                    // const params = {opacity:1};
                    //     new TWEEN.Tween(params)
                    //         .to({ opacity: 0 }, 1000)
                    //         .onUpdate(function () {
     
     
                    //             console.log(new Date().getSeconds(),params.opacity)

                    //         })
                    //         .start();
                }

                setStatus(status = 1) {
     
     
                    this.isFinished = !status;

                    // this.mesh.setOmitOneOpacity && this.mesh.setOmitOneOpacity(status);

                    const params = {
     
      opacity: 1 - status };
                    new TWEEN.Tween(params)
                        .to({
     
      opacity: status }, 16 * 10)
                        .onUpdate(() => {
     
     
                            this.mesh.setOmitOneOpacity && this.mesh.setOmitOneOpacity(params.opacity);
                        })
                        .start();
                }

                start() {
     
     
                    this.setStatus(1);
                }

                isFinished = false;

                /* 动画播放完 隐藏其他实例 */
                finished() {
     
     
                    this.setStatus(0);
                }

                prevAction(delta) {
     
     
                    this.time += delta;
                    if (this.time > this.delay && !this.isFinished) {
     
     
                        for (let i = this.count; i >= 1; i--) {
     
     
                            this.syncOnes(i, i - 1);

                            // if (this.useTween) {
     
     
                            //     const params = { opacity: 1 };

                            //     new TWEEN.Tween(params)
                            //         .to({ opacity: 0 }, this.delay * 1000)
                            //         .onUpdate(() => {
     
     
                            //             this.mesh.setOpacity && this.mesh.setOpacity(i, params.opacity);
                            //         })
                            //         .start();
                            // }
                        }

                        // this.syncOnes(3, 2);
                        // this.syncOnes(2, 1);
                        // this.syncOnes(1);
                        this.time = 0;

                        // const params = {opacity:1};
                        // new TWEEN.Tween(params)
                        //     .to({ opacity: 0 }, this.delay * 1000)
                        //     .onUpdate(function () {
     
     
                        //         // console.log(params.opacity)
                        //         window.setInstanceOpacity && window.setInstanceOpacity(1,params.opacity)
                        //         window.setInstanceOpacity && window.setInstanceOpacity(2,params.opacity)
                        //     })
                        //     .start();
                    }
                }

                syncOnes(index, copyIndex = 0) {
     
     
                    const length = this.mesh.skeleton.bones.length;

                    const copyIndexLeft = 16 * copyIndex * length;

                    // const end = 16 * (index + 1) * length;
                    const left = 16 * index * length;

                    // for (let index = left, i = 0; index < end; index++, i++) {
     
     
                    //     this.mesh.skeleton.boneMatrices[index] = this.mesh.skeleton.boneMatrices[i + copyIndexLeft];
                    // }

                    //使用内置方法 避免遍历 TypedArray.copyWithin(target start end) https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/copyWithin
                    // this.mesh.skeleton.boneMatrices.copyWithin(copyIndexLeft, 0, length * 16);
                    this.mesh.skeleton.boneMatrices.copyWithin(left, copyIndexLeft, copyIndexLeft + length * 16);
                }

                syncIndex(index) {
     
     
                    requestAnimationFrame(() => {
     
     
                        this.syncIndex(index);
                    });
                    this.syncOnes(index);
                    // const { count } = this.mesh;
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值