【Unity Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态
本系列文章由@浅墨_毛星云 出品,转载请注明出处。
文章链接: 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)的两种实现形态相关推荐
- 【Unity Shader编程】之十四 边缘发光Shader Rim Shader 的两种实现形态
分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由@浅墨 ...
- Shader编程】之十四 边缘发光Shader(Rim Shader)的两种实现形态
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/51764028 作者:毛星云(浅 ...
- unity物体边缘发光shader_Shaderlab Notizen 15 Rim Shader(边缘发光)的两种实现形态
一.实现思路 在正常的漫反射Shader的基础之上,在最终的漫反射颜色值出来之后,再准备一个自发光颜色值,附加上去,即得到了最终的带自发光的颜色值. 公式表达: 最终颜色 = (漫反射系数 x 纹理颜 ...
- JUC并发编程第十四篇,StampedLock(邮戳锁)为什么比ReentrantReadWriteLock(读写锁)更快!
JUC并发编程第十四篇,StampedLock(邮戳锁)为什么比ReentrantReadWriteLock(读写锁)更快! 一.ReentrantReadWriteLock(读写锁) 1.读写锁存在 ...
- CSDN 编程竞赛十四期题解
竞赛总览 CSDN编程竞赛十四期:比赛详情 (csdn.net) 本次竞赛题目难度适中,并且题目的解法(思路)也比较多,很适合新人学习. 竞赛题解 题目1.字符串全排列 对K个不同字符的全排列组成的数 ...
- 2019年6月日记-Unity Shader Graph 菲尼尔简单边缘发光
ShaderGraph 菲尼尔反射边缘光 创建菲尼尔反射节点,与Color节点相差获得边缘发光的颜色. 控制菲尼尔节点的大小,调出vector1节点来可视化调整. 新建Remap(重映射)节点,将Ti ...
- 边缘发光材质unity_Unity Shader Graph 小功能实现(一)边缘发光
在Unity 2018.2 版本正式启用了高清渲染管线,shader可视化编程. 现在我们就尝尝鲜,来实现了个物体边缘发光的shader效果. 准备 点击Windos->Package Mang ...
- [转]Windows Shell 编程 第十四章【来源:http://blog.csdn.net/wangqiulin123456/article/details/7988010】...
第十四章 设计Shell集成应用 有一些工具可以使应用程序更紧密地与Shell和底层系统进行集成.也就是说,用户可以象处理系统文档和程序那样处理你的文档和程序.例如,右击文件来显示可用功能列表等.Wi ...
- Unity 渲染教程(十四):雾
原文出处: http://gad.qq.com/program/translateview/7200863 这是关于渲染基础的系列教程的第十四部分.在前面的部分里我们介绍了延迟渲染.这一次我们将在场景 ...
最新文章
- Logback配置文件这么写,TPS提高10倍
- 柴油发电机为什么会出现故障?需要注意的5个常见原因
- 代理模式【介绍、静态代理、动态代理、入门、应用】
- Java Web学习总结(33)——Java Web 程序员如何转型大数据
- 给输入框添加自动检索的功能
- 卡车紧急刹车加强系统(发明畅想)
- Android内核开发:为什么刷机后系统第一次启动会很慢?
- Golang Web应用 创建docker镜像笔记(win 平台)
- 安卓:android.process.media意外停止解决方法
- Visual Studio使用技巧---(1-10)
- CDH 6系列(CDH 6.0.0、CHD 6.1.0等)安装和使用
- 【30-60s计数器电路设计】数电课设
- C++STL之<set>和<map>
- 微信 第三方开放平台 获取小程序授权并绑定小程序到开放平台(都是坑,留下帮助后人) 一
- 企业级呼叫中心 如何构建?
- 车载系统的电源状态及迁移
- 软件行业排名前100名的企业大全
- kafka发送消息的三种方式
- 建筑市场监管平台解密
- turbolinux mysql 5.0 cluste,PostgreSQL存在多个安全漏洞
热门文章
- Flex 是什么? flex和flash是什么关系?(转)
- 【简单】唯一摩尔斯密码词
- 详谈软件测试工程师的分级
- 【评测】SUPRAcap 100囊式深层过滤器 泽平科技一级代理
- MSN的底层通信做的实在不怎么样!
- Noilinux 2.0 wps2019不能输入中文解决办法!
- 统计学基本概念:均值、方差、标准差、协方差
- 聚乙烯亚胺(PEI)超细纤维负载Pd纳米粒子,GA-PEG-PLA 甘草次酸-聚乙二醇-聚乳酸定制合成
- 信用卡迎来史上最强风控?利用数据挖掘进行信用卡评分,提高银行的客户风险识别能力
- 解决方案:Zotero实现参考文献中英文混排,将英文文献中的“等”转成“et al.”