您的位置:首页 > 移动开发 > Unity3D

Unity Shader 二 发光Shader

2016-04-17 19:46 441 查看
哈哈,我又回来了,自从上篇的特效Shader之后,这是这个系列的第二弹。老实说这次想写的内容,我也考虑了很久,最终还是将内容暂定为使用的频率较多的外发光。其实外发光可以说是一个烂大街的Shader了,网上也有很多的例子。但是例子多不就从侧面说明了,这种类别的Shader的重要性吗?作为一个学习为主,内容为主的系列Shader,那么这次的主题就定为它了。。。。。。哈哈哈哈哈哈哈哈哈哈哈

不多说了,先上图:



从这个图片上面,大家也可以看出来,这个其实不是单纯的外发光效果,而是既有内发光也有外发光的效果。根据我的设定调整,这个shader的内发光是黄色的,外发光是白色的。调整系数如下所示:



接下来就到上代码的阶段,这才是最重要的,不过博主还想在这里差个题外话(哈哈,就是这么的啰嗦,来打我啊)。断断续续学习Shader也快有半年,老实说这半年里面在学习的道路上面一直有迷茫,有困惑。最近遇到的一个问题是程序员为什么要学习Shader ? 老实说一直到现在,我还是有些疑惑。但是,我觉得这并不应该成为妨碍我们广大猿猴类学习新技术的理由。(哈哈哈哈哈哈哈哈哈) 我个人的想法是学习Shader可以让我们更好地理解计算机图形学和渲染管线,学习Shader可以让我们更加深层次的理解Unity底层那些我们看不到的东西。比较渲染是每个大型引擎的重中之中,我们不应该只知其然而不知所以然。

而且从现实的层面上来说,目前流行的手机端,暂时限制于性能,一些特别的效果如果能够良好的使用shader来实现会节约很多的效率。

Shader "Custom/LightShader"
{
Properties {
_RimColor ("Rim Color", Color) = (1,1,1,0.5)
_InnerColor ("Inner Color", Color) = (1,1,1,0.5)
_InnerColorPower ("Inner Color Power", Range(0.0,1.0)) = 0.5
_RimPower ("Rim Power", Range(0.0,5.0)) = 2.5
_AlphaPower ("Alpha Rim Power", Range(0.0,8.0)) = 4.0
_AllPower ("All Power", Range(0.0, 10.0)) = 1.0
}
SubShader {
Tags { "Queue" = "Transparent" }

CGPROGRAM
#pragma surface surf Lambert alpha
struct Input {
float3 viewDir;
INTERNAL_DATA
};
float4 _RimColor;
float _RimPower;
float _AlphaPower;
//float _AlphaMin;
float _InnerColorPower;
float _AllPower;
float4 _InnerColor;
void surf (Input IN, inout SurfaceOutput o) {
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
o.Emission = _RimColor.rgb * pow (rim, _RimPower)*_AllPower+(_InnerColor.rgb*2*_InnerColorPower);
o.Alpha = (pow (rim, _AlphaPower))*_AllPower;
}
ENDCG
}
Fallback "VertexLit"
}


这个发光Shader是使用的Unity的surface shader编写的其实老实说看起来并不是很直观,因为里面的很多代码都是经过封装的。所以,代码封装是把双刃剑啊。那么还是老规矩,代码解析开始。

Properties {

_RimColor ("Rim Color", Color) = (1,1,1,0.5) //这个属性的意思是外发光的颜色

_InnerColor ("Inner Color", Color) = (1,1,1,0.5) //这个属性的意思是内发光的颜色

_InnerColorPower ("Inner Color Power", Range(0.0,1.0)) = 0.5 //这个值表示的意思是内发光的强度

_RimPower ("Rim Power", Range(0.0,5.0)) = 2.5 //这个值表示的意思是外发光的强度

_AlphaPower ("Alpha Rim Power", Range(0.0,8.0)) = 4.0 //这个值的意思是外发光的透明度的值

_AllPower ("All Power", Range(0.0, 10.0)) = 1.0 //这个值的意思是控制所有的发光效果的强度

}

Tags { "Queue" = "Transparent" }

因为要使用透明通道,所以这里要声明使用透明队列。

#pragma surface surf Lambert alpha

这句话的意思是使用surface里面封装好的Lambert alpha光照模型,老实说要把Lambert光照模型拆开将的话需要花费很长的时间,这里面包含了很多的内容,如果想要详细了解的话可以看我们的乐乐大神的讲解/article/1383346.html
(再次无情甩锅,哈哈哈哈哈哈哈哈哈)

float3 viewDir;

INTERNAL_DATA

通过声明INTERNAL_DATA,unity会帮你拿到的视向量,详细的可以再次看我们的乐乐大神的博客/article/1383369.html (不要拿西瓜皮丢我,哈哈哈哈哈哈)

float4 _RimColor;

float _RimPower;

float _AlphaPower;

//float _AlphaMin;

float _InnerColorPower;

float _AllPower;

float4 _InnerColor;

这些属性值,都是用来获得我们上面定义的那些在shader面板里面的值。

half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));

这是通过拿该点标准化过的视向量和法向量做点击,由此来算出该点的相应的光照值。

o.Emission = _RimColor.rgb * pow (rim, _RimPower)*_AllPower+(_InnerColor.rgb*2*_InnerColorPower);

o.Emission的代表的含义是该点的自发光强度,这个值是unity封装好的,详细可以看Unity官方API。这里是拿我们上面定义的外发光的rgb颜色值和rim的_RimPower次方和AllPower相乘,另外再加上InnerColor.rgb乘2再乘_InnerColorPower。

o.Alpha = (pow (rim, _AlphaPower))*_AllPower;

o.Alpha代表的含义是该点的透明度的值,通过rim的_AlphaPower次方的值再乘以_AllPower得到结果。

Fallback "VertexLit"

这个话的意思类似于备胎,就是在当前着色器不能用的时候,就使用这个(有点惨啊。。。。。)

其实可能大家觉得上面的运算看起来不直观,不明白是什么意思,在这里我想说一句名言:计算机图形学其实在某种程度上是用来欺骗眼睛的一门学科,这里很多的公式运算很多可能过多的是出于经验而不是纯科学理论。(才不是博主不知道而乱讲呢,嘻嘻嘻嘻嘻嘻嘻嘻嘻)

这次的Shader讲解就先到这里了,因为一些资料没有带回来,所以这次讲解的有点少,下次补上。

欢迎大家来和我交流,我的邮箱是609555184@qq.com , 大家也可以来群里面找我344682050,哈哈哈哈哈哈


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: