news 2026/1/7 14:53:43

斜看地板闪烁?根源竟是采样方式不对

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
斜看地板闪烁?根源竟是采样方式不对

先把答案丢出来:

斜看地板会闪、抖、糊,根本原因不是“地板做得丑”,
也不是“显卡太垃圾”,
而是:屏幕分辨率不够 + 纹理太细 + 采样方式不对
尤其在“斜视角”时,一个屏幕像素在纹理里对应的是又长又瘦的一大片区域
但传统纹理过滤却假装它是一个方的点,只“随便取附近一点颜色”,
导致高频细纹被错误采样,出现闪烁、摩尔纹。

各向异性过滤要解决的,就是这个“一个像素对应一条长条纹理区域”的本质问题

下面我们把这件事,从现象、错觉、数学到显卡实现,用大白话拆开讲清楚。
你看完后,会对“为什么要搞各向异性过滤”有一个非常扎实的底层理解。


一、先回忆一下:你看到的“斜地板闪烁”长啥样?

先在脑子里把画面还原一下:

  • 你玩一个 3D 游戏:FPS、RPG、赛车都行
  • 相机视角稍微压低一点,斜着看地面往远处延伸
  • 地面铺了一张重复的地砖纹理 / 路面砖 / 木地板
  • 然后你开始动——走两步、跑两步、左右晃晃视角

你会看到几种典型现象:

  1. 远处地砖纹理“糊成一坨”,像一条条模糊的带
  2. 走动时地面纹理出现“波纹”在晃,像老电视那种抖动纹
  3. 偶尔某些角度出现奇怪的“花屏条纹、锯齿状斑马线”,一闪一闪的
  4. 明明图是高清贴图,近处看很清,远一点就完全坏掉

最诡异的地方是:

  • 你正对着看一面墙,纹理很正常;
  • 一换成斜视角看地板,问题就非常严重。

这就已经在替你提示“根本原因”了:

斜视角 + 细纹理 + 分辨率 + 采样方式
这几个因素叠加在一起,才炸了锅。


二、用生活里拍衣服的例子理解:这是“数字相机拍花纹衣服”同款问题

你用手机拍过这种场景:

  • 一件密密麻麻细条纹的衬衫
  • 一个带细格子的窗纱
  • 拍电脑屏幕 / 显示器上的小格子图案

你会发现:

  • 手机屏幕上出现各种“奇怪的波纹、干涉条纹”,
  • 甚至根本不像原来的图案。

这叫摩尔纹(Moire Pattern)
本质原因是:

原始图案的“细节频率”太高,
超过了你手机摄像头/显示屏的采样能力,
于是“采样失真”,出现了错误的、假冒的花纹

3D 游戏里的“斜地板闪烁”,和这个本质上一模一样:

  • 地砖纹理就是那件细条纹衬衫
  • 屏幕分辨率就是你的手机摄像头像素
  • 你斜着看 = 相机斜着拍
  • 显卡的纹理采样方式 = 拍照时像素如何取样

“要拍的花纹太细 / 变化太快”时,
采样频率不够,就会产生各种乱七八糟的图案、波纹、闪烁——
这是一个数学层面的必然现象,而不是什么“美术不走心”。


三、说人话版数学:采样理论 + 频率超标 = 必闪

别一看到“数学”两个字就慌,我们只用极简版。

3.1 你要记住一个定理的直觉版:

如果你想用“有限数量的点”来还原一个“连续变化的波形/图案”,
那这些点的间隔不能太大——至少要两倍于图案的最高频率,否则就会失真。
失真的表现就是:

  • 原来是细条纹,结果采出来变成粗条纹
  • 原来是平直线,采出来是弯的
  • 原来是静止的条纹,动一下就出现各种错误花纹

这就是所谓的奈奎斯特采样定理的直觉含义。

对应到我们的场景:

  • “连续变化的图案” = 地砖的纹理(很多明暗交替的细线、格子)
  • “有限数量的点” = 屏幕像素(每个像素采一笔颜色)
  • “采样频率不够” = 一个屏幕像素要代表太多纹理细节,结果抓不住

