news 2026/9/8 23:29:40

three.js DotScreenPass 实战:3 个参数玩转复古网点滤镜

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
three.js DotScreenPass 实战:3 个参数玩转复古网点滤镜

three.js DotScreenPass 实战:3 个参数玩转复古网点滤镜

【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js

往渲染循环里加一个 Pass,三维场景就被啃成一片密集的圆点阵列——three.js 的DotScreenPass就是这么干的后处理滤镜,一行代码把屏幕变成复古半色调(halftone)质感。

先看效果:点阵从哪来

截图右下角那块就是DotScreenPass的输出:同一组人物模型里,其他三格还是常规光影,它却把色彩全部替换成圆点阵列,明暗随亮度变化,越看越像车站出发板上从文字切换到点阵显示的灯箱——这就是该滤镜卖点的"复古感"。

对照这张高饱和物体:它是仓库里另一个网点通道HalftonePass的输出,网点按 RGB 三通道分色。DotScreenPass则输出灰度单网点,两者是仓库半色调效果的两种形态。

最小可跑路径

import 路径决定它走不走 addons 入口:这个模块不在核心包里,必须用three/addons/别名引入,统一导出在 Addons.js#L187。

import * as THREE from 'three'; import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/addons/postprocessing/RenderPass.js'; import { DotScreenPass } from 'three/addons/postprocessing/DotScreenPass.js'; const composer = new EffectComposer( renderer ); composer.addPass( new RenderPass( scene, camera ) ); // 三个参数全部可选,漏传的部分会自动落在 Shader 默认值上 composer.addPass( new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 ) );

跑起来后,composer.render()循环里整屏色块会被旋转的圆点阵列取代。最后一行addPass就是这个滤镜的全部配置,参数语义下一节拆开讲。

3 个参数 3 个问

