Unity Shader Example 21 (Highlighting 边缘光)

主要参考Highlighting System 插件。


效果:


被Plane挡住:


Unity Shader Example 21 (Highlighting 边缘光)_第1张图片



没有被plane挡住:

Unity Shader Example 21 (Highlighting 边缘光)_第2张图片



HighlightableObjectSimple 组件,挂上这个组件的物体更换所有的材质,更换物体的layer。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class HighlightableObjectSimple : MonoBehaviour {
    private List highlightableRenderers;
    private bool zWrite = false;
    private static float transparentCutoff = 0.5f;
    private bool materialsIsDirty = true;
    private int[] layersCache;
    public static int highlightingLayer = 7;
    private Color currentColor;


    private Material highlightingMaterial
    {
        get
        {
            return zWrite ? opaqueZMaterial : opaqueMaterial;
        }
    }

    // Common (for this component) replacement material for opaque geometry highlighting
    private Material _opaqueMaterial;
    private Material opaqueMaterial
    {
        get
        {
            if (_opaqueMaterial == null)
            {
                _opaqueMaterial = new Material(opaqueShader);
                _opaqueMaterial.hideFlags = HideFlags.HideAndDontSave;
            }
            return _opaqueMaterial;
        }
    }

    // Common (for this component) replacement material for opaque geometry highlighting with Z-Buffer writing enabled
    private Material _opaqueZMaterial;
    private Material opaqueZMaterial
    {
        get
        {
            if (_opaqueZMaterial == null)
            {
                _opaqueZMaterial = new Material(opaqueZShader);
                _opaqueZMaterial.hideFlags = HideFlags.HideAndDontSave;
            }
            return _opaqueZMaterial;
        }
    }

    // 
    private static Shader _opaqueShader;
    private static Shader opaqueShader
    {
        get
        {
            if (_opaqueShader == null)
            {
                _opaqueShader = Shader.Find("Hidden/Highlighted/StencilOpaque");
            }
            return _opaqueShader;
        }
    }

    // 
    private static Shader _transparentShader;
    public static Shader transparentShader
    {
        get
        {
            if (_transparentShader == null)
            {
                _transparentShader = Shader.Find("Hidden/Highlighted/StencilTransparent");
            }
            return _transparentShader;
        }
    }

    // 
    private static Shader _opaqueZShader;
    private static Shader opaqueZShader
    {
        get
        {
            if (_opaqueZShader == null)
            {
                _opaqueZShader = Shader.Find("Hidden/Highlighted/StencilOpaqueZ");
            }
            return _opaqueZShader;
        }
    }

    // 
    private static Shader _transparentZShader;
    private static Shader transparentZShader
    {
        get
        {
            if (_transparentZShader == null)
            {
                _transparentZShader = Shader.Find("Hidden/Highlighted/StencilTransparentZ");
            }
            return _transparentZShader;
        }
    }

    void Start()
    {
        InitMaterials(false);
    }

    private void InitMaterials(bool writeDepth)
    {
        highlightableRenderers = new List();

        MeshRenderer[] mr = GetComponentsInChildren();
        CacheRenderers(mr);

        SkinnedMeshRenderer[] smr = GetComponentsInChildren();
        CacheRenderers(smr);

        materialsIsDirty = false;
    }

    private void CacheRenderers(Renderer[] renderers)
    {
        for (int i = 0; i < renderers.Length; i++)
        {
            Material[] materials = renderers[i].sharedMaterials;

            if (materials != null)
            {
                highlightableRenderers.Add(new HighlightingRendererCache(renderers[i], materials, highlightingMaterial, zWrite));
            }
        }
    }
    private void OnEnable()
    {
        HighlightingEffect.highlightingEvent += UpdateEventHandler;
    }
    private void OnDisable()
    {
        HighlightingEffect.highlightingEvent -= UpdateEventHandler;

        if (highlightableRenderers != null)
        {
            highlightableRenderers.Clear();
        }

        // Reset highlighting parameters to default values
        layersCache = null;
        materialsIsDirty = true;
        zWrite = false;

        if (_opaqueMaterial)
        {
            DestroyImmediate(_opaqueMaterial);
        }

        if (_opaqueZMaterial)
        {
            DestroyImmediate(_opaqueZMaterial);
        }
    }

    private void SetColor(Color c)
    {
        if (currentColor == c)
        {
            return;
        }

        if (zWrite)
        {
            opaqueZMaterial.SetColor("_Outline", c);
        }
        else
        {
            opaqueMaterial.SetColor("_Outline", c);
        }

        for (int i = 0; i < highlightableRenderers.Count; i++)
        {
            highlightableRenderers[i].SetColorForTransparent(c);
        }

        currentColor = c;
    }

    private void UpdateEventHandler(bool trigger, bool writeDepth)
    {
        // Update and enable highlighting
        if (trigger)
        {
            // ZWriting state changed?
            if (zWrite != writeDepth)
            {
                materialsIsDirty = true;
            }

            // Initialize new materials if needed
            if (materialsIsDirty)
            {
                InitMaterials(writeDepth);
            }

            SetColor(Color.red);

            if (highlightableRenderers != null)
            {
                layersCache = new int[highlightableRenderers.Count];
                for (int i = 0; i < highlightableRenderers.Count; i++)
                {
                    GameObject go = highlightableRenderers[i].goCached;
                    // cache layer
                    layersCache[i] = go.layer;
                    // temporary set layer to renderable by the highlighting effect camera
                    go.layer = highlightingLayer;
                    // 换材质
                    highlightableRenderers[i].SetState(true);
                }
            }
            
        }
        // Disable highlighting
        else
        {
            if (highlightableRenderers != null)
            {
                for (int i = 0; i < highlightableRenderers.Count; i++)
                {
                    highlightableRenderers[i].goCached.layer = layersCache[i];
                    highlightableRenderers[i].SetState(false);
                }
            }
        }
    }

    private class HighlightingRendererCache
    {
        public Renderer rendererCached;
        public GameObject goCached;
        private Material[] sourceMaterials;
        private Material[] replacementMaterials;
        private List transparentMaterialIndexes;

        // Constructor
        public HighlightingRendererCache(Renderer rend, Material[] mats, Material sharedOpaqueMaterial, bool writeDepth)
        {
            rendererCached = rend;
            goCached = rend.gameObject;
            sourceMaterials = mats;
            replacementMaterials = new Material[mats.Length];
            transparentMaterialIndexes = new List();

            for (int i = 0; i < mats.Length; i++)
            {
                Material sourceMat = mats[i];
                if (sourceMat == null)
                {
                    continue;
                }
                string tag = sourceMat.GetTag("RenderType", true);
                if (tag == "Transparent" || tag == "TransparentCutout")
                {
                    Material replacementMat = new Material(writeDepth ? transparentZShader : transparentShader);
                    if (sourceMat.HasProperty("_MainTex"))
                    {
                        replacementMat.SetTexture("_MainTex", sourceMat.mainTexture);
                        replacementMat.SetTextureOffset("_MainTex", sourceMat.mainTextureOffset);
                        replacementMat.SetTextureScale("_MainTex", sourceMat.mainTextureScale);
                    }

                    replacementMat.SetFloat("_Cutoff", sourceMat.HasProperty("_Cutoff") ? sourceMat.GetFloat("_Cutoff") : transparentCutoff);

                    replacementMaterials[i] = replacementMat;
                    transparentMaterialIndexes.Add(i);
                }
                else
                {
                    replacementMaterials[i] = sharedOpaqueMaterial;
                }
            }
        }

        // Based on given state variable, replaces materials of this cached renderer to the highlighted ones and back
        public void SetState(bool state)
        {
            rendererCached.sharedMaterials = state ? replacementMaterials : sourceMaterials;
        }

        // Sets given color as the highlighting color on all transparent materials for this cached renderer
        public void SetColorForTransparent(Color clr)
        {
            for (int i = 0; i < transparentMaterialIndexes.Count; i++)
            {
                replacementMaterials[transparentMaterialIndexes[i]].SetColor("_Outline", clr);
            }
        }
    }
}


