1.Three.js realiza o efeito de brilho local do material do modelo
2. Resolva o problema de que o efeito de brilho afeta a exibição da imagem de fundo da cena
Uso de APIs relacionadas:
1. EffectComposer (uma estrutura geral para processamento pós-renderização, usada para combinar várias passagens de renderização (passagem) para criar efeitos visuais específicos)
2. RenderPass (é o canal usado para renderizar a cena. Ele pega a cena e a câmera como entrada, usa o renderizador padrão Three.js (renderizador) para renderizar a cena e envia o resultado para a próxima etapa de renderização)
3. UnrealBloomPass (É um efeito de pós-processamento usado em three.js para obter o efeito bloom. Através do desfoque gaussiano e da tecnologia de mesclagem de tela, a área com maior brilho é difusa para obter um efeito bloom realista.)
4. ShaderPass (é um canal de um shader personalizado. Ele permite especificar um código de shader personalizado e aplicá-lo ao resultado da renderização da cena. Dessa forma, você pode criar uma variedade de efeitos gráficos, como desfoque gaussiano, pós- efeitos de processamento, etc.)
Com base no artigo anterior sobre Three.js carregando arquivos de modelo externos glb, fbx, gltf, obj, um novo createEffectComposer (método de sintetizador de efeito) e sceneAnimation (método de renderização de efeito) e getFlowMeaterList (para obter materiais de efeito de brilho ) foram adicionados. método)
Primeiro introduza a API relevante
import {
EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import {
RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import {
UnrealBloomPass} from 'three/examples/jsm/postprocessing/OutlinePass.js'
import {
ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'
Criar método Effect Composer (createEffectComposer): precisa criar dois compositores effectComposer para cena de renderização normal, glowComposer para renderizar efeito de brilho
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.unrealBloomPass = new UnrealBloomPass(new THREE.Vector2(clientWidth, clientHeight), 0, 0, 0)
this.unrealBloomPass.threshold = 1 // 辉光强度
this.unrealBloomPass.strength = 0 // 辉光阈值
this.unrealBloomPass.radius = 1 //辉光半径
this.unrealBloomPass.renderToScreen = false //
// 辉光合成器
this.glowComposer = new EffectComposer(this.renderer)
this.glowComposer.renderToScreen = false
this.glowComposer.addPass(new RenderPass(this.scene, this.camera))
this.glowComposer.addPass(this.unrealBloomPass)
// 着色器
let shaderPass = new ShaderPass(new THREE.ShaderMaterial({
uniforms: {
baseTexture: {
value: null },
bloomTexture: {
value: this.glowComposer.renderTarget2.texture },
tDiffuse: {
value: null
}
},
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')
shaderPass.renderToScreen = true
shaderPass.needsSwap = true
this.effectComposer.addPass(shaderPass)
}
Obtenha o material que precisa de renderização de brilho:
getFlowMeaterList(){
const modelMaterialList= []
this.model.traverse((v) => {
if (v.isMesh && v.material) {
const {
name, color,map } = v.material
// 统一将模型材质 设置为 MeshLambertMaterial 类型
v.material = new THREE.MeshLambertMaterial({
map,
transparent: true,
color,
name,
})
modelMaterialList.push(v)
}
})
this.glowMaterialList = modelMaterialList.map(v=>v.name)
}
Método de renderização de cena (sceneAnimation): manuseie materiais que não requerem brilho. Nota: O efeito de brilho afetará a exibição normal da imagem de fundo da cena e precisa ser processado separadamente ( aqui, julgue se é um material de cena por instância de TRÊS.Cena e, em seguida, processe-o separadamente )
sceneAnimation() {
this.renderAnimation = requestAnimationFrame(() => this.sceneAnimation())
this.controls.update()
// 将不需要处理辉光的材质进行存储备份
this.scene.traverse((v) => {
// 备份一份场景背景然后清空
if (v instanceof THREE.Scene) {
this.materials.scene = v.background
v.background = null
}
if (!this.glowMaterialList.includes(v.name) && v.isMesh) {
// 备份当前材质内容
this.materials[v.uuid] = v.material
// 将不需要辉光的材质设置为黑色
v.material = new THREE.MeshBasicMaterial({
color: 'black' })
}
})
// 执行辉光效果器渲染
this.glowComposer.render()
// 在辉光渲染器执行完之后在恢复材质原效果
this.scene.traverse((v) => {
if (this.materials[v.uuid]) {
v.material = this.materials[v.uuid]
delete this.materials[v.uuid]
}
if (v instanceof THREE.Scene) {
v.background = this.materials.scene
delete this.materials.scene
}
})
// 执行场景效果器渲染
this.effectComposer.render()
}
O código completo pode se referir a: https://gitee.com/ZHANG_6666/Three.js3D/blob/master/src/views/renderModel.js
Comparação de efeito de interface