1.THREEJS高级-全局辉光和部分辉光

辉光

辉光就是让一个模型进行发光,可以实现灯泡,车灯的效果。

全局辉光

threejs官网案例:threejs.org/examples/?q...

  1. 引入实现辉光所需要的扩展库
js 复制代码
//引入后处理扩展库 
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; 
//引入渲染器通道RenderPass 
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; 
// 引入UnrealBloomPass辉光通道 
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
  1. EffectComposer

想要在用threejs输出一张图像,除了必不可少的场景、相机外还需要WebGLRenderer把图像渲染到页面上,如果你需要对一个webgl渲染器的渲染结果进行后期处理,就把它作为EffectComposer的参数。

kotlin 复制代码
this.composer = new EffectComposer(this.renderer)
  1. RenderPass

通过EffectComposer指定需要后期处理的渲染器后。再通过渲染器通道RenderPass指定后处理对应的相机camera和场景scene

// 复制代码
const renderPass = new RenderPass(this.scene, this.camera);
  1. 发光通道UnrealBloomPass

参数1是一个二维向量Vector2,二维向量尺x、y分量要和Canvas画布的宽、高度尺寸保持一致。参数2是发光强度,参数3是发光阈值,参数4是发光半径。

javascript 复制代码
this.bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight),1,0.5,0.5)
  1. EffectComposer添加渲染器通道RenderPass和发光通道。
kotlin 复制代码
// 设置renderPass通道 
this.composer.addPass(renderPass); this.composer.addPass(this.bloomPass)
  1. 循环执行
kotlin 复制代码
this.composer.render()

效果图:前后对比

部分辉光

threejs官网案例threejs.org/examples/q=...

  • 有时候我们只希望部分物体发光,但是辉光会对场景中所有模型产生效果,那么就会导致其他不希望有辉光效果的物体出现了辉光。

  • 想要实现部分模型有辉光的效果就不得不提到图层。

    • 图层简介:图层对象为Object3D对象分配了1-32个图层,编号为0-31。 默认所有 Object3D 对象都存储在第 0 个图层上。图层对象可以用于控制对象的显示,和相机处于同一个图层的物体才可以被显示出来。每个继承自 Object3D 的对象都有一个 Object3D.layers 对象。Mesh、Camera、Group等都继承自基类 Object3D,所以它们都有一个 layers 属性。
  • 具体实现方式如下;

    • 思路:准备两个后处理器 EffectComposer,一个用于产生辉光效果(bloomComposer ),另一个用来正常渲染整个场景(finalComposer)。在创建一个集合对象,用来存储要辉光的模型,主要是用于区分辉光和不辉光的模型
  • 准备基础数据和方法后面要用

javascript 复制代码
BLOOM_SCENE: 1,
bloomLayer: new THREE.Layers(),
materials: {},
darkMaterial: new THREE.MeshBasicMaterial({ color: 'black' })
init() {
  this.bloomLayer.set(this.BLOOM_SCENE);
},
//要启用图层1,才会展示辉光效果
initCamera() {
       ......
  this.camera.layers.enable(1)
},
 //非辉光图层的模型颜色全部变为黑色
darkenNonBloomed(obj) {
  if (obj.isMesh && this.bloomLayer.test(obj.layers) === false) {
    this.materials[obj.uuid] = obj.material;
    obj.material = this.darkMaterial;
  }
},
//恢复非辉光图层的模型颜色
restoreMaterial(obj) {
  if (this.materials[obj.uuid]) {
    obj.material = this.materials[obj.uuid];
    delete this.materials[obj.uuid];
  }
},

initModelGlow(url) {
  const loader = new GLTFLoader()
  loader.load(url, (gltf) => {
    const model = gltf.scene;
    gltf.scene.traverse((obj) => {
      if (obj.isMesh) {
          //注意:设置导入的模型图层与辉光涂层一样才会显示辉光
        obj.layers.set(this.BLOOM_SCENE)
      }
    })
    model.translateX(5)
    this.scene.add(model);
  });
},
  • 创建辉光图层,将辉光物体添加在该图层上,用于区分辉光物体和非辉光物体
kotlin 复制代码
this.bloomLayer.set(this.BLOOM_LAYER);
  • 利用 UnrealBloomPass实现辉光
kotlin 复制代码
let renderScene = new RenderPass(this.scene, this.camera)

this.bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight))
this.bloomPass.strength = this.params.bloomStrength
this.bloomPass.threshold = this.params.bloomThreshold
this.bloomPass.radius = this.params.bloomRadius
  • 准备第一个后处理器 EffectComposer,产生辉光效果