当你远看地板时:

  • 一个屏幕像素占的视角区域很大,
  • 在地板的纹理上,它覆盖了许多条“亮-暗-亮-暗”的砖缝
  • 这就意味着,纹理在屏幕上呈现的是一个极高频的变化

只要频率高到超过屏幕能分辨的能力——
无论你怎么采,都会出错,出现莫名其妙的波纹和闪烁。

3.2 那我们是不是完蛋了?不能显示细节?

其实还有一条路:你可以允许远处细节“被模糊掉”。

也就是说:

既然你远处看不清原始的细节,
与其看到错误乱跳的高频伪影,
不如我主动把它“平均成一块相对稳定的颜色块”。

这就是各种纹理过滤(mipmap、各向异性)的目的:
主动作“平均”,让远处的东西看上去平滑稳定,而不是高频刺眼又乱闪。

但“怎么平均”、“平均哪里”,就是各家算法的区别了。


四、问题关键:在“斜视角”下,一个屏幕像素代表的是一个“细长斜条”

终于该说出那句关键的话了:

斜看地板闪烁的根本原因,就是你看到的那个“一个屏幕像素”,
在纹理里对应的不是一个正方形,而是“被拉得老长的斜斜的长条”。

我们一点点脑补这个画面。

4.1 正对着地板(从上往下看)时发生了什么?

假设:

  • 相机正对地板:
    • 屏幕上的一个像素,对应地板上的一小块区域,差不多就是个方块
    • 这块区域在纹理里也是比较接近方块的区域

你可以想象:

  • 每个屏幕像素都看着一小块“砖纹理”,
  • 纹理没有被很夸张地拉伸

这种情况下:

  • mipmap + 双线性过滤就够了:
    • 用较低分辨率的 mip 层来表示远处的平均颜色
    • 双线性在这块区域附近做插值
    • 效果通常不算太差

4.2 斜着看地板时,情况完全不同

当相机越来越平,越来越往“地平线”方向看时:

  • 屏幕上远处的地板看起来越来越“扁”,
    一整条地砖压缩成了几条细线

这时:

  • 屏幕上的一个像素,在地板平面上的投影,不再是方块,而是一个很长很窄的梯形 / 长条
  • 这个长条在纹理空间(UV)里对应的是:
    • 在 u 方向:覆盖几十甚至上百个 texel(很多砖缝)
    • 在 v 方向:只覆盖少量 texel

简化一下:

一个像素的“采样区域”从原来的“方块”变成了“牙签”。

关键:传统的各向同性纹理过滤(bilinear + mipmap)仍然假装这块区域是“方块”。

4.3 “假装方块”会导致什么?

传统做法:

  1. 用当前缩放比例算出一个 mipmap 级别(比如用 64x64 这一级)
  2. 在这个 mip 层上,对(u,v)附近 4 个 texel 做一次双线性插值

问题是:

  • 这个“选某一级 mipmap + 拿附近 4 个点平均”的逻辑,是基于一个**“各向同性”的假设**:

    在纹理空间里,这个像素对应区域的缩放在两个方向上差不多。

但斜视角的“长条”区域里:

  • 在 X 方向(沿着地板远去方向):
    • 可能缩得特别厉害(一个像素压缩了几十个 texel)
  • 在 Y 方向(横向砖缝):
    • 可能缩得不太多

也就是说:两个方向的缩小比例完全不一样。

然而传统方法:

  • 只用一个“统一缩放系数”去选 mip 级 → 完全对不准实际的“牙签形状区域”
  • 然后只在这级 mip 上“方方正正”地取 4 个点做平均 → 完全没有覆盖到那条“长条”上的所有细节

结果:

对这么大一截长条,
你只看了附近很小一块点,然后说“这就是代表颜色”。

那么在你移动视角、走动时,
这个“只看一点点的代表颜色”会整条跳来跳去 → 产生闪烁、波纹、摩尔纹。

这就是根本原因:
采样区域是长条,但算法当成方块来处理 → 高频信息采样不稳定 → 刷新帧之间差异极大 → 肉眼看到闪烁。


五、从这个角度看:为什么非要“各向异性”?“异”在哪里?

