1. 程式人生 > >shader之——球形煙霧 &&CG函式saturate與abs的用法

shader之——球形煙霧 &&CG函式saturate與abs的用法

今天接到個需求,做一個球形的煙霧,讓3D場景自己在場景裡去擺放,貼圖不是4方連續的,所以看上去有接縫哈,具體的讓特效自己去調效果了:


遇到了一個從來都沒注意過的問題,做了一個球形的煙霧,用了邊緣透明的方式,同時用了Cull Off,但是無論如何都無法顯示背面,找到了原因,在此記錄一下。

shader程式碼如下:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "effects/Smoke"{
Properties {
	_MainTex ("Base layer (RGB)", 2D) = "white" {}
	_ScrollX ("Base layer Scroll speed X", Float) = 1.0
	_ScrollY ("Base layer Scroll speed Y", Float) = 0.0
	_brightness ("brightness", Float) = 2.0
	_color("color",color) = (1,1,1,1)
}

	
SubShader {
	
	Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }

	pass {

	Zwrite Off 
	Cull Off 
	Blend SrcAlpha OneMinusSrcAlpha
	LOD 100

	CGPROGRAM
	#pragma vertex vert
	#pragma fragment frag
 	#include "UnityCG.cginc"

	sampler2D _MainTex;
	float4 _MainTex_ST;
	float _ScrollX;
	float _ScrollY;
	float _brightness;
	fixed4 _color;

struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
    float4 texcoord : TEXCOORD0;
    fixed4 color : COLOR;

};
	struct v2f {
		float4 pos : SV_POSITION;
		float2 uv : TEXCOORD0;
		fixed4 color : TEXCOORD1;
		float NdotV :TEXCOORD2;
	};

	
	v2f vert (appdata v)
	{
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);
		o.uv = TRANSFORM_TEX(v.texcoord.xy,_MainTex) + frac(float2(_ScrollX, _ScrollY) * _Time);
		o.color =  v.color;
		float3 Normal =UnityObjectToWorldNormal( v.normal);
		float3 ViewDir =normalize( WorldSpaceViewDir( v.vertex));
	    o.NdotV =pow (abs(dot (Normal,ViewDir)),3);
		return o;
	}


	fixed4 frag (v2f i) : COLOR
		{
			fixed4 tex = tex2D (_MainTex, i.uv);
			fixed4 o = tex * i.color * _brightness * _color;
			o.a = tex.r * i.color.a * i.NdotV;
			return o;
		}
	ENDCG
	}
   }
}
saturate 與 abs 
o.NdotV =pow (saturate(dot (Normal,ViewDir)),3);
這裡剛開始用了saturate,結果怎麼都不顯示雙面,折騰了好久,師傅告訴我,saturate不是這麼用的 

saturate返回是0到1,而小於0的時候,也就是物體的背面,他永遠是返回0

abs 返回的是絕對值,他才可以把物體背面的法線由負方向變成正常向