找回密码
 立即注册
首页 业界区 业界 【光照】UnityURP中的[HDR贴图]

【光照】UnityURP中的[HDR贴图]

羊夏菡 6 小时前
【从UnityURP开始探索游戏渲染】专栏-直达
HDR贴图的概念与特性

HDR(高动态范围)贴图是Unity URP中用于存储超出标准0-1范围光照信息的特殊纹理格式。与普通LDR(低动态范围)贴图相比,HDR贴图能够存储更广范围的亮度值,通常使用16位或32位浮点精度而非8位整数精度。
HDR贴图主要分为两类:


  • HDR环境贴图‌:用于天空盒和环境光照,通常采用.hdr或.exr格式
  • HDR光照贴图‌:用于烘焙光照信息,存储间接光照数据
HDR贴图解决的问题

亮度范围限制‌:


  • 传统LDR贴图只能表示0-1范围的亮度值,无法准确表现真实世界的光照强度(如阳光直射可能达到100,000尼特)。
细节丢失‌:


  • LDR在高亮区域会产生过曝,丢失细节;在暗部则会产生噪点和色带。
光照计算精度‌:


  • HDR贴图提供更高精度的光照数据,使后期处理(如Bloom、色调映射)效果更自然。
URP中HDR贴图的具体使用

导入HDR环境贴图
  1. csharp
  2. // 通过代码加载HDR贴图
  3. public class HDRLoader : MonoBehaviour {
  4.     public Texture2D hdrTexture;
  5.     void Start() {
  6. // 设置HDR贴图为天空盒
  7.         RenderSettings.skybox.SetTexture("_MainTex", hdrTexture);
  8.     }
  9. }
复制代码
配置HDR天空盒


  • 下载HDR贴图(推荐HDRI Hub等资源网站)
  • 导入Unity项目,确保纹理导入设置中"Texture Shape"设为Cube
  • 创建材质,选择Shader > Skybox > Cubemap
  • 将HDR贴图拖入材质
  • 在Lighting窗口中将材质指定为天空盒
烘焙HDR光照贴图


  • 确保场景物体:

    • 具有Mesh Renderer组件
    • 标记为Contribute GI
    • 启用了Generate Lightmap UVs

  • 在Lighting窗口调整Lightmap Resolution和Scale In Lightmap参数
  • 关闭自动烘焙,手动执行烘焙以获得最佳效果
HDR贴图的高级应用

Light Cookies‌:


  • 使用HDR贴图作为2D遮罩或立方体贴图,控制光源形状和衰减
  • HDR贴图作为Light Cookies可以精确控制光源的形状和衰减特性,相比普通LDR贴图能够表现更广范围的亮度值,特别适合模拟高亮度光源效果如聚光灯、霓虹灯等。URP中支持两种形式的Cookies:

    • 2D平面贴图‌:主要用于聚光灯(Spot Light)
    • 立方体贴图‌:主要用于点光源(Point Light)

2D HDR Cookie实现过程


  • 准备HDR贴图
    1. csharp
    2. // 创建HDR纹理
    3. Texture2D hdrCookie = new Texture2D(512, 512, TextureFormat.RGBAHalf, true);
    4. hdrCookie.wrapMode = TextureWrapMode.Clamp;
    5. hdrCookie.filterMode = FilterMode.Bilinear;
    复制代码
  • 应用到聚光灯
    1. csharp
    2. public class SpotLightCookieSetter : MonoBehaviour {
    3.     public Texture2D hdrCookieTexture;
    4.     public Light spotLight;
    5.     void Start() {
    6.         if(spotLight.type == LightType.Spot) {
    7.             spotLight.cookie = hdrCookieTexture;
    8.             spotLight.cookieSize = 10f;// 控制Cookie影响范围
    9.         }
    10.     }
    11. }
    复制代码
  • 材质设置
    在URP中需要确保材质使用支持HDR的Shader,如Universal Render Pipeline/Lit。
立方体HDR Cookie实现过程


  • 创建HDR立方体贴图
  1. csharp
  2. // 通过代码生成HDR立方体贴图
  3. public Cubemap CreateHDRCubemap(int size) {
  4.     Cubemap hdrCubemap = new Cubemap(size, TextureFormat.RGBAHalf, true);
  5. // 填充各面数据...return hdrCubemap;
  6. }
复制代码

  • 应用到点光源
  1. csharp
  2. public class PointLightCookieSetter : MonoBehaviour {
  3.     public Cubemap hdrCubemap;
  4.     public Light pointLight;
  5.     void Start() {
  6.         if(pointLight.type == LightType.Point) {
  7.             pointLight.cookie = hdrCubemap;
  8.         }
  9.     }
  10. }
