基于软件光栅化的高性能实时隐式串线式头发渲染技术
《Proceedings of the ACM on Computer Graphics and Interactive Techniques》:High-Performance Real-Time Implicit Strand-Based Hair Rendering via Software Rasterization
【字体:
大
中
小
】
时间:2026年07月06日
来源:Proceedings of the ACM on Computer Graphics and Interactive Techniques 3.1
编辑推荐:
摘要
AI总结:要查看此由AI生成的总结,您需要拥有高级访问权限。了解更多信息并登录。
摘要
在本研究中,我们提出了一种高效的延迟软件光栅化流程,用于使用头发网格实时渲染基于单根头发的效果。头发在塑造富有表现力的3D角色方面起着关键作用,但基于单根头发的方法通常仅限
摘要
AI总结:要查看此由AI生成的总结,您需要拥有高级访问权限。了解更多信息并登录。
摘要
在本研究中,我们提出了一种高效的延迟软件光栅化流程,用于使用头发网格实时渲染基于单根头发的效果。头发在塑造富有表现力的3D角色方面起着关键作用,但基于单根头发的方法通常仅限于高端硬件,且多用于少数核心角色。虽然头发网格已被证明是一种能够处理多种发型风格的高效表示方式,但现有的基于网格着色器的实现仍存在显著瓶颈。为解决这些问题,我们采用了一种软件光栅化方法,提升了性能与兼容性。该方法通过结合延迟着色、头发过滤与重建步骤,即便每像素仅使用一个采样点,也能实现高效的远场头发渲染,同时仅需最少的硬件支持。为进一步提升可扩展性,我们还引入了细节层次(LOD)机制,根据观看距离和屏幕空间覆盖范围调整头发的表示程度与着色复杂度,从而在保持视觉质量的同时进一步降低计算成本。据我们所知,这是首个实现效率、灵活性、可扩展性及广泛硬件兼容性相结合的方法。
AI总结(实验性):该总结是通过自动化工具生成的,并非由文章作者撰写或审核。它旨在帮助读者发现相关内容、评估文章相关性,以及让相关领域的读者理解这项工作。它是对作者提供的摘要的补充,而作者提供的摘要仍是论文的主要总结。完整文章才是权威版本。点击此处了解更多信息。点击此处对该总结的准确性、清晰度及实用性发表意见,您的反馈将有助于优化未来的生成版本。要查看此由AI生成的通俗语言总结,您需要拥有高级访问权限。
图1:使用我们的带有细节层次和预计算环境光遮蔽的延迟软件光栅化流程,在不同距离下渲染的多款发型(共48.3万根头发,4K分辨率),并与基于网格着色器的参考实现[Bhokare等人,2025年]进行对比。我们的方法比网格着色器快4倍,质量可与4倍MSAA相媲美。不同发型的LOD强度(从左到右)为λ = {4.0, 5.5, 2.0, 2.8, 3.0}。
1 引言
在计算机图形学中,渲染头发和毛发一直是一个重要的难题。由于头发由数十万根细小的单根毛发构成,具有复杂的体积感,因此它是最难渲染的物体之一:这需要大量小型半透明子像素级几何体,且这些几何体还需具备高频散射特性。这就导致了巨大的渲染计算成本,因为需要处理大量的内存带宽需求和过度绘制问题,同时由于渲染出带有反光效果的细小几何体,还容易产生混叠现象。因此,在实时渲染中,常见的做法是大幅简化头发渲染,要么使用带纹理的表面[Scheuermann,2004年],要么使用卡片结构[Jiang,2016年],直到最近,显式的单根头发渲染才得以在实时环境中实现[Tafuri,2019年;Taillandier和Valdes,2020年]。然而,目前这些基于单根头发的方法通常仅限于高端硬件,且仅适用于少数核心角色。另一方面,人们越来越希望能够在各种硬件上高效地渲染大量具有独特且复杂发型的角色。
为部分缓解这些问题,Bhokare等人[2025年]提出使用头发的粗略笼状结构(即头发网格)以及造型操作符来隐式表示头发单根毛发,仅在渲染时动态生成它们。这种方法大大降低了带宽需求,比常用的线性头发蒙皮技术[LHS][Somasundaram,2015年]更高效。不过,这仅解决了部分问题:仍然需要大量的过度绘制,混叠问题依然存在,从而影响了渲染质量。此外,Bhokare的研究[Bhokare等人,2025年]采用的是基于网格着色器的实现方式,而并非所有现有硬件都支持该方式。
在本研究中,我们提出了一种新的高效实时头发渲染解决方案,它建立在Bhokare等人[2025年]的思想基础上,但将其实现为一种高效的延迟软件光栅化器。这种方法具有诸多优势,包括更好的跨平台兼容性、通过精心设计GPU线程同步提高头发生成效率,以及通过延迟着色仅对可见的头发单根毛发进行着色,从而大幅降低着色计算成本;同时,通过基于头发单根毛发与像素相交数据的后期过滤,减少了混叠现象。我们还通过采用细节层次机制加速这一延迟流程,该机制可在不牺牲视觉效果的前提下减少头发单根毛发的数量及其复杂度。最后,我们利用头发网格结构作为遮挡的替代手段,从而能够使用包含遮挡的复杂基于图像的照明方式,大幅增加了可用于实时渲染显式头发单根毛发的照明类型。所有这些改进共同推动了实时高效头发渲染的发展,使得具有复杂照明效果的头发渲染更加高效,且视觉瑕疵更少(见图1)。具体而言,我们的贡献包括:
• 一种基于快速间接调度的、具备细节层次功能的头发软件光栅化流程,可通过SIMD级寄存器通信并行构建造型后的头发单根毛发,并利用支持原子操作的压缩G缓冲区实现延迟着色;
• 一种基于统计方法的深度图可见性校正方法,用于在运行时动态调整头发的复杂度以适应不同细节层次;
• 一种单遍头发单根毛发连接性重建与过滤方法,借助保守的光栅化技术,即使在仅使用单个采样的流程中,也能生成平滑、无混叠的透明头发单根毛发;
• 一种直接编码在头发网格上的环境光遮蔽项,使得可以在头发模型中使用基于体积的复杂探针式照明。
2 相关工作与背景
头发渲染:早期实现实时头发渲染的方法依赖于带纹理的头发表面[Scheuermann,2004年]或卡片结构[Koh和Huang,2001年]。随着GPU性能的提升,渲染显式的头发单根毛发已成为可能,但存在两个主要问题:一方面,头发的复杂性——每个发型包含超过10万条样条线——使得存储和传输这些显式头发单根毛发变得不切实际;另一方面,半透明头发单根毛发的过度绘制会导致极高的计算成本,且容易出现混叠现象。为解决第一个问题,常见的做法是仅存储、编辑、模拟和传输一组代表性的引导毛发,然后通过线性头发蒙皮技术[LHS][Somasundaram,2015年]对每根实际的头发单根毛发进行插值处理,必要时还可应用一些程序化的造型操作符[Chang等人,2025年]。不过,这种方式需要为每根头发单根毛发存储插值权重,因此在内存占用和带宽方面不太理想。其他较新的方法则尝试利用神经网络来生成头发单根毛发[Rosu等人,2022年],但这些方法距离在实时渲染中得到应用还有很大差距。Bhokare等人[2025年]提出了一种更为简洁的方法,他们利用头发网格结构[Yuksel等人,2009年]作为整个发型的替代表示。该头发网格使用代理几何体来模拟头发的整体形状,通过连接的网格来定义头发束。然后在渲染时,通过在每个头发束内进行插值,在网格着色器中生成显式的头发单根毛发:本质上,这与线性头发蒙皮技术非常相似,只是头发束的边缘充当了引导毛发的作用,不同之处在于,插值权重是由头发单根毛发在头发束中的位置隐式决定的,因此无需存储权重,这大大降低了存储和带宽需求。我们在Bhokare的方法基础上进行了改进,提出了一种基于高效延迟软件光栅化技术的方案,同时提升了其代表性能力,并增加了对细节层次的扩展支持。
软件光栅化:随着完全可编程GPU管道的出现,软件光栅化已被证明是一种可行的渲染流程[Karis等人,2021年;Laine和Karras,2011年],在处理半透明物体或亚像素特征(如点云[Schütz等人,2022年]或半透明高斯曲线[Kerbl等人,2023年])的场景中,其性能甚至优于硬件光栅化。在头发渲染领域,Taillandier和Valdes[2020年]提出在AAA游戏中使用软件光栅化实现高效头发渲染,他们利用基于分块式逐像素深度桶的与顺序无关的透明度处理技术[Everitt,2001年;Thibieroz,2018年]以及分析型线条抗混叠技术。Ishihara和Mishima[2023年]进一步通过仅使用三层结构来实现OIT,从而降低了内存消耗。如今,头发软件光栅化已成为高端AAA游戏引擎的标准[Cifariello Ciardi等人,2022年;Epic Games,2021年;Kulikov,2025年]。我们描述了一种高效的单一桶式延迟软件光栅化流程,用于头发渲染,随后还通过过滤流程来处理半透明性和混叠问题。
头发细节层次:在头发细节层次处理方面,行业通用的做法是将头发单根毛发的表示方式转换为卡片结构,但这通常是一个计算成本高昂且需要手动操作的过程,Zheng等人[2025年]的工作是个例外,他们利用可微渲染技术实现了该过程的自动化。随机简化技术[Cook等人,2007年]已被成功应用于头发简化,通过减少头发单根毛发的数量并加厚剩余的毛发来弥补因减少数量而导致的投影面积损失,同时还可以通过去除控制点来降低头发单根毛发的复杂度[Bhokare等人,2025年]。Zhu等人[2023年;2022年]则通过对头发单根毛发进行分组,来模拟组内的整体散射和内部散射效应。Montazeri等人[2021年;2020年]在布料渲染领域也采用了类似的方法。我们在随机简化技术的基础上开发了用于细节层次处理的方案,同时引入了简单而有效的措施,以避免因这些简化操作而产生的混叠和其他视觉瑕疵。
抗混叠:由于单个头发单根毛发在屏幕上的占据空间极小,因此容易遭受严重的欠采样问题,导致渲染结果出现噪声。此外,头发那种纤细、复杂且高度精细的亚像素结构给抗混叠带来了独特的挑战,传统的抗混叠技术以及现代的时间上采样技术,如AMD的FidelityFX Super Resolution[2021年]或NVIDIA的DLSS 4[2025年],在准确处理这类问题时往往难以避免出现模糊或重影等视觉瑕疵。虽然有一些方法依赖于神经网络[Currius等人,2022年],但Huang等人[2025年]的最新研究表明,一种非神经网络的、基于显式过滤的框架可以提供更好的替代方案。通过实现显式的头发单根毛发连接与方向过滤,他们的算法能够保留亚像素级的连续性以及细小的纤维细节,比如飘动的头发丝,而不会像黑盒神经网络那样出现模糊现象。
背景:头发网格渲染。Bhokare等人[2025年]的核心思路是利用头发网格对头发单根毛发进行隐式定义[Yuksel等人,2009年]。头发网格通过一组几何束来定义头发的整体结构(见图3左侧),这些几何束构成了头发的粗略结构。每个几何束由L层组成,最上层和最下层分别位于头发的根部与尖端。第i层被定义为一种多边形形状(在我们的实现中采用四边形),其顶点为vi,同时每个顶点还对应有切线ti以及uvw坐标。
在渲染过程中,每根头发单根毛发会被构建为一个样条线,该样条线在长度方向w∈[0,1]上均匀分布有N个控制点,其中w=0处的点位于根部层,w=1处的点位于尖端层。每个头发单根毛发的起点会根据其固定的uv坐标进行采样,其基础位置则是通过对该几何束层中的顶点及切线进行双线性插值后,再通过样条线插值计算得到的。最后,通过将造型函数应用于每个控制点的uvw坐标,即可得到最终的头发单根毛发形状。
图2:我们的软件光栅化流程处理的是由多个几何束构成的简单网格格式的发型。首先,通过细节层次预处理阶段创建一个间接调度缓冲区,确定需要渲染多少根头发单根毛发以及多少个控制点。在光栅化阶段,该流程会读取现有的深度缓冲区,并通过atomicMin操作在uint64类型的复合缓冲区中更新头发单根毛发的数据。这些数据随后会被用于逐像素着色,之后还可以通过可选的过滤阶段进一步优化渲染结果。最终,处理后的结果会被混合到主渲染目标中。WG表示工作组。
3 我们的方法
我们为以头发网格形式编码的发型设计的延迟软件光栅化流程如图2所示。其核心原理是,该软件光栅化器接收输入的头发网格以及一个头发单根毛发的标识符(例如由其UV坐标确定),然后动态生成该头发单根毛发,随后将其光栅化为压缩形式的G-Buffer(见3.1节)。G-Buffer中的几何信息随后会被用于着色处理(见3.4节)。为提升效率与图像质量,在光栅化之前的线条生成阶段,我们会应用基于每束线条的细节级别控制,以此减少线条数量并降低其复杂度(见3.2节)。最后,为避免因采样不足以及G缓冲区中缺乏透明度信息而产生的视觉瑕疵,我们会通过过滤处理来重建最终图像(见3.3节),该图像会与场景中的其他部分进行深度合成。
3.1 延迟软件光栅化
为实现远处头发的快速渲染,我们在Bhokare等人[2025]提出的头发网格方法基础上,加入了自定义的软件光栅化引擎。正如Schütz等人[2022]所证明的,软件光栅化在处理大量亚像素级几何结构以及高绘制开销的场景时尤为有效。头发线条几何上极为纤细,通常仅覆盖一个像素,因此在传统的光栅化流程中会产生巨大的计算负担——因为必须执行2×2的片段着色器四元组调度,这会导致多达75%的着色器调用被用于处理辅助任务。此外,构建一条头发线条还需要每个分段访问相邻控制点的数据;若采用简单方式处理,每个线程都会重复读取并重新计算所有之前的顶点数据。另一种方法是使用共享内存存储中间数据,但这仍会占用不必要的存储空间和带宽。
为解决这些问题,我们的实现采用了全工作组范围内的、仅基于寄存器的协同式线条构建方式,从而提升效率并减少内存传输量。为动态调整头发的复杂度,我们会先进行一次预处理,计算出精细的分辨率数据(详情见3.2节),这些数据会被后续的间接调度阶段用来确定所需的工作组数量。屏幕空间中的线条数据会被压缩后存储在每个像素对应的64位宽度的G缓冲区中,进而用于延迟着色。
3.1.1 协同式线条构建
每个由若干线程组成的工作组会协同构建一条头发线条,并通过原子最小值操作将最终结果写入目标图像。虽然Bhokare等人[2025]对线条构建进行了高层级描述,但并未给出高效并行化的具体实现细节。由于构建每条线条的各分段都需要参考前后分段的信息,因此并行化并非易事。若采用简单方式,每个线程都会多次重复计算当前控制点周围的数据依赖关系,才能得到最终的线条分段。为此,我们会将每束线条的层数据写入共享内存,同时利用高效的子组间通信机制,让相邻线程之间共享已计算出的控制点数据。这样一来,每个控制点只需计算一次(见图3)。
第一轮处理会构建一条基础样条线,其中每个控制点的切线都是通过有限差分法根据其前后顶点计算得出的。随后,这些切线会与位置信息一起用于计算两个控制点之间的埃尔米特样条线。基础样条线构建完成后,我们会根据所需的分辨率对其进一步细分,从而得到最终的顶点位置列表。每个位置都会作为样式函数f(x)的输入,进而生成最终的样式化线条。需要注意的是,对于样式化后的线条,我们不再使用样条线,而是直接渲染折线。为了实现样式效果,我们需要为着色计算新的切线值;否则就会出现原始研究[Bhokare等人2025]中提到的着色瑕疵。每个切线值同样是通过前后控制点计算得出的。这种计算最终切线的两阶段依赖关系使得并行化变得复杂;为此,我们的方法再次采用子阶段间通信机制,让相邻线程之间共享顶点和切线数据(见图1)。
图3
为高效实现线条构建的并行化,每个工作组首先会协同将所有层数据加载到共享内存中。每个线程会将自身负责的那段线条的首尾计算位置与相邻线程共享,从而避免重复计算。这一过程会进行两次:第一次是在构建基础样条线的层数据时,第二次则是在构建最终样式化线条时。
3.1.2 用于延迟原子着色的压缩G缓冲区
一旦计算出每段样式化后的线条,我们就会使用数字微分分析器(DDA)线描算法对其进行光栅化。由于头发线条极为纤细,我们会将其视为单像素宽的线条进行光栅化。我们也尝试过渲染较粗的线条,但发现这在远场场景中并不会带来视觉上的提升,反而需要更多的计算资源。
为支持我们的重建滤波器(见3.3节),光栅化阶段会将数据写入两个独立的G缓冲区目标(或数组切片):一个是中心采样G缓冲区,只有当线条以可配置的直径穿过像素中心时才会更新;另一个是保守型G缓冲区,只要线条与任何像素相交就会进行更新。
在这种线状光栅化过程中,为每条线条着色会因绘制开销过大而变得极其耗资源:我们分别测试了基于每个片元的着色方法(类似片段着色器)和基于每个顶点的着色方法,但实际测试中这两种方法的效率都过低。因此,我们采用了延迟着色策略。
对于延迟着色,我们需要以下每像素级别的着色数据(详细内容见3.4节):
• 位置(float3)
• 切线向量(float3)
• 着色参数:反射率(float3)、粗糙度(float)、倾斜度(float)
• 环境光遮蔽值(float)
此外,深度值的较高位还用于支持原子最小值操作。
不过,要让延迟着色方案可行,所有必要的着色数据都必须能够放入帧缓冲区中,并且要同时写入——以避免竞态条件——每个像素的数据量需控制在64位以内。这一限制至关重要,因为重新计算所需的着色数据成本极高:要么需要重新构建整个线条的几何结构,要么需要为每束线条、每条线条及每个分段存储索引,而这很快就会超出可用位数。为解决这一问题,我们对着色所需的数据进行了如下压缩:
(1) 降低深度精度:深度值仅使用24位。
(2) 位置重建:我们不直接存储位置数据(float3),而是采用延迟渲染引擎中的常见方法,从深度值反推位置。这种方法将位置恢复的范围限制在像素内的特定点上,因为只有在那个点上才能精确恢复位置[Mittring 2007]。
(3) 着色参数:我们不在G缓冲区中存储着色参数,而是存储uvw风格坐标,着色时再根据这些坐标查询参数。这样一来,每个像素只需查询一次着色参数,而且整个外观模型只需用三个浮点数即可存储。
(4) 切线向量压缩:我们采用八面体单位向量编码方式对切线向量进行编码,将其从float3压缩为float2。
(5) 数据量化:除深度值外的所有浮点数都被量化为uint8或uint6,进一步降低内存占用(见插图)。
通过上述压缩方式,我们能够让所有必要数据都放入64位的帧缓冲区中,从而实现高效的延迟着色。需要注意的是,与常见的延迟渲染方式一样,我们这里不处理透明度问题:这对头发来说尤为重要,因为头发线条的尺寸通常远远小于单个像素的尺寸,因此多个线条可能会共同影响一个像素的视觉效果,而透明度对于将这些线条与场景中的其他元素合成起来至关重要。我们会在3.3节中讨论,通过后期处理滤波器来解决这个问题。
3.2 细节级别控制
在处理远场渲染时,我们希望通过限制需要渲染的线状图元数量来减轻计算负担,而这可以通过减少线条数量以及降低线条分辨率来实现。我们利用线条生成的实时特性,根据线条在屏幕上的重要性动态生成相应数量的线条。首先,我们会为每束线条进行一次预处理,计算每束线条的数量以及每条线条的精度,然后将这些数据写入仅设备可访问的缓冲区中。这一阶段的每个线程会处理一束线条,并将其对应的数据写入缓冲区。这些数据随后会被软件光栅化引擎中的线条构建阶段作为输入,用于间接调度——即根据每束线条的实际需求分配不同数量的工作组。细节级别控制是根据层在屏幕空间中的覆盖范围来计算的[Unterguggenberger等人2024;2025](见插图),其灵敏度可以通过参数λ来控制,不同的发型或线条数量对应的λ值也可能有所不同。
3.2.1 动态线条数量控制
为降低头发的复杂度,我们采用了受随机简化方法启发的策略[Cook等人2007]。具体而言,我们会根据线条在屏幕空间中的投影覆盖范围,随机移除远处束中的部分线条,从而使每束线条在细节级别控制下的数量满足公式NLOD=clamp(?L?(N+δ)?,1,N),其中N是该束线条的总数量,δ~U[0,1)是每束线条的随机偏移量,用于平滑细节级别之间的过渡,而L∈[0,1]则是细节级别选择值,计算公式为L=clamp(‖AABBmax?AABBmin‖Ry?λ,0,1),其中AABB表示该束线条在屏幕空间中的边界框,经过屏幕垂直分辨率Ry的归一化处理,λ则是细节级别敏感度参数。投影后的边界框是通过将每层的顶点投影到屏幕空间,然后对所有层的边界框进行逐分量取最大值得到的:AABBmin=minimin(sxi,syi,szi,swi),AABBmax=maximax(sxi,syi,szi,swi),其中sxi、syi、szi、swi分别是第i层四个顶点在屏幕空间中的坐标。那些边界框完全位于视图框外的束会被剔除(NLOD=0)。计算得到的数值会被写入一个包含B个条目的间接调度缓冲区的实例计数中,随后通过调度B个线程来完成处理,每个束对应一个线程。
3.2.2 动态线条分辨率控制
我们采用的另一种细节级别控制方式是决定每条线条几何结构中的控制点数量,这种方式本质上可以减少需要光栅化的线段数量。我们仍然使用之前确定的细节级别选择值L(即公式(2)中的值),并参照Bhokare的方法[Bhokare等人2025,公式9],计算每束线条的控制点数量,公式为Craw=max(?L?Cmax?,Clayers),其中Cmax=127是控制点的最大数量,Clayers则是该束线条的层数(这是一个固定的下限)。我们使用L而非其他值,是为了在中间距离处更好地保持曲率。为确保顶点细节级别之间的过渡平滑,我们会将Craw调整为2的幂加1的形式,最终的控制点数量则为C=min(2?log2?(Craw?1)?+1,Cmax),前提是Craw≥3。这一计算同样在处理线条数量计算的同一阶段完成,每个束仍由一个线程负责。最终的计算结果会被存储在GPU缓冲区中,与(间接)调度计数一起存储(每个束对应一个uint4格式的数值),这些数据会被软件光栅化引擎使用。结合公式(1)中的每束线条随机偏移量δ,这种偏移量可用于让不同束之间的线条数量变化错开时间,而上述的调整规则则能确保在常规观看速度下,几何细节级别的切换不会出现在亚像素级别;在我们的测试序列中并未观察到明显的突兀变化现象。
图4
由于细节级别控制导致的线条裁剪而产生的阴影瑕疵。采用随机移除线条的方式可能会导致阴影或深度不透明度图谱出现不一致,进而在使用细节级别控制时产生阴影瑕疵。当深度图是基于完整的线条结构计算的,但最前面的线条(S1)被随机移除后,阴影区域就会变得“过时”。这样一来,剩余的线条(S2)就会错误地采样到发型内部高不透明度区域(见问题部分),从而导致不自然的变暗效果和视觉上的突兀感(见朴素处理方式)。通过根据被移除线条的比例将所有线条向靠近摄像机的方向移动,就可以解决这个问题(见深度校正方式)。
3.2.3 深度比较瑕疵修复
移除线条的一个重要问题是,之前计算好的深度图会失效(重新计算深度图成本很高,而我们希望避免这种情况)。在处理阴影图或不透明度图时,这一问题尤为明显(见图4的问题部分):如果在发型的边缘随机移除一条线条,可能会导致内部的线条变得可见,但其深度值仍然低于存储的深度值。在阴影图中,这就会导致出现暗色区域(见图4的朴素处理方式)。为解决这一问题,我们会在深度测试期间,将内部的线条向摄像机方向移动一个小偏移量Δ,该偏移量的大小取决于线条到摄像机的距离以及剩余线条的比例。
为确定这个偏移量Δ,我们采用了比尔-朗伯定律,并从统计角度考虑整体可见性,公式为V(d)=exp?(?σ?d),其中σ与线条密度成正比。当随机移除部分线条后,只有β=Nremaining/Ntotal比例的线条保留下来,因此线条密度变为σ·β,可见性则变为V′(d)=exp?(?(σ?β)?d)=exp?(?σ?(β?d))。由此可见,减少线条数量相当于让物体所处的有效深度deff = rd减小。要将这种补偿表示为深度空间中的叠加位移,我们需要对指数函数取反,从而得到偏移量Δ=?log?(β)=?log?(NremainingNtotal)。(8)当没有进行剔除操作时(β = 1),该位移为Δ = 0;而随着被移除的线条数量增加(β↓0),该位移也会逐渐增大。3.3 抗锯齿与透明度重建为了降低帧渲染时间,通过原子操作可写入的像素数量极为有限(每个像素仅有64位,其中24位用于存储深度信息),这导致在高分辨率渲染中每个像素只能进行一次采样。这样一来就会产生严重的锯齿现象以及断裂的线条,因为只有穿过像素中心采样点的线条才会被纳入考虑范围(见图5,MSAA 1)。而采用保守的光栅化方法则会导致线条变粗,尤其是对于那些孤立的线条而言(见图5,保守光栅化)。我们采用了黄等人[2025]提出的方法作为灵感来源。不过,他们是通过多遍处理的方式来解决这些问题,其中包括依赖每条线条索引的显式连接步骤,而鉴于我们的帧缓冲区容量有限,无法实现这一做法。因此,我们的解决方案为每个像素存储两层数据:一层是中心采样层,仅记录穿过像素中心的线条;另一层是保守层,记录与像素相交的所有线条的原子最小G缓冲区值。这两层数据共同为过滤算法提供了足够的线条连接信息,从而无需像黄等人[2025]所提出的那样进行显式连接处理。此外,我们还通过为软件光栅化器支持多采样功能来扩展这一方法,即将采样结果存储在uint64格式图像的多个层次中,之后再对其进行处理(见图5,MSAA 8)。不过,由于其在内存和计算成本方面的局限性,我们仅将此方法作为参考。3.3.1 椭圆双边滤波器我们采用类似黄等人[2025]的方法,使用具有方向感知能力的双边滤波器来对中心采样帧缓冲区进行去噪处理。该滤波器的作用范围是一个半径为r = 5的正方形区域(即一个(2r + 1) × (2r + 1)大小的核函数)。对于中心像素P周围偏移量为d的每个相邻像素Q,其位移会被分解为切向分量与法向分量,计算公式为d=Q?P,d∥=d?TP,d⊥=‖d?d∥TP‖。(9)双边权重[黄等人2025,方程11]是由椭圆空间项与颜色相似度项相乘得到的,具体表达式为wPQ=exp?(?d∥2σ∥2?d⊥2σ⊥2)?wspatial?exp?(?‖CP?CQ‖2σc2)?wcolor,(10)其中σ∥ = r · s∥和σ⊥ = r · s⊥是可配置的主轴与次轴标准差,而σc则是颜色相似度标准差(我们将其设定为σc = 0.9)。那些深度与P相差超过1.45 × 10? 3阈值的相邻像素会在加权之前被排除在外。经过滤波后的颜色C^P即为核函数卷积的结果,计算公式为C^P=∑QCQ?wPQ∑QwPQ。图5所示。该滤波器接收两个输入信号:一个是MSAA等级为1时的中心命中渲染结果,另一个是保守渲染结果,后者会记录下所有与线条有接触的像素,无论这些像素是否处于中心命中区域,其主要作用是提供空间参考。这两个输入信号会进入一个两阶段处理流程:首先是重新连接阶段,该阶段通过从附近的中心命中像素处获取阴影信息,来提升那些孤立线条像素的质量;其次是方向性模糊处理,该阶段则沿着线条的切线方向对图像进行平滑处理。这两个阶段都在一个7 × 7大小的核函数处理过程中完成。最终得到的效果在质量上与高采样率的参考结果相当,但所需成本却要低得多。3.3.2 线条连接那些出现在保守帧缓冲区中,但在中心采样帧缓冲区中却没有对应采样数据的像素会被提升处理:它们会从附近的中心命中像素处获取阴影信息。由于保守光栅化层已经记录下了所有与像素有接触的线条,因此这种提升机制无需像黄等人[2025]所提出的那样进行显式连接处理,就能实现视觉上断裂的线条段之间的重新连接。当在保守光栅化层中存在位于中心命中线条前方且深度差异大于5 × 10? 4的更靠近的线条时,重建结果会叠加在现有的中心命中帧缓冲区之上。对于那些经过提升处理的像素,其颜色相似度项会被关闭(wcolor = 1),因为这类像素没有可用于比较的着色颜色。3.3.3 阿尔法值估算每个像素的透明度是通过比较中心采样帧缓冲区中的命中次数与沿切线方向、宽度为wstrip(我们选择的是0.5像素)的带状区域内的保守帧缓冲区中的命中次数来确定的,该带状区域的长度由双边滤波器的核函数直径决定。在这个带状区域内,我们会统计中心命中次数Hcenter与保守帧缓冲区中的命中像素数Hcons,进而根据公式αP=HcenterHcons来估算像素P的透明度。对于那些在中心采样中有命中记录,但在保守层中存在深度差异的像素,其输出透明度为1,因为此时已经发生了混合处理(这对于位于修剪区域前方的、深度分离的线条尤为重要);否则,其透明度则等于αP(详细简化版本见2节)。3.4 着色模型图6展示了预烘焙环境光遮蔽效果的不同表现。这两幅图像都是使用我们的软件光栅化器,在不应用(a)和应用(b)预烘焙环境光遮蔽的情况下,结合LOD技术与重建滤波器(SWR 1+F+L)进行渲染的。环境光遮蔽功能可以通过加深头皮附近以及密集线条簇周围的遮蔽区域,从而为头发模型增添深度与立体感。如3.1节所述,我们将着色处理工作推迟到第二步进行,即在屏幕空间内,利用存储在G缓冲区中的信息来执行着色操作。我们采用的着色模型是基于物理原理的,类似于Pekelis等人[2015]提出的模型,不过我们是根据Chiang的[Chiang等人2016]模型而非Marschner的模型来进行参数调整的。我们通过查询存储在G缓冲区中的uvw坐标来获取每个像素对应的模型参数。点光源的渲染我们是通过直接应用着色模型,再加上类似Kajiya-Kay[1989]提出的朗伯项,以此来模拟多次散射带来的影响。体积阴影则是通过深度透明度图[Yuksel和Keyser 2008]来计算的,我们则利用3.2节中介绍的深度校正方法来获取这些数据。探针照明与预烘焙环境光遮蔽对于基于探针的照明方式,我们采用的标准方法是利用预过滤过的环境贴图来处理镜面反射成分(即单次散射型的头发着色模型),同时运用球面谐波展开方法来处理更为漫射的反射成分(即多次散射型漫反射)。对于镜面反射成分,我们用单个GGX叶片来近似表示R叶片与TRT叶片,进而利用它来查询预过滤后的探针数据。至于漫反射部分,我们则直接采用Ramamoorthi[Ramamoorthi和Hanrahan 2002]提出的以朝向观察方向的纤维法线为基准的辐照度展开方法。这种方法虽然会带来一定的视角依赖效应,但却能够比基于切线的投影方法更好地处理来自不同方向的入射光线[Mehta等人2012]。提升探针着色质量的关键在于我们所采用的预烘焙遮蔽技术。在处理头发模型的场景时,基于屏幕空间的方法[Jiménez等人2016]可能无法达到理想效果,因为这类方法假设的是表面结构,而非类似体积效果的资产。为此,我们充分利用了头发网格的结构特点,预先在头发网格代理模型的每个顶点处烘焙出环境光遮蔽值。这些值在生成线条的过程中会以与位置或切线数据相同的方式被插值处理,随后被 raster化为G缓冲区中的数据,这一过程的效率非常高。图6展示了应用这种预烘焙环境光遮蔽效果后的画面差异。4 实验结果我们在配备NVIDIA RTX 5080显卡(SG大小为32)的系统中,以1920 × 1080的分辨率,使用包含127k条线条的头发模型来测试我们的方法。图7与表1分别展示了在三种不同拍摄距离下——近距、中距和远距——针对两种不同发型模型,所有管线配置下的渲染质量以及GPU的帧渲染时间。我们将自己的延迟式软件光栅化器与Bhokare等人[2025]提出的基于网格着色器的方案进行了对比,同时还考察了是否应用我们提出的LOD技术以及是否采用预烘焙环境光遮蔽功能的效果。在图1中,我们使用了高频环境贴图以及三个点光源来渲染场景;而在图7中,则仅使用了三个点光源。质量方面,在较低采样率下渲染头发模型时,会出现严重的锯齿现象:由于单个线条的宽度小于一个像素,且其子像素覆盖范围会随着拍摄距离的变化而迅速改变,从而导致画面出现闪烁现象,细节信息也会丢失。在MSAA等级为1的情况下,这种现象尤为严重,如图7所示,无论在何种距离下,都会出现严重的线条缺失与碎片化问题。我们的重建滤波器(SWR 1+F)通过整合相邻像素的覆盖信息,有效解决了这一问题,使得渲染出的线条细节水平可与MSAA等级为4至8时的效果相媲美,同时还能保持接近MSAA等级2时的性能表现。再结合LOD技术(SWR 1+F+L,以黄色标出),则能在不影响上述质量的前提下进一步降低远距场景下的计算成本,因此这是我们推荐的配置方案。根据发型的不同,或许还需要调整LOD参数λ,或是修改滤波器中的σ⊥、σ∥参数以及核函数半径。总体而言,我们并未发现有任何情况下该滤波器完全不起作用的情况。性能方面,表1显示,无论在何种拍摄距离或MSAA等级下,我们的软件光栅化器都能展现出优于基于网格着色器方案的性能。在未应用LOD技术的MSAA等级1条件下,软件光栅化器的渲染时间为3.1毫秒,而基于网格着色器的方案则需要13.6毫秒,前者相比后者快了4.4倍。重建滤波器确实会增加一定的计算开销,不过在远距场景下,由于保守层中存在大量的原子操作竞争,会导致渲染时间上升至4.5毫秒(以橙色标出)。为了解决这个问题,我们可以采用引入LOD技术,或者是在远距场景下关闭线条连接处理环节。在整个渲染过程中,计算成本主要集中在线条生成与软件光栅化阶段,即便在需要复杂着色处理的场景中,这一阶段的成本也占据了总计算成本的96%左右,而得益于延迟式着色技术,复杂着色本身的计算成本则非常低。同样,滤波处理带来的计算开销也可忽略不计。LOD技术则在远距场景下能带来最大的性能提升,因为在该距离下,所需的线条数量会从127k减少到21k。对于采用滤波器的软件光栅化器(即我们推荐的配置),其远距渲染时间可从4.5毫秒降至0.4毫秒,降幅达到了11倍;而在近距与中距场景下,其性能则分别提升了12%和28%。相比之下,基于网格着色器的LOD版本在近距与中距场景下的性能反而低于未应用LOD版本的方案(以红色标出)。出现这种反常现象的根本原因在于任务着色器模型存在固有的限制:任务着色器只能以整个工作组的粒度来启动网格着色器任务。而我们的计算预处理阶段则是以每个线程为单位来执行相关操作的——每个线程对应着一组线条——之后再将处理结果传递给间接调度系统,由于具备了更好的并行处理能力,这一过程的计算成本几乎可以忽略不计。而且,在任何拍摄距离下,LOD技术都能带来明显的性能提升。用于确定LOD值的预处理阶段虽然只会增加很小的计算成本(约为总渲染时间的3%),但它却能显著加快线条生成与软件光栅化阶段的处理速度。多个发型模型我们的管线能够轻松处理包含多个发型模型的场景。每个发型模型都会依次经过相同的光栅化与滤波处理流程,处理完成后其结果会被混合到渲染目标中,之后才会处理下一个发型模型。这样一来,即便需要组合大量发型模型,也无需对核心管线进行任何修改。由于在处理不同发型模型之间会保留深度缓冲区,那些被先前处理的发型模型所遮挡的线条会被提前排除,从而减少原子操作带来的竞争,进一步提升整体性能。图1展示的就是以这种方式渲染的包含多个发型模型的场景。表1. 发型模型1发型模型2光栅化器滤波器MSAA近距中距远距近距中距远距软件光栅化器 – 计算13.08(2.68)2.35(2.17)1.81(1.76)3.40(2.87)2.74(2.50)2.40(2.33)?13.72(2.89)2.70(2.37)4.50(4.38)4.23(3.03)3.00(2.60)4.23(4.09)24.10(3.37)2.84(2.56)2.03(1.94)4.37(3.41)3.12(2.76)2.58(2.47)45.97(4.61)3.68(3.21)2.37(2.21)6.24(4.45)3.96(3.33)2.87(2.68)88.27(5.67)4.71(3.77)2.77(2.44)9.10(5.61)4.95(3.85)3.18(2.84)软件光栅化器 – 计算 + LOD12.73(2.30)1.69(1.49)0.25(0.18)3.07(2.52)2.24(1.95)0.35(0.27)?13.35(2.48)1.94(1.56)0.36(0.22)3.79(2.59)2.40(1.97)0.45(0.30)23.73(2.99)2.15(1.81)0.29(0.19)4.08(3.08)2.55(2.17)0.49(0.34)45.54(4.16)2.87(2.36)0.42(0.22)5.95(4.14)3.27(2.65)0.52(0.32)87.71(5.08)3.69(2.78)0.62(0.25)8.56(5.06)4.17(3.03)0.76(0.36)硬件光栅化器 – 网格着色器113.5810.589.6615.0711.2410.55216.4212.149.7518.4712.8310.67419.8014.1510.1422.3614.9211.12823.1416.4710.7626.3818.4412.39硬件光栅化器 – 网格着色器 + LOD119.4513.312.2820.4715.103.02223.1216.542.4025.4919.513.15426.1818.512.6828.6021.193.57828.4020.343.1632.0023.704.60在1920 × 1080分辨率的RTX 5080显卡上进行的GPU帧渲染时间测试结果(单位:毫秒)。括号内的数值为单纯的线条光栅化处理时间。MSAA一列表示每像素的采样数量。红色文字表示由于剔除处理带来的额外开销,导致网格着色器的渲染时间增加。橙色文字则表示由于滤波层中的原子操作竞争而导致的性能下降。以黄色标出的行代表我们获得的最佳性能与质量比。图7. 不同拍摄距离下的渲染质量对比。SWR表示软件光栅化器,F表示重建滤波器,L表示LOD技术,1、2、4、8分别代表不同的MSAA采样数量。放大后的局部视图显示的是当前视角下的中心区域画面。发型模型1的λ值为3.0,而发型模型2的λ值为7.0。5 讨论兼容性方面,我们的解决方案仅依赖于那些被广泛支持的硬件功能,因此能够应用于各种不同的设备上。具体而言,它需要具备支持间接调度的计算着色器功能(自Vulkan 1.0版本起便已支持),同时还需支持64位整数的原子最小值操作。从Vulkan 1.2版本开始,这类原子操作即可被直接支持;在更早版本的系统中,则可以通过相应的扩展功能来实现这些操作。对于那些不支持对图像进行原子操作的设备,我们可以采用基于缓冲区的替代方案。需要说明的是,在整篇论文中,我们统一使用“图像”这一术语,以便与那些与帧缓冲区无关的资源相区分。交互式更新方面,由于继承了头发网格的技术优势,我们只需极少的存储空间,就能实现多种不同的发型效果。此外,头发网格拓扑结构与造型功能都可以实时高效地进行调整,从而实现包括动画和高效物理模拟在内的交互式工作流程。我们的方法非常适合多视图渲染场景,尤其是虚拟现实应用。头发丝的组装只需进行一次,而投影则针对每个视图分别执行。另外,在向多个目标进行渲染时,延迟着色与过滤的计算成本相比光栅化计算成本要低,这使得立体图和多视图输出能够在极低的计算开销下实现。5.1 局限性与未来工作虽然所提出的软件光栅化器在远场渲染方面表现出高性能,但在近场渲染时效率较低,尤其是当头发丝的投影范围超过单个像素时。采用一种混合方案,即对远处的头发使用软件光栅化,而对近距离的头发丝使用硬件光栅化,或许可以解决这一局限。此外,尽管头发丝组装步骤能够很好地分配任务给各个线程,但在进行DDA光栅化时,当线程需要绘制长度不等的线条时会出现任务分配不均的情况。增加控制点的数量可以缓解这一问题,但更均衡的任务分配方案将进一步提升资源利用率。同样地,当控制点数量显著低于GPU子组规模时,让每个工作组处理多根头发丝可能会提高SIMD运算单元的利用效率。最后,还有提升过滤质量与性能的空间,尤其是通过引入时间过滤技术来减少摄像机移动时的闪烁现象。致谢我们想感谢Olivier Maury在本项目期间给予的持续支持。Lukas Lipp和Michael Wimmer则得到了奥地利科学基金(FWF,资助编号F77)的支持。
生物通微信公众号
生物通新浪微博
今日动态 |
人才市场 |
新技术专栏 |
中国科学人 |
云展台 |
BioHot |
云讲堂直播 |
会展中心 |
特价专栏 |
技术快讯 |
免费试用
版权所有 生物通
Copyright© eBiotrade.com, All Rights Reserved
联系信箱:
粤ICP备09063491号