threejs效果比较好的天空和水面

threejs效果比较好的天空和水面

目录

        前言

        一、引入水

        二、引入天空

        总结


前言

本文使用的是threejs提供的 Water 和 Sky 实现天空与水面。水的着色器代码比较复杂,threejs提供了封装的两种水,可以方便使用。


一、引入水

import { Water } from 'three/examples/jsm/objects/Water.js';


initWater(){
      let waterGeometry = new THREE.PlaneBufferGeometry( 1000, 1000 );
      let water = new Water(
        waterGeometry,
        {
          textureWidth: 512,
          textureHeight: 512,
          waterNormals: new THREE.TextureLoader().load( require('../../assets/waternormals.jpg'), ( texture )=> {
            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
          } ),
          alpha: 1.0,
          sunDirection: this.light.position.clone().normalize(),
          sunColor: 0xffffff,
          waterColor: 0x001e0f,
          // waterColor: 'red',
          distortionScale: 3.7,
          fog: this.scene.fog !== undefined
        }
      );
      water.rotation.x = - Math.PI / 2;
      this.water = water
      this.scene.add( water );
  }

 这是水的参数,一个geo,和一些配置。eye除非特殊需求可以不传,他默认相机位置是eye。

render里面更新时间,用来制造水波流动

this.water.material.uniforms[ 'time' ].value += 1.0 / 60.0;

这是法向量贴图https://techbrood.com/threejs/examples/textures/waternormals.jpg

二、引入天空

代码如下:

import { Sky } from 'three/examples/jsm/objects/Sky.js';


initSky(){
      let sky = new Sky();
      let uniforms = sky.material.uniforms;
      uniforms[ 'turbidity' ].value = 10;
      uniforms[ 'rayleigh' ].value = 3;
      uniforms[ 'mieCoefficient' ].value = 0.005;
      uniforms[ 'mieDirectionalG' ].value = 0.7;
      let parameters = {
        distance: 400,
        inclination: 0.49,//倾向
        azimuth: 0.205//方位角
      };
      this.parameters = parameters

      const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(128, {
        format: THREE.RGBAFormat,
        generateMipmaps: true,
        minFilter: THREE.LinearMipmapLinearFilter
      })

      const cubeCamera = new THREE.CubeCamera( 0.01, 1000, cubeRenderTarget );

      this.sky = sky
      this.cubeCamera = cubeCamera
      this.cubeRenderTarget = cubeRenderTarget
      this.updateSun()
    },
    updateSun(){
      let parameters = this.parameters
      let sky = this.sky 
      let cubeCamera = this.cubeCamera 
      let light = this.light
      let theta = Math.PI * ( parameters.inclination - 0.5 );
      let phi = 2 * Math.PI * ( parameters.azimuth - 0.5 );
      light.position.x = parameters.distance * Math.cos( phi );
      light.position.y = parameters.distance * Math.sin( phi ) * Math.sin( theta );
      light.position.z = parameters.distance * Math.sin( phi ) * Math.cos( theta );

      sky.material.uniforms[ 'sunPosition' ].value = light.position.copy( light.position );
      this.water.material.uniforms[ 'sunDirection' ].value =         
      light.position.clone().normalize();
      cubeCamera.update( this.renderer, sky );

      this.scene.background = this.cubeRenderTarget.texture
    },

这里可能有点乱,懒得整理了。主要是sky是返回一个背面渲染的mesh,这里利用cubeCamera去获取mesh的纹理图,就可以作为背景图片了。(注意:new THREE.CubeCamera( 0.01, 1000, cubeRenderTarget )这里的远视点与近视点,设置问题会看不见,坑我半天时间)。如果不想设置背景图片,也可以使用一个大的sky,使得看起来就是天空图。

sky.scale.setScalar( 450000 );
this.scene.add(sky);

这样就不需要cubeCamera了。


总结

只是记录一下,代码很多是官网的案例,但是比较老了,有些参数都没了。我给修改了一下。

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
要在three.js中实现水面倒影效果,可以使用three.js的渲染目标(RenderTarget)和镜面反射(Mirror)材质。 首先,需要创建一个渲染目标对象,用于渲染水面的倒影。这个渲染目标对象需要和场景中的相机和水面的位置对应。可以使用Three.js的WebGLRenderTarget类来创建一个渲染目标对象。 接下来,将水面的材质设置为镜面反射材质(MirrorMaterial)。这个材质需要一个反射贴图,可以使用上一步创建的渲染目标对象作为反射贴图。 最后,在渲染场景时,需要先渲染到渲染目标对象,再将渲染目标对象作为反射贴图应用到水面的材质上。 代码示例: ``` // 创建渲染目标对象 var mirrorRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight ); // 创建水面对象 var waterGeometry = new THREE.PlaneGeometry(1000, 1000); var waterMaterial = new THREE.MirrorMaterial({ color: 0x777777, envMap: mirrorRenderTarget.texture }); var water = new THREE.Mesh(waterGeometry, waterMaterial); water.rotation.x = -Math.PI / 2; scene.add(water); // 渲染场景到渲染目标对象 renderer.render(scene, mirrorCamera, mirrorRenderTarget); // 将渲染目标对象作为反射贴图应用到水面的材质上 waterMaterial.envMap = mirrorRenderTarget.texture; ``` 需要注意的是,这个方法只能实现静态的倒影效果,如果场景中有动态的物体,需要在每一帧重新渲染倒影。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值