如何在Forge Viewer中添加后期处理Shader效果?需实现对象模糊
Forge Viewer 实现局部对象模糊的方案
核心思路和Three.js的postprocessing一致:先将需要模糊的对象单独渲染到离屏缓冲,对缓冲执行模糊处理后,再将结果叠加到主场景画面上。以下是具体实现步骤,适配你使用的@contecht/react-adsk-forge-viewer React TypeScript封装库:
1. 创建离屏渲染目标
Forge Viewer底层基于Three.js,直接用THREE.WebGLRenderTarget创建离屏缓冲,需要先获取Viewer的Three.js渲染器实例:
import * as THREE from 'three'; import type { Autodesk } from '@types/forge-viewer'; // 从React ref获取Viewer实例(假设你已通过组件ref挂载) const viewer = viewerRef.current as Autodesk.Viewing.GuiViewer3D; const threeRenderer = viewer.impl.renderer; // 初始化离屏渲染目标 const renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, type: THREE.FloatType });
2. 单独渲染目标对象到离屏缓冲
渲染前临时修改场景可见性,只保留需要模糊的对象,渲染完成后恢复原状态:
// 替换为你需要模糊的对象集合 const targetObjects: THREE.Object3D[] = getYourTargetObjects(); // 暂存原场景对象的可见性 const originalVisibilities = new Map<THREE.Object3D, boolean>(); const scene = viewer.impl.scene; // 隐藏非目标对象 scene.traverse(obj => { if (!targetObjects.includes(obj)) { originalVisibilities.set(obj, obj.visible); obj.visible = false; } }); // 渲染到离屏缓冲 threeRenderer.setRenderTarget(renderTarget); threeRenderer.render(scene, viewer.impl.camera); threeRenderer.setRenderTarget(null); // 恢复原场景可见性 originalVisibilities.forEach((visible, obj) => { obj.visible = visible; });
3. 实现模糊后处理并叠加到主场景
创建全屏平面网格,使用自定义Shader对离屏纹理做模糊处理,然后添加到Viewer的叠加场景中:
模糊Shader代码
// 顶点着色器 varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } // 片段着色器(9核高斯模糊) uniform sampler2D uTexture; uniform vec2 uResolution; uniform float uBlurStrength; varying vec2 vUv; vec4 blur(sampler2D tex, vec2 uv, vec2 resolution, float strength) { vec4 color = vec4(0.0); vec2 offset = strength / resolution; float kernel[9] = float[](1.0, 2.0, 1.0, 2.0, 4.0, 2.0, 1.0, 2.0, 1.0); float kernelSum = 16.0; int index = 0; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { color += texture2D(tex, uv + vec2(x, y) * offset) * kernel[index] / kernelSum; index++; } } return color; } void main() { gl_FragColor = blur(uTexture, vUv, uResolution, uBlurStrength); }
TypeScript创建全屏模糊平面
// 创建全屏平面几何体 const planeGeo = new THREE.PlaneGeometry(2, 2); const blurMaterial = new THREE.ShaderMaterial({ uniforms: { uTexture: { value: renderTarget.texture }, uResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) }, uBlurStrength: { value: 5.0 } // 可根据需求调整模糊强度 }, vertexShader: /* 上面的顶点着色器字符串 */, fragmentShader: /* 上面的片段着色器字符串 */, transparent: true, blending: THREE.NormalBlending }); const blurPlane = new THREE.Mesh(planeGeo, blurMaterial); // 添加到Viewer的叠加场景,避免干扰原场景逻辑 viewer.impl.createOverlayScene('blur-overlay'); viewer.impl.addOverlay('blur-overlay', blurPlane);
4. 嵌入Viewer渲染循环与窗口适配
Viewer自带渲染循环,需要将离屏渲染逻辑嵌入到渲染更新事件中,同时处理窗口resize:
// 监听Viewer渲染更新,每次刷新时重新生成离屏缓冲 viewer.addEventListener(Autodesk.Viewing.VIEWER_UPDATE_EVENT, () => { // 重复步骤2的渲染逻辑,更新离屏缓冲(可封装成函数复用) blurMaterial.uniforms.uTexture.value = renderTarget.texture; }); // 窗口resize时更新渲染目标和材质分辨率 window.addEventListener('resize', () => { renderTarget.setSize(window.innerWidth, window.innerHeight); blurMaterial.uniforms.uResolution.value.set(window.innerWidth, window.innerHeight); });
针对@contecht/react-adsk-forge-viewer的注意事项
该封装库通过React ref暴露Viewer实例,在组件挂载完成后初始化逻辑即可:
import { ForgeViewer } from '@contecht/react-adsk-forge-viewer'; import { useRef, useEffect } from 'react'; function ModelViewer() { const viewerRef = useRef<Autodesk.Viewing.GuiViewer3D>(null); useEffect(() => { if (!viewerRef.current) return; // 在这里执行上述所有初始化逻辑 initBlurEffect(viewerRef.current); }, []); return ( <ForgeViewer ref={viewerRef} clientId="YOUR_CLIENT_ID" modelUrn="YOUR_MODEL_URN" /* 其他配置项 */ /> ); }
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

