UnityShader入门精要第十三章代码解析(边缘检测)

基于深度法线纹理的边缘检测,使用卷积核Roberts,原理上是右下角的点的法线和深度值减去左上角的深度法线值,左下角的深度法线值减去右上角的深度法线值。

这两句为啥要这样写。。

int isSameDepth = diffDepth < 0.1 * centerDepth;

int isSameNormal = (diffNormal.x + diffNormal.y) < 0.1;

CS:

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

public class bianyuanCS : PostEffectsBase
{
    public Shader bianyuanShader;
    private Material bianyuanMaterial;

    public Material material
    {
        get
        {
            bianyuanMaterial = CheckShaderAndCreateMaterial(bianyuanShader, bianyuanMaterial);
            return bianyuanMaterial;
        }
    }

    [Range(0.0f, 1.0f)]
    public float edgesOnly = 0.0f;
    public Color edgeColor = Color.black;
    public Color backgroundColor = Color.white;
    
    //使用深度法线纹理时使用的采样距离
    public float sampleDistance = 1.0f;

    //灵敏度
    public float sensitivityDepth = 1.0f;
    public float sensitivityNormals = 1.0f;

    private void OnEnable()
    {
        GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
    }

    //在所有不透明物体被渲染完后调用
    [ImageEffectOpaque]
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if(material != null)
        {
            material.SetFloat("_EdgeOnly", edgesOnly);
            material.SetColor("_EdgeColor", edgeColor);
            material.SetColor("_BackgroundColor", backgroundColor);
            material.SetFloat("_SampleDistance", sampleDistance);
            material.SetVector("_Sensitivity", new Vector4(sensitivityNormals, sensitivityDepth,0.0f,0.0f));

            Graphics.Blit(source, destination, material);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }






}

SHADER:

Shader "Custom/bianyuanShader"
{
	Properties
	{
		_MainTex("Base(RGB)",2D) = "white"{}
		_EdgeOnly("Edge Only",Float) = 1.0
		_EdgeColor("Edge Color",Color) = (0,0,0,1)
		_BackgroundColor("Background Color",Color) = (1,1,1,1)
		_SampleDistance("Sample Distance",Float) = 1.0
		_Sensitivity("Sensitivity",Vector) = (1,1,1,1)
	}


	SubShader
	{
		CGINCLUDE

		#include "UnityCG.cginc"

		sampler2D _MainTex;
		float _EdgeOnly;
		fixed4 _EdgeColor;
		fixed4 _BackgroundColor;
		float _SampleDistance;
		fixed4 _Sensitivity;
		half4 _MainTex_TexelSize;

		sampler2D _CameraDepthNormalsTexture;

		struct v2f
		{
			fixed4 pos : SV_POSITION;
			half2 uv[5]: TEXCOORD0;
		};

		v2f vert(appdata_base v)
		{
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			half2 uv = v.texcoord;

			#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				uv.y = 1 - uv.y;
			#endif



			o.uv[0] = uv;


			o.uv[1] = uv + _MainTex_TexelSize * half2(1,1)  * _SampleDistance;
			o.uv[2] = uv + _MainTex_TexelSize * half2(-1,-1) * _SampleDistance;
			o.uv[3] = uv + _MainTex_TexelSize * half2(-1,1) * _SampleDistance;
			o.uv[4] = uv + _MainTex_TexelSize * half2(1,-1) * _SampleDistance;

			return o;

		}

		
		half CheckSame(half4 center,half4 sample)
		{
			half2 centerNormal = center.xy;
			half2 centerDepth = center.zw;
			half2 sampleNormal = sample.xy;
			half2 sampleDepth = sample.zw;

			//abs求整数的绝对值
			half2 diffNormal = abs(centerNormal -  sampleNormal) * _Sensitivity.x;
			half2 diffDepth = abs(centerDepth - sampleDepth) * _Sensitivity.y;

			int isSameNormal = (diffNormal.x + diffNormal.y) < 0.1;

			int isSameDepth = diffDepth < 0.1 * centerDepth;

			return isSameNormal * isSameDepth ? 1.0 : 0.0;
		}

		fixed4 frag(v2f i) : SV_Target 
		{
			//用四个坐标对深度法线图进行采样
			//tex2D()对_CameraDepthNormalsTexture进行采样
			//Unity提供了DecodeDepthNormal函数对采样结果进行解码
			//sample里面xy分量存储法线信息,zw分量存储深度信息
			half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv[1]);
			half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.uv[2]);
			half4 sample3 = tex2D(_CameraDepthNormalsTexture, i.uv[3]);
			half4 sample4 = tex2D(_CameraDepthNormalsTexture, i.uv[4]);

			half edge = 1.0;

			edge *= CheckSame(sample1,sample2);
			edge *= CheckSame(sample3,sample4);

			//
			fixed4 withEdgeColor = lerp(_EdgeColor,tex2D(_MainTex,i.uv[0]),edge);
			fixed4 onlyEdgeColor = lerp(_EdgeColor,_BackgroundColor,edge);

			return lerp(withEdgeColor,onlyEdgeColor,_EdgeOnly);

		}


		ENDCG

		Pass
		{
			ZTest Always Cull Off ZWrite Off

			CGPROGRAM

			#pragma vertex vert 
			#pragma fragment frag 

			ENDCG  
		}
	}
	FallBack Off
	


}

效果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值