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

three.js 智慧城市扫光效果

城市扫光效果在线预览

在这里插入图片描述

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
import gsap from 'gsap'

const size = {
    width: window.innerWidth,
    height: window.innerHeight
}
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(45, size.width / size.height, 0.1, 1000)
camera.position.set(5, 5, 5)
const renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true })
renderer.setSize(size.width, size.height)
renderer.setPixelRatio(window.devicePixelRatio * 1.2)
document.body.appendChild(renderer.domElement)
new OrbitControls(camera, renderer.domElement)
renderer.setAnimationLoop(() =>  renderer.render(scene, camera))

//加载gltf
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath(`https://file.threehub.cn/` + 'js/three/draco/')
dracoLoader.preload()
const loader = new GLTFLoader()
loader.setDRACOLoader(dracoLoader)
loader.load(`https://file.threehub.cn/` + 'models/glb/build.glb', (gltf) => {
    const model = gltf.scene
    model.scale.set(0.01, 0.01, 0.01)
    scene.add(model)
    model.traverse((child) => {
        if (child instanceof THREE.Mesh) {
            child.material.dispose()
            child.material = modifyMaterial()
        }
    })
})

// fbx
new FBXLoader().load(`https://threehub.cn/` + '/files/model/city.FBX', (object3d) => {
    scene.add(object3d)
    object3d.scale.set(0.001, 0.001, 0.001)
    object3d.traverse((child) => {
        if (child instanceof THREE.Mesh) {
            child.material.dispose()
            child.material = modifyMaterial()
        }
    })
})

