three.js 楼层加载动画

2023-11-18

概述

如有不明白的可以加QQ:2354528292;wx: aichitudousien
更多教学视频请访问:https://space.bilibili.com/236087412
源码获取:https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.3c3a645eIMTaft&ft=t&id=714326516274

开发了一个Three.js 使用烘培模型的demo,先看视频效果,整体的效果有水面,太阳,倒影,模型动画,围栏特效,相机动画,楼层动画

three.js 云上城市

创建场景

创建渲染器,灯光,相机,控制器和以前的智慧城市项目一样,从那边照抄过来即可,调用方式如下

	  app = new ZThree("screen");
      app.initThree();
      // app.initHelper();
      app.initOrbitControls();
      light = app.initLight();

      // stats = app.initStatus();
      selectObj = app.initRaycaster();
      window.app = app;
      camera = app.camera;
      // bloomComposer = app.bloomComposer();
      camera.position.set(...this.cameraPosition);
      scene = app.scene;
      renderer = app.renderer;
      renderer.logarithmicDepthBuffer = true;
      renderer.autoClear = false;

      controls = app.controls;
      controls.target.set(...this.target);
      controls.maxDistance = 2000;
      controls.maxPolarAngle = Math.PI / 2.2;
      clock = new THREE.Clock();

创建天空

export function loaderSky(app, water) {
  return new Promise(resolve => {
    let sky = new Sky();
    sky.scale.setScalar(10000);
    app.scene.add(sky);
    let skyUniforms = sky.material.uniforms;

    skyUniforms['turbidity'].value = 1;
    skyUniforms['rayleigh'].value = 3;
    skyUniforms['mieCoefficient'].value = 0.005;
    skyUniforms['mieDirectionalG'].value = 0.8;

    let parameters = {
      inclination: 0.49,
      azimuth: 0.205
    };

    let pmremGenerator = new THREE.PMREMGenerator(app.renderer);

    let sun = new THREE.Vector3();

    let theta = Math.PI * (parameters.inclination - 0.5);
    let phi = 2 * Math.PI * (parameters.azimuth - 0.5);

    sun.x = Math.cos(phi);
    sun.y = Math.sin(phi) * Math.sin(theta);
    sun.z = Math.sin(phi) * Math.cos(theta);

    sky.material.uniforms['sunPosition'].value.copy(sun);
    water.material.uniforms['sunDirection'].value.copy(sun).normalize();

    app.scene.environment = pmremGenerator.fromScene(sky).texture;

    resolve(sky);
  })
}

创建水面

创建一个平面然后加上调用水面的材质就好,很简单

export function loaderWater(app) {
  return new Promise(resolve => {
    let waterGeometry = new THREE.PlaneGeometry(10000, 10000);

    let water = new Water(
      waterGeometry, {
        textureWidth: 512,
        textureHeight: 512,
        waterNormals: new THREE.TextureLoader().load('texture/waternormals.jpg', function (texture) {
          texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        }),
        alpha: 1.0,
        sunDirection: new THREE.Vector3(),
        sunColor: 0xffffff,
        waterColor: 0x001e0f,
        distortionScale: 3.7,
        fog: app.scene.fog !== undefined
      }
    );

    water.rotation.x = -Math.PI / 2;

    app.scene.add(water);

    resolve(water);
  })
}

此时我们看到的效果是

创建模型

export async function loaderShop(app) {
  return new Promise(async resolve => {
    let gltf = await app.loaderGltfDracoModel('model/', 'yun.glb');
    let model = gltf.scene;
    model.getObjectByName('cloud').visible = false;
    const s = 0.1;
    model.scale.set(s, s, s);
    model.position.set(0, -80, 0);
    let allModel = [];
    let mixer = new THREE.AnimationMixer( model );
		mixer.clipAction( gltf.animations[ 0 ] ).play();
    let clickTextObj = [model.getObjectByName('全息店铺标签'), model.getObjectByName('全息城市标签'), model.getObjectByName('云展标签')];
    // loaderRipple();
    app.scene.add(model);
    resolve({
      model,
      allModel,
      clickTextObj,
      mixer
    });
  })
}

开启模型动画

loaderModel.js 文件代码:

let mixer = new THREE.AnimationMixer( model );
mixer.clipAction( gltf.animations[ 0 ] ).play();

渲染模块代码:

const delta = clock.getDelta();
if (model.mixer) {
          model.mixer.update( delta );
 }

此时我们就可以看到模型的动画了。

栅栏动画

生成栅栏的mesh

let ripple;
export function loaderRipple(pos) {
  if (ripple) {
    app.scene.remove(ripple);
    ripple.geometry.dispose();
    ripple.material.dispose();
    ripple = null;
  }
  let vector3s = [];
  for (let i = 0; i < pos.length; i++) {
    vector3s.push(new THREE.Vector3(...pos[i]));
  }
  // 围栏
  let rippleGeometry = getRippleGeometry(vector3s, 60);

  let rippleMaterial = new THREE.ShaderMaterial({
    vertexShader: rippleShader.vs,
    fragmentShader: rippleShader.fs,
    uniforms: rippleShader.uniform,
    side: THREE.DoubleSide,
    transparent: true,
    depthWrite: false
  })

  ripple = new THREE.Mesh(rippleGeometry, rippleMaterial);
  app.scene.add(ripple);
}