HighlightingEffect 挂在Camera上。

以上的,主要就是为了渲染stencilBuffer rendererTexture。


using UnityEngine;

// Delegate for the highlighting event
public delegate void HighlightingEventHandler(bool state, bool zWrite);

[RequireComponent(typeof(Camera))]
public class HighlightingEffect : MonoBehaviour
{
	// Event used to notify highlightable objects to change their materials before rendering to the highlighting buffer begins
	public static event HighlightingEventHandler highlightingEvent;
	
	#region Inspector Fields
	// Stencil (highlighting) buffer depth
	public int stencilZBufferDepth = 0;
	
	// Stencil (highlighting) buffer size downsample factor
	public int _downsampleFactor = 4;
	
	// Blur iterations
	public int iterations = 2;
	
	// Blur minimal spread
	public float blurMinSpread = 0.65f;
	
	// Blur spread per iteration
	public float blurSpread = 0.25f;
	
	// Blurring intensity for the blur material
	public float _blurIntensity = 0.3f;
	
	// These properties available only in Editor - we don't need them in standalone build
	#if UNITY_EDITOR
	// Z-buffer writing state getter/setter
	public bool stencilZBufferEnabled
	{
		get
		{
			return (stencilZBufferDepth > 0);
		}
		set
		{
			if (stencilZBufferEnabled != value)
			{
				stencilZBufferDepth = value ? 16 : 0;
			}
		}
	}
	
