拓冰建站拓冰建站
首页 / 资讯中心 / 正文

three.js WebGPU 节点式像素化后期处理:PixelationPassNode 源码与实战完全指南

three.js WebGPU 节点式像素化后期处理PixelationPassNode 源码与实战完全指南【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js像素化Pixelation是复古游戏与像素艺术风格最常用的一种后期处理手法。在 three.js 的 WebGPU/TSL 渲染链路中PixelationPassNode将传统低分辨率渲染 颜色/法线/深度边缘检测组合封装成一个可直接插入RenderPipeline的美感渲染通道beauty pass。本文以 PixelationPassNode 官方文档 为骨架结合examples/jsm/tsl/display/PixelationPassNode.js源码与官方示例逐步剖析其继承关系、构造参数、公开属性/方法并给出一份完整可运行的实战代码与参数调优建议。读完本文你将能够在自己的 WebGPU 后处理管线中复现出带单像素描边的高质量像素化画面。PixelationPassNode 是什么PixelationPassNode是一个特殊的渲染通道节点render pass node它以低分辨率渲染场景从而在视觉上产生像素方块效果同时通过检测深度边缘与法线边缘在色块交界处保留或增强描边细节避免低分辨率采样把模型轮廓糊成一团。它属于 three.js 的WebGPU/TSLThree Shading Language节点体系其类层次为EventDispatcher → Node → TempNode → PassNode → PixelationPassNode其中父类PassNode的实现位于 src/nodes/display/PassNode.js负责把场景与相机渲染到内部纹理即所谓 beauty passPixelationPassNode则在其基础上改写渲染分辨率与采样方式实现像素化输出。与其功能相对应、但运行在传统 WebGL/EffectComposer链路中的同类组件是 examples/jsm/postprocessing/RenderPixelatedPass.js非节点式 Pass可作为迁移或对比参考。导入方式PixelationPassNode属于插件addon模块不会随 three.js 核心自动打包必须显式导入。推荐使用其附带的TSL 工厂函数pixelationPassimport { pixelationPass } from three/addons/tsl/display/PixelationPassNode.js;若希望使用类本身做类型判断或继承扩展也可以直接导入默认导出import PixelationPassNode from three/addons/tsl/display/PixelationPassNode.js;从源码可见该模块共导出了两个符号PixelationPassNode.js 中pixelationPass只是对new PixelationPassNode(...)的语法糖封装两者等价export const pixelationPass ( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength );构造函数与参数详解new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength )源码中的完整签名与默认值见 PixelationPassNode.jsconstructor( scene, camera, pixelSize 6, normalEdgeStrength 0.3, depthEdgeStrength 0.4 )参数类型默认值含义sceneScene—要被渲染的场景cameraCamera—渲染场景所用的相机pixelSizeNodefloat|number6像素尺寸即最终色块边长对应的缩小倍数normalEdgeStrengthNodefloat|number0.3法线边缘强度depthEdgeStrengthNodefloat|number0.4深度边缘强度参数解析要点scene与camera会被透传给父类PassNode内部渲染目标的光圈被设为PassNode.COLOR。三个数值参数不仅可以是普通数字还可以是TSL 节点对象如uniform(...)包出的变量从而支持运行时通过 GUI 或动画实时调节。官方示例 examples/webgpu_postprocessing_pixel.html 正是把三个参数全部做成uniformeffectController { pixelSize: uniform( 6 ), normalEdgeStrength: uniform( 0.3 ), depthEdgeStrength: uniform( 0.4 ), pixelAlignedPanning: true };公开属性.pixelSize : number默认6像素大小。除了在 shader 中控制色块粒度外它还会影响内部渲染目标的分辨率见下文setSize说明。调大数值色块更大、画面更糊。.normalEdgeStrength : number默认0.3法线边缘强度。控制几何表面朝向突变处如立方体的棱边缘的检测力度与明暗对比。.depthEdgeStrength : number默认0.4深度边缘强度。控制前后景深度突变处物体轮廓、穿插交界边缘的强度。通常可略大于法线边缘强度以强化轮廓。.isPixelationPassNode : boolean只读默认true用于类型检测的只读标志。在拿到不确定的节点对象时可借助node.isPixelationPassNode true判断其是否为像素化通道节点。公开方法.setSize( width : number, height : number )设置通道内部渲染目标的尺寸。这是像素化效果的关键见 PixelationPassNode.jssetSize( width, height ) { const pixelSize this.pixelSize.value ? this.pixelSize.value : this.pixelSize; const adjustedWidth Math.floor( width / pixelSize ); const adjustedHeight Math.floor( height / pixelSize ); super.setSize( adjustedWidth, adjustedHeight ); }也就是说通道内部实际渲染分辨率会被压缩为⌊width / pixelSize⌋ × ⌊height / pixelSize⌋画面先以小分辨率渲染、再被放大回目标尺寸从而形成像素方块。注意这里兼容了pixelSize是 uniform 节点的情形会优先读取this.pixelSize.value因此运行时改大pixelSize也能让内部目标分辨率同步下降。该方法重写了父类 PassNode#setSize。.setup( builder : NodeBuilder ) : PixelationNode节点构建方法用于装配效果对应的 TSL 着色代码返回一个内部的PixelationNode。其实现见 PixelationPassNode.js先从父类取出三张内部缓冲纹理再送入像素化计算节点setup() { const color super.getTextureNode( output ); const depth super.getTextureNode( depth ); const normal super.getTextureNode( normal ); return pixelation( color, depth, normal, this.pixelSize, this.normalEdgeStrength, this.depthEdgeStrength ); }该方法重写了 PassNode#setup。底层实现原理低分辨率渲染 双通道边缘检测要写出稳定的像素化效果单纯降低分辨率是不够的——边缘检测必须拿到几何信息。PixelationPassNode的源码揭示了完整的实现链路。1. 最近邻采样与 MRT 几何缓冲构造函数中向父类传递了NearestFilter采样设置并配置了一套MRT多渲染目标super( PassNode.COLOR, scene, camera, { minFilter: NearestFilter, magFilter: NearestFilter } ); // ... this._mrt mrt( { output: output, // 颜色输出 normal: normalView // 视角空间法线 } );最近邻过滤保证色块边缘锐利、无线性插值的模糊过渡而 MRT 则在渲染场景的同时额外产出法线信息供后续边缘检测使用深度信息由渲染目标本身附带。2. 每帧刷新分辨率 uniform内部的PixelationNode继承自TempNode将其updateType设为NodeUpdateType.FRAME每帧更新并在update()回调中把输入纹理的宽高及倒数写入一个vec4uniformthis._resolution.value.set( width, height, 1 / width, 1 / height );resolution.xy为全分辨率尺寸resolution.zw则是单像素对应的归一化 UV 步长供后续邻域采样使用见 PixelationPassNode.js。3. 深度边缘检测depthEdgeIndicator对当前像素的上、下、左、右四个邻域分别采样深度并计算差值再经由smoothstep( 0.01, 0.02, ... )与floor(...).div(2)归一化为0 或 0.5两级深度边缘指示值——只有深度突变足够明显的像素才会被标记源码 PixelationPassNode.js。4. 法线边缘检测normalEdgeIndicator / neighborNormalEdgeIndicator法线边缘的判断要更精细其规则可以从代码注释中读出只有**较浅更靠近相机**的一侧像素才被允许报告法线边缘借助深度差值符号作为门控depthIndicator用邻域法线与当前法线越接近越趋近 1的normalIndicator避免同一面内部被误判最终输出1 - dot(normal, neighborNormal)与两个指示器相乘的累计值并通过step( 0.1, indicator )二值化源码 PixelationPassNode.js。从源码结构看其中硬编码的normalEdgeBias vec3(1,1,1)处还留有注释This should probably be a parameter说明法线偏置方向目前是固定值未来存在参数化的可能。5. 边缘与色块融合像素化主函数Fn()内使用If按需开启各条分支——当某个强度参数为0时完全跳过对应的边缘计算节省开销源码 PixelationPassNode.js。最终亮度修正强度为const strength dei.greaterThan( 0 ) .select( float( 1.0 ).sub( dei.mul( this.depthEdgeStrength ) ), nei.mul( this.normalEdgeStrength ).add( 1 ) ); return vec4( texel.mul( strength ).rgb, texel.a );即深度边缘处的像素按depthEdgeStrength变暗形成轮廓非法线/深度边缘的区域则整体提亮为1 normalEdgeStrength这正是像素块 单像素描边视觉风格的来源见 PixelationPassNode.js。完整实战示例官方演示页 examples/webgpu_postprocessing_pixel.html 是集成该节点的最小可运行样例其完整使用方式如下。步骤 1配置 importmap由于该示例同时使用 WebGPU 渲染器与 TSL 构建产物需要把相关入口映射到build目录下的模块script typeimportmap { imports: { three: ../build/three.webgpu.js, three/webgpu: ../build/three.webgpu.js, three/tsl: ../build/three.tsl.js, three/addons/: ./jsm/ } } /script步骤 2创建渲染管线并挂载节点import * as THREE from three/webgpu; import { OrbitControls } from three/addons/controls/OrbitControls.js; import { uniform } from three/tsl; import { pixelationPass } from three/addons/tsl/display/PixelationPassNode.js; renderer new THREE.WebGPURenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setAnimationLoop( animate ); renderer.shadowMap.enabled true; document.body.appendChild( renderer.domElement ); // 把三个效果参数做成可实时调用的 uniform const effectController { pixelSize: uniform( 6 ), normalEdgeStrength: uniform( 0.3 ), depthEdgeStrength: uniform( 0.4 ), pixelAlignedPanning: true }; // 将像素化通道作为输出节点 const renderPipeline new THREE.RenderPipeline( renderer ); const scenePass pixelationPass( scene, camera, effectController.pixelSize, effectController.normalEdgeStrength, effectController.depthEdgeStrength ); renderPipeline.outputNode scenePass;之后在动画循环中只需调用renderPipeline.render()每帧都会先以低分辨率渲染场景再套用边缘检测与色块放大。步骤 3用参数面板实时调参官方示例借助WebGPURenderer.inspector暴露出三个核心参数区间即官方示例推荐的调试范围const gui renderer.inspector.createParameters( Settings ); gui.add( effectController.pixelSize, value, 1, 16, 1 ).name( Pixel Size ); gui.add( effectController.normalEdgeStrength, value, 0, 2, 0.05 ).name( Normal Edge Strength ); gui.add( effectController.depthEdgeStrength, value, 0, 1, 0.05 ).name( Depth Edge Strength ); gui.add( effectController, pixelAlignedPanning );关于像素对齐平移pixelAlignedPanning示例使用正交相机并提供辅助函数pixelAlignFrustum()它会根据当前pixelSize计算出单块像素对应的世界单位再微调相机平截体frustum使相机平移时色块始终与屏幕像素网格对齐避免画面出现滑动抖动。只有当相机是正交相机时才需要这一辅助透视相机下该技术不适用。需要 WebGL 旧管线怎么办如果你的项目仍运行在WebGLRenderer EffectComposer上可改用同主题的传统 Pass 类RenderPixelatedPass见 RenderPixelatedPass.jsconst renderPixelatedPass new RenderPixelatedPass( 6, scene, camera ); composer.addPass( renderPixelatedPass );其构造参数含义pixelSize、以及通过options.normalEdgeStrength/options.depthEdgeStrength传入的边缘强度与节点版一一对应便于两个渲染后端之间迁移。参数调优建议综合源码逻辑与示例 GUI 区间可按以下思路调试目标建议做法色块大小调节pixelSize示例区间1 ~ 16步长 1。1约等于无像素化6左右是较自然的复古色块过大时几何会丢失需依赖更强的边缘描边兜底轮廓更黑、更明显增大depthEdgeStrength示例区间0 ~ 1步长 0.05。只对深度突变处生效不易误伤平滑表面转折面棱线更清晰增大normalEdgeStrength示例区间0 ~ 2步长 0.05。对立方体棱、多面体转折效果显著关闭某一类边缘直接把对应强度设为0。源码中会跳过该分支的采样与计算还能略微省下 GPU 开销需要注意pixelSize会同时改变内部渲染分辨率因此该数值越小、渲染开销越高场景较大或需要 60 FPS 时建议先用pixelSize 8起步观察观感再回退。小结PixelationPassNode用约 330 行源码把低分辨率场景渲染 MRT 几何缓冲 深度/法线邻域边缘检测 最近邻放大这一套像素化方案完整封装成 WebGPU/TSL 渲染管线中即插即用的节点并允许通过 TSL 节点参数实现运行时实时调节。它的直接使用入口是 TSL 工厂函数pixelationPass内部逻辑可对照 examples/jsm/tsl/display/PixelationPassNode.js 阅读运行效果可参考 webgpu_postprocessing_pixel.html。若需要更完整的后处理编排知识可继续阅读 PostProcessing 与 RenderPipeline 文档以及其父类 PassNode 的详细 API。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门