Shader实现法线映射、透明效果

法线映射

实现原理:

按纹理映射方式先获取纹理坐标上的像素颜色值,由于颜色值范围在[0,1],法线值为[-1,1],可以使用UnpackNormal函数获取法线值
这里需要注意的是获取的法线值是在切线空间下的值,在使用漫反射公式时,直射光也需要统一转化为在切线坐标下


代码如下:
Shader "LJL/06-Normal" 
{
	Properties 
	{
		_Color("_Color",Color)=(1,1,1,1)
		_MainTex("_MainTex",2D)="white"{}
		_NormalTex("_NormalTex",2D)="bump"{}
		_BumpScale("_BumpScale",float)=1
	}
	SubShader 
	{
		Pass 
		{
			CGPROGRAM
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members wordSpacePosition)
#pragma exclude_renderers d3d11 xbox360

			#include "UnityCG.cginc"
			#include "Lighting.cginc"  

			#pragma vertex vert
			#pragma fragment frag 

			sampler2D _MainTex;
			sampler2D _NormalTex;
			fixed4 _Color;
			float4 _MainTex_ST;
			float4 _NormalMap_ST;
			float _BumpScale;

			struct a2v
			{
				float4 position:POSITION ;
				float3 normal:NORMAL;//固定写法,在调用TANGENT_SPACE_ROTATION宏时会调用
				float4 tangent:TANGENT;//同上
				float4 texcoord:TEXCOORD0 ; 
			};

			struct v2f
			{
				float4 position:SV_POSITION ;
				float4 texcoord:TEXCOORD0 ; 
				float3 tangentLightDir:TEXCOORD1 ;
			};

			v2f vert(a2v v)
			{
				v2f f;
				f.position=mul(UNITY_MATRIX_MVP,v.position) ;

				f.texcoord.xy = v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;
				f.texcoord.zw = v.texcoord.xy*_NormalMap_ST.xy+_NormalMap_ST.zw;

				TANGENT_SPACE_ROTATION ;//得到矩阵rotation,将模型空间转化为切线空间

				//将模型空间的光方向转化为切线空间下的方向
				f.tangentLightDir = normalize(mul(rotation,ObjSpaceLightDir(v.position)));

				return f;
			}

			fixed4 frag(v2f f):SV_Target
			{
				//获取主纹理颜色值
				fixed3 mainTexColor = tex2D(_MainTex,f.texcoord.xy)*_Color;

				//获取法线贴图颜色值
				fixed4 normalTexColor = tex2D(_NormalTex,f.texcoord.zw);
				float3 normalDir = UnpackNormal(normalTexColor);//将颜色值转化为法线值(切线空间下),其中normalDir.z的方向与法线方向一致(法线与切线垂直),normalDir.w决定切线空间方向
				normalDir.xy = normalDir.xy*_BumpScale;//改变xy的值将改变凹凸效果
				normalDir = normalize(normalDir);

				float3 diffuse = _LightColor0.rgb*mainTexColor*max(dot(normalDir,f.tangentLightDir),0);

				float3 temp = diffuse+_LightColor0.rgb*mainTexColor;

				return fixed4 (temp,1);
			}

			ENDCG	
		}
	}

	Fallback "Diffuse"
}



透明效果

实现原理:

控制SV_Target的aphla值,但是在改变aphla中的值时需要对其Pass块加入一些Tags属性

代码如下:
Shader "LJL/07_Aphla" 
{
	Properties 
	{
		_Color("_Color",Color)=(1,1,1,1)
		_AphlaScale("_AphlaScale",Range(0.0, 1.0)) = 0.5
	}
	SubShader 
	{

		Tags{ "Queue"="Transparent" "IngnoreProjector"="True" "RenderType"="Transparent" }

		Pass
		{

			Tags{ "LightMode" = "ForwardBase" }

			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			

			CGPROGRAM

			#include "UnityCG.cginc"
			#include "Lighting.cginc"  

			#pragma vertex vert
			#pragma fragment frag

			fixed _AphlaScale;
			fixed4 _Color;

			struct a2v
			{
				float4 position:POSITION ;
			};

			struct v2f
			{
				float4 position:SV_POSITION ;
			};

			v2f vert(a2v v)
			{
				v2f f;

				f.position=mul(UNITY_MATRIX_MVP,v.position);

				return f;
			}

			fixed4 frag(v2f f):SV_Target
			{
				fixed aphla=_Color.a*_AphlaScale;

				return fixed4(_Color.rgb,aphla);
			}

			ENDCG
		}
	}

	Fallback "Diffuse"
}


效果如下图:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值