【URP】Unity[后处理]胶片颗粒FilmGrain

【从UnityURP开始探索游戏渲染】专栏-直达

Film Grain的定义与作用

Film Grain是一种模拟传统摄影胶片颗粒感的后期处理效果,通过添加随机噪点纹理增强画面的艺术表现力。其核心用途包括:

  • 复古风格模拟:重现胶片摄影的颗粒质感,增强怀旧氛围
  • 画面细节强化:掩盖低分辨率纹理的瑕疵,提升视觉丰富度
  • 电影感塑造:配合色调映射、色差等效果构建电影级视觉风格

发展历史

  • 传统胶片时代‌:物理银盐颗粒形成的自然噪点
  • 数字时代初期‌:通过简单噪声算法模拟(如Perlin噪声)
  • 现代游戏引擎‌:HDRP/URP等管线集成预设化系统,支持物理准确的颗粒分布模型(如Kodak系列预设)

原理

Unity URP中的Film Grain效果通过噪声纹理叠加和亮度响应曲线实现胶片颗粒模拟.

噪声生成机制

  • 预设纹理采样‌:内置Kodak/Agfa等胶片颗粒的预烘焙LUT纹理(64x64分辨率),通过屏幕UV坐标进行双线性采样
  • 动态噪声合成‌:当选择"Custom"模式时,使用Simplex噪声算法实时生成3D噪声场,通过时间参数实现动态流动效果
  • 色彩空间转换‌:噪声值在YCoCg色彩空间进行混合,避免RGB通道直接叠加导致的色偏问题

亮度响应系统

hlsl float grainIntensity = intensity * (1 - smoothstep(0.5, 1.0, luminance)); 

该公式根据像素亮度动态调节颗粒强度,使暗部保留更多噪点(响应曲线参数控制过渡斜率)

实现示例

该Shader实现包含噪声纹理平铺、亮度自适应调节和色彩安全混合三个关键技术点

  • Filmgrain.shader

    Shader "PostProcessing/FilmGrain" {     Properties {         _GrainTex ("Noise Texture", 2D) = "white" {}         _Intensity ("Intensity", Range(0,1)) = 0.5         _Response ("Response", Range(0,1)) = 0.8     }     SubShader {         Pass {             HLSLPROGRAM             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"              TEXTURE2D(_GrainTex);             SAMPLER(sampler_GrainTex);             float _Intensity;             float _Response;              float4 Frag(Varyings input) : SV_Target {                 float2 uv = input.uv * float2(80,45); // 平铺噪声                 float3 grain = SAMPLE_TEXTURE2D(_GrainTex,sampler_GrainTex,uv).rgb;                  float luminance = Luminance(SceneColor.rgb);                 float adaptive = lerp(1.0, 1.0-luminance, _Response);                  return SceneColor * (1.0 + grain * _Intensity * adaptive);             }             ENDHLSL         }     } } 

管线集成流程

  • 渲染阶段‌:在URP的PostProcessingStack中插入FilmGrainPass,执行顺序在Tonemapping之后、FXAA之前
  • 性能优化‌:采用1/4分辨率渲染噪声纹理,通过硬件线性滤波降低带宽消耗
  • 移动端适配‌:使用ARM NEON指令集加速噪声计算,在GPU Tile-Based架构下减少内存访问次数

URP实现流程

  • FilmGrainExample.cs

    using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal;  [VolumeComponentMenu("Post-processing/Film Grain")] public class CustomFilmGrain : VolumeComponent, IPostProcessComponent {     public FilmGrainLookupParameter type = new FilmGrainLookupParameter(FilmGrainLookup.Kodak_200);     public ClampedFloatParameter intensity = new ClampedFloatParameter(0f, 0f, 1f);     public ClampedFloatParameter response = new ClampedFloatParameter(0.8f, 0f, 1f);      public bool IsActive() => intensity.value > 0f;     public bool IsTileCompatible() => false; } 
  • FilmGrainRenderer.cs

    using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal;  public class FilmGrainRenderer : ScriptableRendererFeature {     class CustomPass : ScriptableRenderPass {         // 渲染逻辑实现...     }     public override void Create() {         // 初始化代码...     } } 

参数详解与用例

参数 类型 说明 典型用例
Type Enum 预设颗粒类型(Kodak200/400等) 选择Agfa400模拟16mm胶片
Intensity 0-1 颗粒可见度 0.3-0.5用于复古RPG游戏
Response 0-1 亮度响应曲线 0.7使亮部颗粒减弱
Texture 2D 自定义噪点贴图 制作数字故障艺术效果

操作步骤(URP 2022.1+)

  • 创建Volume对象:GameObject > Volume

  • 添加Film Grain覆盖:Add Override > Film Grain

  • 配置参数示例:

    Type = Kodak500T
    Intensity = 0.4
    Response = 0.65

性能优化建议

  • 移动端使用Quarter分辨率
  • 动态调整Intensity(剧情过场时增强)
  • 禁用非必要时的Volume更新

【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

发表评论

评论已关闭。

相关文章