Three.js realizes the local glow effect of model materials and solves the problem that glow affects the display of scene background images

1.Three.js realizes the local glow effect of the model material

2. Solve the problem that the glow effect affects the display of the scene background image

Use of related APIs:

1. EffectComposer (a general framework for post-rendering processing, used to combine multiple rendering passes (pass) to create specific visual effects)

2. RenderPass (is the channel used to render the scene. It takes the scene and the camera as input, uses the Three.js default renderer (renderer) to render the scene, and outputs the result to the next rendering pass)

3. UnrealBloomPass (It is a post-processing effect used in three.js to achieve the bloom effect. Through Gaussian blur and screen blending technology, the area with higher brightness is diffused to achieve a realistic bloom effect.)

4. ShaderPass (is a channel of a custom shader. It allows you to specify a custom shader code and apply it to the rendering result of the scene. This way you can create a variety of graphics effects, such as Gaussian blur, post-processing effects, etc.)

On the basis of the previous article on Three.js loading external glb, fbx, gltf, obj model files, a new createEffectComposer (effect synthesizer method) and sceneAnimation (effect render method) and getFlowMeaterList (to obtain glow effect materials) method)

First introduce the relevant api

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'

Create Effect Composer method (createEffectComposer): need to create two compositors effectComposer for normal rendering scene, glowComposer for rendering glow effect

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)
	}

Get the material that needs glow rendering:

   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)
   }

Rendering scene method (sceneAnimation): handle materials that do not require glow. Note: The glow effect will affect the normal display of the scene background image and needs to be processed separately ( here, use instanceof THREE.Scene to judge whether it is a scene material and then process it separately )

   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()
	}

The complete code can refer to: https://gitee.com/ZHANG_6666/Three.js3D/blob/master/src/views/renderModel.js

Interface effect comparison
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/weixin_43835425/article/details/132370548