shader特效代码

Bloom后处理效果

Bloom的cs代码

using System.Collections.Generic;
using UnityEngine;

public class bloom : PostEffectsBase
{
    public Shader bloomShader;
    private Material bloomMaterial;
    public Material material
    {
        get
        {
            //根据PostEffectsBase中的方法检测,第一个参数指定了该特效需要使用的Shader,第二个参数则是用于后期处理的材质;
            //该函数首先检查Shader的可用性,检查通过后返回一个使用了该shader的材质,否则返回Null.
            bloomMaterial = CheckShaderAndCreateMaterial(bloomShader, bloomMaterial);
            return bloomMaterial;
        }
    }

    //高斯模糊的叠带次数
    [Range(0, 4)]
    public int iterations = 3;

    //高斯模糊的叠带范围
    [Range(0.2f, 4.0f)]
    public float blurSpread = 0.6f;

    //降采样的数值
    [Range(1, 8)]
    public int downSample = 2;

    //luminanceThreshold,大多数情况下图像亮度不会超过1.但如果我们开启了HDR,硬件会允许我们把颜色值储存在一个更高精度范围的缓冲中,
    //此时像素的亮度就会超过1.
    [Range(0.0f, 4.0f)]
    public float luminanceThreshold = 0.6f;



    //OnRenderImage函数
    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (material != null)
        {
            material.SetFloat("_luminanceThreshold", luminanceThreshold);

            //将图像进行降采样不仅可以减少需要处理的像素,提高性能,而且适当的降采样旺旺还可以得到更好的模糊效果
            int rtW = src.width / downSample;
            int rtH = src.height / downSample;

            //定义第一个缓存buffer0,并吧src中的图像缩放后储存到buffer0中。
            RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);
            buffer0.filterMode = FilterMode.Bilinear;

            //调用shader中的第一个Pass提取图像中较亮的区域,提到的较亮区域将储存在buffer0 中。
            Graphics.Blit(src, buffer0, material, 0);

            for (int i = 0; i < iterations; i++)
            {
                material.SetFloat("_BlurSize", 1.0f + i * blurSpread);
                //定义buffer1
                RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                //调用第二个pass,输入buffer0,输出buffer1.
                Graphics.Blit(buffer0, buffer1, material, 1);

                RenderTexture.ReleaseTemporary(buffer0);
                //将输出的buffer1重新赋值给buffer0
                buffer0 = buffer1;
                buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);

                //调用第三个pass,输入buffer0(上面输出的buffer1),输出buffer1(新的buffer1)
                Graphics.Blit(buffer0, buffer1, material, 2);
                //将新的buffer1再次给buffer0赋值
                buffer0 = buffer1;
            }
            //第四个Pass,将buffer0赋值给贴图_Bloom
            material.SetTexture("_Bloom", buffer0);
            Graphics.Blit(src, dest, material, 3);

            RenderTexture.ReleaseTemporary(buffer0);
        }
        else
        {
            Graphics.Blit(src, dest);
        }
    }

}

PostEffectsBase的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//在编辑器状态下可执行该脚本来查看效果
[ExecuteInEditMode]
//屏幕后处理特效一般需要绑定在摄像机上
[RequireComponent(typeof(Camera))]
public class PostEffectsBase : MonoBehaviour
{


    void Start()
    {
        CheckResources();
    }



    protected void CheckResources()
    {
        bool isSupported = CheckSupport();
        //如果显卡检测 返回false
        if (isSupported == false)
        {
            //NotSupported()方法,即不显示
            NotSupported();
        }
    }
    //检查显卡是否支持
    protected bool CheckSupport()
    {
        //如果显卡不支持图像后期处理
        if (SystemInfo.supportsImageEffects == false)
        {
            //返回false
            return false;
        }
        //如果支持图像后处理,返回true
        return true;
    }
    //图像不显示
    protected void NotSupported()
    {
        enabled = false;
    }


    //CheckShaderAndCreateMaterial函数接受两个参数,第一个参数指定了改特效需要使用的Shader
    //第二个参数则是用于后期处理的材质。该函数首先检查Shader的可用性,检查通过后就返回一个使
    //用了该shader的材质,否则返回null.
    protected Material CheckShaderAndCreateMaterial(Shader shader, Material material)
    {   //如果shader为空
        if (shader == null)
        {
            return null;
        }
        //shader.isSupported:能在终端用户的图形卡上运行这个着色器&& 并且存在material 他的shader是我们输入的shader
        if (shader.isSupported && material && material.shader == shader)
        {
            return material;
        }

        if (!shader.isSupported)
        {
            return null;
        }
        //上面都不满足的话,重新创建新的材质球
        else
        {
            material = new Material(shader);
            //hideFlags:控制对象销毁的位掩码
            //HideFlags.DontSave对象不会保存到场景中。加载新场景时不会被破坏。
            material.hideFlags = HideFlags.DontSave;
            return material;
        }

    }
}