复制代码

  • 完整示例:HDR Cookie光照场景

    • HDRCookieDemo.cs
      1. using UnityEngine;
      2. using UnityEngine.Rendering.Universal;
      3. public class HDRCookieDemo : MonoBehaviour {
      4.     public Texture2D spotCookie;
      5.     public Cubemap pointCookie;
      6.     public Light spotLight;
      7.     public Light pointLight;
      8.     void Start() {
      9.         // 设置聚光灯Cookie
      10.         spotLight.type = LightType.Spot;
      11.         spotLight.cookie = spotCookie;
      12.         spotLight.cookieSize = 8f;
      13.         // 设置点光源Cookie
      14.         pointLight.type = LightType.Point;
      15.         pointLight.cookie = pointCookie;
      16.         // 确保使用HDR
      17.         spotLight.useColorTemperature = true;
      18.         pointLight.useColorTemperature = true;
      19.     }
      20. }
      复制代码

关键参数调整


  • 亮度控制‌:HDR Cookie的亮度值可以超过1.0,实现超亮光源效果
  • 衰减调节‌:通过Cookie的边缘渐变控制光源衰减
  • 色彩范围‌:HDR支持更广的色域表现
性能优化建议


  • 合理控制HDR Cookie分辨率(通常512x512足够)
  • 对远处光源使用较低分辨率Cookie
  • 考虑使用压缩的HDR格式(如BC6H)减少内存占用
  • 动态加载和卸载HDR Cookie资源
反射探针‌:


  • 生成HDR立方体贴图用于高质量反射
  • HDR反射探针通过捕获场景环境生成高动态范围立方体贴图,为物体提供更真实的反射效果。相比传统LDR反射贴图,HDR立方体贴图能够存储更广范围的亮度值(0-65504),保留亮部和暗部细节,特别适合表现金属、玻璃等高反射材质。
  • 创建并配置反射探针
    1. csharp
    2. // 创建反射探针并设置HDR属性
    3. GameObject probeObj = new GameObject("HDR_ReflectionProbe");
    4. ReflectionProbe probe = probeObj.AddComponent<ReflectionProbe>();
    5. probe.mode = ReflectionProbeMode.Realtime;
    6. probe.hdr = true;// 启用HDR
    7. probe.resolution = 512;// 分辨率
    8. probe.shadowDistance = 50f;// 阴影距离
    9. probe.cullingMask = LayerMask.GetMask("Default");// 渲染层
    10. probe.boxProjection = true;// 启用盒投影
    复制代码
  • 烘焙HDR立方体贴图
    1. csharp
    2. // 手动触发烘焙
    3. IEnumerator BakeHDRProbe(ReflectionProbe probe) {
    4.     probe.RenderProbe();
    5.     while(probe.IsFinishedRendering(probe.GetInstanceID()) == false) {
    6.         yield return null;
    7.     }
    8.     Debug.Log("HDR Cubemap烘焙完成");
    9. }
    复制代码
  • 在Shader中采样HDR反射贴图
    1. glsl
    2. // URP Shader中采样HDR反射探针
    3. half3 SampleHDRReflection(float3 worldPos, float3 worldNormal) {
    4.     float3 reflectDir = reflect(-_WorldSpaceCameraPos.xyz, worldNormal);
    5.     half4 encodedCubemap = SAMPLE_TEXTURECUBE(unity_SpecCube0, samplerunity_SpecCube0, reflectDir);
    6.     half3 decodedColor = DecodeHDREnvironment(encodedCubemap, unity_SpecCube0_HDR);
    7.     return decodedColor;
    8. }
    复制代码
完整示例


  • HDRReflectionDemo.cs
    1. using UnityEngine;
    2. using UnityEngine.Rendering.Universal;
    3. public class HDRReflectionDemo : MonoBehaviour {
    4.     public Material reflectiveMaterial;
    5.     public Light directionalLight;
    6.     void Start() {
    7.         // 1. 创建HDR反射探针
    8.         var probeObj = new GameObject("HDR_Probe");
    9.         var probe = probeObj.AddComponent<ReflectionProbe>();
    10.         probe.size = new Vector3(20, 20, 20);
    11.         probe.hdr = true;
    12.         probe.resolution = 1024;
    13.         // 2. 设置反射材质参数
    14.         reflectiveMaterial.SetFloat("_Metallic", 1.0f);
    15.         reflectiveMaterial.SetFloat("_Smoothness", 0.95f);
    16.         // 3. 动态更新反射探针
    17.         StartCoroutine(UpdateProbe(probe));
    18.     }
    19.     IEnumerator UpdateProbe(ReflectionProbe probe) {
    20.         while(true) {
    21.             probe.RenderProbe();
    22.             while(!probe.IsFinishedRendering(probe.GetInstanceID())) {
    23.                 yield return null;
    24.             }
    25.             yield return new WaitForSeconds(1f); // 每秒更新一次
    26.         }
    27.     }
    28. }
    复制代码
