本系列文章由@浅墨_毛星云 出品,转载请注明出处。  
文章链接: http://blog.csdn.net/poem_qianmo/article/details/51764028
作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442
本文工程使用的Unity3D版本: 5.2.1 

这篇文章主要讲解了如何在Unity3D中分别使用Surface Shader和Vertex & Fragment Shader来编写边缘发光Shader。

一、最终实现的效果

边缘发光Shader比较直观的一个运用便是模拟宇宙中的星球效果。将本文实现的边缘发光Shader先赋一个Material,此Material再赋给一个球体,加上Galaxy Skybox, 实现的效果如下图:

当然,边缘发光Shader也可以实现例如暗黑三中精英怪的高亮效果,将一个怪物模型本身的Shader用边缘发光Shader替代,实现效果如下图:

以下是本文实现的Shader在编辑器中的一些效果图。

  

  

二、Shader实现思路分析

思路方面,其实理解起来非常简单,就是在正常的漫反射Shader的基础之上,在最终的漫反射颜色值出来之后,再准备一个自发光颜色值,附加上去,即得到了最终的带自发光的颜色值。

按公式来表达,也就是这样:

最终颜色 = (漫反射系数 x 纹理颜色 x RGB颜色)+自发光颜色

按英文公式来表达,也就是这样:

FinalColor=(Diffuse x Texture x RGBColor)+Emissive

三、Surface Shader版边缘发光Shader实现