shader代码:

Shader "Unlit/Bloom"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    //高斯模糊较亮的区域 
    _Bloom("Bloom(RGB)",2D) = "Black"{}
    //阔值,提取大于这个亮度的区域 后面将在 大于这个值 的区域里进行高斯模糊
    _luminanceThreshold("luminanceThreshold",Float) = 0.5
        //控制不同迭代之间高斯模糊的模糊区域范围  也就是uv偏移的范围
        _BlurSize("Blur Size",Float) = 1.0
    }
        SubShader
    {
        CGINCLUDE
         #include "UnityCG.cginc"  
        sampler2D _MainTex;
        half4 _MainTex_TexelSize;
        sampler2D _Bloom;
        Float _luminanceThreshold;
        float _BlurSize;



        ///提取交亮区域的 顶点.片元 着色器
        struct v2f {
        float4 pos :SV_POSITION;
        half2 uv :TEXCOORD0;
        };
        v2f vertExtractBright(appdata_img v)
        {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);
            o.uv = v.texcoord;
            return o;
        }
        //通过主贴图得到一个灰度值
        fixed4 luminance(fixed4 color) {
            return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
        }
        fixed4 fragExtractBright(v2f i) :SV_Target {
            ///我们降采样得到的亮度值减去阔值_luminanceThreshold,并把结果截取到0到1的范围内,然后
            ///我们把该值和原像素相乘,得到提取后的两部区域
            ///这样就是低于_luminanceThreshold显示为黑色

            fixed c = tex2D(_MainTex , i.uv);
        //clamp(x,a,b),如果x<a,返回a,x>b,返回b,否则返回为x;
        fixed val = clamp(luminance(c) - _luminanceThreshold, 0.0, 1.0);

        return c * val;
    }



            ///使用Unity提供的_MainTex_Texel_TexelSize变量,计算相邻文理坐标的的偏移(也是高斯模糊的写法)
            //竖方向跟横方向的两个顶点着色器公用的v2f输出定义
            struct v2fBlur {
                float4 pos : SV_POSITION;
                half2 uv[5]:TEXCOORD0;
            };
    //竖直方向的
    v2fBlur vertBlurV(appdata_img v) {
        v2fBlur o;
        o.pos = UnityObjectToClipPos(v.vertex);
        half2 uv = v.texcoord;

        o.uv[0] = uv;
        o.uv[1] = uv + float2 (0.0,_MainTex_TexelSize.y * 1.0) * _BlurSize;
        o.uv[2] = uv - float2 (0.0,_MainTex_TexelSize.y * 1.0) * _BlurSize;
        o.uv[3] = uv + float2 (0.0,_MainTex_TexelSize.y * 2.0) * _BlurSize;
        o.uv[4] = uv - float2 (0.0,_MainTex_TexelSize.y * 2.0) * _BlurSize;

        return o;
    }

    //水平方向的
    v2fBlur vertBlurH(appdata_img v) {
        v2fBlur o;
        o.pos = UnityObjectToClipPos(v.vertex);
        half2 uv = v.texcoord;

        o.uv[0] = uv;
        o.uv[1] = uv + float2 (_MainTex_TexelSize.x * 1.0 , 0.0) * _BlurSize;
        o.uv[2] = uv - float2 (_MainTex_TexelSize.x * 1.0 , 0.0) * _BlurSize;
        o.uv[3] = uv + float2 (_MainTex_TexelSize.x * 2.0 , 0.0) * _BlurSize;
        o.uv[4] = uv - float2 (_MainTex_TexelSize.x * 2.0 , 0.0) * _BlurSize;

        return o;
    }

    //定义两个pass公用的片元着色器
    fixed4 fragBlur(v2fBlur i) : SV_Target{

    float weight[3] = {0.4026, 0.2442, 0.0545};

    fixed3 sum = tex2D(_MainTex,i.uv[0]).rgb * weight[0];

    for (int j = 1; j < 3; j++) {
        sum += tex2D(_MainTex,i.uv[j * 2 - 1]).rgb * weight[j];
        sum += tex2D(_MainTex,i.uv[j * 2]).rgb * weight[j];
    }
    return fixed4(sum,1.0);

    }


        ///混合亮部图像和原图像时使用的 顶点.片元 着色器
        struct v2fBloom {
            float4 pos :SV_POSITION;
            half4 uv :TEXCOORD0;
        };

        v2fBloom vertBloom(appdata_img v) {
            v2fBloom  o;
            o.pos = UnityObjectToClipPos(v.vertex);
            o.uv.xy = v.texcoord;
            o.uv.zw = v.texcoord;

            #if UNITY_UV_STARTS_AT_TOP
            if (_MainTex_TexelSize.y < 0.0)
                o.uv.w = 1.0 - o.uv.w;
            #endif

            return o;
        }
        fixed4 fragBloom(v2fBloom i) :SV_Target{
            return tex2D(_MainTex, i.uv.xy) + tex2D(_Bloom,i.uv.zw);

        }

        ENDCG



        ZTest Always Cull Off ZWrite Off

        pass {
            CGPROGRAM
            #pragma vertex vertExtractBright
            #pragma fragment  fragExtractBright
            ENDCG
        }

        pass {

            CGPROGRAM
            #pragma vertex vertBlurV
            #pragma fragment  fragBlur
            ENDCG
        }

        pass {

            CGPROGRAM
            #pragma vertex vertBlurH
            #pragma fragment  fragBlur
            ENDCG
        }

        pass {

            CGPROGRAM
            #pragma vertex vertBloom
            #pragma fragment  fragBloom
            ENDCG
        }

    }
        FallBack Off
}