生成栅栏的geometry

function getRippleGeometry(points = [], height = 10) {
  let positions = []
  let uvs = []
  for (let i = 0, j = positions.length, t = uvs.length; i < points.length - 1; i++) {
    let vUvyMax = 1
    let left = points[i]
    let right = points[i + 1]
    positions[j++] = left.x
    positions[j++] = 0
    positions[j++] = left.y
    uvs[t++] = 0
    uvs[t++] = 0

    positions[j++] = right.x
    positions[j++] = 0
    positions[j++] = right.y
    uvs[t++] = 1
    uvs[t++] = 0

    positions[j++] = left.x
    positions[j++] = height
    positions[j++] = left.y
    uvs[t++] = 0
    uvs[t++] = vUvyMax

    positions[j++] = left.x
    positions[j++] = height
    positions[j++] = left.y
    uvs[t++] = 0
    uvs[t++] = vUvyMax

    positions[j++] = right.x
    positions[j++] = 0
    positions[j++] = right.y
    uvs[t++] = 1
    uvs[t++] = 0

    positions[j++] = right.x
    positions[j++] = height
    positions[j++] = right.y
    uvs[t++] = 1
    uvs[t++] = vUvyMax
  }
  let geometry = new THREE.BufferGeometry()
  geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3))
  geometry.addAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvs), 2))
  return geometry;
}

使用的shader:

export const rippleShader = {
  vs:"\n  precision lowp float;\n  precision lowp int;\n  ".concat(THREE.ShaderChunk.fog_pars_vertex, "\n  varying vec2 vUv;\n  void main() {\n    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n    vUv = uv;\n    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    ").concat(THREE.ShaderChunk.fog_vertex, "\n  }\n"),
  fs: "\n  precision lowp float;\n  precision lowp int;\n  uniform float time;\n  uniform float opacity;\n  uniform vec3 color;\n  uniform float num;\n  uniform float hiz;\n\n  varying vec2 vUv;\n\n  void main() {\n    vec4 fragColor = vec4(0.);\n    float sin = sin((vUv.y - time * hiz) * 10. * num);\n    float high = 0.92;\n    float medium = 0.4;\n    if (sin > high) {\n      fragColor = vec4(mix(vec3(.8, 1., 1.), color, (1. - sin) / (1. - high)), 1.);\n    } else if(sin > medium) {\n      fragColor = vec4(color, mix(1., 0., 1.-(sin - medium) / (high - medium)));\n    } else {\n      fragColor = vec4(color, 0.);\n    }\n\n    vec3 fade = mix(color, vec3(0., 0., 0.), vUv.y);\n    fragColor = mix(fragColor, vec4(fade, 1.), 0.85);\n    gl_FragColor = vec4(fragColor.rgb, fragColor.a * opacity * (1. - vUv.y));\n  }\n",
  uniform:{
    time: {
      type: "pv2",
      value: 0
  },
  color: {
      type: "uvs",
      value: new THREE.Color('#1E90FF')
  },
  opacity: {
      type: "pv2",
      value: 0.8
  },
  num: {
      type: "pv2",
      value: 8
  },
  hiz: {
      type: "pv2",
      value: 0.15
  }
  }
}

此时在调用相机的飞行函数,此函数在智慧城市项目中也有详细介绍,在调用相机的飞行函数后执行生成栅栏的函数即可

app.initRaycaster('click', (selectObj) => {
        if (selectObj) {
          console.log(selectObj);
          // return;
          let object = selectObj.object;
          app.flyTo({
            position: textPos[object.name].position
          })
          loaderRipple(textPos[object.name].rippleVec)
        }
      }, model.clickTextObj);