现在,“各向异性”的含义就清楚了:

  • 各向同性(isotropic):假设在所有方向上的缩放情况差不多,只用一个整体缩放系数
  • 各向异性(anisotropic):承认不同方向上缩放不一样,沿着缩放最大的方向做更多处理

回到上面的“牙签”比喻:

  • 在斜地板上,一个像素对应一个“长条”区域
  • 各向同性过滤只在长条附近取很少几个点,基本上是在胡猜

而各向异性过滤做的事情是:

承认你是长条,那我就沿着长条方向多取样几次,
让这些细节“平均”起来,防止乱跳。

所以:

  • 斜看地板闪烁的根本原因,可以简化成一句话:

    各向同性采样用“正方形 + 少量样本”硬套一个“长条高频区域”,
    结果把大量细节信息采样错误,产生高频伪影和闪烁。

  • 各向异性过滤正是针对这种情况设计的:

    不再强行用“方形假设”,而是沿着长轴多采点平均。


六、从“采样足迹”的角度再形象一点:脚踩在哪儿的问题

图形学里有一个词叫texture footprint(采样足迹)。
直白点讲就是:

这个像素在纹理上到底“踩到了哪些区域”。

我们把“一个屏幕像素”想象成“你的一只脚”:

  • 当你正对地板站着:
    • 你的脚底印在地板上的形状差不多是个略微矩形的印记
  • 当你斜着站,脚往前伸:
    • 你的脚底印在地板上的形状就变成了一个很长的斜斜的形状

传统过滤相当于:

  • 不管你的脚印实际是啥
  • 我都假装你的脚印是一个小方块,只在方块中间取一点“颜色”

各向异性过滤则是:

  • 先大致估计你的脚印形状(长多少、宽多少、斜多少)
  • 然后在这块长条脚印内多踩几个点取样
  • 把这些点的颜色平均作为最终结果

高频地砖纹理就像:

  • 地上有很多黑白相间的条纹
  • 你脚印跨过好几条
  • 你如果只看脚印中间一点是不是黑的,那你稍微挪一小点脚,这一条就从“黑”跳成“白”
  • 但如果你平均踩了好几个点:
    • 左边黑、右边白,中间灰 → 平均起来就稳定灰色,移动也不怎么跳

这就是“多点采样平均”的直觉。

采样足迹越长、高频越严重的地方,各向异性过滤就越有价值,
而这恰恰就是“斜着看地板”的典型场景。


七、再回答一个关键问题:

“根本原因到底是分辨率不够,还是算法傻?”

严格来说,是两个因素叠加:

  1. 硬件采样频率有限(屏幕分辨率有限)

    • 一个像素就只给你这一个地方显示颜色
    • 你总不能让一个像素展示三个颜色同时闪 → 必然需要降频(模糊)或失真(闪烁)
  2. 传统各向同性算法的“模型过于简单”

    • 它只考虑“整体缩小了多少”,而不区分方向
    • 当缩小在某个方向特别狠时(长条情况),它的模型就严重失真
    • 等于你手里本来就只有一个采样位置,还偏偏选在了最不代表平均值的位置附近
    • 随视角轻微变化,采样位置波动 → 显示颜色剧烈跳变 → 闪烁、波纹

所以说:

  • “根本原因”的土话版本可以说是:

    屏幕像素不够 + 传统取样方法不聪明 → 面对斜视高频纹理时必挂。

  • 各向异性过滤就是:

    在“聪明地选择多个采样点 + 平均”的方向上升级了一层,
    让有限的像素能更平稳地代表一个“瘦长复杂区域”。


八、把这个根本原因放在三个不同视角下理解一遍

为了让你真的做到“死记在脑子里”,我们换三种角度再说一遍:

8.1 图形学视角:

  • “斜看地板”时,一个屏幕像素在纹理空间的映射区域呈各向异性缩放(长宽比例极端)
  • 各向同性滤波只根据一个标量(整体缩放率)选择 mip 级和滤波核
  • 没办法正确覆盖整个 anisotropic footprint,导致 aliasing

→ 根因:采样核和真实足迹形状严重不匹配。

