shader学习之路(1)- half lambert
在学习这个shader之前先提个经常使用概念。即光照模型。LightModel(光照模型)即是对于物体怎么对打在其上的光做出视觉反应的数学模型。意即表达物体对光反应产生的视觉效果与入射光、物体表面属性等数值相关联的数学表达。
大致了解了光照模型的概念,接下来介绍下今天的主角,Half Lambert模型,该模型是Valve在开发经典游戏《Half-Life(半衰期)》(半条命这个译名真是后无古人的误翻啊……)是发明的,在曾经的游戏中。一旦模型背对着光源,模型表面的亮度会立马减少。使得整个模型显得平面化,毕竟游戏世界并不是像现实中有各种漫散射光能照亮背光的一面。所以half-lambert算法提高了物体在背对光源时的亮度,由于其并不是依据真实物理推算出来的结果。而不过一种视觉感受的提升,所以事实上现方式并不复杂。非常多shader入门书籍都介绍过这样的算法,不必操心全然看不懂。
未启用/启用half-lambert算法(右側为启用)
如今我们来看看怎么实现这个算法,首先由于vs对shaderkeyword高亮支持并不太好(联网工具包中的shader高亮插件事实上还行)。所以能够用引擎自带的mono dev或者sublime text来编写Cg文件,这个看大家个人喜好了,有空我会介绍下vs和sublime text对shaderkeyword高亮的设置。
打开unity3d,在project栏中的Assets下建立Materials Shader两个目录(良好的资源管理是开发工程的必要前提),在shader中创建一个surface shader并将之命名为halfLambert。
打开shader文件,能够看到默认的属性栏Properties。这以下的变量不仅要在以下的代码中使用。同一时候也能在引擎的inspector中进行调整。
如今我们将其改动为例如以下属性:
接下来在SubShader块中,能够看到这样一段定义
这是定义shader所使用的光照模型,由于我们是自己定义模型,所以要改为
还记得先前在Properties定义的三个变量吗,只在Properties中声明的话尽管能在inspector中看到。但还不能在subshader中使用,所以在SubShader块中须要再次声明,例如以下图
接下来我们開始编写该模型的主要部分,例如以下
这个函数的命名是有规则的,Lighting+模型名,该模型名称就是你刚才是在#pragma surface中命名的模型名称。这样unity就能自行编译链接该shader所使用的模型。
整个half-lambert模型的关键在于此
Lambert模型中的difLight在dot()方法下,处于[0,1]的范围中。因此hLambert的范围就在[0.5,1]中,提高了总体的漫反射值,其值的变化例如以下
剩余的则是surf代码
写完了shader代码后。如今须要将shader使用在物体上,在Material中建立一个新的Material,并将该shader拖入当中
在场景中建立一个Sphere后,将该Material赋予当中
最后效果如图,右側是未使用half-lambert算法的效果,能够看到half-lambert的确是明显提升了物体材质表面的亮度,在视觉上更加明亮。
完整代码例如以下:
Shader "Custom/halfLambert" { Properties { _EmissiveColor("Emissive Color", Color) = (1, 1, 1, 1) _AmbientColor("Ambient Color", color) = (1, 1, 1, 1) _SliderValue("Slider", Range(0,10)) = 2.5 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf HalfLambert // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 float4 _EmissiveColor; float4 _AmbientColor; float _SliderValue; inline float4 LightingHalfLambert(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; } struct Input { float2 uv_MainTex; }; void surf(Input IN, inout SurfaceOutput o) { float4 c; c = pow((_EmissiveColor + _AmbientColor), _SliderValue); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
P.S 初次写有关3d图形学的博客,时间仓促。还有好多内容没有说明确,还请各路大佬多多指导!
參考书目:
1.Unity Shaders and Effects Cookbook - (美)Kenny Lammers
2.Unity3d shader 编程 - 98jy.net,化石(编)
posted on 2018-01-24 13:29 yjbjingcha 阅读(222) 评论(0) 编辑 收藏 举报