想象你深夜走进一间空旷的美术馆,展厅中央静静立着一尊雕塑,四周一片漆黑,你手里只有一支探照灯。你绕着雕塑缓缓走动,每到一处便举起灯照一下——背面的阴影、侧面的轮廓、正面的高光,每一次都只能看到一帧侧影。你拍下十几张这样的照片,然后所有的灯全部熄灭。这时,你能否仅凭脑海中这些零散的侧影,画出从任何一个新角度望过去“应该”看到的样子? NeRF(神经辐射场)就是为回答这个问题而生的“空间记忆师”。它从多张不同角度的照片出发,学会一个极其朴素却强大的规律:房间里的每一个立体小点,从哪个方向看是什么颜色、它有多“实心”、能否挡住光线。一旦学会,无论你站在哪里举起探照灯,它都能在脑海里“算”出那张照片,甚至能算出你从未真实拍过的角度。这套技术正在悄悄重塑三维视觉——从电影特效的虚拟场景,到自动驾驶的街景重建,再到数字人的可交互形象,背后都有它的身影。这篇文章,我们就用这支探照灯,把NeRF从里到外照个通透。
对AI从业者而言,读懂NeRF意味着掌握“隐式神经表示 + 可微渲染”这一新范式,无论是做图形学研究、三维视觉落地,还是突破传统渲染管线瓶颈,它都是绕不开的基石。
目录
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
NeRF整体架构:相机\u2192射线\u2192MLP\u2192体渲染 CameraImage PlaneMLP F\u03b8Ray r(t)=o+tdCamera
光线采样:探照灯的扫描路径
你举着探照灯检查这间黑暗的美术馆,最笨也最可靠的办法,是让灯光沿一条直线扫过去,然后在这条直线上一个点一个点地确认:“这里有没有东西?这里是什么颜色?”NeRF 的第一步正是如此——它把每个像素想象成一支探照灯,从相机位置发射出一条光线,然后沿着这条光线取出一串三维检查点,挨个询问场景的信息。这些检查点,就是“采样点”。
这些光线在数学上是一条射线。相机位置记作起点 \(\mathbf{o}\),像素指向场景的方向记作 \(\mathbf{d}\),而 \(t\) 则是你沿着光线走出去的距离,像一把从零开始丈量的尺子。美术馆的墙不会无限远,所以我们要把检查范围限制在“近平面”和“远平面”之间,只扫描房间里真正可能有雕塑的那一段空间。
在原始实现中,每条像素光线会在近远平面之间均匀地取 64 个点,并且每个点还会附带上一个微小的随机抖动。这个抖动看似不起眼,却至关重要——如果所有光线都在完全相同的位置上取样,重建出的场景就会出现像百叶窗一样的条纹伪影。采样范围的选择也需要经验:框得太窄会漏掉物体,框得太宽则会让大量算力浪费在空荡荡的空气上。
所以,采样点就是探照灯扫描路径上的一串路标。路标选得够密、够准,后续的观察与重建才能既省力又清晰。
- 光线起点\(\mathbf{o}\) 是相机(探照灯)所在的位置,每条光线都从这一点出发。
- 方向向量\(\mathbf{d}\) 表示这条光线射向场景的方向,由像素在图像上的位置决定,通常被归一化为单位长度。
- 距离参数\(t\) 是沿光线前进的路程,改变 \(t\) 就得到光线上不同的三维点。
- 扫描范围\(t_{\text{near}}\) 与 \(t_{\text{far}}\) 圈定了采样区间,只在这个区间内均匀取点。
位置编码:给每个坐标盖邮戳
现在你已经在光线上布满了检查点,可还有一个尴尬的问题:如果直接把三维坐标丢给神经网络,它会“脸盲”。两个紧挨在一起的采样点,坐标数值几乎一样,网络根本分不清谁是谁,更别提表达雕塑表面那些精细的纹理了。这就像快递员送件时地址只写到“3 楼”——他分不清 302 和 303,必须把门牌号用各种格式写到快递单上,才能精确送达。
研究发现,普通的 MLP 对低频变化非常敏感,对高频细节却相当迟钝,这个现象叫“频谱偏置”。位置编码的解法很直接:在把坐标喂给网络之前,先把它映射到一个布满“正弦波”的高维空间。这相当于给每个三维坐标盖上了一枚独一无二的邮戳——不同位置的坐标经过不同频率的正弦、余弦变换后,彼此之间产生了显著的差异,网络一眼就能认出“这是 302 房间,那不是 303”。
原始论文中,位置坐标使用 10 个频率段,而观察方向只用了 4 个频率段。为什么方向要用更少的频率?因为颜色随视角的变化通常是平滑的,而空间位置上的纹理细节则剧烈得多。频率段 \(L\) 就像镜头倍数——倍数越高,能捕捉的细节越细,但也越容易把噪声一并放大。
位置编码这枚“邮戳”,让网络第一次看清了雕塑上每一道细小的刻痕。没有它,NeRF 只会画出一团模糊的色块;有了它,连石像眼角的纹路都能被复原出来。
- 原始坐标\(p\) 是采样点的某一个坐标分量,取值范围在整个场景空间内。
- 频率倍数\(2^{k}\) 控制正弦波振动的快慢,\(k\) 越大,波形变化越剧烈。
- 正余弦投射把 \(2^{k}\pi p\) 同时送入正弦与余弦,得到一对相位不同的特征。
- 向量拼接把所有频率下的正余弦结果连同原始坐标拼成一个大向量,作为网络的输入。
体渲染积分:彩色玻璃层层叠
你站在一座彩色玻璃窗前,窗上叠着好几层颜色深浅不一的玻璃。最前面一层是淡蓝色,后面一层是红色,再后面是绿色——你看到的最终颜色,绝不是任何单层玻璃的颜色,而是所有玻璃层层叠加、彼此遮挡之后的结果。NeRF 的“体渲染”做的正是这件叠玻璃的事:一条光线上有很多采样点,每个点都有密度和颜色,我们要把它们按顺序“叠”起来,算出最终进入眼睛的颜色。
光线每穿过一个点,都会被这个点的密度“挡住”一部分。我们把光线能活着走到某个点、还没被前面物体全部挡住的概率,称为透射率 \(T(t)\)。如果前面某个点密度极大,几乎不透明,那么后面点的颜色再鲜艳也传不出来——就像叠在最前面的黑色玻璃,直接把后面所有的颜色都遮死了。密度 \(\sigma\) 负责描述“实心程度”,颜色 \(\mathbf{c}\) 负责描述“这个点本身长什么样”。
技术实现时,连续的积分被离散化成逐点累加:每个采样点贡献“当前透射率 × 该点遮挡比例 × 该点颜色”,一路累加过去。这个累加过程必须可微,因为训练时损失函数的梯度要沿着这条颜色链一路传回网络,告诉每个采样点“你的密度该调大一点还是调小一点”。
往深里说,体渲染积分就是那句俗话的数学版本:“你看到的颜色,是前面所有玻璃叠出来的总和。”NeRF 的全部学问,最终都收敛到这个积分式上。
- 密度场\(\sigma(\mathbf{r}(t))\) 表示光线在位置 \(\mathbf{r}(t)\) 处遇到的密度,值越大越不透明。
- 颜色场\(\mathbf{c}(\mathbf{r}(t))\) 是该位置自带的 RGB 颜色。
- 透射率\(T(t)\) 是光线从起点走到 \(t\) 处仍未被完全遮挡的概率,由密度的累积积分经指数衰减得到。
- 积分合成把“到达概率 × 遮挡概率 × 颜色”在整段光线上积分,就是最终像素颜色。
网络结构:记录空间的小本本
现在你已经把一条条光线变成了一个个彩色像素,但这些像素背后的“空间知识”存放在哪里?NeRF 的回答是一本“空间小本本”——一个全连接神经网络。你告诉它一个采样点的五维信息(三维位置加二维观察方向),它翻一翻小本本,吐出四个数字:一个密度值 \(\sigma\) 和三个颜色通道。这本小本本不是照片集,而是把整个美术馆的“物质分布”压缩到了网络的权重里。
为什么要五维输入而不是三维?因为颜色和观察角度有关。你从正面看雕塑,会看到高光;从侧面看,高光就消失了。密度不一样——雕塑的“实心程度”是客观的,不随你的视线变化。所以作者做了巧妙的设计:位置先单独经过 8 层全连接层,提取出密度;等到第五层之后,才把观察方向拼接进去,用于预测颜色。这样一来,密度天然地与视角无关,符合物理直觉。
网络最后一层会对输出做约束:密度经过 ReLU 激活保证非负(密度不可能为负),颜色经过 sigmoid 激活压到 0 到 1 之间(颜色亮度不能超界)。整个网络就像一个可微分的大函数,输入任意一个空间位置和观察方向,都能得到该处的密度与颜色——这就是“神经辐射场”中“场”字的含义。
有了这本小本本,探照灯不再需要真的照到雕塑——无论你提出哪个角度的查询,它都能像查字典一样,把答案精确地写给你。
- 空间坐标\(\mathbf{x} = (x,y,z)\) 是采样点的三维坐标,经过位置编码后作为主输入。
- 观察方向\(\mathbf{d}=(\theta,\phi)\) 是光线的方向,决定颜色中视角相关的高光成分。
- 网络参数\(\Theta\) 是所有可学习的权重和偏置,相当于小本本上的全部笔记。
- 输出\(\sigma\) 是密度标量,\(\mathbf{c}\) 是 RGB 颜色向量。
分层采样:先看轮廓再看细节
一支探照灯在美术馆里扫过时,聪明的观察者不会把灯光均匀地撒满整个房间。他会先快速扫一遍,找到雕塑大概在哪个区域,然后让灯光集中在那片区域,仔细端详每一个细节。NeRF 的“分层采样”策略正是这套思路,只不过把“扫一眼”和“仔细看”交给了两个不同的网络。
第一个网络叫“粗网络”,它在每条光线上均匀地取 64 个点,快速估算出场景的大致轮廓。粗网络输出的密度和颜色经过体渲染后,会留下每个采样点的权重 \(w_i\)——这个权重直观地反映了“这条光线最终看到的颜色,有多大比例是来自这个点”。把所有权重归一化,就得到一个概率分布:概率高的地方,说明雕塑的实体集中在那里。
第二个网络叫“细网络”,它按照粗网络给出的概率分布在同一条光线上再取 128 个点。注意,这次不是均匀取,而是“哪里概率高就往哪里多取”。两个网络在训练时一损俱损、一荣俱荣:粗网络负责探路,细网络负责精雕细琢,最终渲染时只用细网络的采样结果。这就像先用手掌摸一遍雕塑确定大致形状,再用指尖沿着刻痕细细描过每一道纹路。
分层采样是在用“先粗看再细看”的直觉,换取同样的采样预算下更清晰的图像。这是 NeRF 在算力受限时代能跑起来的关键一招。
- 采样点权重分母中的 \(T_i\) 是透射率,\(\sigma_i\) 是该点密度,\(\delta_i\) 是相邻采样点的间距。
- 归一化把所有采样点的 \(w_i\) 求和,再逐点相除,把权重变成总和为 1 的概率分布。
- 重采样按 \(\hat{w}_i\) 这个分布从所有采样点中进行随机抽取,概率高的点会被抽到更多次。
- 两阶段配合粗网络均匀采样,细网络按权重聚焦,完成由粗到精的递进。
损失设计:照片对照着改
想象一位学画的新手,他每画完一张雕塑写生,师傅都会把真实照片和他的画并排放在一起,一笔一笔地对照:“这里颜色偏深了,那里轮廓画粗了。”NeRF 的训练就是这样一个“一对一辅导”的过程——只不过“师傅”就是真实照片,“学生”就是粗网络和细网络。
损失函数选的是最朴素的 MSE(均方误差):把 NeRF 渲染出的像素颜色,与真实照片上对应像素的颜色相减、平方、再求和。这个数字刻画了“合成照片”与“真实照片”之间的差距。差距越小,说明网络对场景的理解越准确。值得注意的是,粗网络和细网络都要参与计算损失——粗网络的输出也要拿去和真实照片比较,这样它才能学会“哪里该多撒点”,为细网络铺好路。
整个损失能够工作的前提,是“渲染”这个操作本身必须可微。传统渲染管线把几何投影到屏幕后就直接丢弃了中间量,梯度无处可传;而 NeRF 的体渲染积分每一步都是平滑的加减乘除,误差信号可以沿着光线一路倒推回网络参数。这也是“可微渲染”这个新范式最迷人之处。
师徒对照式的训练看似笨拙,却极其稳定。MSE 不会给任何像素“开后门”,每一处偏色都会被忠实记录,逼着网络一点点修正自己对整个空间的认知。
- 渲染像素\(\hat{C}(\mathbf{r})\) 是 NeRF 对光线 \(\mathbf{r}\) 渲染出的预测颜色。
- 真实像素\(C(\mathbf{r})\) 是同一光线上真实照片对应的颜色,作为监督信号。
- 逐条光线误差两者相减取平方,衡量这条光线预测偏了多少。
- 汇总训练集对所有光线求和,得到整个批次的损失。
与传统渲染对比:手绘画师与写生画家
传统三维渲染像是“手工画家”:必须先请模型师用三角网格搭出雕塑的骨架,再请材质师贴上一层“皮肤”,灯光师打好每一盏灯,渲染器才能把画面画出来。任何一个环节缺失,画就画不出来——没有网格,一切免谈。而 NeRF 像一位“写生画家”:它完全不需要看网格,只凭多角度的照片,直接在脑海里构建一个连续的场景函数,然后挥毫泼墨,画出一个从未真实存在的角度。
具体到技术层面:光栅化把三角形逐个投影到屏幕上,速度快得惊人,但前提是你必须拥有完整的三角形网格;光线追踪则让光线的路径像台球一样在几何表面弹跳,效果极其逼真,但每弹跳一次都要做一次射线与三角形的求交运算。两者都是“先有几何,再谈着色”。NeRF 把几何彻底藏了起来——它不再显式存储三角形,而是用神经网络的权重隐式地编码几何与外观,体渲染积分本身就是“着色”过程。
下面这条渲染方程,是传统计算机图形学的基石:它描述了某个点发出的光等于自发光的亮度,加上所有入射光经过材质反射后贡献的总和。传统方法要解这个方程,必须已知几何法线、BRDF 材质参数、光源分布——每一个都要人手动建模。而 NeRF 的巧妙之处在于,它让网络把所有这些物理量“一锅炖”进权重里,你只管输入坐标、输出颜色。
如果说传统渲染是“有米才能下锅”的手工艺,那 NeRF 就是“看菜下饭”的写生派——素材(数据)足够多,它就能凭空复原出完整的空间味道。
- 出射辐射\(L_o\) 是观察方向 \(\omega_o\) 上最终看到的颜色亮度。
- 自发光项\(L_e\) 是该点自身发出的光,比如灯泡的表面。
- BRDF 反射项\(f_r\) 描述材质如何把入射光反射到出射方向,\(\mathbf{n}\cdot\omega_i\) 是光线入射角的余弦衰减。
- 半球积分对法线上方整个半球所有方向的入射光累加。
工程实现:让NeRF走出实验室
从论文公式到能跑的工程代码,中间还隔着许多“后勤工作”。就像探照灯在美术馆里能否照得准,不仅取决于灯本身,还取决于你站的位置、灯光的朝向、甚至电池够不够用。NeRF 落地时同样要处理好三件事:数据、训练和加速。
数据准备是第一步。NeRF 需要每个相机拍摄时的精确位置和朝向,这个信息通常不会记录在照片文件里,而是用 COLMAP 这样的传统三维重建工具从照片中估计出来。同时还要估算场景的近远平面范围——太大,采样点浪费在空处;太小,雕塑被裁掉。训练阶段的技巧同样关键:官方实现用 Adam 优化器配合学习率衰减,粗采样 64 点、细采样 128 点,批大小约 1024 条光线,通常要训练几十万步才能收敛。
对于工程落地,纯 NeRF 的慢是出了名的——训练数小时、渲染一张图也要几秒。后来的加速方案各显神通:有的提前用低分辨率粗渲染剔除空白区域的采样点;有的把位置编码换成可学习的哈希表(如 instant-NGP),训练速度提升上百倍;还有的将整个场景替换成更小更快的表示方式。理解这些加速手段之前,先吃透基础 NeRF 的每一个环节,才是捷径。
工程实现的过程,就是把探照灯从“实验室里能转”调校到“野外也能打”的过程。数据、采样、优化、加速——每一环都值得反复打磨。
- 网络参数\(\theta\) 是所有可学习权重的集合,即“空间小本本”的全部内容。
- 损失梯度\(\nabla_{\theta}\mathcal{L}\) 是损失函数对每个参数的偏导,指出“哪个方向能让误差降得更快”。
- 学习率\(\alpha\) 是每次更新的步长,太大会震荡,太小会蜗牛爬。
- 参数更新沿梯度反方向迈一步,损失就小一点,如此反复迭代。
AI 应用场景
电影特效与虚拟拍摄
阶段:新视角合成(模型推理)
解决的问题:传统电影特效需要美工逐帧搭建三维场景、绑定材质灯光,成本极高;如果实拍镜头角度不够,后期合成时难以补齐。NeRF 从实拍照片中隐式学习场景,可在任意虚拟视角重新渲染,让“补拍”不再需要回到现场。
具体案例:某特效公司拍摄一段雕塑环绕镜头时,现场只采集了 20 张照片,随后用 NeRF 重建辐射场,导演在虚拟摄影棚里把机位推进到雕塑基座附近,渲染出从未真实拍摄过的低角度镜头,画面与实拍素材无缝融合。
自动驾驶的街景重建
阶段:场景隐式建模(训练 + 渲染)
解决的问题:自动驾驶需要高精度的三维街景,传统激光雷达扫描价格昂贵,且对玻璃、反光表面束手无策。NeRF 能用普通车载摄像头视频重建连续场景,对反光与半透明物体也有不错的表达能力。
具体案例:某智能驾驶团队用一辆装有 6 个环视摄像头的数据采集车,在路口绕行两圈,采集约 300 帧画面,离线训练一个小型 NeRF,重建出路口花坛、路灯和过往车辆的连续辐射场,用来补充仿真环境中难以手工搭建的复杂路况。
数字人与商品展示
阶段:神经辐射场拟合(模型训练)
解决的问题:电商平台想让用户 360° 查看商品,传统方式要搭建旋转拍摄台或用工业级扫描仪;NeRF 只需手机围绕商品拍一段视频,就能生成可交互的三维展示,成本下降一个数量级。
具体案例:一家鞋类电商发起“光影鞋展”活动,工作人员用手机在 20 秒内绕新款球鞋拍摄一周,后台训练轻量 NeRF,用户在网页上拖拽鼠标,就能从任意角度欣赏鞋面皮革在不同光照下的反光细节。
Python 演示
"""micro-NeRF: 2D continuous scene learning via volume rendering"""import numpy as np PE_L, HID, NS, NP, EP = 4, 32, 24, 5, 300CAM = [0.0, 1.4, 2.8, 4.2]NEW = 5.6R_CT = 1.6TS = np.linspace(0.2, 2.6, NS) def scene(p): x, y = p[..., 0] - 0.15, p[..., 1] r = np.sqrt((x / 0.35) ** 2 + (y / 0.20) ** 2) dens = np.where(r < 1, 4.0 * (1 - r), 0.0) rgb = np.broadcast_to(np.array([0.2, 0.8, 0.3]), p.shape[:-1] + (3,)) return dens, rgb def pe(p): enc = [p] for k in 2.0 ** np.arange(PE_L): enc += [np.sin(k * np.pi * p), np.cos(k * np.pi * p)] return np.concatenate(enc, axis=-1) def make_rays(angles, n_pix): out = [] for a in angles: c = np.array([R_CT * np.cos(a), R_CT * np.sin(a)]) fwd = -c / R_CT right = np.array([-fwd[1], fwd[0]]) for i in range(n_pix): s = (i - (n_pix - 1) / 2) / n_pix * 1.4 d = c + right * s - fwd * 0.4 - c out.append((c, d / np.linalg.norm(d))) return out def render(rays, func): dt = TS[1] - TS[0] pix = [] for o, d in rays: p = o[None, :] + TS[:, None] * d[None, :] dens, col = func(p) a = 1 - np.exp(-dens * dt) T = np.concatenate([[1], np.cumprod(1 - a)[:-1]]) pix.append(((T * a)[:, None] * col).sum(0)) return np.array(pix) class Net: def __init__(s, nin): s.w1 = np.random.randn(nin, HID) * 0.3 s.b1 = np.zeros(HID) s.w2 = np.random.randn(HID, 4) * 0.3 s.b2 = np.zeros(4) def fwd(s, x): s.x = x s.h = np.maximum(0, x @ s.w1 + s.b1) s.raw = s.h @ s.w2 + s.b2 s.dens = np.maximum(0, s.raw[:, 0]) s.col = 1 / (1 + np.exp(-s.raw[:, 1:])) return s.dens, s.col def bwd(s, gd, gc, lr): n = len(s.x) g = np.zeros_like(s.raw) g[:, 0] = gd * (s.raw[:, 0] > 0) g[:, 1:] = gc * s.col * (1 - s.col) s.w2 -= lr * s.h.T @ g / n s.b2 -= lr * g.sum(0) / n gh = (g @ s.w2.T) * (s.h > 0) s.w1 -= lr * s.x.T @ gh / n s.b1 -= lr * gh.sum(0) / n def main(): np.random.seed(42) rays = make_rays(CAM, NP) gt = render(rays, scene) gtn = render(make_rays([NEW], NP), scene) net = Net(pe(np.zeros((1, 2))).shape[1]) dt = TS[1] - TS[0] for ep in range(EP): loss = 0.0 for k, (o, d) in enumerate(rays): p = o[None, :] + TS[:, None] * d[None, :] dens, col = net.fwd(p) a = 1 - np.exp(-dens * dt) T = np.concatenate([[1], np.cumprod(1 - a)[:-1]]) w = T * a pr = (w[:, None] * col).sum(0) gl = 2 * (pr - gt[k]) / 3 gw = col @ gl S = 0.0 ga = np.zeros(NS) for i in range(NS - 1, -1, -1): ga[i] = gw[i] * T[i] - S / (1 - a[i] + 1e-8) S += gw[i] * w[i] net.bwd(ga * dt * (1 - a), w[:, None] * gl[None, :], 0.6) loss += ((pr - gt[k]) ** 2).sum() if ep % 50 == 0: print("epoch", ep, "loss", round(loss, 5)) new = render(make_rays([NEW], NP), lambda p: net.fwd(p)) print("new view MSE:", round(float(np.mean((new - gtn) ** 2)), 6)) if __name__ == "__main__": main()
for k in 2.0 ** np.arange(PE_L):生成 4 个不同频率的倍数,用于构造位置编码的傅里叶特征。enc += [np.sin(k * np.pi * p), np.cos(k * np.pi * p)]把坐标映射到不同频率的正弦与余弦,实现“盖邮戳”。T = np.concatenate([[1], np.cumprod(1 - a)[:-1]])逐点计算透射率,前面点越不透明,后面点能见度越低。pix.append(((T * a)[:, None] * col).sum(0))体渲染合成:把“透射率 × 遮挡率 × 颜色”沿光线求和。gl = 2 * (pr - gt[k]) / 3对 MSE 损失求梯度,指向预测与真实差异的方向。ga[i] = gw[i] * T[i] - S / (1 - a[i] + 1e-8)体渲染反向传播:把误差从合成像素沿光线逐点回传。net.bwd(ga * dt * (1 - a), w[:, None] * gl[None, :], 0.6)把光线上每个点的梯度送进网络,更新权重。
常见误区
误区位置编码的频率段 L 设得越大,能表达的细节越多,性能一定越好,所以直接拉到最大。
正解这是一个典型的“过犹不及”。频率越高,网络越容易把训练照片中的采样噪声、光线不一致当成真实细节学习进去,导致合成的新视角出现高频噪点和闪烁。原始论文中 L=10 是反复调出来的平衡点:既能表达纹理细节,又不至于过拟合。实际使用时应该根据场景复杂度做消融实验。
为何常见:人们容易把“特征维度更大 = 容量更大 = 效果更好”的直觉套用到位置编码上,忽略了频率引入的是“高频噪声放大”的风险。
误区为了让渲染更清晰,就把每条光线的采样点从 64 加到 512,认为点越多积分越准。
正解均匀增加采样点确实能提高积分精度,但收益急剧递减,而训练时间几乎线性增长。NeRF 的真正王牌是分层采样:先用粗网络判断“哪里值得看”,再针对性加密。同样预算下,分层采样的效果远好于盲目均匀加点。如果渲染仍有雾感,优先检查的是网络是否收敛、场景范围是否合理,而不是单纯堆采样数。
为何常见:数值积分直觉告诉人们“步长越小越精确”,但忽略了计算代价和 NeRF 两阶段采样的精妙设计。
误区NeRF 的名字里带“辐射”,渲染时又发射光线,所以本质就是传统光线追踪加了个神经网络。
正解传统光线追踪的前提是场景有显式几何(三角形网格),光线在表面反射、折射,需要做射线与三角形求交。NeRF 没有显式几何,它把整个场景编码成连续函数,光线穿过的是“密度场”而不是“表面”,颜色靠体渲染积分累加。两者共享“光线”这个词,哲学却完全不同:一个是物理模拟,一个是数据拟合。
为何常见:两者都涉及“光线”“辐射”等术语,视觉流程上都有从相机发射光线的阶段,容易让人混淆。
误区NeRF 训练完了,就应该像传统游戏引擎一样 60 帧每秒跑起来。
正解标准 NeRF 即使在推理阶段,每条光线也要采样 128 个点、各自过一遍 8 层 MLP,渲染一张 800×800 的图像在 GPU 上仍需数秒。真正实现实时渲染的是后来的一系列加速工作:plenoxels 用体素网格替换 MLP,instant-NGP 用哈希编码加速特征查找;这些方案与原始 NeRF 已经有很大差距。
为何常见:人们容易把“训练完成”和“实时可用”画等号,忽略了 NeRF 的连续场查询本就昂贵,需要专用加速手段才能逼近实时。
面试题
Q1. 射线方程 r(t)=o+td 中,符号 o 表示什么?
- A.光线方向矢量
- B.光线起点位置← 正确答案
- C.场景背景颜色
- D.像素曝光时间
答案:B。o 是相机或像素光线的起点,即探照灯的位置;d 才是方向矢量。t 是沿光线的距离参数,颜色和曝光时间与射线方程无关。
Q2. NeRF 中使用位置编码的主要目的是什么?
- A.降低网络参数量
- B.增强高频细节表达← 正确答案
- C.减少训练数据需求
- D.替代体渲染积分
答案:B。MLP 有频谱偏置,倾向于拟合低频变化,位置编码先用不同频率的正弦余弦把坐标映射到高维空间,让网络能捕捉雕塑表面刻痕这类高频细节。它不改变网络参数量,也不能替代渲染积分。
Q3. 体渲染公式中 σ(t) 表示采样点的什么属性?
- A.体积密度← 正确答案
- B.表面法线
- C.光源强度
- D.纹理坐标
答案:A。σ 是体积密度,描述该点“实心程度”和挡光能力。法线、光源强度、纹理坐标都不是辐射场直接输出的量。
Q4. 粗采样网络输出的权重 w_i 在分层采样中的作用是什么?
- A.渲染最终背景色
- B.指导细网络重采样← 正确答案
- C.计算正则化惩罚
- D.替换位置编码
答案:B。粗网络输出的权重归一化后形成概率分布,细网络按这个分布集中采样,实现“先看轮廓再看细节”。权重本身不直接参与最终渲染,也不用于正则化。
Q5. NeRF 训练时采用的损失函数是?
- A.交叉熵损失
- B.均方误差损失← 正确答案
- C.感知特征损失
- D.对抗生成损失
答案:B。NeRF 用渲染像素与真实像素的 MSE 作为损失,逐像素比较颜色差异。交叉熵用于分类,感知损失依赖预训练网络,对抗损失属于 GAN 体系,都不是原版 NeRF 的选择。
Q6. 细网络的采样点主要来自哪里?
- A.均匀随机分布
- B.粗网络的权重分布← 正确答案
- C.场景包围盒角落
- D.固定的稀疏网格
答案:B。细网络按照粗网络归一化后的权重(概率分布)进行重要性采样,密度高的区域会获得更多采样点,实现算力聚焦。均匀分布是粗采样的方式,包围盒角落与稀疏网格都不是答案。
Q7. 位置编码频率 L 设置过大时,最可能出现什么问题?
- A.过拟合高频噪声← 正确答案
- B.训练速度大幅提升
- C.网络不再需要激活
- D.颜色通道自动扩展
答案:A。过高的频率会让网络把照片中的噪声、光照不一致等高频干扰当成真实细节记忆,导致渲染新视角时出现噪点和闪烁。训练速度不会变快,网络结构不会改变,颜色通道也不会因频率变化。
Q8. 与传统光栅化渲染相比,NeRF 的显著特点有哪些?
- A.渲染过程完全可微← 正确答案
- B.场景表示为连续场← 正确答案
- C.无需显式三角网格← 正确答案
- D.天然支持实时渲染
答案:ABC。NeRF 用连续辐射场替代显式几何,体渲染全程可微,让梯度能流回网络,这是它可训练的前提。但标准 NeRF 推理速度慢,离实时渲染很远,D 错误。
Q9. 下列哪些属于 NeRF 训练流程中的关键技巧?
- A.粗网络均匀采样← 正确答案
- B.细网络按 PDF 重采样← 正确答案
- C.位置编码输入网络← 正确答案
- D.直接回归像素坐标
答案:ABC。分层采样(粗均匀 + 细聚焦)和位置编码都是 NeRF 的基石。NeRF 学习的是空间坐标到密度和颜色的映射,不是直接回归像素坐标,D 错误。
Q10. 关于体渲染公式 C=∫T(t)σ(t)c(t)dt,下列说法正确的有?
- A.T(t) 表示透射率← 正确答案
- B.σ(t) 表示体积密度← 正确答案
- C.c(t) 表示该点颜色← 正确答案
- D.T(t) 表示场景法线
答案:ABC。透射率 T(t) 是光线走到 t 处未被遮挡的概率,σ(t) 是密度,c(t) 是颜色,三者共同决定合成像素。法线在体渲染公式中并没有直接出现,D 错误。