跳到主要內容

URP + Gamma

 新增 GammaCorrectionFeature 用於 URP pipeline


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class GammaCorrectionFeature : ScriptableRendererFeature
{
    public static GammaCorrectionFeature Instance { get; private set; }

    [System.Serializable]
    public class Settings
    {
        [Range(-0.1f, 5.0f)]
        public float gamma = 1.0f;
        public Shader gammaShader = null;
        [Tooltip("0 = 標準Gamma校正, 1 = 對比度風格調整")]
        [Range(0, 1)]
        public float gammaMode = 0f;
        public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
    }

    public Settings settings = new Settings();
    GammaCorrectionPass gammaPass;

    public override void Create()
    {
        Instance = this;

        gammaPass = new GammaCorrectionPass(settings);
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if (settings.gammaShader == null)
        {
            Debug.LogWarning("GammaCorrectionFeature: Gamma Shader is null!");
            return;
        }

        // 不要在這裡設定target,在Execute中處理
        renderer.EnqueuePass(gammaPass);
    }
}

public class GammaCorrectionPass : ScriptableRenderPass
{
    private Material gammaMaterial;
    private GammaCorrectionFeature.Settings settings;
    private RTHandle tempColorTarget;

    const string commandBufferName = "Gamma Correction Pass";

    public GammaCorrectionPass(GammaCorrectionFeature.Settings settings)
    {
        this.settings = settings;
        renderPassEvent = settings.renderPassEvent;

        if (settings.gammaShader != null)
        {
            gammaMaterial = new Material(settings.gammaShader);
        }
    }

    public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    {
        RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
        descriptor.msaaSamples = 1;
        descriptor.depthBufferBits = 0;
        
        RenderingUtils.ReAllocateIfNeeded(ref tempColorTarget, descriptor, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_TempColorTarget");
    }

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        if (gammaMaterial == null)
        {
            return;
        }

        CommandBuffer cmd = CommandBufferPool.Get(commandBufferName);

        // 在Execute中獲取camera color target是安全的
        RTHandle cameraColorTarget = renderingData.cameraData.renderer.cameraColorTargetHandle;

        // 設定gamma值
        gammaMaterial.SetFloat("_Gamma", settings.gamma);
        gammaMaterial.SetFloat("_GammaMode", settings.gammaMode);

        // 使用更基本的blit方法
        cmd.Blit(cameraColorTarget, tempColorTarget, gammaMaterial);
        cmd.Blit(tempColorTarget, cameraColorTarget);

        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }

    public override void OnCameraCleanup(CommandBuffer cmd)
    {
        // RTHandle會自動管理
    }

    public void Dispose()
    {
        tempColorTarget?.Release();
        if (gammaMaterial != null)
        {
            Object.DestroyImmediate(gammaMaterial);
        }
    }
}


新增用於 Gamma 調整 shader

Shader "Hidden/GammaCorrectionForGammaSpace"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Gamma ("Gamma", Float) = 2.2
        _GammaMode ("Gamma Mode", Float) = 0  // 0 = 標準gamma, 1 = 對比度調整
    }
    SubShader
    {
        Cull Off ZWrite Off ZTest Always
        
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            sampler2D _MainTex;
            float _Gamma;
            float _GammaMode;
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                
                // 針對Gamma色彩空間的特殊處理
                if (_GammaMode < 0.5)
                {
                    // 方法1: 標準gamma校正(適用於微調)
                    col.rgb = pow(col.rgb, _Gamma);
                }
                else
                {
                    // 方法2: 對比度風格調整(更明顯的效果)
                    col.rgb = pow(col.rgb, 1.0 / _Gamma);
                    // 可選:添加額外的對比度調整
                    col.rgb = (col.rgb - 0.5) * _Gamma + 0.5;
                    col.rgb = saturate(col.rgb);
                }
                
                return col;
            }
            ENDCG
        }
    }
}


打開 Player -> Graphics,點擊 Render Pipeline



點上面的 Render Data


在 Renderer2D 上面新增 Gamma Correction Feature,點最下面的 Add Renderer Feature,會有剛剛新增好的 
Gamma Correction Feature



將剛剛新增的 GammaCorrection Shader 拉進去

然後選擇 After Rendering Post Processing


這樣去調整 Gamma 值就可以了

留言

這個網誌中的熱門文章

comfyUI 運行出錯 FATAL: kernel fmha_cutlassF_f32_aligned_64x64_rf_sm80 is for sm80-sm100, but was built for sm37

在公司的圖形機器上運行 ComfyUI + WAN 時出現下面問題   FATAL: kernel fmha_cutlassF_f32_aligned_64x64_rf_sm80 is for sm80-sm100, but was built for sm37 算圖機使用的 torch 版本如下 torch 2.7.1+cu118 torchaudio 2.7.1+cu118 torchsde 0.2.6 torchvision 0.22.1+cu118 檢查 cuda 版本 GeForce RTX 5090 CUDA Version: 13.0 從官網看 RTX 5090 支持 12.0 版本 CUDA 這是因爲本地的 pytorch 版本太舊 到官網查詢版本 https://pytorch.org/get-started/locally/ $ pip3 install torch torchvision --index-url https://download.pytorch.org/whl/cu126 查詢目前版本 $ pip list | findstr torch 使用這個版本后出現下面問題 後面查詢 no kernel image 問題其實還是 pytorch 並不支持 sm_120( Blackwell架構) 查看后發現并沒有支持 sm_120 CUDA architectures : [' sm_37 ', 'sm_50', 'sm_60', 'sm_61', 'sm_70', 'sm_75', 'sm_80', 'sm_86', 'sm_90', 'compute_37'] sm_50, sm_52, sm_53 : Maxwell (GTX 900 系列) sm_60, sm_61, sm_62 : Pascal (GTX 1000, P100) sm_70, sm_72, sm_75 : Volta/Turing (V100, RTX ...
仔細回想最近的作的 stripping level,還是回頭來說說 import dll 這回事吧;因為從事遊戲改版所以很多事情是言不由衷的,某天發現 server 發送給 client 封包是 big5 encode,第一時間覺得為何不用 unicode 呢?但仔細想也許是遊戲剛規劃時 DB 都已經存了 big5 編碼字串可能已經改不動了,想想也是就算了,結果一包到 android 就發生了 GetEncoding error,因為 android 是採用 unicode 編碼的,在網路上找了找終於找到解法,可以參考底下網址的討論串,主要是下載  I18N.dll、I18N.CJK.dll、I18N.West.dll 並丟到 Assets 資料夾下就可以了,當時還不是很了解為什麼只知道把 dll 都丟進去在手機上就可以跑,直到使用 stripping level 後整個又掛了,才認真去 trace, 問題在於勾選 strip asm 包檔後 I18N.CJK 就沒被包到 apk 裡面,而要解決 strip asm(~"~ 沒辦法 strip asm 很吸引我,一定要想辦法克服)採用了 link.xml 的方式,但這樣要怎麼知道弄進哪些 lib 呢?

熟悉 Unity Memory

    打開始跟 app memory 奮戰,摸索了好一陣子,不管是跑在 andorid 還是 Ios,之前做 WebPlayer 的經驗都派不上用場,也好在網路上資源很多,只要不恥繁找就能找到你所想要的,在此分享的主要是 android(ps. ~"~ 手頭上只有兩台 android 設備)。