006-基础Shader-贴图、法线贴图Shader实现

 用于学习《Unity Shader 入门精要》过程记录

 注意点:

1.声明贴图属性变量同名称变量  name_ST,存放贴图的缩放、平移信息

2.从法线贴图中获取法线的向量信息,在将向量信息转换至空间单位向量

3.法线向量信息参与漫反射颜色和光照颜色的计算

在场景中添加一个球体,将法线贴图Shader值给其Material,具体效果如下图

TexMain/TexBump 

 

 

Shader "ShaderStudy/006"
{
	//属性
	Properties
	{
		//定义一个颜色属性 ColorDiffuse
		_ColorDiffuse ("ColorDiffuse",Color)=(1,1,1,1)
		//定义一个颜色属性 ColorSpecular 用于高光反射
		_ColorSpecular("ColorSpecular",Color)=(1,1,1,1)
		//定义一个数值 FloatGloss 用于控制高光区域大小	(值越大,反射区域越小)
		_FloatGloss("FloatGloss",Range(1,200))=3
		//定义一个2D图片 _TexMain 用于存放表面贴图
		_TexMain("TexMain",2D)="white"{}

		//法线贴图
		_TexBump("TexBump",2D)="bump"{}
		//法线强度
		_FloatBump("FloatBump",Range(-1,1))=0
	}

	SubShader
	{
		Pass
		{
			//定义光照模型为 ForwardBase
			Tags{"LightMode"="ForwardBase"}

			//CG 程序开始
			CGPROGRAM

			//编译指令 顶点着色器代码在 name(vert)中
			#pragma vertex vert
			//编译指令 片元着色器代码在 name(frag)中
			#pragma fragment frag

			//添加Lighting.cginc库文件 包含_LightColor0
			#include "Lighting.cginc"

			//声明颜色属性变量  _ColorDiffuse
			fixed4 _ColorDiffuse;
			//声明颜色属性变量  _ColorSpecular
			fixed4 _ColorSpecular;
			//声明Float属性变量  _FloatGloss
			float _FloatGloss;
			//声明 2DTexture属性变量 _TexMain 存放颜色贴图
			sampler2D _TexMain;
			//声明float4属性变量 _TexMain_ST 存放图片的缩放和平移数据
			float4 _TexMain_ST;
			//声明 2DTexture属性变量 _TexBump 存放法线贴图
			sampler2D _TexBump;
			//声明float4属性变量 _TexMain_ST 存放图片的缩放和平移数据
			float4 _TexBump_ST;
			//声明Float属性变量 ——FloatBump 存放法线强度
			float _FloatBump;

			//定义结构体 用于顶点着色器的输入数据
			struct v2a
			{
				//定义 pos 为模型顶点位置信息
				float4 pos:POSITION;
				//定义 normal 为模型顶点法线信息
				float3 normal:NORMAL;
				//定义 texcoord 为第一组纹理坐标的顶点信息
				float4 texcoord:TEXCOORD0;
				//定义 tangent 为模型顶点的切线信息
				float4 tangent:TANGENT;
			};


			//定义一个结构,用于顶点着色器的输出数据
			struct v2f
			{
				//定义 posSV 为存放顶点的裁剪空间位置
				float4 posSV:SV_POSITION;
				//定义 uv 为存放主纹理和法线纹理经过缩放平以后对应的颜色坐标
				float4 uv:TEXCOORD0;

				//定义TtoW0,1,2 存放变换矩阵的信息
				float4 TtoW0:TEXCOORD1;
				float4 TtoW1:TEXCOORD2;
				float4 TtoW2:TEXCOORD3;
			};

			//顶点着色器 输入参数为结构体v2a(name)  输出参数为结构体 v2f(name)
			v2f vert(v2a v)
			{
				v2f o;
				//计算顶点坐标在 裁剪空间中的位置
				o.posSV=UnityObjectToClipPos(v.pos);

				//获取主纹理经过缩放和平移后对应的 颜色坐标
				o.uv.xy=v.texcoord.xy*_TexMain_ST.xy+_TexMain_ST.zw;
				//获取法线纹理经过缩放和平移后对应的 颜色坐标
				o.uv.zw=v.texcoord.xy*_TexBump_ST.xy+_TexBump_ST.zw;

				//将顶面坐标 转换成世界空间坐标
				float3 posWorld=mul(unity_ObjectToWorld,v.pos).xyz;
				//将顶点法线 转换至空间坐标
				fixed3 normalWorld=UnityObjectToWorldNormal(v.normal);
				//将顶点切线 转换至空间坐标
				fixed3 tangentWorld=UnityObjectToWorldDir(v.tangent.xyz);
				//将顶点负切线 转换至空间坐标
				fixed3 binormalWorld=cross(normalWorld,tangentWorld)*v.tangent.w;

				//给变换矩阵赋值
				o.TtoW0=float4(tangentWorld.x,binormalWorld.x,normalWorld.x,posWorld.x);
				o.TtoW1=float4(tangentWorld.y,binormalWorld.y,normalWorld.y,posWorld.y);
				o.TtoW2=float4(tangentWorld.z,binormalWorld.z,normalWorld.z,posWorld.z);

				return o;
			}


			//片元着色器 输入参数为结构体 v2f(name) 输出存贮到渲染目标
			fixed4  frag(v2f i) : SV_Target
			{
				//顶点在世界空间下的坐标
				float3 posWorld=float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
				//顶点到主光源的单位向量
				fixed3 normalLight=normalize(UnityWorldSpaceLightDir(posWorld));
				//顶点到摄像机的单位向量
				fixed3 normalView=normalize(UnityWorldSpaceViewDir(posWorld));
				
				//对法线纹理进行采样 获取纹理向量
				fixed3 bump=UnpackNormal(tex2D(_TexBump,i.uv.zw));
				//添加法线强度信息
				bump.xy*=_FloatBump;
				bump.z=sqrt(1.0-max(0,dot(bump.xy,bump.xy)));
				//将纹理向量 转换至空间单位向量
				bump=normalize(half3(dot(i.TtoW0.xyz,bump),dot(i.TtoW1.xyz,bump),dot(i.TtoW2.xyz,bump)));


				//获取片元在主帖图中的颜色信息
				fixed3 colorTexMain=tex2D(_TexMain,i.uv).rgb*_ColorDiffuse;
				//漫反射颜色
				fixed3 colorDiffuse=_LightColor0.rgb*colorTexMain*max(0,dot(bump,normalLight));

				//Blinn光照效果 场景中的主光线向量+视角向量  根据经验这样计算出的效果比较理想
				fixed3 normalHalf=normalize(normalLight+normalView);
				//光照颜色
				fixed3 colorSpecular=_LightColor0.rgb*_ColorSpecular.rgb*pow(max(0,dot(bump,normalHalf)),_FloatGloss);

				//环境光信息
				fixed3 colorAmbient=UNITY_LIGHTMODEL_AMBIENT.xyz*colorTexMain;

				//环境光的颜色+片元光照颜色+反光颜色
				return fixed4(colorAmbient+colorDiffuse+colorSpecular,1.0);
			}
			//CG程序结束
			ENDCG
		}
	}
	FallBack "Specular"
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值