shader入门10 透明效果1

实现透明效果的方法

在Unity中我们通常有两种方法可以实现透明效果

1.透明度测试

透明度测试只能控制物体完全透明或者完全不透明,所以大部分情况下使用的都是透明度混合的效果

2.透明度混合

透明度混合需要考虑渲染顺序.之前从来没考虑过渲染顺序的问题是因为对于不透明物体,有深度缓冲这种机制的存在.

深度缓冲会对物体进行深度测试,原理利用缓存中的深度判断物体与摄像机之间的距离.
渲染一个片元时,如果它的深度比缓存深度高,说明它已经被某个物体遮挡住了,不应该渲染出来.
否则就渲染这个片元,并把颜色存入深度缓存中.

使用深度缓冲,我们不必关心渲染顺序,因为深度缓冲会判断相机的位置来进行渲染.而我们使用透明度混合时,被透明物体遮挡的物体,不论他的深度是否大于深度缓存,都应该被渲染出来.这就产生了矛盾.所以我们使用透明度混合时,是需要关闭深度写入的.这样不会更新深度缓存的值.
我们只关闭了深度写入,并没有关闭深度测试,所以不透明的物体依然可以遮挡透明物体.

unity为我们提供了一个默认的渲染队列来解决这个问题.
我们可以通过定义tag的方式实现透明度测试或者透明度混合

Tags{ "Queue"="AlphaTest"}//透明度测试
Tags{ "Queue"="Transparent"}//透明度混合
  • Background(1000) 最早被渲染的物体的队列。
  • Geometry (2000) 不透明物体的渲染队列。大多数物体都应该使用该队列进行渲染,也是Unity Shader中默认的渲染队列。
  • AlphaTest (2450) 有透明通道,需要进行Alpha Test的物体的队列,比在Geomerty中更有效。
  • Transparent(3000) 半透物体的渲染队列。一般是不写深度的物体,Alpha Blend等的在该队列渲染。
  • Overlay (4000) 最后被渲染的物体的队列,一般是覆盖效果,比如镜头光晕,屏幕贴片之类的。

代码

透明度测试代码

“IgnoreProjector”="True"关闭投影器影响
“RenderType”="Transparent"的作用请参考这篇文章 https://blog.csdn.net/u013477973/article/details/80607989

Shader "Custom/NewSurfaceShader"
{
	Properties{
		_Color("Color",Color) = (1,1,1,1)//贴图颜色
		_MainTex("Main Tex",2D) = "white"{}//贴图纹理
		_Cutoff("Alpha Cutoff",Range(0,1))=0.5//透明度测试中低于这个值的颜色会被消除
	}
	SubShader
	{
		Tags{"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="Transparent"}
		pass {
			Tags{ "LightMode" = "ForwardBase" }
			CGPROGRAM
			#include "Lighting.cginc"
			#pragma vertex vert
			#pragma fragment frag
			fixed4 _Color;//贴图颜色
			sampler2D _MainTex;//贴图纹理
			fixed _Cutoff;
			float4 _MainTex_ST;
			struct a2v {
				float4 vertex:POSITION;//赋值模型空间顶点位置
				float3 normal:NORMAL;//赋值模型空间法线
				float4 texcoord:TEXCOORD0;//第一张贴图
			};
			struct v2f {
				float4 position:SV_POSITION;//输出的屏幕位置
				float3 worldNormal: TEXCOORD0;//世界坐标系法线
				float3 worldPos : TEXCOORD1;//世界坐标系位置
				float2 uv:TEXCOORD2;//贴图纹理的uv
			};
			v2f vert(a2v v) {
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);//剪裁空间的位置
				f.uv = TRANSFORM_TEX(v.texcoord, _MainTex);//贴图纹理的uv + 缩放平移
				f.worldNormal = UnityObjectToWorldNormal(v.normal);//世界坐标法线
				f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//世界坐标的位置
				return f;
			}
			fixed4 frag(v2f f) :SV_Target{
				fixed3 worldNormal = normalize(f.worldNormal);//单位化
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(f.worldPos));//环境光方向
				fixed4 texColor = tex2D(_MainTex, f.uv);//贴图颜色
				clip(texColor.a - _Cutoff);//相减为负数则完全透明
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//环境颜色
				fixed halfLambert = 0.5 * dot(worldNormal,worldLightDir) + 0.5;//半兰伯特光照系数
				fixed3 diffuse = texColor.rgb* _Color.rgb * halfLambert * _LightColor0.rgb;//漫反射最终效果 Blinn-Phong模型的高光反射
				return fixed4(diffuse+ambient ,1);//最终效果
			}
			ENDCG
		}
	}
	FallBack "Transparent/Cutout/VertexLit"//设置合适的fallback
}

效果

低于_Cutoff的部分完全透明,看起来像个无头骑士一样
在这里插入图片描述

透明度混合代码


Shader "Custom/NewSurfaceShader"
{
	Properties{
		_Color("Color",Color) = (1,1,1,1)//贴图颜色
		_MainTex("Main Tex",2D) = "white"{}//贴图纹理
		_AlphaScale("_AlphaScale",Range(0,1))=1//透明度
	}
	SubShader
	{
		Tags{"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="Transparent"}
		pass {
			Tags{ "LightMode" = "ForwardBase" }
			ZWrite Off//关闭深度写入
			Blend SrcAlpha OneMinusSrcAlpha//设置混合因子 开启透明混合
			CGPROGRAM
			#include "Lighting.cginc"
			#pragma vertex vert
			#pragma fragment frag
			fixed4 _Color;//贴图颜色
			sampler2D _MainTex;//贴图纹理
			fixed _AlphaScale;
			float4 _MainTex_ST;
			struct a2v {
				float4 vertex:POSITION;//赋值模型空间顶点位置
				float3 normal:NORMAL;//赋值模型空间法线
				float4 texcoord:TEXCOORD0;//第一张贴图
			};
			struct v2f {
				float4 position:SV_POSITION;//输出的屏幕位置
				float3 worldNormal: TEXCOORD0;//世界坐标系法线
				float3 worldPos : TEXCOORD1;//世界坐标系位置
				float2 uv:TEXCOORD2;//贴图纹理的uv
			};
			v2f vert(a2v v) {
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);//剪裁空间的位置
				f.uv = TRANSFORM_TEX(v.texcoord, _MainTex);//贴图纹理的uv + 缩放平移
				f.worldNormal = UnityObjectToWorldNormal(v.normal);//世界坐标法线
				f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//世界坐标的位置
				return f;
			}
			fixed4 frag(v2f f) :SV_Target{
				fixed3 worldNormal = normalize(f.worldNormal);//单位化
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(f.worldPos));//环境光方向
				fixed4 texColor = tex2D(_MainTex, f.uv);//贴图颜色
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//环境颜色
				fixed halfLambert = 0.5 * dot(worldNormal,worldLightDir) + 0.5;//半兰伯特光照系数
				fixed3 diffuse = texColor.rgb* _Color.rgb * halfLambert * _LightColor0.rgb;//漫反射最终效果 Blinn-Phong模型的高光反射
				return fixed4(diffuse+ambient ,texColor.a*_AlphaScale);//最终效果
			}
			ENDCG
		}
	}
	FallBack "Transparent/VertexLit"//设置合适的fallback
}

效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值