news 2026/9/8 23:23:33

10 分钟调出复古半色调点阵:three.js DotScreenPass 实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
10 分钟调出复古半色调点阵:three.js DotScreenPass 实战指南

10 分钟调出复古半色调点阵:three.js DotScreenPass 实战指南

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

three.js 的DotScreenPass是一个半色调后处理通道:场景渲染完成后,它把整幅画面重绘成密集圆点阵列,让屏幕看起来像报纸印刷或老式点阵屏。读完这篇,你能拿到一段可直接粘贴的接入代码,以及一套运行时调节网点旋转与脉冲的配方。

先让画面"变味儿"——最小可运行接入

DotScreenPass是 addon 模块,不在核心包里,必须显式引入。下面这段代码把它接进场景渲染之后的后处理链:

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 ) ); composer.addPass( new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 ) ); function animate() { requestAnimationFrame( animate ); composer.render(); } animate();

跑起来后,整块画面被圆点阵列覆盖:亮的地方点又大又亮,暗的地方几乎沉进黑里,颜色信息被点阵的明暗代替——就是报纸放大看的那种质感。这个构造写法在官方运行示例 examples/webgl_postprocessing_advanced.html 里原样出现。

三个旋钮怎么拧——参数调优速查

构造函数收三个参数,对应三个旋钮:网点从哪开始旋转、点阵斜多少、点有多大。

new DotScreenPass( center, angle, scale );

三个参数都是可选的,省略就沿用着色器默认值:

参数含义默认值推荐范围
center网点相位原点( 0.5, 0.5 )屏幕中心( 0, 0 )屏幕角落
angle网点旋转角,弧度1.57(约 π/2)0 ~ 6.28
scale网点密度,越大点越小1.00.5 ~ 2.0

scale从 1.0 拖到 0.5,颗粒感立刻粗一倍——相当于同一张网点底片是放大打印还是缩小打印的差别。angle设成0.5,点阵会微微倾斜,多几分手绘报纸的味道。

让网点"动"起来——运行时动态调参 ✨

pass.uniforms和材质共享同一份引用,改完下一帧就生效,无需重建 pass。把angle在动画帧里每次加一点,网点就开始缓慢转圈:

const dotScreen = new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 ); composer.addPass( dotScreen ); function animate() { requestAnimationFrame( animate ); dotScreen.uniforms.angle.value += 0.01; dotScreen.uniforms.scale.value = 0.6 + 0.3 * Math.sin( Date.now() * 0.001 ); composer.render(); } animate();

跑起来后,angle每帧加 0.01 让点阵慢转,scale由正弦波驱动,网点粗细来回"呼吸"。想让网点相位挪位置,用dotScreen.uniforms.center.value.copy( new THREE.Vector2( 0.3, 0.7 ) )一行搞定。

滤镜背后那 20 行着色器——半色调算法拆解

视觉效果的核心是 DotScreenShader.js 里的片元着色器,算法沿用了 glfx.js 的实现。关键代码就这么多:

float pattern() { float s = sin( angle ), c = cos( angle ); vec2 tex = vUv * tSize - center; vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale; return ( sin( point.x ) * sin( point.y ) ) * 4.0; } void main() { vec4 color = texture2D( tDiffuse, vUv ); float average = ( color.r + color.g + color.b ) / 3.0; gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a ); }

拆成三步理解:1)取 RGB 平均值average当这个像素的灰度亮度;2)把 UV 换算到像素空间,以center为原点按angle旋转、再乘scale——两个旋钮的数学来源就藏在这几行;3)对旋转后坐标分别取sin再相乘,得到 [-1, 1] 间的周期性调制值,放大 4 倍后叠加到average * 10.0 - 5.0的亮度基底上,形成"明暗靠点阵表达"的半色调观感,原图 alpha 原样保留。

想自定义网点造型——45° 新闻纸排布、CMYK 彩色分色——改pattern()这一个函数,再把自己的 ShaderMaterial 传给 pass 即可。

组合拳实战——后处理链级联配置

网点滤镜单飞能看,级联出味道:场景渲染 → 伽马校正 → 网点 → 渐晕。通道顺序直接决定最终观感,比如伽马校正放在网点后面,网点本身的黑白也会被校正,整体色调明显变亮。下面这条链可直接嵌入项目:

import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js'; import { GammaCorrectionShader } from 'three/addons/shaders/GammaCorrectionShader.js'; import { VignetteShader } from 'three/addons/shaders/VignetteShader.js'; const composer = new EffectComposer( renderer ); composer.addPass( new RenderPass( scene, camera ) ); composer.addPass( new ShaderPass( GammaCorrectionShader ) ); const dotScreen = new DotScreenPass( new THREE.Vector2( 0, 0 ), 0.5, 0.8 ); composer.addPass( dotScreen ); const vignette = new ShaderPass( VignetteShader ); vignette.uniforms[ 'offset' ].value = 1.6; vignette.uniforms[ 'darkness' ].value = 0.95; composer.addPass( vignette );

运行后画面是点阵质感加四角压暗,一股老电影放映机的味道。offset/darkness取 1.6 和 0.95 来自官方 advanced 示例,照抄不会出错。

踩坑清单与资源释放 ⚠️

  • 漏调 dispose 会泄漏 GPU 资源:动态重建后处理链时,先把旧 pass 摘掉再释放,chrome://gpu里 WebGL 纹理数不再上涨才算干净:
dotScreen.dispose();

这一行会释放 ShaderMaterial 和全屏四边形几何体,不执行的话这两块显存就一直挂着。

  • scale与网点密度是反比:数值越大点越小越细密,越小点越大越粗。新手最常搞反,第一次想"调细"结果调出一颗大圆点。
  • 渲染管线边界Pass基类模块注释明确只服务WebGLRenderer后处理。项目走 WebGPU + TSL 的话,请改用 DotScreenNode 文档 里的 Node 实现,这个 Pass 不能原样搬过去。
  • 别手动设tDiffusetSizerender()每帧自动写入上一通道纹理和缓冲区宽高,你自己设了也会被覆盖,白忙活。

如果你只带走这几句

  • 引入路径three/addons/postprocessing/DotScreenPass.js,挂进EffectComposer才生效;
  • 构造三参center/angle/scale全部可省,省了就用默认值;
  • 想要更细的网点,把scale往大了调——它是反比;
  • 动画帧里改uniforms,下一帧即生效,不用重建;
  • 移除通道前dispose()一次,显存还给你。

参考:官方文档|Pass 源码|着色器源码|Pass 基类|运行示例

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

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

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

嵌入式黑盒通信协议逆向实战:物理层盲猜与光耦反相

1. 这不是教科书里的“协议分析”,而是一次真实的嵌入式黑盒攻防现场 你手头有一块从旧工业控制器上拆下来的PCB,没有原理图,没有芯片手册,只有几根裸露的飞线和一个正在运行的、完全不对外暴露通信逻辑的设备。它用某种未知时序在…

作者头像 李华