构造函数三参皆可选:源码只在参数不为undefined时才写入对应 uniform(DotScreenPass.js#L28-L47),漏传就沿用DotScreenShader声明的默认值。

  • center : Vector2— 点阵中心,默认(0.5, 0.5)即屏幕中心。官方示例传(0, 0),把网点相位原点挪到左上角,点阵看起来像"锚定"在画面角落。源码用.copy()拷贝,你构造后无需再留这个 Vector2 的引用。
  • angle : number— 点阵旋转角,弧度,默认 1.57(≈π/2)。它改的不是"单个点的倾斜",而是整片点格旋转;传 0.5 会得到轻微斜向的排布,动态改它时差异最直观。
  • scale : number— 反直觉点:数值越大,网点越小。直觉里"放大"应该变大,但这里它其实是采样网格的频率:越大点越细密,越小点越粗颗粒。示例里的 0.8 属于中等设置。

剩下的tDiffusetSize两个 uniform 是输入纹理和缓冲区尺寸,每次render()开头就被覆盖(DotScreenPass.js#L82-L83),你不用管。

让它动起来:运行时动态调参

pass.uniformsmaterial共享同一份引用——构造时this.uniforms直接传进了 ShaderMaterial(DotScreenPass.js#L54-L61)——所以改值下一帧生效,不必重建 pass:

const dot = new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 ); composer.addPass( dot ); function animate() { requestAnimationFrame( animate ); dot.uniforms.angle.value += 0.01; // 角度持续累加,点阵会缓慢"转" dot.uniforms.scale.value = 0.6 + 0.3 * Math.sin( performance.now() * 0.001 ); // 密度沿正弦起伏,产生呼吸脉动 composer.render(); }

参数与画面行为一一对应:angle管旋转,scale管密度,center管相位原点——移动它相当于把整片点阵屏幕滑动。前两者一起动,就是复古滤镜的经典形态。

片元着色器三步算完

整套算法就是DotScreenShader里的三步(DotScreenShader.js#L52-L71):

  1. 取亮度float average = ( color.r + color.g + color.b ) / 3.0;——RGB 平均,颜色信息从这里起被扔掉,这就是输出呈灰度点阵的原因。
  2. 旋坐标vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;——像素坐标先按center平移、按angle旋转,再乘scale。"angle 管旋转、scale 管点疏密"的数学出处就在这里。
  3. 乘调制return ( sin( point.x ) * sin( point.y ) ) * 4.0;——两组正弦波像两把梳子交错相乘,得到周期性的明暗斑;最后加上average * 10.0 - 5.0这个放大 10 倍的亮度基底,即"亮处点稀疏、暗处点密集"的半色调观感。

想要 45° 新闻纸排布或 CMYK 分色,改pattern()函数、自制 ShaderMaterial 再交给 pass 即可。

放进管线里

DotScreenPass很少单独出场,卡在色调校正和渐晕之间是最稳的链路:伽马先修亮度,网点通道负责去色,渐晕收边。

composer.addPass( new RenderPass( scene, camera ) ); composer.addPass( new ShaderPass( GammaCorrectionShader ) ); const dot = new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 ); composer.addPass( dot ); const vignette = new ShaderPass( VignetteShader ); vignette.uniforms[ 'offset' ].value = 1.6; // 官方示例的取值,暗角强度 vignette.uniforms[ 'darkness' ].value = 0.95; composer.addPass( vignette );

webgl_postprocessing_advanced.html#L166 就是同一套组合思路:DotScreenPass与 Film、Sepia、Bloom、Bleach 并排对比。实践中再叠FilmPass(胶片颗粒)和SepiaShader(怀旧色调),老放映机的质感就齐了。

⚠️ 容易踩的坑

  • scale方向必错:默认1.0,数值越大点越小。想要"更大的点",去调小它。
  • 原色不可逆:片元输出的是单通道灰度vec3( average * 10.0 - 5.0 + pattern() )。想保留场景色彩得换HalftonePass(examples/jsm/postprocessing/HalftonePass.js,网点按 RGB 分通道),两者同屏叠加也换不出彩色点阵。
  • dispose()不能省:DotScreenPass.js#L104-L110 会释放材质与全屏四边形。动态重建后处理链时不释放旧 pass,GPU 资源就漏了。
  • 适用范围:基类Pass的注释明确只服务于 WebGLRenderer 管线;项目已迁 WebGPU 的话,仓库里另有基于 node 体系的实现,用法不共享本 pass 的 API。

🎯 一句话速查

  • three/addons/postprocessing/DotScreenPass.js引入,挂在EffectComposer上;
  • 构造 3 参center / angle / scale全部可选,记住 scale 越大点越小;
  • 运行时直接改pass.uniforms.center / angle / scale,下一帧生效;
  • 不用了调用pass.dispose(),释放材质与全屏几何体。

DotScreenPass.js|DotScreenShader.js|Pass.js|官方文档|运行示例

【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 23:25:03

Win10下USBasp驱动安装全攻略:从原理到Zadig解决方案

简介:Windows 10下使用USBasp、USBisp等AVR编程器时,常因驱动签名问题导致设备无法识别,直接影响固件烧录与调试,给开发造成不小困扰。这套一键驱动安装方案已处理签名验证难题,面向AVR单片机开发者和电子爱好者&#…

作者头像 李华
网站建设 2026/9/8 23:24:56

勤哲Excel服务器V13.0.144:稳定部署、注册激活与运维实践

简介:勤哲Excel服务器2017 V13.0.144是一款基于Excel的数据库管理系统,面向需要集中管理数据、保障数据安全并提升协作效率的企业团队,尤其适合财务、人力、生产制造等业务场景。压缩包共9个文件、约178.69MB,包含txt说明文档、ex…

作者头像 李华
网站建设 2026/9/8 23:20:53

Unieap模型驱动快速开发平台实践:从零搭建设备资产管理系统

简介:Unieap简单小项目是一份基于Unieap 3.4框架的企业级应用示例,适合Java开发者和流程管理人员快速入门。该框架本身涵盖工作流引擎、表单设计、数据模型和权限控制等能力,并支持BPMN 2.0标准,可处理并行分支、循环、事件触发等…

作者头像 李华
网站建设 2026/9/8 23:18:49

嵌入式信创软件测试全攻略:从环境定性到稳定性验证

上个季度我全程参与了一块国产 CPU 加国产操作系统的嵌入式主控板第三方测评,项目启动前我本来觉得这事不复杂,毕竟测过的嵌入式软件不算少:交叉编译、刷机、跑用例,流程熟得很。真正开始搭环境、定方案之后才发现,嵌入…

作者头像 李华