【从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() {
- // 初始化代码...
- }
- }
复制代码 参数详解与用例
参数类型说明典型用例TypeEnum预设颗粒类型(Kodak200/400等)选择Agfa400模拟16mm胶片Intensity0-1颗粒可见度0.3-0.5用于复古RPG游戏Response0-1亮度响应曲线0.7使亮部颗粒减弱Texture2D自定义噪点贴图制作数字故障艺术效果操作步骤(URP 2022.1+)
- 创建Volume对象:GameObject > Volume
- 添加Film Grain覆盖:Add Override > Film Grain
- 配置参数示例:
Type = Kodak500T
Intensity = 0.4
Response = 0.65
性能优化建议
- 移动端使用Quarter分辨率
- 动态调整Intensity(剧情过场时增强)
- 禁用非必要时的Volume更新
<blockquote>
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |