【UnityShader自学日志】线框自发光着色器

1、新建一个无光照着色器(Unlit Shader),重命名为“Unlit_wire”

2、修改其代码如下

Shader "PACKT/unlit_wireframe1" {

	Properties
	{
		//线框着色器所需要的三个属性
		_Color("Color", Color) = (0,0,0,0) //模型的颜色
		_EdgeColor("Edge Color", Color) = (0,1,0,1) //线框的颜色
		_Width("Width", float) = 0.1 //线框的粗细
	}
	SubShader
	{
		//指定着色器以透明方式渲染
		Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }
		LOD 100
        
        //第一遍绘制背面
		Pass
		{
			//指定混合模式
			//混合模式,即产生新颜色的方式,可用下面公式来表达
			//新颜色 = 源颜色 * 源因数 + 目的颜色 * 目的因数
			//SrcAlpha和OneMinusSrcAlpha的含义为使用源颜色中的alpha通道值作为源因数,用1减去alpha通道值作为目的因数
			Blend SrcAlpha OneMinusSrcAlpha
			//渲染模型背面
			Cull Front
			//AlphaTest令着色器只渲染Alpha通道大于一定值的像素,而将小于该值的像素直接丢弃
			AlphaTest Greater 0.5 

			CGPROGRAM
			#pragma vertex vert  //顶点处理器函数vert
			#pragma fragment frag  //片元处理器函数frag

			uniform float4 _Color;
			uniform float4 _EdgeColor;
			uniform float _Width;

			//定义了顶点处理器的输入数据
			struct appdata
			{
				float4 vertex : POSITION; //顶点坐标
				float4 texcoord1 : TEXCOORD0; //贴图的纹理坐标
				float4 color : COLOR; //顶点颜色
			};

			//定义了由顶点处理器向片元处理器传送的数据
			struct v2f
			{
				float4 pos : POSITION;
				float4 texcoord1 : TEXCOORD0;
				float4 color : COLOR;
			};

			//顶点处理器代码
			//为模型的顶点计算正确的投影坐标,并且把顶点所对应的纹理坐标和颜色一起打包传送给片元处理器代码
			v2f vert(appdata v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.texcoord1 = v.texcoord1;
				o.color = v.color;
				return o;
			}

			//片元处理器代码
            //最终为模型在画面中覆盖的像素计算颜色值
			fixed4 frag(v2f i) : COLOR
			{
				fixed4 answer;

				float lx = step(_Width, i.texcoord1.x);
				float ly = step(_Width, i.texcoord1.y);
				float hx = step(i.texcoord1.x, 1.0 - _Width);
				float hy = step(i.texcoord1.y, 1.0 - _Width);

				answer = lerp(_EdgeColor, _Color, lx*ly*hx*hy);

				return answer;
			}
			ENDCG
		}


        //第二遍绘制正面
		Pass
			{
				Blend SrcAlpha OneMinusSrcAlpha
				Cull Back
				AlphaTest Greater 0.5

				CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

				uniform float4 _Color;
			    uniform float4 _EdgeColor;
			    uniform float _Width;

			    struct appdata
			    {
				    float4 vertex : POSITION; 
				    float4 texcoord1 : TEXCOORD0; 
				    float4 color : COLOR; 
			    };

			    struct v2f
			    {
				    float4 pos : POSITION;
				    float4 texcoord1 : TEXCOORD0;
				    float4 color : COLOR;
			    };

			    v2f vert(appdata v)
			    {
				    v2f o;
				    o.pos = UnityObjectToClipPos(v.vertex);
				    o.texcoord1 = v.texcoord1;
				    o.color = v.color;
				    return o;
			    }

			    fixed4 frag(v2f i) : COLOR
			    {
				    fixed4 answer;

			        float lx = step(_Width, i.texcoord1.x);
			        float ly = step(_Width, i.texcoord1.y);
			        float hx = step(i.texcoord1.x, 1.0 - _Width);
			        float hy = step(i.texcoord1.y, 1.0 - _Width);

			        answer = lerp(_EdgeColor, _Color, lx*ly*hx*hy);

			        return answer;
			    }
				ENDCG
			}
	}
	Fallback "Vertex Colored", 1
}

PS:对于透明渲染方式来说,必须先绘制距离摄像机较远的表面,后绘制较近的表面才能获得正确的透明结果。由于物体的背面一定比正面远,所以第一遍渲染必须先绘制背面。

PS Again:此着色器更加接近底层的硬件着色器,若想更加深入了解硬件着色器可查找“可编程图形管线”的相关知识。

 

你可能感兴趣的:(UnityShader)