Three 之 three.js (webgl)Layers 图层的简单介绍和简单实用

Three 之 three.js (webgl)Layers 图层的简单介绍和简单实用

目录

Three 之 three.js (webgl)Layers 图层的简单介绍和简单实用

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键代码


一、简单介绍

Three js (官网: Three.js – JavaScript 3D Library) 开发的一些知识整理,方便后期遇到类似的问题,能够及时查阅使用。

本节介绍, three 开发网页 3D 场景,three.js Layers 图层的简单介绍和简单实用,如果有不足之处,欢迎指出,或者你有更好的方法,欢迎留言。

  • 什么是 Layers

Layers 对象为 Object3D 分配 1个到 32 个图层。32个图层从 0 到 31 编号标记。 在内部实现上,每个图层对象被存储为一个 bit mask, 默认的,所有 Object3D 对象都存储在第 0 个图层上。

图层对象可以用于控制对象的显示。当 camera 的内容被渲染时与其共享图层相同的物体会被显示。每个对象都需要与一个 camera 共享图层。

每个继承自 Object3D 的对象都有一个 Object3D.layers 对象。

Layers() 创建一个新的图层对象,该对象默认与第 0 图层关联

属性 .mask : Integer

用 bit mask 表示当前图层对象与 0 - 31 中的哪些图层相对应。所属层所对应的比特位为 1,其他位位 0。

  • 涉及的方法:

.disable ( layer : Integer ) : undefined

layer - 一个 0 - 31 的整数。

删除图层对象与参数指定图层的对应关系。

.enable ( layer : Integer ) : undefined

layer - 一个 0 - 31 的整数。

增加图层对象与参数指定图层的对应关系。

.set ( layer : Integer ) : undefined

layer - 一个 0 - 31 的整数。

删除图层对象已有的所有对应关系,增加与参数指定的图层的对应关系。

.test ( layers : Layers ) : Boolean

layers - 一个图层对象。

如果传入图层对象与当前对象属于相同的一组图层,则返回 true,否则返回 false。

.isEnabled ( layer : Integer ) : Boolean

layer - an integer from 0 to 31.

Returns true if the given layer is enabled.

.toggle ( layer : Integer ) : undefined

layer - 一个 0 - 31 的整数。

根据参数切换对象所属图层。

.enableAll () : undefined

Add membership to all layers.

.disableAll () : undefined

Remove membership from all layers.

二、实现原理

1、对应的 Object 进行对应的 layers 设置

object.layers.set(layer);

2、camera 开启使能对应的 layers 渲染

      this.camera.layers.enable(0); // enabled by default
      this.camera.layers.enable(1);
      this.camera.layers.enable(2);

      // 使能或者使不能 layer 1
      this.camera.layers.toggle(1);

      // 使能所有
      this.camera.layers.enableAll();

      // 使不能所有
      this.camera.layers.disableAll();

三、注意事项

1、注意查看 layers 是 mask 的 二进制对用的值,例如 mask 为 8 ,二进制是 001000,layers 为 3

// 创建一个图层对象
let layer = new THREE.Layers();
// 设置图层为3
layer.set(3)
Mesh.layers = layer;

// 控制台可以查看mask值是8(二进制 ...001000),表示的就是图层3
console.log(layer.mask)


 this.camera.layers.enable(0); // enabled by default
 this.camera.layers.enable(1);
 this.camera.layers.enable(2);
 // 控制台可以查看mask值是7(二进制 ...000111),表示的使能图层 0 ,1,2
 console.log(this.camera.layers) 

2、如果发现 layers 的 Object light 渲染不对,可以使能 light d对用的 layers 试试

      light.layers.enable(0);
      light.layers.enable(1);
      light.layers.enable(2);

3、注意 vue 中的 method 下定义的函数方法,里面在定义函数时,可能使用 lambda 的方式定义的函数(可以是作为委托事件),才能获取到 vue 中定义的全局变量参数

 initGui() {

      const layers = {

        //注意: 使用 lambda 才能访问 this.camera , 使用 function()  访问不到 this.camera
        'toggle red':() => {
          this.camera.layers.toggle(0);

        }

      };

      const gui = new GUI();
      gui.add(layers, 'toggle red');


    },

四、效果预览

 

五、实现步骤

创建 Vue 的 Three 开发环境,可参考博文:

Vue 之 Vue Cli 创建 Three js 工程( 网页 3D )的简单整理(一些注意事项)_仙魁XAN的博客-CSDN博客

 1、在 src/App.vue 中添加代码,步骤基本 Three 环境,以及点击 按钮进行不同 layers 层级渲染显示

