ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Zemax偏振敏感散射仿真实战:从BSDF设置到分通道探测

Zemax偏振敏感散射仿真实战:从BSDF设置到分通道探测

做光机仿真这么多年,我越来越觉得:偏振和散射这两个词放到一起的时候,绝大多数人第一反应不是兴奋,而是头疼。都说Zemax能算偏振,也能算散射,但真要模拟一个偏振敏感的散射过程,很多人第一步就卡住了——不是软件不会用,而是不知道该在哪个设置里把这两件事“接”起来。

这次我想把这一整套思路彻底捋一遍:为什么有些项目非要“偏振敏感的散射”不可,Zemax里到底哪些机制在管偏振、哪些在管散射,以及我实际搭建仿真时会怎么设置物体、光源、探测器和BSDF,最后再把踩过的坑按“速查表”的方式列出来。这篇文章适合正在做杂散光分析、激光雷达光学、薄膜散射评估或者想搞清楚Zemax偏振追迹到底能干什么的同行,尤其是那些已经在非序列模式下遇到过“散射不生效”“探测器只有强度没有偏振”的读者。

1. 同样叫散射,为什么偏偏要加“偏振敏感”四个字

1.1 散射仿真真正丢掉的另一半信息

常规的散射仿真,大家最熟的做法就是给表面塞一个BSDF,光线打上去之后重新采样方向和功率,然后看探测器上能量分布。这个流程本身没问题,但里面藏了一个非常关键的简化:几乎所有默认散射模型都在假设“散射前后的偏振态不参与计算”,或者至少没有把偏振态当成BSDF的自变量。

实际物理并不是这样。一束S偏振光打到粗糙表面,和同角度的P偏振光打上去,散射能量、角分布往往有明显差别。更复杂的是,散射光里还会出现偏振态的改变——原本是线偏振光,散射一圈回来可能变成了部分偏振光。这些信息落到探测器上,就成了“退偏程度”“偏振对比度”这类指标,很多系统的成败恰恰就卡在这些指标上。

所以,“偏振敏感的散射过程”和普通散射仿真的本质区别,就是它的BSDF不再是一个标量函数,而是一个带有偏振输入/输出维度的响应,专业一点讲是4x4的穆勒矩阵形式,或者至少是能够区分同偏振、正交偏振通道的pBRDF/pBSDF。只算强度的话,等于把散射过程中最值钱的偏振特征全部扔掉了。

1.2 哪些项目实际要求“偏振敏感”

先举一个最常见的场景:激光雷达接收链路。发射端通常是线偏振激光,回波信号经过目标散射之后,同偏振方向的分量往往携带了目标的表面特性,而正交偏振分量则反映了多次散射、体散射或粗糙介质的细节。如果你在Zemax里只做标量散射追迹,算出来的回波功率和实际系统测试完全对不上,接收端那一路偏振分光镜就白设计了。

第二个典型场景是镀膜镜头的杂散光。很多人以为杂散光只需要看角度和能量就够了,但实际在车载摄像头、AR/VR光学中,表面膜层的偏振效应会直接影响鬼像的可见度,特别是那些经过两个以上表面散射的光路,偏振状态已经绕了好几圈,最终到达传感器上的强度分布和标量近似差得很远。

第三个场景是生物医学光学里的OCT和荧光检测。组织散射会强烈退偏,散射光的偏振保持度是判断组织类型的一个重要特征。这类仿真如果不用偏振敏感散射,就完全失去了建模意义。

所以我的判断是:只要系统里有偏振器件,或者接收端对偏振有选择性,那散射仿真就不能再只用标量BSDF糊弄过去了。这也是我把这个题目单独拿出来的原因,它不是Zemax里的“高级技巧”,而是很多项目绕不过去的刚需。

2. 在Zemax里,偏振与散射不是天然的“一家人”

2.1 非序列模式才是主战场

Zemax分为序列模式和非序列模式,这个概念大多数人都知道。但真要处理偏振敏感的散射,我强烈建议直接进非序列模式(NSC),别在序列模式里硬抠。

序列模式擅长的是透镜系统里“一件一件有序发生”的光学事件,偏振追迹可以做,衍射计算也可以做,但散射这个东西在序列模式里更像一个附加项,处理连续多次、随机方向的散射路径非常吃力。非序列模式则不同,光线打在物体上之后可以选择反射、折射、散射、吸收,路径完全由几何和概率决定,这才符合散射过程的物理本质。

