博客 / 詳情

返回

【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開始探索遊戲渲染】專欄-直達
(歡迎點贊留言探討,更多人加入進來能更加完善這個探索的過程,🙏)
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.