前言
本篇给大家分享一下在threejs中如何实现材质边缘通道发光的效果
在上一篇 Three.js加载外部glb,fbx,gltf,obj 模型文件 的文章基础上
一、引入需要的API
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js'
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js'
二、新加入两个方法
- 创建效果合成器:createEffectComposer
- 选择材质:onChangeModelMeaterial
创建效果合成器方法
// 创建效果合成器
createEffectComposer() {
const { clientHeight, clientWidth } = this.container
this.effectComposer = new EffectComposer(this.renderer)
const renderPass = new RenderPass(this.scene, this.camera)
this.effectComposer.addPass(renderPass)
this.outlinePass = new OutlinePass(new THREE.Vector2(clientWidth, clientHeight), this.scene, this.camera)
this.outlinePass.visibleEdgeColor = new THREE.Color('#4d57fd') // 可见边缘的颜色
this.outlinePass.hiddenEdgeColor = new THREE.Color('#8a90f3') // 不可见边缘的颜色
this.outlinePass.edgeGlow = 2.0 // 发光强度
this.outlinePass.edgeThickness = 1 // 边缘浓度
this.outlinePass.edgeStrength = 4 // 边缘的强度,值越高边框范围越大
this.outlinePass.pulsePeriod = 100 // 闪烁频率,值越大频率越低
this.effectComposer.addPass(this.outlinePass)
// 抗锯齿
let effectFXAA = new ShaderPass(FXAAShader)
effectFXAA.uniforms.resolution.value.set(1 / clientWidth, 1 / clientHeight)
this.effectComposer.addPass(effectFXAA)
}
// 选择材质方法
onChangeModelMeaterial(name) {
const mesh = this.model.getObjectByName(name)
this.outlinePass.selectedObjects = [mesh]
}
三、修改动画帧函数渲染方式,使用effectComposer.render进行渲染
sceneAnimation() {
this.renderAnimation = requestAnimationFrame(() => this.sceneAnimation())
this.effectComposer.render()
this.controls.update()
}
四、在页面中去使用
<script setup>
import { reactive, computed } from "vue";
const store = useMeshEditStore();
const config = reactive({
meshName: null,
color: null,
wireframe: false,
depthWrite: true,
opacity: 1,
});
// 选择材质
const onChangeMaterialType = (mesh) => {
const { name } = mesh
config.meshName = name;
const activeMesh = state.modelApi.onChangeModelMeaterial(name);
const { color, wireframe, depthWrite, opacity } = activeMesh.material;
Object.assign(config, {
color: new THREE.Color(color).getStyle(),
wireframe,
depthWrite,
opacity,
});
const originMaterial = state.originalMaterials.get(mesh.uuid)
activeMeshMap.value = {
url: getModelMaps(mesh),
name: mesh.name,
mapId: mesh.mapId,
material: originMaterial
}
};
// 获取模型自带贴图
const getModelMaps = (mesh) => {
const originMaterial = state.originalMaterials.get(mesh.uuid)
const materials = Array.isArray(originMaterial) ? originMaterial : [originMaterial]
let textureMapUrl
materials.forEach(texture => {
if (texture.map && texture.map.image) {
const canvas = document.createElement('canvas')
const { width, height } = texture.map.image
canvas.width = width
canvas.height = height
const context = canvas.getContext('2d')
context.drawImage(texture.map.image, 0, 0)
textureMapUrl = canvas.toDataURL('image/png', .5)
canvas.remove()
}
})
return textureMapUrl
}
<script>
五、完整的代码可参考:gitee.com/ZHANG_6666/…
六、界面效果对比
1.选中前
2.选中后