在非序列模式里,每个物体都可以单独设置散射模型。常见操作是右键物体打开Object Properties,找到Scattering选项卡,里面可以选散射模型、设置散射分数、指定每根光线分裂出的散射光线数量。模型列表里通常能看到朗伯散射(Lambertian)、Henyey-Greenstein、ABg等选项。注意,朗伯散射是“余弦分布”的标量模型,不代表偏振;ABg模型则是用一组拟合参数去逼近实测BSDF曲线,后面我详细说。

2.2 偏振态在追迹中的传递方式

偏振信息在Zemax中是以光线携带的状态量形式存在的。光源可以被设置成特定的偏振态,比如线偏振、圆偏振,或者直接给定琼斯向量/斯托克斯参数;光线在表面上发生折射、反射时,Zemax会根据膜层(Coating)或材料折射率,按菲涅尔公式更新光线的偏振态,这一点是做偏振系统仿真的基础。

但这里有一个微妙的地方:当一根光线触发“散射事件”时,散射模型决定了新的传播方向、能量是否重新分配,而光线的偏振状态呢?在绝大多数默认散射模型里,偏振态并不会因为“散射到这个方向”而单独计算一遍。也就是说,新的方向被采样出来了,能量被乘上了BSDF的权重,但偏振状态继续沿用散射前的值,或者最多在镀膜反射/透射的框架内更新,而不会真正按照“这个方向的pBSDF应该输出什么偏振态”来更新。

这么说可能有点抽象,我换一种说法。如果把BSDF想象成一个“方向分配器”,那么默认模型里的分配器只在乎“从哪个方向来、往哪个方向去、分配多少能量”,至于来的光是横着振还是竖着振,它根本不管,也不改变振动状态。这就是我说的“不是一家人”:偏振部分跟的是光线追迹的通用逻辑,散射部分只负责方向和功率,两者在默认设置下并没有深度耦合。

2.3 默认模型与真正偏振BSDF之间的差距

所以,如果你想做的“偏振敏感散射”是严格物理意义上的,那就不能指望直接选一个“Lambertian”然后打开偏振追迹,整个偏振敏感散射就自动出来了。差别在于:

  • 标量BSDF:BSDF值只与入射、出射方向有关,输出能量是标量,不区分偏振通道。
  • 偏振BSDF(pBSDF):除了方向,还依赖入射光的偏振态和出射光的分析偏振态,通常用穆勒矩阵的各个分量描述。

Zemax能不能做到真正意义上的偏振BSDF?能,但往往需要“绕路”,常见的手段有三种:

第一种,用自定义DLL散射模型。Zemax允许用户编写DLL作为散射模型,这样你可以在光线打到表面时自己做运算,包括根据入射/出射方向计算一个4x4穆勒矩阵,然后把新的斯托克斯参数写回到光线上。这是最彻底也最麻烦的方式。

第二种,把偏振BSDF拆成几个标量通道分别仿真。比如你只关心“同偏振通道”和“正交偏振通道”,那就分别测量或拟合这两个通道的BSDF,然后在Zemax里跑两次标量散射仿真,再用两个探测器分别收集结果。这种方案工程上最实用,也不要求你会写DLL。

第三种,在物理上把偏振通道切开。入射光先用偏振片起偏,散射后出射方向再放一个偏振分析片,这样即便Zemax内部用的是标量BSDF,最后探测器拿到的也已经是被“偏振投影”之后的能量了。这种“用光学器件替软件补功能”的思路,我在很多项目里都验证过,可靠性反而最高。

3. 五步搭一个偏振敏感散射仿真:从光源到探测器

3.1 基线和几何:先让结构“长对”

我不建议一上来就堆参数。第一步永远是建立一套“无散射、无偏振片”的基线模型,确认几何布局、坐标方向、探测器视野都正确。

举个例子,我们要模拟一束线偏振光以45度角入射到一块粗糙的镀铝反射镜上,然后分析它反射散射光在两个正交偏振通道里的分布。在非序列模式下,我会先放一个矩形面作为反射镜,材料设成Mirror,表面先不开散射;再放一个光源,比如Source Ellipse,位置和方向调整到45度入射;最后在反射方向放一个探测器。

跑一遍,确认镜面反射光斑打到了探测器正中央,能量大小接近100%,再开始下一步。这个步骤花不了五分钟,但它能帮我排除一大半“后面结果怎么这么奇怪”的问题,因为你所有后续偏振、散射分析的基线都是从这里来的。

这里特别提醒:光源的方向一定要用局部坐标看清楚。很多人设置的45度结果是入射角完全不同的另一个角度,最后分析偏振时怎么都对不上。Zemax里的光源方向、物体倾斜角、探测器法线方向这三个坐标系,我建议直接在3D Layout里打开光路确认,别只看数字。

