欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity 屏幕特效 之 基础知识简介,屏幕灰度特效实现

程序员文章站 2022-05-24 23:45:52
...

Unity 屏幕特效 之 基础知识简介,屏幕灰度特效实现

 

目录

Unity 屏幕特效 之 基础知识简介,屏幕灰度特效实现

一、前言:

二、函数介绍

三、Graphics.Blit()函数

四、MonoBehaviour.OnRenderImage(RenderTexture,RenderTexture) 函数

五、Shader 脚本模板(仅供参考)

六、屏幕特效示例

七、示例特效 shader 和 脚本代码


 

一、前言:

unity shader中的pass是会顺序执行的,但是由于在图像处理中我们常常需要使用一个pass的处理结果作为另一个pass的输入,这个时候就需要用到OnRenderImage()函数了。


二、函数介绍

MonoBehaviour.OnRenderImage(RenderTexture source,RenderTexture destination)

官方描述Description

OnRenderImage is called after all rendering is complete to render image.,该函数在所有的渲染完成后由monobehavior自动调用。

官方解释:该函数允许我们使用着色器滤波操作来修改最终的图像,输入原图像source,输出的图像放在desitination里。


三、Graphics.Blit()函数

该函数的作用就是通过一个shader将原图的像素放置到destionation中。

Unity 屏幕特效 之 基础知识简介,屏幕灰度特效实现

四、MonoBehaviour.OnRenderImage(RenderTexture,RenderTexture) 函数

Unity 屏幕特效 之 基础知识简介,屏幕灰度特效实现
 

五、Shader 脚本模板(仅供参考)

Shader "xxxx/xxxxxx"
{
	Properties
	{
		_MainTex("Base (RGB)", 2D) = "white" {}

		......
                ......

	}

		SubShader
		{
			Pass
			{
				CGPROGRAM
				#pragma vertex vert_img
				#pragma fragment frag
				#pragma fragmentoption ARB_precision_hint_fastest
				#include "UnityCG.cginc"

				uniform sampler2D _MainTex;

				......

				fixed4 frag(v2f_img i) : COLOR
				{

				        fixed4 finalColor;
                                        
                                        .......
                                        .......

				        return finalColor;
			         }

		     ENDCG
		}
	}
	
	FallBack off
			
}

六、屏幕特效示例

屏幕特效案例测试,如下:

1、写一个让图片变为灰度图的屏幕特效;

2、新建一个shader,进行屏幕特效原图转为灰度图;

3、然后新建一个脚本,把脚本拖动到主相机下,然后将 shader 赋予相应变量即可;

(注意在示例中,我们用到了Material::SetTexture()函数,这是给材质赋值的,我们这里把原图的值赋值给_MainTex,然后shader处理的时候采样的图片就是相机得到的场景图片了,这里可以设置所有类型的值,你也可以尝试自己写一个滑动条,然后动态设置图片的灰度级别)

4、工程效果测试图

Unity 屏幕特效 之 基础知识简介,屏幕灰度特效实现

 

七、示例特效 shader 和 脚本代码

Shader "Unlit/ZTestImageEffect"
{
	Properties
	{
		_MainTex("Base (RGB)", 2D) = "white" {}
		_LuminosityAmount("Brightness Amount", Range(0.0, 1)) = 1.0
	}

		SubShader
		{
			Pass
			{
				CGPROGRAM
				#pragma vertex vert_img
				#pragma fragment frag
				#pragma fragmentoption ARB_precision_hint_fastest
				#include "UnityCG.cginc"

				uniform sampler2D _MainTex;
				fixed _LuminosityAmount;

				fixed4 frag(v2f_img i) : COLOR
				{
					//Get the colors from the RenderTexture and the uv's
					//from the v2f_img struct
					fixed4 renderTex = tex2D(_MainTex, i.uv);

				//Apply the Luminosity values to our render texture
				float luminosity = 0.299 * renderTex.r + 0.587 * renderTex.g + 0.114 * renderTex.b;
				fixed4 finalColor = lerp(renderTex, luminosity, _LuminosityAmount);


				return finalColor;
			}

		ENDCG
		}
	}
	
	FallBack off
			
}
using UnityEngine;
using System.Collections;

/// <summary>
/// 1、表示在编辑器模式下运行
/// 2、实时变化灰度参数。这个就是脚本里设置Shader中的参数值
/// 3、Shader中根据这个参数值把灰度效果渲染到RenderTexture上
/// </summary>
[ExecuteInEditMode]
public class TestImageEffectGrey : MonoBehaviour
{
    #region Variables
    public Shader curShader;                // 进行屏幕变化的 shader
    public float grayScaleAmount = 1.0f;    // 灰度与原色的插值比例
    private Material curMaterial;           // shader 对应的材质
    #endregion

    #region Properties
    // curMaterial的属性
    Material material
    {
        get
        {
            if (curMaterial == null)
            {
                curMaterial = new Material(curShader);
                curMaterial.hideFlags = HideFlags.HideAndDontSave;
            }
            return curMaterial;
        }
    }
    #endregion

    void Start()
    {
        // 判断但钱是否支持图片特效
        if (!SystemInfo.supportsImageEffects)
        {
            enabled = false;
            return;
        }

        // 判断材质是否为空,并且当前材质是否支持
        if (!curShader && !curShader.isSupported)
        {
            enabled = false;
        }
    }

    // 屏幕特效处理
    void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
    {
        if (curShader != null)
        {
            material.SetFloat("_LuminosityAmount", grayScaleAmount);

            Graphics.Blit(sourceTexture, destTexture, material);
        }
        else
        {
            Graphics.Blit(sourceTexture, destTexture);
        }
    }

    void Update()
    {
        // 保持 值在 0,1 之间
        grayScaleAmount = Mathf.Clamp(grayScaleAmount, 0.0f, 1.0f);
    }

    void OnDisable()
    {
        // 销毁当前材质
        if (curMaterial)
        {
            DestroyImmediate(curMaterial);
        }
    }
}