//混合着色
function modifyMaterial() {
    const material = new THREE.MeshBasicMaterial({
        color: '#28A1CC',
        // wireframe: true,
        opacity: 0.2,
        transparent: true,
        side: THREE.DoubleSide
    })
    material.onBeforeCompile = (shader) => {
        shader.fragmentShader = shader.fragmentShader.replace(/#include <dithering_fragment>/, `#include <dithering_fragment> //替换标记`)
        addColor(shader)
        addWave(shader)
        addLightLine(shader)
        addToTopLine(shader)
    }
    return material
}

//  
function addColor(shader) {
    //   获取物体的高度差
    const uHeight = 1200

    shader.uniforms.uTopColor = {
        value: new THREE.Color('#e9eaef')
    }
    shader.uniforms.uHeight = {
        value: uHeight
    }

    shader.vertexShader = shader.vertexShader.replace(
        '#include <common>',
        `
      #include <common>
      varying vec3 vPosition;
      `
    )

    shader.vertexShader = shader.vertexShader.replace(
        '#include <begin_vertex>',
        `
      #include <begin_vertex>
      vPosition = position;
  `
    )

    shader.fragmentShader = shader.fragmentShader.replace(
        '#include <common>',
        `
      #include <common>

      uniform vec3 uTopColor;
      uniform float uHeight;
      varying vec3 vPosition;

        `
    )
    shader.fragmentShader = shader.fragmentShader.replace(
        '//替换标记',
        `

      vec4 distGradColor = gl_FragColor;

      // 设置混合的百分比
      float gradMix = vPosition.y/uHeight;
      // 计算出混合颜色
      vec3 gradMixColor = mix(distGradColor.xyz,uTopColor,gradMix);
      gl_FragColor = vec4(gradMixColor,1);
        //替换标记

      `
    )
}

/**
 *添加扩散波
 * */
function addWave(shader) {
    // 设置扩散的中心点
    shader.uniforms.uSpreadCenter = { value: new THREE.Vector2(0, 0) }
    //   扩散的时间
    shader.uniforms.uSpreadTime = { value: -2000 }
    //   设置条带的宽度
    shader.uniforms.uSpreadWidth = { value: 40 }

    shader.fragmentShader = shader.fragmentShader.replace(
        '#include <common>',
        `
      #include <common>

      uniform vec2 uSpreadCenter;
      uniform float uSpreadTime;
      uniform float uSpreadWidth;
      `
    )

    shader.fragmentShader = shader.fragmentShader.replace(
        '//替换标记',
        `
     float spreadRadius = distance(vPosition.xz,uSpreadCenter);
    //  扩散范围的函数
    float spreadIndex = -(spreadRadius-uSpreadTime)*(spreadRadius-uSpreadTime)+uSpreadWidth;

    if(spreadIndex>0.0){
        gl_FragColor = mix(gl_FragColor,vec4(1,1,1,1),spreadIndex/uSpreadWidth);
    }

    //替换标记
    `
    )

    gsap.to(shader.uniforms.uSpreadTime, {
        value: 800,
        duration: 3,
        ease: 'none',
        repeat: -1
    })
}

function addLightLine(shader) {
    //   扩散的时间
    shader.uniforms.uLightLineTime = { value: -1500 }
    //   设置条带的宽度
    shader.uniforms.uLightLineWidth = { value: 200 }

    shader.fragmentShader = shader.fragmentShader.replace(
        '#include <common>',
        `
        #include <common>


        uniform float uLightLineTime;
        uniform float uLightLineWidth;
        `
    )

    shader.fragmentShader = shader.fragmentShader.replace(
        '//替换标记',
        `
      float LightLineMix = -(vPosition.x+vPosition.z-uLightLineTime)*(vPosition.x+vPosition.z-uLightLineTime)+uLightLineWidth;

      if(LightLineMix>0.0){
          gl_FragColor = mix(gl_FragColor,vec4(0.8,1.0,1.0,1),LightLineMix /uLightLineWidth);

      }

      //替换标记
      `
    )

    gsap.to(shader.uniforms.uLightLineTime, {
        value: 1500,
        duration: 5,
        ease: 'none',
        repeat: -1
    })
}

function addToTopLine(shader) {
    //   扩散的时间
    shader.uniforms.uToTopTime = { value: 0 }
    //   设置条带的宽度
    shader.uniforms.uToTopWidth = { value: 40 }

    shader.fragmentShader = shader.fragmentShader.replace(
        '#include <common>',
        `
          #include <common>


          uniform float uToTopTime;
          uniform float uToTopWidth;
          `
    )

    shader.fragmentShader = shader.fragmentShader.replace(
        '//替换标记',
        `
        float ToTopMix = -(vPosition.y-uToTopTime)*(vPosition.y-uToTopTime)+uToTopWidth;

        if(ToTopMix>0.0){
            gl_FragColor = mix(gl_FragColor,vec4(0.8,0.8,1,1),ToTopMix /uToTopWidth);

        }

        //替换标记
        `
    )

    gsap.to(shader.uniforms.uToTopTime, {
        value: 500,
        duration: 3,
        ease: 'none',
        repeat: -1
    })
}



/**
 * 名称: 城市光影
 * 作者: 优雅永不过时 https://github.com/z2586300277
 * 参考来源:https://github.com/Fate-ui/WebglStudy 
 */


http://www.kler.cn/a/380692.html

相关文章:

  • 写作词汇积累:见笑、尽显、稀疏、染指
  • ROM修改进阶教程------修改刷机包init.rc 自启用户自定义脚本的一些基本操作 代码格式与注意事项
  • Android--java实现手机亮度控制
  • 2. SQL窗口函数使用
  • Golang的容器化技术实践总结
  • EsChatPro 接入国内 DeepSeek 大模型
  • Linux系统基础-多线程超详细讲解(5)_单例模式与线程池
  • Android 网易游戏面经
  • 快来了解一下服务器虚拟化!!!
  • FlowDroid 分析最新Android 构建 APK出错
  • XLSTM+transformer时间序列预测代码
  • Java学习—反射机制:解锁代码的无限可能
  • TMDOG的Gin学习笔记_01——初识Gin框架
  • 【算法】(Python)贪心算法
  • 学习记录:js算法(八十三):全排列
  • CentOS Linux教程(12)--常用编辑器
  • 【综合算法学习】(第十九篇)
  • 32位汇编——通用寄存器
  • 30条勒索病毒处置原则
  • 图文并茂java源码解析-HashMap
  • 二百七十三、Kettle——ClickHouse中增量导入数据准确性统计表数据(1天1次)
  • Sigrity Power SI 3D-EM Full Wave Spatial模式如何查看空间电压频域曲线操作指导
  • 自杀一句话木马(访问后自动删除)
  • 影刀RPA实战:嵌入python,如虎添翼
  • Docker Compose部署Powerjob
  • golang rocketmq开发