3.2 光源偏振与表面散射参数设置

基线没问题之后,开始给光源加偏振态。在光源属性里找到偏振设置,把琼斯向量设为线性偏振。这里要注意定义线偏振方向时,一定要明确它是在全局坐标还是光源本地坐标下定义的,否则你以为是P偏振,实际追迹出来的可能是S偏振。

然后是表面的散射设置。回到矩形面的Object Properties,打开Scattering选项卡:

  • Scatter Model:先选一个常用模型,工程上优先推荐ABg,因为它有明确的拟合物理意义。
  • Scatter Fraction:设为0.05,表示5%的能量参与散射,其余95%走镜面反射路径。这个值要根据实际样品的散射程度来。
  • Number of Scatter Rays:设定每根光线散射出多少根子光线,比如1000。注意,这个值越大,统计噪声越小,但追迹时间也越长。

如果你手里已经有实测BSDF数据,那就把它拟合成ABg参数。ABg模型的常见形式是:

BSDF = A / (B + |β - β0|^g)

其中β是方向角度的投影函数,A、B、g是拟合系数。拟合的时候有几个经验:B不要设成0,否则在镜面反射方向会出现无穷大;g通常取值在1到3之间;A的大小决定了散射总体强度。把拟合好的参数填到Zemax的ABg模型里,散射角分布就会更接近实测。

3.3 用偏振片物理分离偏振通道

接下来是重头戏:如何在探测器端把偏振信息“读出来”。

我常用的做法是在反射散射光的路径上,放置两个偏振片和分析探测器:

  • 一路偏振片的透光方向与入射光偏振方向平行,探测器收集同偏振通道;
  • 另一路偏振片的透光方向与入射光偏振方向垂直,探测器收集正交偏振通道。

在Zemax里,可以用琼斯矩阵面或者偏振片类物体来实现。这样做的好处是,软件不需要“额外理解”穆勒矩阵,它只是严格按照光学器件的行为追迹光线,而最终探测器得到的数据,就已经是经过偏振投影后的散射强度了。

有人会问:这不是没有真正做“偏振敏感的散射”吗?确实,严格说它是用光学器件实现了偏振通道的提取,而不是在BSDF内部做偏振耦合。但从工程设计角度,这个结果恰恰就是你在真实光路中会测到的数值,和实验测量具有最强的可比性。如果项目只需要区分同偏振和正交偏振,这种方法完全够用。如果你的BSDF本身包含偏振信息,就需要结合自定义DLL再做耦合,这个我在下一节讲。

3.4 采样策略与结果解读

放进两个偏振通道探测器之后,追迹参数要重新调整。因为散射能量本身占比很小,又被偏振片分掉一大半,能到达探测器的光线数很少,噪声会非常明显。我的经验是:先开比较少量的光线(比如10万根)观察分布形状是否合理,确定探测器位置和视场没问题之后,再加到500万甚至1000万根做最终收敛计算。

另外要开“分裂光线”或“重要性采样”。重要性采样可以让散射光线重点朝探测器的方向传播,避免大量光线散射到无用方向造成浪费。Zemax里可以在物体或探测器上设置重要性采样目标,把采样效率提高一个数量级。

结果解读时,不要只盯着探测器上的辐照度彩色图,要导出数值,逐像素分析两个偏振通道的功率比。如果一个通道明显比另一个强,说明该表面的散射确实存在偏振选择性;如果两个通道几乎一样,那可能说明你选的散射模型是标量的,偏振差异主要来自镀膜反射而非体散射。这个判断本身,就已经是研究成果了。

4. 我踩过的坑:偏振散射仿真常见问题排查

4.1 探测器只给强度,看不到偏振态?

这是我收到最多的一个问题。很多人把探测器放在那里,跑完分析,发现只能看到辐照度,根本看不到Stokes参数或偏振度,于是以为Zemax不支持偏振分析。

其实非序列模式的探测器对象本质上是能量计,它记录的是辐照度,不是完整的电场或偏振矢量。想看偏振状态,办法有两个:

  • 在光源到探测器之间放偏振片,用“物理滤波”的方式让探测器只接收某个偏振分量;
  • 在序列模式里用偏振光瞳图(Polarization Pupil Map)查看每个光瞳点的椭圆偏振信息,但那不是散射场景。

所以如果你的目标是散射光的偏振特征,那就老老实实通过偏振片分离通道,再比较各通道的能量,而不是指望探测器直接吐出偏振度。这一点想通了,很多“软件不支持”的抱怨就能少一半。