8.2 码农视角:

  • 屏幕上一个像素最终就是一次纹理采样,只是你用一些插值(bilinear、mipmap)在附近多取一点
  • 理论上这个像素对应的是一大片纹理区域,但你只用一个简化模型估计它
  • 对于斜着的地板,这片区域是个大长条,你却在长条附近某个点附近取三四个样本
  • 视角一动,长条在纹理里的位置一变,你采样点就跳到另外一堆完全不一样的地方 → 结果颜色暴跳

→ 根因:采样点太少 + 位置敏感,导致帧间不稳定。

8.3 玩家视角:

  • 远处地砖太细,屏幕装不下这么多花纹
  • 游戏每一帧都在“猜”这个像素到底该是什么颜色
  • 一会儿猜偏多一点白,一会儿偏多一点黑,就像荧光灯闪烁
  • 各向异性就是“我不再瞎猜,只要你是特别长的一条,我就多看几个地方综合一下”

→ 根因:每帧猜测不稳定,引发肉眼可见的闪烁感。


九、顺便澄清几句常见误会

9.1 “是不是我贴图分辨率太低才闪?”

不准确。

  • 分辨率低 → 近处看糊,细节不够
  • 但远处斜视闪烁/波纹 → 即便你用 4K、8K 贴图也照样会出现,只是花纹更密集而已

根因在于:

不是“贴图分辨率不够”,
而是屏幕分辨率 + 采样方式对“远处高频”根本 hold 不住。

9.2 “是不是我地板模型太少面?”

只要模型网格足够平滑(没明显顶点稀疏导致插值怪异),

  • 地板的闪烁基本都是纹理采样问题不是网格问题。

当然:

  • 若地板网格几何本身很粗糙,也会导致光照不平滑、阴影跳变,那是另一条线的坑。

9.3 “是不是抗锯齿没开?”

FXAA、SMAA、TAA 这些图像空间的抗锯齿,

  • 主要处理的是“几何边缘”的 aliasing(比如物体轮廓的锯齿)
  • 对“纹理本身内部的高频”帮助有限

斜地板闪烁,更多是“纹理 aliasing” + “时间不稳定”的问题。
TAA 有时会缓解一点,但也可能带来“拖影/糊”的副作用。

真正对症下药的,就是 mipmap + 各向异性过滤。


十、一句话收尾:

“斜看地板闪烁”的根本原因是什么?

用一口气讲完这句话:

当你斜着看地板时,
屏幕上的一个像素在地板纹理空间里对应的是一块又长又窄的“长条区域”
里面包含了大量密密麻麻的高频细节(砖缝、线条),
但传统各向同性纹理过滤却仍然假装这块区域是“一个小方块”,只在附近取少量样本,
导致采样完全覆盖不到实际那条长条里的所有细节,
视角一动、足迹稍微偏一点,就采到完全不同的高频信息,
于是每一帧显示的颜色都大幅跳变,
就在你眼里表现为:地板纹理闪烁、抖动、出莫尔纹

各向异性过滤要解决的,就是这个“长条采样区域 vs 方块采样模型”之间的结构性矛盾:
承认各方向缩放不同,沿“最被压扁的方向”多采几次,做平均,让结果稳定下来。

以后只要你看到:

  • 游戏里“斜着看地面一闪一闪”,
  • 或你自己项目里远处路面细纹乱跳,

脑子里就可以自动翻译成:

“哦,这就是因为一个屏幕像素在纹理里对应的是一条超长的区域,
但采样方法还当它是个方块在随便取颜色。”

这,才是“斜看地板闪烁”的“根本原因”。

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

我是如何构建我的第一个 RAG 管道

原文:towardsdatascience.com/how-i-built-my-first-rag-pipeline-6e178326e3c8 LLM 的幻觉甚至对像谷歌这样的科技巨头都是一个问题(只需问 Gemini 每天推荐吃多少石头……剧透一下,是一天一个)。虽然我们仍然不知道如何教授 LLM…

作者头像 李华
网站建设 2025/12/27 22:19:37

【Leetcode】1857. Largest Color Value in a Directed Graph

题目地址: https://leetcode.com/problems/largest-color-value-in-a-directed-graph/description/ 给定给一个 n n n个顶点的无权有向图,每个顶点有个颜色。一条路径的颜色数定义为其所有顶点里,颜色使用频率最高的那个颜色的使用频率。问…

作者头像 李华