kotlin 复制代码
this.bloomComposer = new EffectComposer(this.renderer)
this.bloomComposer.renderToScreen = false; //不渲染到屏幕
this.bloomComposer.addPass(renderScene)
this.bloomComposer.addPass(this.bloomPass)
  • 这块不是很懂,貌似是利用ShaderPass着色器合成最终通道(不包含辉光特效)
php 复制代码
const mixPass = new ShaderPass(
new THREE.ShaderMaterial({
  uniforms: {
    baseTexture: { value: null },
    bloomTexture: { value: this.bloomComposer.renderTarget2.texture }
  },
  vertexShader: '\t\t\tvarying vec2 vUv;\n' +
    '\n' +
    '\t\t\tvoid main() {\n' +
    '\n' +
    '\t\t\t\tvUv = uv;\n' +
    '\n' +
    '\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n' +
    '\n' +
    '\t\t\t}',
  fragmentShader: '\t\t\tuniform sampler2D baseTexture;\n' +
    '\t\t\tuniform sampler2D bloomTexture;\n' +
    '\n' +
    '\t\t\tvarying vec2 vUv;\n' +
    '\n' +
    '\t\t\tvoid main() {\n' +
    '\n' +
    '\t\t\t\tgl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );\n' +
    '\n' +
    '\t\t\t}',
  defines: {}
}), 'baseTexture'
);
mixPass.needsSwap = true;
  • 利用 finalComposer 渲染,finalComposer 将加入两个通道,一个是 bloomComposer 的渲染结果,另一个则是正常的渲染结果。
kotlin 复制代码
this.finalComposer = new EffectComposer(this.renderer);
this.finalComposer.addPass(renderScene);
this.finalComposer.addPass(mixPass);
  • 循环渲染

    先将不辉光的模型材质设置为黑色,模型设置为黑色后,辉光也没有效果。然后执行辉光合成器的render进行渲染,此时场景渲染辉光,而不需要辉光的模型因为设置了黑色,所以也看不出来。到此,场景中需要辉光的模型就实现了辉光,而不需要辉光的模型目前是看不见的,所以接下来,我们要将材质设置为黑色的模型还原成原本的材质颜色,再执行最终合成器的render进行渲染,因为finalComposer合成器中不包含辉光特效,所以第二次redner后,只渲染了正常不辉光的模型,而第一次渲染辉光的模型也被混合在一起了,所以场景最终就实现了一部分模型辉光,一部分不辉光。

kotlin 复制代码
render() {
  this.scene.traverse(this.darkenNonBloomed)
  // 渲染辉光合成器\
  this.bloomComposer.render()
  // 还原不会光的材质
  this.scene.traverse(this.restoreMaterial)
  // 渲染最终合成器
  this.finalComposer.render()
  // this.renderer.render(this.scene, this.camera)
},

效果图

以下案例源码在此处: gitee.com/ldglys/thre... 如果对您有所帮助请给个star。如果有不懂的可留言,看到会回复。

相关推荐
一颗烂土豆10 小时前
🚴‍♂️ Vue3 + Three.js 实战:如何写一个“不晕车”的沉浸式骑行播放器 🎥
vue.js·游戏·three.js
Elaine3362 天前
Gemini生成的3D交互圣诞树(娱乐版)
3d·交互·three.js·前端可视化
Awu12272 天前
Vue3自定义渲染器:原理剖析与实践指南
前端·vue.js·three.js
龙猫不热3 天前
THREE.js 关于Material基类下的depthTest 和 depthWrite的理解
前端·three.js
阿里巴啦6 天前
用React+Three.js 做 3D Web版搭建三维交互场景:模型的可视化摆放与轻量交互
前端·react·three.js·模型可视化·web三维·web三维交互场景
阿里巴啦8 天前
React + Three.js + R3F + Vite 实战:可交互的三维粒子化展厅
react.js·three.js·粒子化·drei·postprocessing·三维粒子化
叫我詹躲躲9 天前
基于 Three.js 的 3D 地图可视化:核心原理与实现步骤
前端·three.js
map_3d_vis9 天前
JSAPIThree 加载单体三维模型学习笔记:SimpleModel 简易加载方式
学习笔记·three.js·gltf·glb·初学者·三维模型·mapvthree·jsapithree·simplemodel
Addisonx13 天前
深度复盘 III: 核心逻辑篇:构建 WebGL 数字孪生的“业务中枢”与“安全防线”
webgl·three.js
爱看书的小沐13 天前
【小沐学WebGIS】基于Three.JS绘制二三维地图地球晨昏效果(WebGL / vue / react )
javascript·vue.js·gis·webgl·three.js·opengl·晨昏线