如果读过这个系列第一篇文章的朋友,应该还记得这个系列的第一篇文章(传送门:http://blog.csdn.net/poem_qianmo/article/details/40723789),里面的TheFirstShader,它就是一个标准的使用Unity Surface Shader实现的边缘发光Shader。

利用Unity自身的Shader封装,Surface Shader,也就是Shaderlab,算是新手或者想快速上手的童鞋学习Unity中Shader书写的一个非常好的切入点。

这边贴出经过加强的第一期TheFirstShader详细注释后的源代码。可以发现里面关于主要框架的注释都是中英双语的,因为发现不少国外友人也关注了我在Github上的Shader repo(https://github.com/QianMo/Awesome-Unity-Shader),为了方便他们以及后面更多的国外友人,以后如果周末写博客的时间充裕,就干脆写中英双语的注释得了。

OK,详细注释后的Surface Shader版可发光Shader源代码如下:

Shader "Learning Unity Shader/Lecture 14/Surface Rim Shader"
{//-----------------------------------【属性 || Properties】------------------------------------------  Properties{//主颜色 || Main Color_MainColor("【主颜色】Main Color", Color) = (0.5,0.5,0.5,1)//漫反射纹理 || Diffuse Texture_MainTex("【纹理】Texture", 2D) = "white" {}//凹凸纹理 || Bump Texture_BumpMap("【凹凸纹理】Bumpmap", 2D) = "bump" {}//边缘发光颜色 || Rim Color_RimColor("【边缘发光颜色】Rim Color", Color) = (0.17,0.36,0.81,0.0)//边缘发光强度 ||Rim Power_RimPower("【边缘颜色强度】Rim Power", Range(0.6,36.0)) = 8.0//边缘发光强度系数 || Rim Intensity Factor_RimIntensity("【边缘颜色强度系数】Rim Intensity", Range(0.0,100.0)) = 1.0}//----------------------------------【子着色器 || SubShader】---------------------------------------  SubShader{//渲染类型为Opaque,不透明 || RenderType OpaqueTags{"RenderType" = "Opaque" }//-------------------------开启CG着色器编程语言段 || Begin CG Programming Part---------------------- CGPROGRAM//【1】声明使用兰伯特光照模式 ||Using the Lambert light mode#pragma surface surf Lambert  //【2】定义输入结构 ||  Input Structstruct Input{//纹理贴图 || Texturefloat2 uv_MainTex;//法线贴图 || Bump Texturefloat2 uv_BumpMap;//观察方向 || Observation directionfloat3 viewDir;  };//【3】变量声明 || Variable Declaration//边缘颜色float4 _MainColor;//主纹理sampler2D _MainTex;  //凹凸纹理  sampler2D _BumpMap;//边缘颜色float4 _RimColor;//边缘颜色强度float _RimPower;//边缘颜色强度float _RimIntensity;//【4】表面着色函数的编写 || Writing the surface shader functionvoid surf(Input IN, inout SurfaceOutput o){//表面反射颜色为纹理颜色  o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb*_MainColor.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)*_RimIntensity;}//-------------------结束CG着色器编程语言段 || End CG Programming Part------------------  ENDCG}//后备着色器为普通漫反射 || Fallback use DiffuseFallback "Diffuse"
}

稍微琢磨一下就明白,此Shader其实就是用利用了Unity5中封装好的Standard Surface Output结构体中的Emission(自发光)属性,来达到这样的边缘光效果,技术含量很有限。这边附一下Unity5中的SurfaceOutputStandard原型:

// Unity5 SurfaceOutputStandard原型:
struct SurfaceOutputStandard
{fixed3 Albedo;                  // 漫反射颜色fixed3 Normal;                  // 切线空间法线half3 Emission;                 //自发光half Metallic;                    // 金属度;取0为非金属, 取1为金属half Smoothness;             // 光泽度;取0为非常粗糙, 取1为非常光滑half Occlusion;                 // 遮挡(默认值为1)fixed Alpha;                      // 透明度
};

将此Shader赋给Material后在编辑器效果图:

里面有6个参数,包括主颜色、纹理、凹凸纹理、边缘发光颜色、边缘颜色强度、边缘颜色强度系数这六个参数可以定制与调节,只要贴图资源到位,就很容易可以调出自己满意的效果来。

四、可编程Shader版边缘发光Shader的实现

这篇文章核心主要就是实现本节的这个可编程版(也就是Vertex & Fragment Shader)边缘发光Shader。大家知道,Vertex & Fragment Shader是比Surface Shader更高一段位的实现形态,有更大的可控性,更好的可编程性,可以实现更加丰富的效果,是更贴近CG着色语言的一种Shader形态。

OK,直接贴出经过详细注释的Vertex & Fragment Shader版边缘发光Shader实现源代码:

Shader "Learning Unity Shader/Lecture 14/Basic Rim Shader"
{//-----------------------------------【属性 || Properties】------------------------------------------  Properties{//主颜色 || Main Color_MainColor("【主颜色】Main Color", Color) = (0.5,0.5,0.5,1)//漫反射纹理 || Diffuse Texture_TextureDiffuse("【漫反射纹理】Texture Diffuse", 2D) = "white" {}    //边缘发光颜色 || Rim Color_RimColor("【边缘发光颜色】Rim Color", Color) = (0.5,0.5,0.5,1)//边缘发光强度 ||Rim Power_RimPower("【边缘发光强度】Rim Power", Range(0.0, 36)) = 0.1//边缘发光强度系数 || Rim Intensity Factor_RimIntensity("【边缘发光强度系数】Rim Intensity", Range(0.0, 100)) = 3}//----------------------------------【子着色器 || SubShader】---------------------------------------  SubShader{//渲染类型为Opaque,不透明 || RenderType OpaqueTags{"RenderType" = "Opaque"}//---------------------------------------【唯一的通道 || Pass】------------------------------------Pass{//设定通道名称 || Set Pass NameName "ForwardBase"//设置光照模式 || LightMode ForwardBaseTags{"LightMode" = "ForwardBase"}//-------------------------开启CG着色器编程语言段 || Begin CG Programming Part----------------------  CGPROGRAM//【1】指定顶点和片段着色函数名称 || Set the name of vertex and fragment shader function#pragma vertex vert#pragma fragment frag//【2】头文件包含 || include#include "UnityCG.cginc"#include "AutoLight.cginc"//【3】指定Shader Model 3.0 || Set Shader Model 3.0#pragma target 3.0//【4】变量声明 || Variable Declaration//系统光照颜色uniform float4 _LightColor0;//主颜色uniform float4 _MainColor;//漫反射纹理uniform sampler2D _TextureDiffuse; //漫反射纹理_ST后缀版uniform float4 _TextureDiffuse_ST;//边缘光颜色uniform float4 _RimColor;//边缘光强度uniform float _RimPower;//边缘光强度系数uniform float _RimIntensity;//【5】顶点输入结构体 || Vertex Input Structstruct VertexInput {//顶点位置 || Vertex positionfloat4 vertex : POSITION;//法线向量坐标 || Normal vector coordinatesfloat3 normal : NORMAL;//一级纹理坐标 || Primary texture coordinatesfloat4 texcoord : TEXCOORD0;};//【6】顶点输出结构体 || Vertex Output Structstruct VertexOutput {//像素位置 || Pixel positionfloat4 pos : SV_POSITION;//一级纹理坐标 || Primary texture coordinatesfloat4 texcoord : TEXCOORD0;//法线向量坐标 || Normal vector coordinatesfloat3 normal : NORMAL;//世界空间中的坐标位置 || Coordinate position in world spacefloat4 posWorld : TEXCOORD1;//创建光源坐标,用于内置的光照 || Function in AutoLight.cginc to create light coordinatesLIGHTING_COORDS(3,4)};//【7】顶点着色函数 || Vertex Shader FunctionVertexOutput vert(VertexInput v) {//【1】声明一个顶点输出结构对象 || Declares a vertex output structure objectVertexOutput o;//【2】填充此输出结构 || Fill the output structure//将输入纹理坐标赋值给输出纹理坐标o.texcoord = v.texcoord;//获取顶点在世界空间中的法线向量坐标  o.normal = mul(float4(v.normal,0), _World2Object).xyz;//获得顶点在世界空间中的位置坐标  o.posWorld = mul(_Object2World, v.vertex);//获取像素位置o.pos = mul(UNITY_MATRIX_MVP, v.vertex);//【3】返回此输出结构对象  || Returns the output structurereturn o;}//【8】片段着色函数 || Fragment Shader Functionfixed4 frag(VertexOutput i) : COLOR{//【8.1】方向参数准备 || Direction//视角方向float3 ViewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);//法线方向float3 Normalection = normalize(i.normal);//光照方向float3 LightDirection = normalize(_WorldSpaceLightPos0.xyz);//【8.2】计算光照的衰减 || Lighting attenuation//衰减值float Attenuation = LIGHT_ATTENUATION(i);//衰减后颜色值float3 AttenColor = Attenuation * _LightColor0.xyz;//【8.3】计算漫反射 || Diffusefloat NdotL = dot(Normalection, LightDirection);float3 Diffuse = max(0.0, NdotL) * AttenColor + UNITY_LIGHTMODEL_AMBIENT.xyz;//【8.4】准备自发光参数 || Emissive//计算边缘强度half Rim = 1.0 - max(0, dot(i.normal, ViewDirection));//计算出边缘自发光强度float3 Emissive = _RimColor.rgb * pow(Rim,_RimPower) *_RimIntensity;//【8.5】计在最终颜色中加入自发光颜色 || Calculate the final color//最终颜色 = (漫反射系数 x 纹理颜色 x rgb颜色)+自发光颜色 || Final Color=(Diffuse x Texture x rgbColor)+Emissivefloat3 finalColor = Diffuse * (tex2D(_TextureDiffuse,TRANSFORM_TEX(i.texcoord.rg, _TextureDiffuse)).rgb*_MainColor.rgb) + Emissive;//【8.6】返回最终颜色 || Return final colorreturn fixed4(finalColor,1);}//-------------------结束CG着色器编程语言段 || End CG Programming Part------------------  ENDCG}}//后备着色器为普通漫反射 || Fallback use DiffuseFallBack "Diffuse"
}

相信不少朋友已经看出来了,与普通的漫反射Shader相比,这个Shader的魔力就在于多出了“8.4准备自发光参数”和“8.5在最终颜色中加入自发光颜色"两个步骤而已,前面都是普通的Vertex & Fragment Shader常规写法。

将此Shader赋给Material,得到的效果如下:

  

  

当然,你也可以将这两个Shader用于场景中各种模型,以下是一组效果图:

OK,这篇文章的内容大致如此。我们下篇文章,再会。

附: 本文配套源码下载链接

【Github】本文Shader源码

【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态相关推荐

  1. 【Unity Shader编程】之十四 边缘发光Shader Rim Shader 的两种实现形态

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由@浅墨 ...

  2. Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://blog.csdn.net/poem_qianmo/article/details/51764028 作者:毛星云(浅 ...

  3. unity物体边缘发光shader_Shaderlab Notizen 15 Rim Shader(边缘发光)的两种实现形态

    一.实现思路 在正常的漫反射Shader的基础之上,在最终的漫反射颜色值出来之后,再准备一个自发光颜色值,附加上去,即得到了最终的带自发光的颜色值. 公式表达: 最终颜色 = (漫反射系数 x 纹理颜 ...

  4. JUC并发编程第十四篇,StampedLock(邮戳锁)为什么比ReentrantReadWriteLock(读写锁)更快!

    JUC并发编程第十四篇,StampedLock(邮戳锁)为什么比ReentrantReadWriteLock(读写锁)更快! 一.ReentrantReadWriteLock(读写锁) 1.读写锁存在 ...

  5. CSDN 编程竞赛十四期题解

    竞赛总览 CSDN编程竞赛十四期:比赛详情 (csdn.net) 本次竞赛题目难度适中,并且题目的解法(思路)也比较多,很适合新人学习. 竞赛题解 题目1.字符串全排列 对K个不同字符的全排列组成的数 ...

  6. 2019年6月日记-Unity Shader Graph 菲尼尔简单边缘发光

    ShaderGraph 菲尼尔反射边缘光 创建菲尼尔反射节点,与Color节点相差获得边缘发光的颜色. 控制菲尼尔节点的大小,调出vector1节点来可视化调整. 新建Remap(重映射)节点,将Ti ...

  7. 边缘发光材质unity_Unity Shader Graph 小功能实现(一)边缘发光

    在Unity 2018.2 版本正式启用了高清渲染管线,shader可视化编程. 现在我们就尝尝鲜,来实现了个物体边缘发光的shader效果. 准备 点击Windos->Package Mang ...

  8. [转]Windows Shell 编程 第十四章【来源:http://blog.csdn.net/wangqiulin123456/article/details/7988010】...

    第十四章 设计Shell集成应用 有一些工具可以使应用程序更紧密地与Shell和底层系统进行集成.也就是说,用户可以象处理系统文档和程序那样处理你的文档和程序.例如,右击文件来显示可用功能列表等.Wi ...

  9. Unity 渲染教程(十四):雾

    原文出处: http://gad.qq.com/program/translateview/7200863 这是关于渲染基础的系列教程的第十四部分.在前面的部分里我们介绍了延迟渲染.这一次我们将在场景 ...

最新文章

  1. Logback配置文件这么写,TPS提高10倍
  2. 柴油发电机为什么会出现故障?需要注意的5个常见原因
  3. 代理模式【介绍、静态代理、动态代理、入门、应用】
  4. Java Web学习总结(33)——Java Web 程序员如何转型大数据
  5. 给输入框添加自动检索的功能
  6. 卡车紧急刹车加强系统(发明畅想)
  7. Android内核开发:为什么刷机后系统第一次启动会很慢?
  8. Golang Web应用 创建docker镜像笔记(win 平台)
  9. 安卓:android.process.media意外停止解决方法
  10. Visual Studio使用技巧---(1-10)
  11. CDH 6系列(CDH 6.0.0、CHD 6.1.0等)安装和使用
  12. 【30-60s计数器电路设计】数电课设
  13. C++STL之<set>和<map>
  14. 微信 第三方开放平台 获取小程序授权并绑定小程序到开放平台(都是坑,留下帮助后人) 一
  15. 企业级呼叫中心 如何构建?
  16. 车载系统的电源状态及迁移
  17. 软件行业排名前100名的企业大全
  18. kafka发送消息的三种方式
  19. 建筑市场监管平台解密
  20. turbolinux mysql 5.0 cluste,PostgreSQL存在多个安全漏洞

热门文章

  1. Flex 是什么? flex和flash是什么关系?(转)
  2. 【简单】唯一摩尔斯密码词
  3. 详谈软件测试工程师的分级
  4. 【评测】SUPRAcap 100囊式深层过滤器 泽平科技一级代理
  5. MSN的底层通信做的实在不怎么样!
  6. Noilinux 2.0 wps2019不能输入中文解决办法!
  7. 统计学基本概念:均值、方差、标准差、协方差
  8. 聚乙烯亚胺(PEI)超细纤维负载Pd纳米粒子,GA-PEG-PLA 甘草次酸-聚乙二醇-聚乳酸定制合成
  9. 信用卡迎来史上最强风控?利用数据挖掘进行信用卡评分,提高银行的客户风险识别能力
  10. 解决方案:Zotero实现参考文献中英文混排,将英文文献中的“等”转成“et al.”