毛发效果

cginc的代码:

struct v2f {
	float4 pos : SV_POSITION;
	half2 uv : TEXCOORD0;
	half2 uv1 : TEXCOORD1;
	fixed4 diff : COLOR;
};
 
float _FurLength;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _FurTex;
float4 _FurTex_ST;
float _Blur;
 
v2f vert(appdata_base v)
{
	v2f o;
	v.vertex.xyz += v.normal * _FurLength * FURSTEP;
	o.pos = UnityObjectToClipPos(v.vertex);
	o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
	o.uv1 = TRANSFORM_TEX(v.texcoord, _FurTex);
	float3 worldNormal = normalize(mul(v.normal, (float3x3) unity_WorldToObject));
	o.diff = LambertDiffuse(worldNormal);
	o.diff.a = 1 - (FURSTEP * FURSTEP);
	float4 worldPos = mul(unity_ObjectToWorld ,v.vertex);
	o.diff.a += dot(normalize(_WorldSpaceCameraPos.xyz- v.vertex), worldNormal) - _Blur;
	return o;
}
 
float _CutOff;
float _Thickness;
 
fixed4 frag(v2f i) : SV_Target
{
	fixed4 col = tex2D(_MainTex, i.uv);
	fixed alpha = tex2D(_FurTex, i.uv1).r;
	col *= i.diff;
	col.a *= step(lerp(_CutOff, _CutOff + _Thickness, FURSTEP), alpha);
	return col;
}

shader代码:

Shader "Custom/FurShader"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
	_FurTex("Fur pattern", 2D) = "white" {}
	_Diffuse("Diffuse value", Range(0, 3)) = 1

		_FurLength("Fur length", Range(0.0, 1)) = 0.5
		_CutOff("Alpha cutoff", Range(0, 1)) = 0.5
		_Blur("Blur", Range(0, 1)) = 0.5
		_Thickness("Thickness", Range(0, 0.5)) = 0
	}

		CGINCLUDE

		fixed _Diffuse;
	inline fixed4 LambertDiffuse(float3 worldNormal)
	{
		float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
		float NdotL = max(0.2, dot(worldNormal, lightDir));
		return NdotL * _Diffuse;
	}


	ENDCG

		SubShader
	{
		Tags{ "RenderType" = "Transparent"   "Queue" = "Transparent"  "LightMode" = "ForwardBase" }
		ZWrite Off
		Blend SrcAlpha OneMinusSrcAlpha
		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.05
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.10
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.15
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.20
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.25
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.30
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.35
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.40
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.45
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.50
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.55
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.60
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.65
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.70
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.75
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.80
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.85
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.90
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}

		Pass
	{
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define FURSTEP 0.95
#include "UnityCG.cginc"
#include "FurHelper.cginc"
		ENDCG
	}
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值