最后我们就可以看到,在点击了店铺标签后生成一个个栅栏了
![在这里插入图片描述](https://img-blog.csdnimg.cn/27de9280c80143ba8c56845516cd8d04.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5oiR5oOz5b2T5Zad5rC05Lq6,size_20,color_FFFFFF,t_70,g_se,x_16

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

three.js 楼层加载动画 的相关文章

  • Three.js 中的文本几何

    我在 Three js r74 中的 TextGeometry 遇到一些问题 我该如何正确实施 这是我的代码笔 codepen io cheesyeyes pen eJqZxK 提前致谢 好吧 对于每个正在寻找简单答案而不是链接和其他超载示
  • 3D 图形矩阵 4x4 中最后一行的 magic 4 的用途是什么?

    当我阅读有关WebGL的书时 我看到了下一个矩阵描述 有关于书中最后一行的信息 WebGL 初学者指南 初学者指南 Diego Cantor Brandon Jones 神秘的第四排 第四排没有任何特殊之处 意义 元素 m4 m8 m12
  • Hello world WebGL 并行性示例

    围绕 WebGL 似乎有许多用于运行并行处理的抽象 例如 https github com MaiaVictor WebMonkeys https github com MaiaVictor WebMonkeys https github
  • 如何在 Ubuntu 的 headless chrome 中启用 WebGL?

    如何在 Ubuntu 14 的 headless chrome 中启用 webgl 或安装 webgl 我尝试安装 libosmesa6 但这没有帮助 有人可以指出我正确的方向吗 我想使用 webgl 来处理无头 chrome 和 sele
  • THREE.js 导入的模型不应用面部纹理

    我正在尝试导入使用 THREEJS 导出器从搅拌机导出的模型 到目前为止 模型已加载并出现在我的场景中 并且正确应用了材质 汽车应为黄色 玻璃应为透明 但它并没有将我的纹理应用到以 tga 形式保存的汽车上 如果我不将纹理包含在模型所在的服
  • Three.js:通过触摸和设备方向旋转相机

    我正在使用 Threejs 制作一个 3D 项目 它允许使用计算机设备的鼠标控制相机 还允许使用触摸事件和智能手机的设备方向事件进行控制 举个例子 这个网站 http lacostewinter seeourwork cn en intro
  • 动画 GIF 作为 THREE.js 中的纹理

    我正在寻找一种在 THREE js 中使用 GIF 动画作为纹理的方法 我目前可以加载纹理 甚至是 GIF 格式 但它无法播放动画 有什么办法可以做到吗 我发现了一些像这样的链接 https github com JordiRos GLGi
  • 无法让 raycaster.intersectObjects() 从远处返回相交的对象

    我有一个包含几个随机数的散点图Sprite用作数据点的对象 我想检测鼠标指针 光标 和Sprite对象 我用来检测交叉点的设置如下 var projector new THREE Projector window addEventListe
  • Three.js:基于图像的光照(IBL)

    I m searching to add an IBL to my scene and objects But I can t find anything on the web There are some examples with an
  • 一次性渲染阴影

    考虑到阴影投射的成本 我想知道对于动态定位的静态对象 例如 程序城市 是否有一个功能或可能 实验性的方法可以在 Three js 中仅渲染一次阴影贴图 甚至在 webgl 中 因此 结果可以在静态对象的下一帧中免费使用 仅当物体移动时才会进
  • 在 Three.js 中获取 Object3D 的大小

    我的场景中有这个 3D 对象 var icon new THREE Object3D var iconTexture THREE ImageUtils loadTexture images icon png iconMaterial new
  • 使用 ThreeJS 获取球体纹理上的点击位置

    目前 我有一个带有纹理的球体 它绕 y 轴旋转 我还有在 3D 空间中单击的位置 以及球体上的旋转位置 我认为 目标 获取纹理上的位置 例如 我想获取我点击的图像的哪个方块 参见示例球体和下图 在实践中 我不会使用此图像 但我觉得这将是一个
  • WebGL2 FBO 深度附件值

    我只是尝试使用 WebGL2 渲染场景的深度值 如下所示 Texture depthTexture gl createTexture gl bindTexture gl TEXTURE 2D depthTexture gl texImage
  • Three.js - 如何翻译几何图形

    我有一个脚本 可以定位各种宽度 高度和深度的立方体 并且正在努力根据 xAxis yAxis 和 zAxis 也有所不同 将它们准确地排列起来 var geometry new THREE BoxGeometry width height
  • 上传统一块的正确顺序是什么?

    在示例页面中https www lighthouse3d com tutorials glsl tutorial uniform b locks https www lighthouse3d com tutorials glsl tutor
  • Three.js :face4 生成三角形而不是正方形

    我正在尝试使用 tree js 自定义几何图形生成一个正方形 但是这段代码 var cubeGeo new THREE Geometry cubeGeo vertices push new THREE Vector3 25 25 25 cu
  • 如何在 Three.js 场景中包含 OVRManager?

    我创建了几个 Three js Javascript 演示应用程序 正在我的新 Oculus Go 中进行试验 我正在尝试让 Go 控制器在我的应用程序中执行某些操作 根据 Oculus 开发人员中心的说法 最好的办法是将 OVRManag
  • 开始使用 Three.js 中的行进立方体

    我是 Three js 的新手 正在寻找教程来帮助我开始了解如何在 Three js 中使用 Marching Cubes 到目前为止 我在 Three js 中看到的一些使用它的项目对我来说有点复杂 所以一个简单的教程会很好 谢谢 像您一
  • 在每一帧上更新整个 VBO 是绘制许多变化的独特三角形的最有效方法吗?

    答复我之前的问题 https stackoverflow com questions 24592099 drawing many unique triangles with a single draw call for better per
  • 如何在react-三纤维中提取并播放动画

    嗯 我有 gltf 动画模型 我成功加载模型 但无法播放嵌入的动画 我想知道是否可以以任何方式解决它 顺便说一句 我正在反应中工作 先感谢您 在这里您可以找到型号https drive google com file d 1ZVyklaQu

随机推荐