Unity Shader 学习笔记(19) 屏幕后处理效果、调整亮度、饱和度、对比度

44 篇文章 5 订阅
36 篇文章 5 订阅

Unity Shader 学习笔记(19) 屏幕后处理效果、调整亮度、饱和度、对比度

参考书籍:《Unity Shader 入门精要》


屏幕后处理效果(screen post-processing effects)

即在渲染完场景得到屏幕图像后在进行处理的效果,如景深、运动模糊等。

Unity提供接口方便处理渲染后的图像:OnRenderImage。第一个参数渲染得到纹理,第二个参数是输出到屏幕的纹理。
MonoBehaviour.OnRenderImage (RenderTexture src, RenderTexture dest)

在上面函数内,通常使用Graphics.Blit函数处理渲染纹理。
在这里插入图片描述

  • source:当前屏幕的渲染纹理或上一步处理完的渲染纹理。
  • dest:目标渲染纹理,为null时就直接把结果显示在屏幕上。
  • mat:使用的材质,材质的shader会进行屏幕后处理,source会传入这个shader名为_MainTex的纹理。
  • pass:默认-1,即顺序调用Shader内所有Pass。否则只会调用给定索引的Pass。
  • sacle:源纹理的缩放。
  • offset:源纹理的偏移量。

实现屏幕后处理效果的基类 PostEffectsBase

using UnityEngine;

/// <summary>
/// 屏幕后处理效果基类
/// </summary>
[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class PostEffectsBase : MonoBehaviour
{
    private Camera mainCamera;
    public Camera MainCamera { get { return mainCamera = mainCamera == null ? GetComponent<Camera>() : mainCamera; } }
 
    public Shader targetShader;
    private Material targetMaterial = null;
    public Material TargetMaterial { get { return CheckShaderAndCreateMaterial(targetShader, targetMaterial); } }

    /// <summary>
    /// 检测资源,如果不支持,关闭脚本活动
    /// </summary>
    protected void Start()
    {
        if (CheckSupport() == false)
            enabled = false;
    }

    /// <summary>
    /// 检测平台是否支持图片渲染
    /// </summary>
    /// <returns></returns>
    protected bool CheckSupport()
    {
        if (SystemInfo.supportsImageEffects == false)
        {
            Debug.LogWarning("This platform does not support image effects or render textures.");
            return false;
        }
        return true;
    }

    /// <summary>
    /// 检测需要渲染的Shader可用性,然后返回使用了该shader的material
    /// </summary>
    /// <param name="shader">指定shader</param>
    /// <param name="material">创建的材质</param>
    /// <returns>得到指定shader的材质</returns>
    protected Material CheckShaderAndCreateMaterial(Shader shader, ref Material material)
    {
        if (shader == null || !shader.isSupported)
            return null;

        if (material && material.shader == shader)
            return material;

        material = new Material(shader);
        material.hideFlags = HideFlags.DontSave;
        return material;
    }
}


调整亮度(Brightness)、饱和度(Saturation)、对比度(Contrast)

调整后图像与原图对比:
在这里插入图片描述

通过mono脚本处理屏幕后效果:

public class BrightnessSaturationAndContrast : PostEffectsBase
{
    [Range(0.0f, 3.0f)]
    public float brightness = 1.0f;
    [Range(0.0f, 3.0f)]
    public float saturation = 1.0f;
    [Range(0.0f, 3.0f)]
    public float contrast = 1.0f;

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (TargetMaterial != null)
        {
            TargetMaterial.SetFloat("_Brightness", brightness);
            TargetMaterial.SetFloat("_Saturation", saturation);
            TargetMaterial.SetFloat("_Contrast", contrast);
        }
        Graphics.Blit(src, dest, TargetMaterial);
    }
}

材质的shader:

Pass { 
	// 关掉深度写入,避免挡住后面物体渲染,(如果OnRenderImage在所有不透明Pass后直接执行(而非所有都渲染完)) 
	ZTest Always Cull Off ZWrite Off
	
	...
	
	fixed4 frag(v2f i) : SV_Target {
		fixed4 renderTex = tex2D(_MainTex, i.uv);  
		  
		// 亮度
		fixed3 finalColor = renderTex.rgb * _Brightness;
		
		// 饱和度
		fixed luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
		fixed3 luminanceColor = fixed3(luminance, luminance, luminance);	// 饱和度为0的颜色值
		finalColor = lerp(luminanceColor, finalColor, _Saturation);	
		
		// 对比度
		fixed3 avgColor = fixed3(0.5, 0.5, 0.5);		// 对比度为0的颜色值
		finalColor = lerp(avgColor, finalColor, _Contrast);
		
		return fixed4(finalColor, renderTex.a);  
	}  
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值