	// Downsampling factor getter/setter
	public int downsampleFactor
	{
		get
		{
			if (_downsampleFactor == 1)
			{
				return 0;
			}
			if (_downsampleFactor == 2)
			{
				return 1;
			}
			return 2;
		}
		set
		{
			if (value == 0)
			{
				_downsampleFactor = 1;
			}
			if (value == 1)
			{
				_downsampleFactor = 2;
			}
			if (value == 2)
			{
				_downsampleFactor = 4;
			}
		}
	}
	
	// Blur alpha intensity getter/setter
	public float blurIntensity
	{
		get
		{
			return _blurIntensity;
		}
		set
		{
			if (_blurIntensity != value)
			{
				_blurIntensity = value;
				if (Application.isPlaying)
				{
					blurMaterial.SetFloat("_Intensity", _blurIntensity);
				}
			}
		}
	}
	#endif
	#endregion

	#region Private Fields
	// Highlighting camera layers culling mask
	//private int layerMask = (1 << HighlightableObject.highlightingLayer);
    private int layerMask = (1 << HighlightableObjectSimple.highlightingLayer);
	
	// This GameObject reference
	private GameObject go = null;
	
	// Camera for rendering stencil buffer GameObject
	private GameObject shaderCameraGO = null;
	
	// Camera for rendering stencil buffer
	private Camera shaderCamera = null;
	
	// RenderTexture with stencil buffer
	private RenderTexture stencilBuffer = null;
	
	// Camera reference
	private Camera refCam = null;
	
	// Blur Shader
	private static Shader _blurShader;
	private static Shader blurShader
	{
		get
		{
			if (_blurShader == null)
			{
				_blurShader = Shader.Find("Hidden/Highlighted/Blur");
			}
			return _blurShader;
		}
	}
	
	// Compositing Shader
	private static Shader _compShader;
	private static Shader compShader 
	{
		get
		{
			if (_compShader == null)
			{
				_compShader = Shader.Find("Hidden/Highlighted/Composite");
			}
			return _compShader;
		}
	}
	
	// Blur Material
	private static Material _blurMaterial = null;
	private static Material blurMaterial
	{
		get
		{
			if (_blurMaterial == null)
			{
				_blurMaterial = new Material(blurShader);
				_blurMaterial.hideFlags = HideFlags.HideAndDontSave;
			}
			return _blurMaterial;
		}
	}
	
	// Compositing Material
	private static Material _compMaterial = null;
	private static Material compMaterial
	{
		get
		{
			if (_compMaterial == null)
			{
				_compMaterial = new Material(compShader);
				_compMaterial.hideFlags = HideFlags.HideAndDontSave;
			}
			return _compMaterial;
		}
	}
	#endregion
	
	
	void Awake()
	{
		go = gameObject;
		refCam = GetComponent();
	}
	
	void OnDisable()
	{
		if (shaderCameraGO != null)
		{
			DestroyImmediate(shaderCameraGO);
		}
		
		if (_blurShader)
		{
			_blurShader = null;
		}
		
		if (_compShader)
		{
			_compShader = null;
		}
		
		if (_blurMaterial)
		{
			DestroyImmediate(_blurMaterial);
		}
		
		if (_compMaterial)
		{
			DestroyImmediate(_compMaterial);
		}
		
		if (stencilBuffer != null)
		{
			RenderTexture.ReleaseTemporary(stencilBuffer);
			stencilBuffer = null;
		}
	}
	
