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。如果有不懂的可留言,看到会回复。

相关推荐
小彭努力中1 天前
138. CSS3DRenderer渲染HTML标签
前端·深度学习·3d·webgl·three.js
优雅永不过时·1 天前
three.js实现地球 外部扫描的着色器
前端·javascript·webgl·three.js·着色器
阿铎前端5 天前
Three.js PBR材质
vue·three.js
二三ErSan7 天前
深入探索ES 3D Editor:一个基于ThreeJS + Vue 3 + Naive UI的三维编辑器
three.js
Sword999 天前
【ThreeJs原理解析】第2期 | 旋转、平移、缩放实现原理
前端·three.js·源码阅读
小白菜学前端9 天前
Threejs 材质贴图、光照和投影详解
前端·3d·three.js
破浪前行·吴10 天前
使用@react-three/fiber,@mkkellogg/gaussian-splats-3d加载.splat,.ply,.ksplat文件
前端·react.js·three.js
格瑞@_@17 天前
11.Three.js使用indexeddb前端缓存模型优化前端加载效率
前端·javascript·缓存·three.js·indexeddb缓存
谢小飞17 天前
我做了三把椅子原来纹理这样加载切换
前端·three.js
小白菜学前端18 天前
ThreeJS创建一个3D物体的基本流程
3d·three.js