2、运行工程 (npm run serve ),在浏览器中查看,不同操作,即可显示不同layers 的 Object 渲染

六、关键代码

1、src/App.vue

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

<script>

import * as THREE from 'three';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';


export default {
  name: 'ThreeTest',
  components: {},

  data() {
    return {}
  },

  mounted() {

    this.container;
    this.stats;
    this.camera;
    this.scene;
    this.renderer;
    this.theta = 0;
    this.radius = 100;

    this.init();
    this.animate();

  },
  methods: {

    init() {

      this.container = document.createElement('div');
      document.body.appendChild(this.container);

      this.addSceneCameraAndLight();

      this.addObjectsWithLayers();

      this.initRenderer();

      this.addStatus();

      // Init gui
      this.initGui();

      // window.addEventListener
      window.addEventListener('resize', this.onWindowResize);

    },

    addSceneCameraAndLight(){

      this.camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
      this.camera.layers.enable(0); // enabled by default
      this.camera.layers.enable(1);
      this.camera.layers.enable(2);
      console.log(this.camera.layers)

      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0xf0f0f0);

      const light = new THREE.PointLight(0xffffff, 1);
      light.layers.enable(0);
      light.layers.enable(1);
      light.layers.enable(2);


      this.scene.add(this.camera);
      this.scene.add(light);

    },

    initRenderer(){
      this.renderer = new THREE.WebGLRenderer();
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.container.appendChild(this.renderer.domElement);

    },

    addStatus(){
      this.stats = new Stats();
      this.container.appendChild(this.stats.dom);
    },

    // 添加测试物体,并设置他们的层为 0 1 2
    addObjectsWithLayers(){

      const colors = [0xff0000, 0x00ff00, 0x0000ff];
      const geometry = new THREE.BoxGeometry(20, 20, 20);

      for (let i = 0; i < 100; i++) {

        const layer = (i % 3);

        const object = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({color: colors[layer]}));

        object.position.x = Math.random() * 400 - 200;
        object.position.y = Math.random() * 400 - 200;
        object.position.z = Math.random() * 400 - 200;

        object.rotation.x = Math.random() * 2 * Math.PI;
        object.rotation.y = Math.random() * 2 * Math.PI;
        object.rotation.z = Math.random() * 2 * Math.PI;

        object.scale.x = Math.random() + 0.5;
        object.scale.y = Math.random() + 0.5;
        object.scale.z = Math.random() + 0.5;

        object.layers.set(layer);

        this.scene.add(object);

      }

    },

    initGui() {

      const layers = {

        //注意: 使用 lambda 才能访问 this.camera , 使用 function()  访问不到 this.camera
        'toggle red':() => {
          this.camera.layers.toggle(0);

        },

        'toggle green':  () =>{

          this.camera.layers.toggle(1);

        },

        'toggle blue': () => {

          this.camera.layers.toggle(2);

        },

        'enable all': () => {

          this.camera.layers.enableAll();

        },

        'disable all': () => {

          this.camera.layers.disableAll();

        }

      };

      const gui = new GUI();
      gui.add(layers, 'toggle red');
      gui.add(layers, 'toggle green');
      gui.add(layers, 'toggle blue');
      gui.add(layers, 'enable all');
      gui.add(layers, 'disable all');

    },

    onWindowResize() {

      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();

      this.renderer.setSize(window.innerWidth, window.innerHeight);

    },

    animate() {

      requestAnimationFrame(this.animate);

      this.render();
      this.stats.update();

    },

    render() {

      this.theta += 0.1;

      this.camera.position.x = this.radius * Math.sin(THREE.MathUtils.degToRad(this.theta));
      this.camera.position.y = this.radius * Math.sin(THREE.MathUtils.degToRad(this.theta));
      this.camera.position.z = this.radius * Math.cos(THREE.MathUtils.degToRad(this.theta));
      this.camera.lookAt(this.scene.position);

      this.renderer.render(this.scene, this.camera);

    },

  },

  // beforeDestroy 废弃,使用 beforeUnmount
  beforeUnmount() {
    this.container = null;
    this.stats = null;
    this.camera = null;
    this.scene = null;
    this.renderer = null;
    this.theta = null;
    this.radius = null;
    console.log("beforeUnmount");
  }
}

</script>

<style>

#app {

  text-align: center;
  height: 100%;
}

* {
  /*初始化样式*/
  margin: 0;
  padding: 0;
}

html {
  /*用于 获取 屏幕的可视宽高*/
  width: 100%;
  height: 100%;
  overflow: hidden;
}


</style>

猜你喜欢

转载自blog.csdn.net/u014361280/article/details/124087875