网站公告 | 首次推出unity3d 完整学习路线,最强课程配套、服务!详情点击
查看: 1244|回复: 6
收起左侧

[再来一次] UnityShader学习笔记(一) 漫反射着色

[复制链接]

[再来一次] UnityShader学习笔记(一) 漫反射着色[复制链接]

再来一次 发表于 2017-1-10 16:40:52 [显示全部楼层] 回帖奖励 |倒序浏览 |阅读模式 回复:  6 浏览:  1244
本帖最后由 再来一次 于 2017-1-10 16:44 编辑

      大家好,我是Zander。今天我们来学习一下漫反射着色器。任何优秀的着色器开始总会依赖于一个基础的漫反射组件或者光照模型。因此从漫反射部分开始着色器的编写是非常有意义的。
Baidu百科
    漫反射(diffuse)是指光线被粗糙表面无规则地向各个方向反射的现象。当一束平行光触及光滑物体表面时,光线则发生规律性反射,反射后的光线也相互平行,这种规律性反射称为光的单向反射或镜面反射。但物体的光滑程度是相对的,而一般物体的表面多粗糙不平,入射线虽然为平行光线,但反射后的光线则向各个方向分散,此种现象为光的漫反射。
实现:
添加属性:
[AppleScript] 纯文本查看 复制代码
_EmissiveColor ("Emissive Color", Color) = (1,1,1,1)
                _AmbientColor  ("Ambient Color", Color) = (1,1,1,1)
                _MySliderValue ("This is a Slider", Range(0,10)) = 2.5

Unity提供了很多类型让我们在着色器中使用,下面描述了这些类型:
                                                                  表面着色器的属性类型
Rang(min,max)创建Float属性、以滑动条的形式便于在最大值和最小值之间进行调节
Color创建色块,可以在Inspector面板上通过拾色器获取颜色值=(float,float,float,float)
2D创建纹理属性,允许直接拖拽一个纹理
Rect创建一个非2次方的纹理属性,作为2DGUI元素
Cube在Inspector面板上创建一个立方贴图属性,允许用户直接拖拽立方贴图作为着色器属性
Float在Inspector面板上创建一个非滑动条的float属性
Vector创建一个拥有4个Float值的属性,可以用以标记方向或颜色
参考:这些属性都记录在Unity手册里 ,网址 :https://docs.unity3d.com/Manual/SL-Properties.html  

现在我们创建了一些属性  ,我们可以在材质的Inspector面板上调整属性,如果我们想要在着色器代码里通过变量名来获得它的属性值,则必须在SubShader里面创建与之对应的另一个变量
[AppleScript] 纯文本查看 复制代码
float4 _EmissiveColor;
                float4 _AmbientColor;
                float _MySliderValue;
现在让我们将_EmissiveColor的属性值加到_AmbientColor属性值上,然后把计算结果赋给o.Albedo
[AppleScript] 纯文本查看 复制代码
void surf (Input IN, inout SurfaceOutput o) 
                {
                        float4 c;
                        c =  pow((_EmissiveColor + _AmbientColor), _MySliderValue);
                        
                        o.Albedo = c.rgb;
                        o.Alpha = c.a;
[color=#444444][font=Tahoma,]}
上面使用了一个Pow(arg1,arg2)函数,  大家可以在http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html查阅各种着色器的CG函数
这样一个简单的漫反射shader就完成了  ,全部代码:

[AppleScript] 纯文本查看 复制代码
Shader "Custom/BasicDiffuse" {
	Properties {
		_EmissiveColor ("Emissive Color", Color) = (1,1,1,1)
		_AmbientColor  ("Ambient Color", Color) = (1,1,1,1)
		_MySliderValue ("This is a Slider", Range(0,10)) = 2.5
	}

	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM	
		#pragma surface surf Lambert

	     float4 _EmissiveColor;
		float4 _AmbientColor;
		float _MySliderValue;
		
		

		struct Input 
		{
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o) 
		{
			float4 c;
			c =  pow((_EmissiveColor + _AmbientColor), _MySliderValue);
			
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		
		ENDCG
	}
	FallBack "Diffuse"
}

从实际的经验来看,我们永远不会认为一个只使用自带光照模型的项目是个好项目。我们希望创建自定义光照模型来实现各种效果,比如实现边缘高亮的效果、或者实现更多基于立方贴图的光照,接下来我们将介绍如何创建自定义光照模型。
将#pragma标记修改为如下代码:
[AppleScript] 纯文本查看 复制代码
#pragma surface surf BasicDiffuse
在subshader中加入如下代码:

[AppleScript] 纯文本查看 复制代码
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)
		{
			float difLight = max(0, dot (s.Normal, lightDir));
			
			float4 col;
			col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);
			col.a = s.Alpha;
			return col;
		}

保存后,和之前的对比如图:

实现原理:
   #pragma surface指令告诉着色器将使用哪个光照模型来计算。在我们创建的第一个着色器代码中,默认使用Lighting.cgnic文件里包含的Lambert光照模型,所以可以使用这种光照模型来计算。现在我们告诉着色器将使用名叫BasicDiffuse的光照模型;
   通过声明一个新的光照模型函数我们就能创建一个新的光照模型了,当完成了这个步骤后,便可以将函数名替换成你想要的任何名字。函数名的格式是 : Linghting<任意名字>。 你可以使用三种格式的光照模型函数:
     一:该函数用于不需要视角方向的前向着色。
[AppleScript] 纯文本查看 复制代码
half LightingName(SurfaceOutput s,half3 lightDir, half atten){}    

