首页 > 其他分享 >three.js 智慧城市扫光效果

three.js 智慧城市扫光效果

时间:2024-10-30 10:17:37浏览次数:3  
标签:uniforms fragmentShader 扫光 float shader js three value include

城市扫光效果在线预览

在这里插入图片描述

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 
 */

标签:uniforms,fragmentShader,扫光,float,shader,js,three,value,include
From: https://blog.csdn.net/guang2586/article/details/143358211

相关文章

  • Fastjson枚举序列化和反序列化的推荐实现
    一、背景项目中定义了很多dto,包含枚举类型,而且这些枚举全都自定义标志码。比如7001对应某种操作。返回前台时,需要转化为对应的7001,前台传入后台时也希望7001转化为枚举。二、研究思路一开始,研究了fastjson的默认实现。发现只有不自定义类似7001这种默认值的时候,可以自动转化......
  • 【SpringMVC】传递json,获取url参数,上传文件
    【传递json数据】【json概念】一种轻量级数据交互格式,有自己的格式和语法,使用文本表示一个对象或数组的信息,其本质上是字符串,负责在不同的语言中数据传递与交换json数据以字符串的形式体现【json字符串与Java对象互转】我们需要在pom.xml中增加对json的依赖【对象转jso......
  • Vue.js组件开发全面指南:从基础到高级应用
    1.Vue.js组件概述1.1什么是Vue.js组件Vue.js组件是Vue.js框架中的核心概念,它是一种封装了特定功能的可复用代码单元。每个组件可以包含自己的模板、逻辑和样式,使得开发者能够构建大型应用时,像搭积木一样组合这些独立的组件。组件基于自定义元素进行扩展,使得开发者能够创......
  • 【前端】在 Next.js 开发服务器中应该如何配置 HTTPS?
    在Next.js的开发环境中,默认情况下是使用HTTP协议的。但是,您可以通过一些配置来启用HTTPS。这在开发阶段可能很有用,尤其是在需要测试涉及安全传输的应用场景时。下面是如何在Next.js开发环境中配置HTTPS的步骤:方法一:使用https模块您可以使用Node.js的内置模......
  • 【前端】在 Next.js 中添加对 API 的监控和日志记录
    API的监控和日志记录对于维护系统的稳定性和性能至关重要。良好的监控和日志记录可以帮助您及时发现和解决问题。以下是一些常用的监控和日志记录实践和技术:1.日志记录使用框架内置的日志功能Next.js本身提供了基本的日志记录功能,但您可能需要更详细的日志来调试问题......
  • webstorm 项目如何配置支持 nodejs
    WebStorm是JetBrAIns推出的一款强大的JavaScript开发IDE,支持Node.js是其内置的功能。要配置WebStorm以支持Node.js项目,您需要进行几个步骤:确保已安装Node.js、在WebStorm中配置Node.js解释器、设置语言版本及库、调整运行/调试配置。下面,我们将详细介绍如何进行这些设......
  • js.相同的树
    链接:100.相同的树-力扣(LeetCode)题目:给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。示例1:输入:p=[1,2,3],q=[1,2,3]输出:true示例2:输入:p=[1,2],q=[1,null,......
  • eslint配置文件eslintrc.js
    eslintrc.js是ESLint的配置文件,主要用于定义代码质量和风格规则。ESLint是一个流行的JavaScript和TypeScript代码静态分析工具,可以帮助开发者识别和修复潜在的代码问题,确保代码的一致性和质量。1.功能配置规则:在eslintrc.js中,你可以指定ESLint应该应用哪些......
  • JS-数组、函数、类与对象
    JS进阶数组数组可以存放任意类型的元素letarr=['小胖',12,true,28.9];console.log(arr,arr.length);增arr[4]='newValue';改arr[4]='changedValue';删不会改变数组的长度,使用undefined赋值deletearr[4];查console.log(arr[4]);//undefined多......
  • 基于node.js+vue机房设备管理系统的研究与实现(开题+程序+论文)计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容一、选题背景关于机房设备管理系统的研究,现有研究主要以设备的基础监控和简单维护为主[1][2] 。专门针对涵盖用户管理、机房预约、设备借用归还、设备报修换新以及......