three.js 多通道组合

2024-01-02 19:55:57

效果:

代码:

<template>
  <div>
    <el-container>
      <el-main>
        <div class="box-card-left">
          <div id="threejs" style="border: 1px solid red"></div>
          <div style="border: 1px solid skyblue; padding: 10px; margin: 10px">
            <el-form label-width="0px">
              <el-form-item>
                <el-switch
                  v-model="wireframe"
                  active-text="线模型"
                  inactive-text="面模型"
                >
                </el-switch>
              </el-form-item>
              <el-form-item>
                <el-switch
                  v-model="outlinePassFlag"
                  active-text="有发光描边"
                  inactive-text="无发光描边"
                >
                </el-switch>
              </el-form-item>
              <el-form-item>
                <el-switch
                  v-model="glitchPassFlag"
                  active-text="有闪屏效果"
                  inactive-text="无闪屏效果"
                >
                </el-switch>
              </el-form-item>
              <el-form-item>
                <el-switch
                  v-model="filmPassFlag"
                  active-text="有模拟电视屏幕效果"
                  inactive-text="无模拟电视屏幕效果"
                >
                </el-switch>
              </el-form-item>
              <el-form-item>
                <el-switch
                  v-model="afterimagePassFlag"
                  active-text="有重影效果"
                  inactive-text="无重影效果"
                >
                </el-switch>
              </el-form-item>
              <el-form-item>
                <el-switch
                  v-model="dotScreenPassFlag"
                  active-text="有点网效果"
                  inactive-text="无点网效果"
                >
                </el-switch>
              </el-form-item>
              <el-form-item>
                <el-switch
                  v-model="HalftonePassFlag"
                  active-text="有半色调效果"
                  inactive-text="无半色调效果"
                >
                </el-switch>
              </el-form-item>
              <el-form-item>
                <el-switch
                  v-model="shaderPassFlag"
                  active-text="有半色调效果"
                  inactive-text="无半色调效果"
                >
                </el-switch>
              </el-form-item>
            </el-form>

            <br />
            <!-- <div class="box-right">  <el-button type="primary" >面与线框切换</el-button></div> -->
            <div style="text-align:left;">
            相关文章:
            <div style="color:blue;margin-top:5px;">
            http://www.taodudu.cc/news/show-4413505.html?action=onClick
            </div>
            <div style="color:blue;margin-top:5px;">
            https://blog.csdn.net/webMinStudent/article/details/130786714
            </div>
            </div>
          </div>
        </div>
      </el-main>
    </el-container>
  </div>
</template>
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// 效果制作器
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
// 渲染通道
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
// 发光描边OutlinePass
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
// 闪屏效果
import { GlitchPass } from "three/examples/jsm/postprocessing/GlitchPass.js";
// 电视效果
import { FilmPass } from "three/examples/jsm/postprocessing/FilmPass.js";
// AfterimagePass  重影效果
import { AfterimagePass } from "three/examples/jsm/postprocessing/AfterimagePass.js";
// ClearPass  清除背景通道
import { ClearPass } from "three/examples/jsm/postprocessing/ClearPass.js";
// DotScreenPass  点网效果
import { DotScreenPass } from "three/examples/jsm/postprocessing/DotScreenPass.js";
// 半色调效果
import { HalftonePass } from "three/examples/jsm/postprocessing/HalftonePass.js";
// 着色器通道
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js";