二:该函数用于需要视角方向的前向着色
[AppleScript] 纯文本查看 复制代码
half LightingName(SurfaceOutput s,half3 lightDir,half3 viewDir ,half atten){}

三:该函数用于需要使用延迟着色的项目。
[AppleScript] 纯文本查看 复制代码
half LightingName_PrePass(SurfaceOutput s,half4 light){}


点积函数是CG语言的另一个内置数学函数,我们可以用它来比较两个向量在空间里的方向。点积函数会检查两个向量是相互平行还是相互垂直。任意两个向量都可以通过点积函数获得-1 ~1的夹角范围,-1表示平行向量并背离你的方向,1也表示平行向量,不过是朝向你的方向,0表示和你垂直的方向向量
矢量点积(或内积)的归一化向量N和L是测量两个向量之间夹角的方法。两个向量之间的夹角越小,点积越大,表面可以接受的入射光也越多
  为了完成漫反射计算,我们需要将Unity和SurfaceOutput结构体提供给我们的数据做乘法运算。为此我们需要乘上s.Albedo(来自Sur的函数)和_LightColor0.rgb(来自Unity) 然后再将结果与(difLight * atten)相乘, 最后,返回这个值作为颜色值。

接下来我们创建一个HalfLambert光照模型
Half Lambert是由Valve公司提出的技术,是一种用于在低光照区域照亮物体的技术。它基本上提高了材质和物体表面周围的漫反射光照。
Half lambert光照模型最早用于《半条命》游戏的技术,它用来防止某个物体的背光面丢失形状并且显得太过平面化。这种技术是完全没有基于任何物理原理的,而仅仅是一种感性的视觉增强。
我们将上面自定义的光照模型的漫反射计算结果乘以0.5,然后讲下面的代码加入至光照函数里:
[AppleScript] 纯文本查看 复制代码
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)
		{
			float difLight = max(0, dot (s.Normal, lightDir));
			float hLambert  = difLight*0.5 +0.5;

			float4 col;
			col.rgb = s.Albedo * _LightColor0.rgb * (hLambert * atten * 2);
			col.a = s.Alpha;
			return col;
		}

三种漫反射对比如图:


在UnityShader中,我们还可以通过渐变纹理(ramp texture)来控制漫反射光照的颜色,这允许你突出表面的颜色,来模拟更多的反射光照或者或者其他高级的灯光设置。可以在很多卡通风格的游戏中看到这种技术,通常在你想要更加艺术的画面效果,并且不需要很多真实物理模拟的光照模型时可以使用渐变纹理。
准备一张渐变纹理图片:

修改光照函数:
[AppleScript] 纯文本查看 复制代码
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten)
		{
			float difLight = dot (s.Normal, lightDir);
			float hLambert = difLight * 0.5 + 0.5;
			float3 ramp = tex2D(_RampTex, float2(hLambert)).rgb;
			
			float4 col;
			col.rgb = s.Albedo * _LightColor0.rgb * (ramp);
			col.a = s.Alpha;
			return col;
		}



为了了解更多关于Unity内置的大量的Cg功能,我们可以访问Unity安装目录下的Unity5.4\Editor\Data\CGIncludes。不同的版本在相应不同的安装目录下,里面有三个文件需要特别注意,UnityCG.cginc 、Lighting.cginc和UnityShaderVariables.cginc。目前我们的着色器使用的正是这三个文件里的功能。

好了,这一章就写到这,欢迎大家加入QQ群:280993838 。或者关注我的公众号:




免费评分

参与人数 1泰斗币 +50 收起 理由
里斯 + 50 原创内容,666,再接再厉。。。.

查看全部评分

+1
1242°C
6
  • 里斯
  • 里斯
  • nham123
  • 铁蛋儿
  • 星星点灯
过: 他们
最近访问 头像模式 列表模式
因分享而快乐,学习以自强!
里斯 发表于 2017-1-10 16:43:46 显示全部楼层
膜拜神贴,后面的请保持队形~

刚一登陆就看到更新的文章,这个运气简直跟今天北京的天气一样。
因分享而快乐,学习以自强!
里斯 发表于 2017-1-10 16:43:50 显示全部楼层
膜拜神贴,后面的请保持队形~

刚一登陆就看到更新的文章,这个运气简直跟今天北京的天气一样。
因分享而快乐,学习以自强!
nham123 发表于 2017-1-11 17:29:07 显示全部楼层
dfgdf gfsgfdg dfgsdgfd dgdfsgfdg dfgdfsgfdsgdfgfd dfgfdgdfgfdgfdgsdfgfsdgfdsgfsdg
因分享而快乐,学习以自强!
铁蛋儿 发表于 2017-1-17 11:47:31 显示全部楼层
果断回帖,如果沉了就是我弄沉的很有成就感
因分享而快乐,学习以自强!
星星点灯 发表于 2017-1-23 10:34:29 显示全部楼层
不错,又占了一个沙发!
因分享而快乐,学习以自强!
钢之怪诞 发表于 2017-2-17 09:42:27 显示全部楼层
资源甚好,发帖艰辛,且阅且珍惜。
因分享而快乐,学习以自强!

本版积分规则

VR/AR版块|Unity3d|Unreal4|新手报道|小黑屋|站点地图|沪ICP备14023207号-9|【泰斗社区】-专注互联网游戏和应用的开发者平台 ( 沪ICP备14023207号-9 )|网站地图

© 2001-2013 Comsenz Inc.  Powered by Discuz! X3.2

1
QQ