Threejs制作大海效果

        threeJs制作大海效果,实际上是绘制一个平面模型,在平面模型的表面渲染出波浪的效果,因为模型的长和宽要足够的大,有望不到边的效果,如果项目中添加了拖动效果的话,还需要在拖动的Control中添加允许的拖动角度,这样可以防止用户不下心看到了海面的下面就露馅了,哈哈。

        好了,下面开始说下怎么实现海面的效果,Threejs官方里包含了组件Water,使用这个组件可以快速绘制大海的效果,包含海面波浪的动态效果,首先我们需要创建一个场景,按照以往的步骤,场景,相机,渲染器等

initScene(){
      scene = new THREE.Scene();
    },
    initCamera(){
      this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
      this.camera.position.set(100,100,100);
    },
 initRenderer(){
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.container = document.getElementById("container")
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.renderer.setClearColor('#294f9a', 1.0);
      this.container.appendChild(this.renderer.domElement);
    },
    initControl(){
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      // // 最大角度
      this.controls.maxPolarAngle = Math.PI / 2.2;
    },
    initAnimate() {
      requestAnimationFrame(this.initAnimate);
      this.renderer.render(scene, this.camera);
    },

        接着创建一个平面模型作为海面,在海面的模型中添加水纹贴图,通过threejs提供的组件绘制出波浪效果,

 initWater(){
      const waterGeometry = new THREE.PlaneGeometry(10000, 10000);
      this.water = new Water(
          waterGeometry,
          {
            textureWidth: 512,
            textureHeight: 512,
            waterNormals: new THREE.TextureLoader().load('/static/images/waternormals.jpg', function (texture) {
              texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            }),
            sunDirection: new THREE.Vector3(),
            sunColor: 0xffffff,
            waterColor: 0x294f9a,
            distortionScale: 3.7,
          }
      );
      this.water.rotation.x = - Math.PI / 2;
      scene.add(this.water)
}

需要注意的是大海的颜色和initRendeder中this.renderer.setClearColor('#294f9a', 1.0);设置的颜色有关,大家可以根据需要设置不同的大海颜色。下面提供了波浪的贴图。放到对应的位置。

        

然后将这个模型加入到场景中,因为水需要有波浪的动态效果,所以需要在渲染的时候不断更新波浪的动态效果

initAnimate() {
      this.water.material.uniforms["time"].value += 1.0 / 60.0;
      requestAnimationFrame(this.initAnimate);
      this.renderer.render(scene, this.camera);
    },

大海效果

完整的代码如下

<template>
  <div id="container"></div>
</template>

<script>
import * as THREE from 'three'
import {OrbitControls} from "three/addons/controls/OrbitControls";
import { Water } from 'three/examples/jsm/objects/Water.js';

let scene;
export default {
  name: "sea-page",
  data() {
    return{
      camera:null,
      water:undefined,
    }
  },
  methods:{
    initScene(){
      scene = new THREE.Scene();
    },
    initCamera(){
      this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
      this.camera.position.set(100,100,100);
    },
    initWater(){
      const waterGeometry = new THREE.PlaneGeometry(10000, 10000);
      this.water = new Water(
          waterGeometry,
          {
            textureWidth: 512,
            textureHeight: 512,
            waterNormals: new THREE.TextureLoader().load('/static/images/waternormals.jpg', function (texture) {
              texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            }),
            sunDirection: new THREE.Vector3(),
            sunColor: 0xffffff,
            waterColor: 0x294f9a,
            distortionScale: 3.7,
          }
      );
      this.water.rotation.x = - Math.PI / 2;
      scene.add(this.water)
    },
    initRenderer(){
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.container = document.getElementById("container")
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.renderer.setClearColor('#294f9a', 1.0);
      this.container.appendChild(this.renderer.domElement);
    },
    initControl(){
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      // // 最大角度
      this.controls.maxPolarAngle = Math.PI / 2.2;
    },
    initAnimate() {
      this.water.material.uniforms["time"].value += 1.0 / 60.0;
      requestAnimationFrame(this.initAnimate);
      this.renderer.render(scene, this.camera);
    },
    initPage(){
      this.initScene();
      this.initCamera();
      this.initRenderer();
      this.initControl();
      this.initWater();
      this.initAnimate();
    }
  },
  mounted() {
    this.initPage()
  }
}
</script>

<style scoped>
#container{
  position: absolute;
  width:100%;
  height:100%;
  overflow: hidden;
}

</style>

好了,如果有问题可以在评论区给我留言。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baker_zhuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值