Unity之Shader在模型上渲染积雪效果-三

Unity之Shader在模型上渲染积雪效果

          在游戏中有时会用到下雪的场景,这样就需要在模型上产生积雪效果,这个工作如果要美术做贴图的话,这个工作量将是非常的庞大,比如下雪10分钟的积雪程度和下雪30分钟,50分钟肯定不一样,这样一个模型需要美术做好多积雪模型,这样美术会崩溃的,并且这么多贴图放在项目中,会造成资源包原来越大,不利于开发。

          这时利用Shader编程来实现积雪效果,通过调整某些设定好的数值改变积雪程度。

          下面进入Shader编程

首先在Project面包  Create->Shader,双击打开创建的Shader脚本,编写代码如下

<span style="font-size:14px;">Shader "Custom/BaseDiffuse" {
	Properties {
	    //基本贴图 类型为 2D 默认颜色为white
	    _MainTex ("Base (RGB)", 2D) = "white" {}
		//法线贴图 类型为 2D  
		_Bump ("Bump", 2D) = "bump" {}
		//定义一个滑动条,类型为 Range 取值范围 0 - 1
		_Snow ("Snow Level", Range(0, 1)) = 0
		// 定义一个颜色,类型为 Color 默认值为 (1, 1, 1, 1)
		_SnowColor ("Snow Color", Color) = (1, 1, 1, 1)
		//定义一个方向,类型为 Vector 默认值为 (0, 1, 0)
		_SnowDirection ("Snow Direction", Vector) = (0, 1, 0)
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf BasicDiffuse
		//在CG模块重新声明Properties模块中的变量
		sampler2D _MainTex;
		sampler2D _Bump;
		float _Snow;
		float4 _SnowColor;
		float4 _SnowDirection;

		struct Input { //定义 Input 结构,
			float2 uv_MainTex;
			float2 uv_Bump;
			float3 worldNormal; INTERNAL_DATA //如果SurfaceOutput中设定了Normal值的话,
			//通过worldNormal可以获取当前点在世界中的法线值
		};

		void surf (Input IN, inout SurfaceOutput o) {
		    // 获取UV贴图的值 

		    half4 c = tex2D (_MainTex, IN.uv_MainTex);

			//UnpackNormal是定义在UnityCG.cginc文件中的方法,这个文件中包含了一系列常用的CG变量
			//以及方法。UnpackNormal接受一个fixed4的输入,并将其转换为所对应的法线值(fixed3)

			o.Normal = UnpackNormal(tex2D(_Bump, IN.uv_Bump));

			//首先看这个条件的不等式的左侧,对雪的方向和输入点的世界法线方向进行点积。
			//WorldNormalVector通过输入的点和这个点的法线值,来计算它在世界坐标中的方向;
			//右侧的lerp函数:当Snow取最小值1时,这个函数将返回1,而Snow取最大值时,返回-1。
			//这样我们就可以通过设定Snow的值来控制积雪的阈值,要是积雪等级Snow是0时,不等
			//式左侧不可能大于右侧,因此完全没有积雪;相反要是_Snow取最大值1时,由于左侧必定大于-1,
			//所以全模型积雪。而随着取中间值的变化,积雪的情况便会有所不同。

			if (dot(WorldNormalVector(IN, o.Normal), _SnowDirection.xyz) > lerp(1, -1, _Snow))
			{
			    //达到积雪阀值的位置渲染雪的颜色
			    o.Albedo = _SnowColor.rgb;
			}else
			{
			    //未达到积雪阀值的位置渲染贴图颜色
			    o.Albedo = c.rgb;
			}
			o.Alpha = c.a;
		}

		// Shader中对于方法的名称有着比较严格的约定,想要创建一个光照模型,首先要做的是
		//按照规定的规则声明一个光照计算的函数名字,即 Lightig<FunctionName>,
		//对于BasicDiffuse方法名,名称要写为下方的LightingBasicDiffuse,光照模型的计算式在surf方法
		//的表面颜色之后,根据输入的光照条件对原来的颜色在这种光照下的表现进行计算,最后输出新的
		//颜色值给渲染单元完成在屏幕的绘制.

		inline float4 LightingBasicDiffuse(SurfaceOutput s, fixed3 lightDir, fixed atten)
		{
		    //s.Normal 光照表面法向量,lightDir 光线方向, atten 光强衰减
			// dot(s.Normal, lightDir) 为光照表面的法向量与光线方向的点积
			//max( , )返回两个参数中较大的一个

		    float difLight = max(0, dot(s.Normal, lightDir));
			float4 col;

			//下面的表达式是计算漫反射的公式
			//即 发射率 * 光颜色 * (光照表面的法向量与光线方向的点击) * 光照衰减
			//乘以2 是增强颜色值

			col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);

			//设置透明度

			col.a = s.Alpha;
			return col;
		}

		ENDCG
	} 
	FallBack "Diffuse"
}

</span>
创建材质球,选择材质球的Shader为自己创建的   Custom/BaseDiffuse 
然后选择模型相应的基本贴图和发现贴图,如下所示


设置 SnowLevel(下雪强度), Snow Color(雪的颜色),以及 Snow Direction(雪的方向)

效果如下所示



通过修改不同的参数达到不同的效果






































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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值