4.2 散射比例没生效,或者追迹时间爆炸

有的读者遇到过:明明在物体属性里设置了散射分数和散射光线数,结果探测器上还是只有一条镜面反射亮斑,看不到散射分布。这种问题大多是散射设置没有被正确应用到光线上。

我的排查顺序是:

  • 先确认物体是否选中了散射模型,而不是只在“膜层”里设置了反射率。
  • 再确认散射分数是否为0或太小,5%听起来不大,但肉眼在探测器上已经能看到明显的漫反射背景。
  • 再确认是否开启了“分裂光线”并且阈值设得合理。设置散射光线数1000,但最小相对功率阈值太大,弱散射光线在分裂后直接就被剔除了,导致你看起来好像没有散射。

追迹时间爆炸则是反过来的问题。由于散射会让每根光线指数级分裂,很快内存和CPU就扛不住了。我常用两个办法:一是对不太重要的物体把散射分数设小甚至关掉,只保留关键表面的散射;二是使用重要性采样把宝贵的光线“导向”重要区域。

4.3 自定义BSDF加载失败或结果错乱

自定义DLL模型是处理偏振敏感散射的一条正路,但坑也最多。最常见的加载失败原因是版本和位数不匹配。如果Zemax是64位的,DLL必须是64位编译;同时DLL接口函数名和参数列表必须符合Zemax的规范,稍微差一个参数,软件直接就报错。

我建议不要直接在完整系统里调试自定义DLL,先建一个最简单模型:一个平面,一束平行光,一个探测器。自定义DLL只返回一个恒定BSDF值,比如0.1,跑通了再逐步加入方向依赖、偏振依赖。这样能快速区分是接口问题还是算法问题。

如果你不想从零写DLL,还有一种折中点:把偏振BSDF拆成四个标量BSDF,分别对应穆勒矩阵的四个关键元素,然后在Zemax里做四次仿真,最后在后处理里组合。虽然操作麻烦,但可以把“软件能不能算”变成“我能怎么算”,主动权完全在自己手里。

4.4 授权模块不可用导致功能缺失

这一类问题和模型本身没关系,但很影响使用心情。比如启动追迹时提示某个功能项不可用,或者分析菜单里的偏振相关按钮置灰。很多情况下是许可证模块没有包含对应的Zemax功能,而不是模型设置错了。

这时候我会先检查Zemax的许可证状态,确认当前授权包含哪些模块。遇到过“failover feature not available”类似提示的,通常需要先重启Zemax,再检查许可证服务是否正常启动。如果问题持续存在,就要对照授权清单看是否真的购买了对应模块。记住一个原则:软件报错不等于你的仿真思路错了,先排除授权和环境问题,再做模型诊断,能省很多白费的精力。

5. 几点实战体会

5.1 先建立“无散射基准”再谈偏振效应

这套流程我用了很多次:先关掉散射,用偏振片把同偏振和正交偏振两个通道的功率测出来;然后打开散射,再看两个通道的变化。这一步能帮你把“偏振变化”和“散射变化”两个因素解耦。很多时候你会发现,散射前后偏振通道差异已经确定了,散射只是把总能量摊到了更多方向上,并没有引入新的偏振选择。如果一上来就开满散射加偏振,出了奇怪数据你根本不知道问题出在哪。

5.2 ABg拟合:把曲线变成参数再去比较

偏振敏感散射的验证,最怕的就是“这个结果对不对说不清”。我现在的习惯是把实测BSDF曲线拟合到ABg参数,不管做几次实验、换几个批次样品,最后都落到A、B、g三个数字上。这样在Zemax里改模型时,只需调整参数,仿真的可复现性就好很多。如果同一个样品在不同偏振通道下拟合出的A、B、g差异很大,那就说明这个表面的偏振敏感散射效应非常强,值得用更精细的模型去描述。

5.3 工程精度vs物理完备性

最后想分享一个观点:对多数工程场景,“偏振片+多个通道分别仿真”这种简化方案已经能回答90%的问题。真正需要完整穆勒矩阵级pBSDF的项目其实很少,而且即使你需要,也要考虑测量数据是否支持、拟合误差是否可控、自定义DLL的开发成本是否值得。

我见过太多人一上来就要做最完整的偏振散射模型,最后卡在DLL开发和BSDF测量上,项目周期被拖得很长。反而是那些先用分通道近似做出结果、再逐步补齐物理细节的同事,最后交付的东西既可信又能落地。做仿真这事,物理完备性永远服务于工程判断。下次你再被问到“能不能模拟偏振敏感的散射过程”,希望这篇文章能帮你少走几步弯路。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进