关键参数优化建议


  • 分辨率选择‌:根据目标平台性能选择256-2048分辨率,移动端建议512
  • 更新频率‌:实时探针可选择"Via Scripting"模式按需更新
  • 盒投影‌:室内场景务必启用Box Projection实现距离相关反射
  • 混合距离‌:多个探针间设置Blend Distance实现平滑过渡
  • HDR解码‌:确保Shader中正确使用DecodeHDREnvironment函数处理HDR数据
性能优化


  • 对静态物体使用Baked模式探针,动态物体使用Realtime模式
  • 通过Importance属性控制多个探针的混合权重
  • 使用Time Slicing分散探针更新负载
  • 合理设置Culling Mask避免渲染不必要对象
  • 移动平台可降低HDR精度至R11G11B10格式
全局光照‌:


  • HDR贴图提供更精确的间接光照计算基础
  • 准备HDR环境贴图
    首先需要获取HDR环境贴图(.hdr或.exr格式),推荐从HDRI Hub等资源网站下载高质量的HDR天空盒贴图。导入Unity后需将纹理类型设置为"Cube"并启用HDR选项:
    1. csharp
    2. // 通过代码验证HDR贴图设置
    3. void CheckHDREnvironment(Texture2D hdrTexture) {
    4.     if(hdrTexture.format != TextureFormat.RGBAHalf) {
    5.         Debug.LogError("请使用HDR格式贴图(RGBAHalf)");
    6.     }
    7. }
    复制代码
  • 配置HDR全局光照

    • 在URP渲染管线中设置HDR环境光:
    1. csharp
    2. public class HDRGlobalIllumination : MonoBehaviour {
    3.     public Cubemap hdrCubemap;
    4.     public Material skyboxMaterial;
    5.     void Start() {
    6. // 设置HDR天空盒
    7.         RenderSettings.skybox = skyboxMaterial;
    8.         skyboxMaterial.SetTexture("_Tex", hdrCubemap);
    9. // 启用HDR全局光照
    10.         RenderSettings.ambientMode = AmbientMode.Skybox;
    11.         DynamicGI.UpdateEnvironment();
    12.     }
    13. }
    复制代码
  • 烘焙HDR光照贴图

    • 确保场景静态物体:

      • 具有Mesh Renderer组件
      • 标记为Contribute GI
      • 启用了Generate Lightmap UVs

    • 在Lighting窗口设置:
      1. csharp
      2. Lightmapping.lightingSettings.lightmapResolution = 40;// 每单位分辨率
      3. Lightmapping.lightingSettings.lightmapper = Lightmapper.ProgressiveGPU;
      4. Lightmapping.lightingSettings.filteringMode = LightmapFiltering.Advanced;
      复制代码
    • 执行烘焙:
      1. csharp
      2. Lightmapping.BakeAsync();// 异步烘焙避免卡顿
      复制代码

材质Shader适配


  • 在URP Lit Shader中增强HDR间接光采样:
    1. glsl
    2. // 在URP Shader中增加HDR间接光处理
    3. half3 SampleHDRIndirectLight(float3 worldPos, float3 normal) {
    4.     half3 indirectDiffuse = SampleSH9(normal); // 球谐光照
    5.     half4 encodedCubemap = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflect(-worldPos, normal), 0);
    6.     half3 decodedColor = DecodeHDREnvironment(encodedCubemap, unity_SpecCube0_HDR);
    7.     return indirectDiffuse * 0.5 + decodedColor * 0.5; // 混合光照
    8. }
    复制代码
实时更新策略


  • 对于动态物体,结合光照探针和反射探针:
    1. csharp
    2. public class DynamicHDRGI : MonoBehaviour {
    3.     public ReflectionProbe hdrProbe;
    4.     public LightProbeGroup lightProbes;
    5.     void Update() {
    6. // 每2秒更新一次探针
    7. if(Time.frameCount % 120 == 0) {
    8.             hdrProbe.RenderProbe();
    9.             LightProbes.Tetrahedralize();
    10.         }
    11.     }
    12. }
    复制代码
性能优化


  • 静态物体使用烘焙光照贴图,动态物体使用HDR光照探针
  • 根据距离分级使用不同分辨率的HDR贴图(近处1024,远处256)
  • 使用BC6H压缩格式减少HDR贴图内存占用
  • 通过脚本控制探针更新频率避免性能峰值
性能优化建议


  • 合理控制HDR贴图分辨率,平衡质量与性能
  • 移动平台考虑使用压缩的HDR格式(如ASTC HDR)
  • 对远处或小物体使用较低分辨率的HDR光照贴图
  • 动态加载和卸载HDR贴图以管理内存
HDR贴图是URP实现高质量渲染的重要工具,正确使用可以显著提升场景的真实感和视觉冲击力
<blockquote>
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册