	void Start()
	{
		// Disable if Image Effects is not supported
		if (!SystemInfo.supportsImageEffects)
		{
			Debug.LogWarning("HighlightingSystem : Image effects is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if Render Textures is not supported
		if (!SystemInfo.supportsRenderTextures)
		{
			Debug.LogWarning("HighlightingSystem : RenderTextures is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if required Render Texture Format is not supported
		if (!SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32))
		{
			Debug.LogWarning("HighlightingSystem : RenderTextureFormat.ARGB32 is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if HighlightingStencilOpaque shader is not supported
		if (!Shader.Find("Hidden/Highlighted/StencilOpaque").isSupported)
		{
			Debug.LogWarning("HighlightingSystem : HighlightingStencilOpaque shader is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if HighlightingStencilTransparent shader is not supported
		if (!Shader.Find("Hidden/Highlighted/StencilTransparent").isSupported)
		{
			Debug.LogWarning("HighlightingSystem : HighlightingStencilTransparent shader is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if HighlightingStencilOpaqueZ shader is not supported
		if (!Shader.Find("Hidden/Highlighted/StencilOpaqueZ").isSupported)
		{
			Debug.LogWarning("HighlightingSystem : HighlightingStencilOpaqueZ shader is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if HighlightingStencilTransparentZ shader is not supported
		if (!Shader.Find("Hidden/Highlighted/StencilTransparentZ").isSupported)
		{
			Debug.LogWarning("HighlightingSystem : HighlightingStencilTransparentZ shader is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if HighlightingBlur shader is not supported
		if (!blurShader.isSupported)
		{
			Debug.LogWarning("HighlightingSystem : HighlightingBlur shader is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Disable if HighlightingComposite shader is not supported
		if (!compShader.isSupported)
		{
			Debug.LogWarning("HighlightingSystem : HighlightingComposite shader is not supported on this platform! Disabling.");
			this.enabled = false;
			return;
		}
		
		// Set the initial intensity in blur shader
		blurMaterial.SetFloat("_Intensity", _blurIntensity);
	}
	
	// Performs one blur iteration
	public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
	{
		float off = blurMinSpread + iteration * blurSpread;
		blurMaterial.SetFloat("_OffsetScale", off);
		Graphics.Blit(source, dest, blurMaterial);
	}
	
	// Downsamples source texture
	private void DownSample4x(RenderTexture source, RenderTexture dest)
	{
		float off = 1.0f;
		blurMaterial.SetFloat("_OffsetScale", off);
		Graphics.Blit(source, dest, blurMaterial);
	}
	
	// Render all highlighted objects to the stencil buffer
	void OnPreRender()
	{
		#if UNITY_4_0
		if (this.enabled == false || go.activeInHierarchy == false)
		#else
		if (this.enabled == false || go.active == false)
		#endif
			return;
		
		if (stencilBuffer != null)
		{
			RenderTexture.ReleaseTemporary(stencilBuffer);
			stencilBuffer = null;
		}
		
		// Turn on highlighted shaders
		if (highlightingEvent != null)
		{
			highlightingEvent(true, (stencilZBufferDepth > 0));
		}
		// We don't need to render the scene if there's no HighlightableObjects
		else
		{
			return;
		}

		stencilBuffer = RenderTexture.GetTemporary((int)GetComponent().pixelWidth, (int)GetComponent().pixelHeight, stencilZBufferDepth, RenderTextureFormat.ARGB32);

		if (!shaderCameraGO)
		{
			shaderCameraGO = new GameObject("HighlightingCamera", typeof(Camera));
			shaderCameraGO.GetComponent().enabled = false;
			shaderCameraGO.hideFlags = HideFlags.HideAndDontSave;
		}
		
		if (!shaderCamera)
		{
			shaderCamera = shaderCameraGO.GetComponent();
		}
		
		shaderCamera.CopyFrom(refCam);
		//shaderCamera.projectionMatrix = refCam.projectionMatrix;		// Uncomment this line if you have problems using Highlighting System with custom projection matrix on your camera
		shaderCamera.cullingMask = layerMask;
		shaderCamera.rect = new Rect(0f, 0f, 1f, 1f);
		shaderCamera.renderingPath = RenderingPath.VertexLit;
		shaderCamera.hdr = false;
		shaderCamera.useOcclusionCulling = false;
		shaderCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
		shaderCamera.clearFlags = CameraClearFlags.SolidColor;
		shaderCamera.targetTexture = stencilBuffer;
		shaderCamera.Render();
		
		// Turn off highlighted shaders
		if (highlightingEvent != null)
		{
			highlightingEvent(false, false);
		}
	}
	
	// Compose final frame with highlighting
	void OnRenderImage(RenderTexture source, RenderTexture destination)
	{
		// If stencilBuffer is not created by some reason
		if (stencilBuffer == null)
		{
			// Simply transfer framebuffer to destination
			Graphics.Blit(source, destination);
			return;
		}
		
		// Create two buffers for blurring the image
		int width = source.width / _downsampleFactor;
		int height = source.height / _downsampleFactor;
		RenderTexture buffer = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);
		RenderTexture buffer2 = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);
		
		// Copy stencil buffer to the 4x4 smaller texture
		DownSample4x(stencilBuffer, buffer);
		
		// Blur the small texture
		bool oddEven = true;
		for (int i = 0; i < iterations; i++)
		{
			if (oddEven)
			{
				FourTapCone(buffer, buffer2, i);
			}
			else
			{
				FourTapCone(buffer2, buffer, i);
			}
			
			oddEven = !oddEven;
		}
		
		// Compose
		compMaterial.SetTexture("_StencilTex", stencilBuffer);
		compMaterial.SetTexture("_BlurTex", oddEven ? buffer : buffer2);
		Graphics.Blit(source, destination, compMaterial);
		
		// Cleanup
		RenderTexture.ReleaseTemporary(buffer);
		RenderTexture.ReleaseTemporary(buffer2);
		if (stencilBuffer != null)
		{
			RenderTexture.ReleaseTemporary(stencilBuffer);
			stencilBuffer = null;
		}
	}
}


HighlightingInclude.cginc

#ifndef HIGHLIGHTING_CG_INCLUDED
#define HIGHLIGHTING_CG_INCLUDED

#include "UnityCG.cginc"

// Opaque
uniform fixed4 _Outline;

struct appdata_vert
{
	float4 vertex : POSITION;
};

float4 vert(appdata_vert v) : POSITION
{
	return mul(UNITY_MATRIX_MVP, v.vertex);
}

fixed4 frag() : COLOR
{
	return _Outline;
}

// Transparent
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform fixed _Cutoff;

struct appdata_vert_tex
{
	float4 vertex : POSITION;
	float2 texcoord : TEXCOORD0;
};

struct v2f
{
	float4 pos : POSITION;
	float2 texcoord : TEXCOORD0;
};

v2f vert_alpha(appdata_vert_tex v)
{
	v2f o;
	o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
	o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
	return o;
}

fixed4 frag_alpha(v2f i) : COLOR
{
	clip(tex2D(_MainTex, i.texcoord).a - _Cutoff);
	return _Outline;
}
#endif


HighlightingStencilOpaque.shader


Shader "Hidden/Highlighted/StencilOpaque"
{
	CGINCLUDE
	#include "HighlightingInclude.cginc"
	ENDCG
	
	SubShader
	{
		Pass
		{
			ZWrite Off
			ZTest Always
			Lighting Off
			Fog { Mode Off }
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			ENDCG
		}
	}
	
	Fallback Off
}


HighlightingStencilOpaqueZ.shader


Shader "Hidden/Highlighted/StencilOpaqueZ"
{
	CGINCLUDE
	#include "HighlightingInclude.cginc"
	ENDCG
	
	SubShader
	{
		Pass
		{
			ZWrite On
			ZTest LEqual
			Lighting Off
			Fog { Mode Off }
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			ENDCG
		}
	}
	
	Fallback Off
}



HighlightingStencilTransparent.shader


Shader "Hidden/Highlighted/StencilTransparent"
{
	Properties
	{
		_MainTex ("", 2D) = "" {}
		_Cutoff ("", Float) = 0.5
	}
	
	CGINCLUDE
	#include "HighlightingInclude.cginc"
	ENDCG
	
	SubShader
	{
		Pass
		{
			ZWrite Off
			ZTest Always
			Lighting Off
			Fog { Mode Off }
			
			CGPROGRAM
			#pragma vertex vert_alpha
			#pragma fragment frag_alpha
			#pragma fragmentoption ARB_precision_hint_fastest
			ENDCG
		}
	}
	
	Fallback Off
}


HighlightingStencilTransparentZ.shader

Shader "Hidden/Highlighted/StencilTransparentZ"
{
	Properties
	{
		_MainTex ("", 2D) = "" {}
		_Cutoff ("", Float) = 0.5
	}
	
	CGINCLUDE
	#include "HighlightingInclude.cginc"
	ENDCG
	
	SubShader
	{
		Pass
		{
			ZWrite On
			ZTest LEqual
			Lighting Off
			Fog { Mode Off }
			
			CGPROGRAM
			#pragma vertex vert_alpha
			#pragma fragment frag_alpha
			#pragma fragmentoption ARB_precision_hint_fastest
			ENDCG
		}
	}
	
	Fallback Off
}



HighlightingBlur.shader


Shader "Hidden/Highlighted/Blur"
{
	Properties
	{
		_MainTex ("", 2D) = "" {}
		_Intensity ("", Range (0.25,0.5)) = 0.3
	}
	
	SubShader
	{
		Pass
		{
			ZTest Always
			Cull Off
			ZWrite Off
			Lighting Off
			Fog { Mode Off }
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			
			#include "UnityCG.cginc"
			
			uniform sampler2D _MainTex;
			uniform half4 _MainTex_TexelSize;
			uniform half _OffsetScale;
			uniform fixed _Intensity;
			
			struct v2f
			{
				float4 pos : POSITION;
				half2 uv[4] : TEXCOORD0;
			};
			
			v2f vert (appdata_img v)
			{
				// Shader code optimized for the Unity shader compiler
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				
				half2 offs = _MainTex_TexelSize.xy * _OffsetScale;
				
				o.uv[0].x = v.texcoord.x - offs.x;
				o.uv[0].y = v.texcoord.y - offs.y;
				
				o.uv[1].x = v.texcoord.x + offs.x;
				o.uv[1].y = v.texcoord.y - offs.y;
				
				o.uv[2].x = v.texcoord.x + offs.x;
				o.uv[2].y = v.texcoord.y + offs.y;
				
				o.uv[3].x = v.texcoord.x - offs.x;
				o.uv[3].y = v.texcoord.y + offs.y;
				
				return o;
			}
			
			fixed4 frag(v2f i) : COLOR
			{
				fixed4 color1 = tex2D(_MainTex, i.uv[0]);
				fixed4 color2 = tex2D(_MainTex, i.uv[1]);
				fixed4 color3 = tex2D(_MainTex, i.uv[2]);
				fixed4 color4 = tex2D(_MainTex, i.uv[3]);
				fixed4 color;
				color.rgb = max(color1.rgb, color2.rgb);
				color.rgb = max(color.rgb, color3.rgb);
				color.rgb = max(color.rgb, color4.rgb);
				color.a = (color1.a + color2.a + color3.a + color4.a) * _Intensity;
				
				return color;
			}
			
			ENDCG
		}
	}
	
	Fallback off
}


HighlightingComposite.shader


Shader "Hidden/Highlighted/Composite"
{
	Properties
	{
		_MainTex ("", 2D) = "" {}
		_BlurTex ("", 2D) = "" {}
		_StencilTex ("", 2D) = "" {}
	}
	
	SubShader
	{
		Pass
		{
			ZTest Always
			Cull Off
			ZWrite Off
			Lighting Off
			Fog { Mode off }
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			
			#include "UnityCG.cginc"
			
			struct v2f
			{
				float4 pos : POSITION;
				half2 uv[2] : TEXCOORD0;
			};
			
			uniform sampler2D _MainTex;
			uniform sampler2D _BlurTex;
			uniform sampler2D _StencilTex;
			float4 _MainTex_TexelSize;
			
			v2f vert (appdata_img v)
			{
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				
				o.uv[0] = v.texcoord.xy;
				o.uv[1] = v.texcoord.xy;
				
				if (_MainTex_TexelSize.y < 0)
					o.uv[1].y = 1 - o.uv[1].y;
				
				return o;
			}
			
			fixed4 frag(v2f i) : COLOR
			{
				fixed4 framebuffer = tex2D(_MainTex, i.uv[0]);
				fixed4 stencil = tex2D(_StencilTex, i.uv[1]);
				
				if (any(stencil.rgb))
				{
					return framebuffer;
				}
				else
				{
					fixed4 blurred = tex2D(_BlurTex, i.uv[1]);
					fixed4 color;
					color.rgb = lerp(framebuffer.rgb, blurred.rgb, saturate(blurred.a - stencil.a));
					color.a = framebuffer.a;
					return color;
				}
			}
			
			ENDCG
		}
	}
	
	SubShader
	{
		Pass
		{
			SetTexture [_MainTex] {}
		}
	}
	
	Fallback Off
}






你可能感兴趣的:(unity3d,shader)