export default {
  data() {
    return {
      name: "",
      scene: null, // 场景对象
      camera: null, // 相机对象
      renderer: null,
      effectComposer: null,
      mesh: null,
      mesh1: null,
      geometry: null,
      group: null,
      material: null,
      texture: null,
      effectComposer: null,
      wireframe: false,
      outlinePass: null, // 发光描边
      outlinePassFlag: false, //  发光描边开关标志
      glitchPass: null, //  闪屏
      glitchPassFlag: false, //  闪屏开关标志
      filmPass: null, //  模拟电视
      filmPassFlag: false, //  模拟电视开关标志
      afterimagePass: null, //  重影效果
      afterimagePassFlag: false, //  重影效果关标志
      dotScreenPass: null, //  点网效果
      dotScreenPassFlag: false, //  点网效果关标志
      halftonePass: null, //  半色调效果
      HalftonePassFlag: false, //  半色调效果关标志
      shaderPass: null, //  着色器效果
      shaderPassFlag: false, //  着色器效果关标志
    };
  },
  watch: {
    wireframe: {
      handler(v) {
        this.changeLine();
      },
      deep: true,
      immediate: true,
    },
    shaderPassFlag: {
      handler(v) {
        if (this.effectComposer && this.shaderPass) {
          if (v) {
            // 效果制作器添加 着色器效果
            this.effectComposer.addPass(this.shaderPass);
          } else {
            // 效果制作器删除 着色器效果
            this.effectComposer.removePass(this.shaderPass);
          }
        }
      },
    },
    HalftonePassFlag: {
      handler(v) {
        if (this.effectComposer && this.halftonePass) {
          if (v) {
            // 效果制作器添加 半色调效果通道
            this.effectComposer.addPass(this.halftonePass);
          } else {
            // 效果制作器删除 半色调效果通道
            this.effectComposer.removePass(this.halftonePass);
          }
        }
      },
    },
    dotScreenPassFlag: {
      handler(v) {
        if (this.effectComposer && this.dotScreenPass) {
          if (v) {
            // 效果制作器添加 点网效果通道
            this.effectComposer.addPass(this.dotScreenPass);
          } else {
            // 效果制作器删除 点网效果通道
            this.effectComposer.removePass(this.dotScreenPass);
          }
        }
      },
    },
    afterimagePassFlag: {
      handler(v) {
        if (this.effectComposer && this.afterimagePass) {
          if (v) {
            // 效果制作器添加 发光描边通道
            this.effectComposer.addPass(this.afterimagePass);
          } else {
            // 效果制作器删除 发光描边通道
            this.effectComposer.removePass(this.afterimagePass);
          }
        }
      },
    },
    outlinePassFlag: {
      handler(v) {
        if (this.effectComposer && this.outlinePass) {
          if (v) {
            // 效果制作器添加 发光描边通道
            this.effectComposer.addPass(this.outlinePass);
          } else {
            // 效果制作器删除 发光描边通道
            this.effectComposer.removePass(this.outlinePass);
          }
        }
      },
    },
    glitchPassFlag: {
      handler(v) {
        if (this.effectComposer && this.glitchPass) {
          if (v) {
            // 效果制作器添加 闪屏效果通道
            this.effectComposer.addPass(this.glitchPass);
          } else {
            // 效果制作器删除 闪屏效果通道
            this.effectComposer.removePass(this.glitchPass);
          }
        }
      },
    },
    filmPassFlag: {
      handler(v) {
        if (this.effectComposer && this.filmPass) {
          if (v) {
            // 效果制作器添加 电视屏幕效果通道
            this.effectComposer.addPass(this.filmPass);
          } else {
            // 效果制作器删除 电视屏幕效果通道
            this.effectComposer.removePass(this.filmPass);
          }
        }
      },
    },
  },
  created() {},
  mounted() {
    this.name = this.$route.query.name;
    this.init();
  },
  methods: {
    goBack() {
      this.$router.go(-1);
    },
    outlinePassFn() {
      // 创建发光描边通道对象
      this.outlinePass = new OutlinePass(
        new this.$three.Vector2(1000, 800),
        this.scene,
        this.camera
      );
      // 设置描边颜色
      this.outlinePass.visibleEdgeColor.set(0xf01414);
      // 设置描边厚度
      this.outlinePass.edgeThickness = 5;
      // 设置描边发光强度
      this.outlinePass.edgeStrength = 6;
      // 设置模型闪烁频率
      this.outlinePass.pulsePeriod = 2;
      // 发光描边对象添加网格模型对象
      this.outlinePass.selectedObjects = [this.mesh];
    },
    glitchPassFn() {
      // 创建闪屏对象
      this.glitchPass = new GlitchPass();
    },
    // 点网效果
    dotScreenPassFn() {
      // 创建闪屏对象
      this.dotScreenPass = new DotScreenPass();
    },
    // 半色调效果
    HalftonePassFn() {
      // 创建闪屏对象
      this.halftonePass = new HalftonePass();
    },
    filmPassFn() {
      /**
       *  FilmPass通道可以通过扫描线和失真模拟电视屏幕
       *  new FilePass(nlntensity, slntensity, sCount, grayscale)
       *  nlntensity 控制屏幕的颗粒程度
       *  slntensity 控制屏幕上扫描线的显著程度
       *  sCount 控制扫描线的数量
       *  grayscale 接收一个布尔值,指定是否将图像转为灰度图
       *  */
      this.filmPass = new FilmPass(20, 10, 1000, false);
    },
    // 重影效果
    afterimagePassFn() {
      this.afterimagePass = new AfterimagePass();
    },
    // 着色器效果
    shaderPassFn() {
      const pixelationShader = {
        uniforms: {
          tDiffuse: { value: null },
          resolution: { value: new this.$three.Vector2(window.innerWidth, window.innerHeight) },
          pixelSize: { value: 5.0 }, // Adjust this value to control pixelation size
        },
        vertexShader: `
          varying vec2 vUv;
          void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
          }
        `,
        fragmentShader: `
          uniform sampler2D tDiffuse;
          uniform vec2 resolution;
          uniform float pixelSize;

          varying vec2 vUv;

          void main() {
            vec2 dxy = pixelSize / resolution;
            vec2 coord = dxy * floor(vUv / dxy);
            gl_FragColor = texture2D(tDiffuse, coord);
          }
        `,
      };
      this.shaderPass = new ShaderPass(pixelationShader);
    },
    // 后处理操作
    afterCure() {
      // 创建效果制作器对象
      this.effectComposer = new EffectComposer(this.renderer);
      // 创建渲染器通道对象
      const renderPass = new RenderPass(this.scene, this.camera);
      // 效果制作器添加 渲染器通道
      this.effectComposer.addPass(renderPass);
      // 发光描边
      this.outlinePassFn();
      // // 闪屏
      this.glitchPassFn();
      // // 模拟电视屏幕
      this.filmPassFn();
      // 重影效果
      this.afterimagePassFn();
      // 点网效果
      this.dotScreenPassFn();
      // 半色调效果
      this.HalftonePassFn();
      // 着色器效果
      this.shaderPassFn();
      // this.effectComposer.addPass(pixelationPass);
      // const clearPass = new ClearPass('white', 1);
      // this.effectComposer.addPass(clearPass);
    },
    init() {
      // 1,创建场景对象
      this.scene = new this.$three.Scene();
      /**
       * 创建四面缓冲几何体 TetrahedronGeometry(radius, detail)
       * radius: 四面体的半径;
       * detail: 默认值是0,将这个值设为一个大于0的数,将会为它添加一些顶点,使其不再是一个四面体
       *  */
      this.geometry = new this.$three.TetrahedronGeometry(50, 0);
      // 创建材质对象
      this.material = new this.$three.MeshBasicMaterial({
        color: 0xffffaa,
        wireframe: this.wireframe, // 将几何体渲染位线框,默认是false
      });
      // 创建网格对象
      this.mesh = new this.$three.Mesh(this.geometry, this.material);
      this.scene.add(this.mesh); // 将网格对象添加到场景中
      // 包围盒的辅助对象
      const box = new this.$three.BoxHelper(this.mesh, 0xffffff);
      this.scene.add(box);
      // 创建辅助坐标轴对象; 150 坐标轴长度
      const axesHelper = new this.$three.AxesHelper(150);
      this.scene.add(axesHelper);
      // 创建相机对象
      this.camera = new this.$three.PerspectiveCamera(60, 1, 0.01, 1000);
      // 设置相机对象的位置
      this.camera.position.set(200, 200, 100);
      this.camera.lookAt(0, 0, 0);
      // 创建渲染器对象
      this.renderer = new this.$three.WebGLRenderer();
      this.renderer.setSize(1000, 800); // 设置渲染尺寸
      // this.renderer.render(this.scene, this.camera); // 开始渲染
      window.document
        .getElementById("threejs")
        .appendChild(this.renderer.domElement);

      // 创建相机空间轨道控制器
      const controls = new OrbitControls(this.camera, this.renderer.domElement);
      controls.addEventListener("change", () => {
        this.renderer.render(this.scene, this.camera);
      });
      this.afterCure();
      this.renderFun();
    },
    // 点击切换按钮时触发
    changeLine() {
      let wf = JSON.parse(JSON.stringify(this.wireframe));
      if (this.mesh) {
        this.mesh.material.wireframe = wf;
        this.renderer.render(this.scene, this.camera); // 开始渲染
      }
    },
    renderFun() {
      this.effectComposer.render();
      window.requestAnimationFrame(this.renderFun);
    },
  },
};
</script>
//
<style lang="less" scoped>
.msg {
  padding: 20px;
  text-align: left;
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
  .span {
    margin: 0 30px 30px 0;
    // white-space: nowrap;
  }
  .p {
    text-align: left;
  }
}
.box-card-left {
  display: flex;
  align-items: flex-start;
  flex-direction: row;

  width: 100%;
  .box-right {
    text-align: left;
    padding: 10px;
    .xyz {
      width: 100px;
      margin-left: 20px;
    }
    .box-btn {
      margin-left: 20px;
    }
  }
}
.el-form-item {
  margin: 0;
}
</style>

文章来源:https://blog.csdn.net/yinge0508/article/details/135347068
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。