新增 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
留言
張貼留言