日夜交替重点

252 阅读2分钟
// 渲染器色调映射的曝光值  
renderer.toneMappingExposure = 0.1  
// 创建天空球  
class SphereSky{  
    constructor(radius, uTime, envMap, nightMap){  
        // 几何体  
        const geometry = new THREE.SphereGeometry(radius, 32, 32)  
        // 材质,用环境纹理  
        const material = new THREE.MeshBasicMaterial({  
        map : envMap,  
        side : THREE.BackSide, // 背面渲染  
        })  
        this.mesh = new THREE.Mesh(geometry, material)  
        // 旋转90度  
        this.mesh.rotation.y = - Math.PI / 2  
        }  
        material.onBeforeCompile = shader => {  
        // 片段着色器  
        shader.fragmentShader = shader.fragmentShader.replace(  
        '#include <dithering_fragment>',  
        '#include <dithering_fragment>  
        gl_FragColor = mix(vec4(0.0,0.0,0.0,1.0),gl_FragColor,0.1)  
        // 0,0,0,1.0为全黑,gl_FragColor为材质本色  
        '  
        ) 
        
        // 添加太阳函数
        addSun(){
            // 创建天空球里面的太阳  
                let sunGeometry = new THREE.SphereGeometry(  
                100, // 半径  
                32,  
                32,// 像素  
                )  
                let sunMaterial = new THREE.MeshStandarMaterial({  
                // 发光材质  
                emissive : 0xfffcc  
                })  
                this.sun = new THREE.Mesh(sunGeometry,sunMaterial)  
                // 设置位置  
                this.sun.position.set(500,500,4000)  
                // 将太阳添加进天空球  
                this.mesh.add(this.sun)  
                // 给sun添加直线光  
                let sunLight = new THREE.DirectionLight(0xffffcc,2)  
                this.sun.add(sunLight)  
                // 设置shadow的属性  
                sunLight.castShadow = true  
                sunLight.shadow.camera.near = 0.1  
                sunLight.shadow.camera.far = 100000  
                sunLight.shadow.camera.left = -10000  
                sunLight.shadow.camera.right = 10000  
                sunLight.shadow.camera.top = 1000  
                sunLight.shadow.camera.bottom = -1000  
                // 阴影像素  
                sunLight.shadow.mapSize.width = 20480  
                sunLight.shadow.mapSize.height = 20480  
                sunLIght.shadow.radius = 5
        }
        // 更新太阳位置
        updateSun(time){
            this.sun.position.z = Math.cos(((time - 6)* 2 * Math.PI) / 24) * 4000  
            this.sun.position.y = Math.sin(((time - 6) * 2 * Math.PI) / 24) * 4000
        }
    }  
}

动态变化函数

let sphereSky = new SphereSky()

// gsap动态修改时间  
let uTime = {  
    value : 0,  
}  
gsap.to(uTime,{  
    value : 24, 
    duration : 24,  
    repeat : -1,// 重复  
    ease : 'linear',  
    onUpdate ; () => {
    sphereSky.updateSun(uTime.value)
    // 根据值来修改渲染器色调映射的值  
    if(uTime.value > 6){ / /大于六点就是早上  
        sphereSky.sun.visible =true  
    }  
    if(uTime.value > 18){ // 大于16点就是晚上  
        sphereSky.sun.visible = false // 隐藏太阳
    }
    if(Math.abs(uTime.value - 12) < 4){ // 8点到16点亮度不变
        renderer.toneMappingExposure = 1
    }
    if(Math.abs(uTime.value - 12) >= 6){ // 18点以后亮度不变
        renderer.toneMappingExposure = 0.3
    }
    // [0,8],[16,18]这两个区间亮度随强度变化
    if(Math.abs(uTime.value - 12) >= 4 || Math.abs(uTime.value - 12) <= 6 ){
        // [0,8] x越大,strength越大, [16,18]x越大,strength越小
        let strength = 1 - Math.abs(uTime.value - 12) / 2 
        strength < 0.3 ? strength = 0.3 : strength = strength
        renderer.toneMappingExposure = strength
    }
})

添加太阳光光晕效果

// 创建纹理加载器  
const textureLoader = new THREE.TextureLoader()  
// 加载纹理  
const textureFlare0 = textureLoader.load()  
const textureFlare1 = textureLoader.load()  
  
// 创建光晕实例  
const lensflare = new Lensflare()  
// 往光晕实例中添加光晕元素  
lensflare.addElement(new LensflareElement(  
    textureFlare0,// 光晕纹理  
    700, // 光晕大小  
    0, // 与mesh的距离  
))  
lensflare.addElement(new LensflareElement(  
    textureFlare0,// 光晕纹理  
    500, // 光晕大小  
    0.4, // 与mesh的距离  
))  
lensflare.addElement(new LensflareElement(  
    textureFlare0,// 光晕纹理  
    300, // 光晕大小  
    0.75, // 与mesh的距离  
))  
lensflare.addElement(new LensflareElement(  
    textureFlare0,// 光晕纹理  
    150, // 光晕大小  
    1, // 与mesh的距离  
))  
// 添加到Mesh内  
sunLight.add(lensflare)

开启晚上led效果

// 获取led的材质  
traverse(child => {  
//声明一个变量存储led材质  
    let ledMaterial  
    if(child.isMesh &&  
        child.material.name == 'Led' &&  
        ledMaterial == null  
    ){  
        ledMaterial = child.material  
    }  
})  
// 创建一个视屏材质  
let video = document.createElement('video')  
video.src = 'path'  
video.autoplay = true  
video.loop = true  
video.muted = true  
video.play()  
let videoMaterial = new THREE.VideoTexture(video)  
  
// 之前的发光效果 通道 
this.unrealBloomPass = new UnrealBloomPass()  
this.unrealBloomPass.enabled = false  
this.unrealBloomPass.threshold = 0.25  
this.unrealBloomPass.strength = 1  
this.unrealBloomPass.radius = 2

// 早上的回调  
() => {  
    ledMaterial.emissive = new THREE.Color(0x000000)  
    // 关闭发光效果通道  
    this.unrealBloomPass.enabled = false  
}  
// 夜晚的回调  
() => {  
    ledMaterial.emissive = new THREE.Color(0x99cc99)  
    ledMaterial.emissiveMap = videoMaterial  
    ledMaterial.emissiveIntensity = 1  
    // 开启发光效果通道  
    this.unrealBloomPass.enabled = true  
}
  if(uTime.value > 6 && uTime.value <= 18 && !this.isDay){ / /大于六点并且小于十八点就是早上  
        sphereSky.sun.visible =true
        this.isDay = true
        dayCallback()
    }  
    if((uTime.value > 18 || uTime.value < 6) && this.isDay){ // 大于18点或者小于6点就是晚上  
        sphereSky.sun.visible = false // 隐藏太阳
        this.isDay = false
        nightCallback()
    }