三言两语说shader(六)外发光、表面shader

来源:互联网 发布:java 图形界面案例 编辑:程序博客网 时间:2024/05/24 15:38

外发光(Rim Light),网上也很多例子。可用来做怪物受击时的身体闪光等。

我一开始以为和轮廓描边差不多,实际上样子是类似,原理还是完全不同的。

手头工程里有个顶点像素shader的例子,但是我发现Unity Surface Shader Examples里就有Rim Light,所谓简单就是美,直接贴这个官方例子,顺便说说Surface Shader好了。


考虑到这次的内容比较简单,多插入一些闲扯。

先贴个有意思的链接:

Shader的编写到底应该是美术的事情还是程序的事情?

去年这个时候有个老外给出了内容很丰富的回答,主要谈了技术美术(TA)的职责、以及shader的学习方法。


他提到一个观点是不要用Surface Shader,主要是效率并不高。然后学习最好从Cg入手,这点我还是比较赞同的。

实际上我也是先看Cg,在一开始刻意绕开了Surface Shader,因为自己一贯以来都是走的从底层到顶层的道路。


但话又说回来,既然Unity担心开发者写像素shader写光照写得太烦,好心好意作了封装提供这个东西,那我们顺着它的思路花点时间了解掌握的话,还是会很有帮助的。


关于Surface Shader,类似这种文章讲得比我深入细致多了,我也就不多重复了。

【Unity Shaders】初探Surface Shader背后的机制


下面贴个Rim Light效果图:


为了显眼我把光调成了红色。可以看到轮廓描边是在模型边缘外侧添色,而外发光仅仅是模型自身边缘内侧在变色。


以下是官方的代码,抄一遍,为了简明我把Tags也注掉了:

Shader "MyShader/RimLight" {    Properties {_MainTex ("Texture", 2D) = "white" {}_BumpMap ("Bumpmap", 2D) = "bump" {}_RimColor ("Rim Color", Color) = (0.26,0.19,0.16,0.0)_RimPower ("Rim Power", Range(0.5,8.0)) = 3.0    }    SubShader {//Tags { "RenderType" = "Opaque" }CGPROGRAM#pragma surface surf Lambertstruct Input {float2 uv_MainTex;float2 uv_BumpMap;float3 viewDir;};      sampler2D _MainTex;sampler2D _BumpMap;float4 _RimColor;float _RimPower;      void surf (Input IN, inout SurfaceOutput o) {o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));o.Emission = _RimColor.rgb * pow (rim, _RimPower);}ENDCG    }     Fallback "Diffuse"}

顺带分享一些学习方法。

当我们看到一些不认识的标识符、函数名等的时候,可以按以下步骤来:

1.到Unity官方文档搜索,看是不是ShaderLab的用词或句法。

2.到Unity安装目录下的Editor/Data/CGIncludes里搜。

3.到HLSL的msdn文档搜,看是不是Cg/HLSL的关键字或函数。Cg也有官方文档,要找也能找到,不过考虑到NVIDIA已经弃更了,就不谈了。

4.网上搜相关文章

5.技术群里问,比如乐乐同学的这个群就很不错 383373850


这里的UnpackNormal是UnityCG.cginc里的预定义函数,作用是从法线贴图取得法向量。

saturate是Cg/HLSL的内置函数,就是做一个Clamp。这句也是关键,意思是法向量和视线方向越垂直,rim值就越大。

最后Emission计算作了一个幂次计算,由于rim值是个0-1之间的小数,所以Power越大发光区域反而越细,Power设得比较小的时候就通体发光了。


0 0
原创粉丝点击