马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
【Unity Shader Graph 使用与特效实现】专栏-直达
视差遮挡贴图(Parallax Occlusion Mapping,简称POM)是计算机图形学中一种紧张的技能,用于在不增加多少复杂度的前提下为表面增加深度感和细节。在Unity URP的Shader Graph中,Parallax Occlusion Mapping节点提供了一个直观的方式来创建这种结果,让开辟者能够通过简单的节点连接实现高质量的视觉体现。
视差结果基于人类视觉感知原理,当观察者移动时,靠近的物体相对于远处的物体会出现更显着的位移。POM技能正是模拟了这种现象,通过对纹理坐标进行智能偏移,创造出表面凹凸不平的错觉。与传统的法线贴图相比,POM能够提供更加真实的深度感和自遮挡结果,特别是在视角较陡的环境下。
描述
Parallax Occlusion Mapping节点是Shader Graph中用于实现高级视差结果的核心组件。该节点通过处理输入的高度贴图信息,计算出适当的UV偏移和深度偏移,从而在材质表面产生立体感和深度错觉。
视差遮挡贴图的工作原理是基于光线追踪的概念。当光线(视线)与表面相交时,体系会根据高度贴图中的信息模拟光线在凹凸表面上的行进路径。通过多步采样和插值计算,找到光线与表面多少的精确交点,进而确定应该显示哪个纹理位置的像素。
在Shader Graph中使用Parallax Occlusion Mapping节点时,必要注意版本兼容性问题。假如在包含自界说函数节点或子图形的图形中使用此节点时遇到纹理采样错误,可以通过升级到Unity 10.3或更高版本来解决这些问题。这是因为早期版本在处理复杂节点连接时大概存在一些限制和bug。
一个常见的技能要点是:当将雷同的Texture2D分配给POM节点和Sample Texture 2D节点时,必要避免UV坐标被转换两次。这种环境会导致纹理采样不精确,产生意外的视觉结果。为解决这个问题,开辟者可以使用Split Texture Transform节点的Texture Only端口连接到Sample Texture 2D节点的UV端口,确保UV坐标只被精确处理一次。
Parallax Occlusion Mapping技能特别适用于必要高细节体现但受限于性能的场景,比如:
- 游戏中的墙面、地面材质
- 复杂表面的科学可视化
- 修建可视化中的材质细节
- 虚拟现实环境中的高沉浸感场景
端口
Parallax Occlusion Mapping节点包含多个输入和输出端口,每个端口都有特定的功能和用途。理解这些端口的作用对于精确使用该节点至关紧张。
输入端口
输入端口决定了POM结果的具体体现和行为。每个输入端口都接受特定类型的数据,并影响最终的视觉结果。
- Heightmap:这是POM结果的核心输入,接受一个Texture2D类型的高度贴图。高度贴图通常是一张灰度图像,其中白色代表高点,黑色代表低点。高度贴图的质量直接决定了POM结果的精细程度和真实感。建议使用高分辨率、无压缩的高度贴图以获得最佳结果。
- Heightmap Sampler:此端口界说如何对高度贴图进行采样,接受Sampler State类型。采样器状态控制着纹理的过滤方式和寻址模式,如点过滤、双线性过滤或三线性过滤。精确的采样器设置可以避免视觉瑕疵,特别是在低角度观察时。
- Amplitude:浮点型输入,控制高度贴图应用的强度,单位为厘米。这个参数决定了表面凹凸的显着程度。较高的值会产生更猛烈的深度感,但大概在某些视角下出现失真;较低的值则产生更微妙的结果。通常必要根据场景标准和观察距离来调整此参数。
- Steps:浮点型输入,界说算法线性搜索执行的步调数。步数越多,结果越精确,但性能开销也越大。在实际应用中,必要在质量和性能之间找到平衡。通常8-16步对于大多数应用已经足够,但对于极端角度或必要高质量结果的环境,大概必要24步或更多。
- UVs:Vector 2类型输入,指定采样器用来采样纹理的UV坐标。这是底子的纹理坐标输入,通常来自模子的默认UV或经过其他节点处理后的UV坐标。
- Tiling:Vector 2类型输入,控制纹理在UV空间中的重复次数。这个参数允许在不修改原始网格UV的环境下调整纹理密度,对于创建无缝重复的材质模式非常有用。
- Offset:Vector 2类型输入,对输入UV应用偏移量。这个参数可以用于动画结果或动态调整纹理位置。
- Primitive Size:Vector 2类型输入,界说对象空间中UV空间的大小。例如,Unity内置的平面网格的原始大小为(10,10)。这个参数对于确保差别尺寸的模子上POM结果的一致性非常紧张。
- Lod:浮点型输入,指定用于采样高度贴图的细节级别。该值应始终为正值,较高的值表示使用更模糊的mip级别。Lod控制可以资助在远处减少POM结果的细节,优化性能。
- Lod Threshold:浮点型输入,界说POM结果开始淡出的高度贴图Mip级别。这等效于高清渲染管线(HDRP)光照材质中的Fading Mip Level Start属性。这个参数可以平滑地过渡到远处的平面纹理,避免远处出现视觉瑕疵。
输出端口
输出端口提供了POM处理后的结果,可以连接到其他节点或主节点的相应输入。
- Pixel Depth Offset:浮点型输出,表示应用于深度缓冲区的偏移量,用于产生深度感。这个输出对于实现精确的深度交互结果至关紧张。要启用依赖深度缓冲区的结果,例如阴影和屏幕空间环境光遮挡,必要将此输出连接到主节点上的Depth Offset输入。这样确保了POM表面的凹凸能够精确地投射和接收阴影。
- Parallax UVs:Vector 2类型输出,表示添加视差偏移后的UV坐标。这些修改后的UV应该用于采样颜色贴图、法线贴图和其他表面属性贴图,以确保全部纹理都与POM结果保持一致。使用原始UV采样其他纹理会导致纹理与多少不匹配,破坏视觉一致性。
生成的代码示例
理解Parallax Occlusion Mapping节点背后生成的代码对于高级使用和调试非常有资助。以下示例代码表示此节点的一种大概结果,并解释了关键部分的功能。- // 计算视图方向并调整对象尺度
- float3 ParallaxOcclusionMapping_ViewDir = IN.TangentSpaceViewDirection * GetDisplacementObjectScale().xzy;
- // 计算视图方向与表面法线的点积
- float ParallaxOcclusionMapping_NdotV = ParallaxOcclusionMapping_ViewDir.z;
- // 计算最大高度值,将振幅从厘米转换为适当的尺度
- float ParallaxOcclusionMapping_MaxHeight = Amplitude * 0.01;
- // 根据平铺值调整最大高度
- ParallaxOcclusionMapping_MaxHeight *= 2.0 / ( abs(Tiling.x) + abs(Tiling.y) );
- // 计算UV空间中的尺度因子
- float2 ParallaxOcclusionMapping_UVSpaceScale = ParallaxOcclusionMapping_MaxHeight * Tiling / PrimitiveSize;
- // 将视图向量转换到UV空间
- float3 ParallaxOcclusionMapping_ViewDirUV = normalize(float3(ParallaxOcclusionMapping_ViewDir.xy * ParallaxOcclusionMapping_UVSpaceScale, ParallaxOcclusionMapping_ViewDir.z));
- // 设置POM参数结构
- PerPixelHeightDisplacementParam ParallaxOcclusionMapping_POM;
- ParallaxOcclusionMapping_POM.uv = UVs.xy;
- // 输出高度变量
- float ParallaxOcclusionMapping_OutHeight;
- // 执行主要的POM计算,得到视差调整后的UV
- float2 _ParallaxOcclusionMapping_ParallaxUVs = UVs.xy + ParallaxOcclusionMapping(Lod, Lod_Threshold, Steps, ParallaxOcclusionMapping_ViewDirUV, ParallaxOcclusionMapping_POM, ParallaxOcclusionMapping_OutHeight);
- // 计算像素深度偏移
- float _ParallaxOcclusionMapping_PixelDepthOffset = (ParallaxOcclusionMapping_MaxHeight - ParallaxOcclusionMapping_OutHeight * ParallaxOcclusionMapping_MaxHeight) / max(ParallaxOcclusionMapping_NdotV, 0.0001);
复制代码 这段生成的代码展现了POM技能的内部工作机制:
- 视图方向转换:代码首先将观察方向转换到切线空间,这是处理表面相对方向的标准方法。切线空间允许算法独立于模子的实际朝向工作。
- 高度计算:通过振幅参数计算最大高度值,并进行适当的单位转换和标准调整。这一步确保高度值与场景的其他部分保持比例一致。
- UV空间变换:将视图向量转换到UV空间,这是POM算法的核心部分。这种转换使得算法能够在纹理坐标空间中模拟光线行进。
- POM函数调用:实际的视差遮挡映射计算发生在ParallaxOcclusionMapping函数中。这个函数执行多步光线行进,通过高度贴图找到视线与表面的交点。
- 深度偏移计算:最后,根据计算出的高度值和视图方向计算像素深度偏移。这个值用于修改深度缓冲区,确保POM表面能够精确地与场景中的其他多少体交互。
理解这段代码有助于开辟者更好地调试POM结果,特别是在遇到视觉异常或性能问题时。例如,假如POM结果在某些角度出现断裂,大概是Steps参数过低;假如深度结果不显着,大概是Amplitude值必要调整。
实际应用示例
为了更好地理解Parallax Occlusion Mapping节点的使用,以下是一个完整的应用示例,展示如何创建一个具有深度感的砖墙材质。
首先,必要准备以下纹理资源:
- 颜色贴图:砖墙的漫反射颜色
- 法线贴图:砖墙的表面方向信息
- 高度贴图:砖缝和砖块的高度变化
- 粗糙度贴图:砖墙的光泽度变化
在Shader Graph中创建新图形,并按照以下步调连接节点:
- 添加Parallax Occlusion Mapping节点到画布
- 将高度贴图连接到Heightmap输入
- 设置适当的Amplitude值(例如0.5,根据实际标准调整)
- 设置Steps值为16,平衡质量和性能
- 将模子的UV0输出连接到UVs输入
- 设置适当的Tiling值,如(2,2)使纹理重复两次
- 根据模子尺寸设置Primitive Size(平面模子通常为(10,10))
- 将Parallax UVs输出连接到颜色贴图、法线贴图和粗糙度贴图的Sample Texture 2D节点的UV输入
- 将Pixel Depth Offset输出连接到主节点的Depth Offset输入
通过这样的设置,当摄像机在砖墙前移动时,砖缝会出现适当的视差位移,产生真实的深度感。砖块似乎从表面凸出,而砖缝则凹陷进去,即使实际多少体是完全平坦的。
性能考虑和最佳实践
使用Parallax Occlusion Mapping时,性能是一个紧张考虑因素。以下是一些优化建议:
- 步调数优化:Steps参数对性能影响最大。在远处或小表面上使用较少的步数,可以通过根据距离动态调整Steps值来实现。
- 纹理压缩:使用适当压缩的高度贴图可以减少内存带宽使用。对于高度贴图,通常建议使用BC5(DXTC_RG)格式存储高度数据。
- LOD过渡:合理设置Lod Threshold,确保在远处平滑过渡到平面着色,避免突然的视觉变化。
- 振幅比例:根据场景标准设置适当的Amplitude值。过高的值会导致不自然的变形和性能问题。
- 视锥裁剪:确保POM结果只在必要时计算,通过适当的视锥裁剪和遮挡剔除来避免不可见表面的计算。
【Unity Shader Graph 使用与特效实现】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)
|