软高光的金属效果

学了书里的这一章有很多知识我也很不了解,于是查了一些资料,渐渐的明朗了一些,,一下结合书里的知识和网上的资料与我的理解来说明

主要原理是Cook-Torrance光照模型的算法,是BRDF(双向反射分布函数)的一种,具体算法请看后面

新建一个shader

先浏览一下变量
_MainTint 主色调
_RoughnessTex   粗糙度贴图(控制高光大小)
_Roughness 表面粗糙程度
_SpecularColor  高光颜色
_SpecPower  高光强度

_Fresnel   菲涅尔值(反射系数)

 Properties {_MainTint ("Diffuse Tint", Color) = (1,1,1,1)_MainTex ("Base (RGB)", 2D) = "white" {}_RoughnessTex ("Roughness texture", 2D) = "" {}_Roughness ("Roughness", Range(0,1)) = 0.5//表面粗糙度 贴图_SpecularColor ("Specular Color", Color) = (1,1,1,1)//高光颜色_SpecPower ("Specular Power", Range(0,30)) = 2//高光强度_Fresnel ("Fresnel Value", Range(0,1.0)) = 0.05}

粗糙度越大反射的光越多,所以高光的范围也就越大,像漫反射就是太粗糙了

Fresnel菲涅尔值:

菲涅尔效果是根据观察者的观察表面来调整反射率来实现的。
比如你从水面,油漆表面或者丝绸的正上方看,反射光泽的柔和效果基本没有,如果侧着或平着看的话,反射光泽的柔和效果就很明显,这就是菲涅尔效果。
我们简单地通过点积操作计算表明法线与视线之间夹角的余弦值,再将这个值加权。
对于较平滑表面,加权系数设置较小之间(油漆效果,丝绸等),对于比较凹凸的表面,加权系数设置为更高(水波,液体等)。

算法方面:

主要在LightingMetallicSoft()函数里实现

     inline fixed4 LightingMetallicSoft(SurfaceOutput s, fixed3 lightDir,half3 viewDir, fixed atten){float3 halfVector = normalize(lightDir+ viewDir);//normalize转化成单位向量float NdotL = saturate(dot(s.Normal, normalize(lightDir)));//入射光与表面法线向量的点积当作漫反射光照强度因子float NdotH_raw = dot(s.Normal, halfVector);//两个单位向量的点积得到两个向量的夹角的cos值float NdotH = saturate(/*NdotH_raw*/dot(s.Normal, halfVector));//如果x小于0返回 0;如果x大于1返回1;否则返回x;把x限制在0-1float NdotV = saturate(dot(s.Normal, normalize(viewDir)));float VdotH = saturate(dot(halfVector, normalize(viewDir)));float geoEnum = 2.0 * NdotH;float3 G1 = (geoEnum * NdotV) / NdotH;float3 G2 = (geoEnum * NdotL) / NdotH;float3 G =  min(1.0f, min(G1, G2));//取小的float roughness = tex2D(_RoughnessTex, float2(NdotH_raw * 0.5 + 0.5, _Roughness)/*uv*/).r;float fresnel = pow(1.0-VdotH, 5.0);//pow()函数:求x的y次方(次幂)fresnel *= (1.0 - _Fresnel);fresnel += _Fresnel;float3 spec = float3(fresnel * G * roughness * roughness) * _SpecPower;float4 c;c.rgb = (s.Albedo * _LightColor0.rgb * NdotL)+  (spec * _SpecularColor.rgb) * (atten * 2.0f);//_LightColor0场景中平行光的颜色c.a = s.Alpha;return c;}

乍看可能有点眼晕,看我慢慢道来。。。= =

参数:
lightDir  光照方向
viewDir  当前坐标的视角方向
atten  光照的衰减值

dot()求点积
两个单位向量的点积得到两个向量的夹角的cos值

入射光与表面法线向量的点积当作漫反射光照强度因子
    
NdotL = saturate(dot(s.Normal, normalize(lightDir)));      
float NdotH_raw = dot(s.Normal, halfVector);
saturate(x)函数    如果x小于0返回 0;如果x大于1返回1;否则返回x;把x限制在0-1

float NdotH = saturate(dot(s.Normal, halfVector));
float NdotV = saturate(dot(s.Normal, normalize(viewDir)));
float VdotH = saturate(dot(halfVector, normalize(viewDir)));

以上求了各种方向的夹角cos值

查了一下维基

http://en.wikipedia.org/wiki/Specular_highlight#Cook.E2.80.93Torrance_model
翻译一下主要部分

Cook–Torrance光照模型用了一个反射(specular)的形式

//v viewDir 意为World Space View Direction。就是当前坐标的视角方向
//N normal法线方向向量     
//L light光线方向向量      
//H  半角向量用来计算镜面反射(specular reflection)的中间方向矢量(halfway vector)
//E  摄像机/人眼观察的方向向量
//G  几何衰减系数    描述由于微平面(microfacets)产生的自投影
//F  菲涅尔值(反射系数)
//D   微平面分布函数( Beckmann distribution factor )

本shader得算法与wiki的略有不同,
但G的求法完全相同:

如图为维基中求法:

以下为代码:

     <pre name="code" class="cpp">           float geoEnum = 2.0 * NdotH;float3 G1 = (geoEnum * NdotV) / NdotH;float3 G2 = (geoEnum * NdotL) / NdotH;float3 G =  min(1.0f, min(G1, G2));//取小的

方法是完全相同的。

从粗糙贴图的R通道中读取粗糙值roughness = tex2D(_RoughnessTex, float2(NdotH_raw * 0.5 + 0.5, _Roughness)/*uv*/).r;

求菲涅尔值(反射系数)

pow(x,y)函数:求x的y次方(次幂)

fresnel = pow(1.0-VdotH, 5.0);    fresnel *= (1.0 - _Fresnel);fresnel += _Fresnel;高光占整个物体比率 = 菲涅尔值(反射系数) * 几何衰减系数 * 粗糙值的平方再与外部可控的SpecPower高光强度做积spec = float3(fresnel * G * roughness * roughness) * _SpecPower;

最终反射颜色_LightColor0是场景中平行光的颜色atten是光照的衰减值 c.rgb = (s.Albedo * _LightColor0.rgb * NdotL)+  (spec * _SpecularColor.rgb) * (atten * 2.0f);

给出了三种不同粗糙程度的贴图如下:

粗糙度由上到下依次减弱

最后实现了一个这样的效果:

最右侧是最粗糙的也是亮的范围最大的,,左面的粗糙度依次减小

用胶囊体看的金属效果不是很明显(柔光较明显),各位可以用不同的模型试试

全代码如下:

Shader "Custom/testShader" {Properties {_MainTint ("Diffuse Tint", Color) = (1,1,1,1)_MainTex ("Base (RGB)", 2D) = "white" {}_RoughnessTex ("Roughness texture", 2D) = "" {}_Roughness ("Roughness", Range(0,1)) = 0.5//表面粗糙度 贴图_SpecularColor ("Specular Color", Color) = (1,1,1,1)//高光颜色_SpecPower ("Specular Power", Range(0,30)) = 2//高光强度_Fresnel ("Fresnel Value", Range(0,1.0)) = 0.05}SubShader {Tags { "RenderType"="Opaque" }LOD 200CGPROGRAM
#pragma surface surf MetallicSoft
#pragma target 3.0//软金属sampler2D _MainTex;sampler2D _RoughnessTex;//表面粗糙度 贴图float _Roughness;//表面粗糙度 值float _Fresnel;float _SpecPower;float4 _MainTint; float4 _SpecularColor;//viewDir 意为World Space View Direction。就是当前坐标的视角方向//N normal      //V view     //L light       //H  半角向量用来计算镜面反射(specular reflection)的中间方向矢量(halfway vector)inline fixed4 LightingMetallicSoft(SurfaceOutput s, fixed3 lightDir,half3 viewDir, fixed atten){float3 halfVector = normalize(lightDir+ viewDir);//normalize转化成单位向量float NdotL = saturate(dot(s.Normal, normalize(lightDir)));//入射光与表面法线向量的点积当作漫反射光照强度因子float NdotH_raw = dot(s.Normal, halfVector);//两个单位向量的点积得到两个向量的夹角的cos值float NdotH = saturate(/*NdotH_raw*/dot(s.Normal, halfVector));//如果x小于0返回 0;如果x大于1返回1;否则返回x;把x限制在0-1float NdotV = saturate(dot(s.Normal, normalize(viewDir)));float VdotH = saturate(dot(halfVector, normalize(viewDir)));float geoEnum = 2.0 * NdotH;float3 G1 = (geoEnum * NdotV) / NdotH;float3 G2 = (geoEnum * NdotL) / NdotH;float3 G =  min(1.0f, min(G1, G2));//取小的float roughness = tex2D(_RoughnessTex, float2(NdotH_raw * 0.5 + 0.5, _Roughness)/*uv*/).r;float fresnel = pow(1.0-VdotH, 5.0);//pow()函数:求x的y次方(次幂)fresnel *= (1.0 - _Fresnel);fresnel += _Fresnel;float3 spec = float3(fresnel * G * roughness * roughness) * _SpecPower;float4 c;c.rgb = (s.Albedo * _LightColor0.rgb * NdotL)+  (spec * _SpecularColor.rgb) * (atten * 2.0f);//_LightColor0场景中平行光的颜色c.a = s.Alpha;return c;}struct Input {float2 uv_MainTex;};void surf (Input IN, inout SurfaceOutput o) {half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;o.Albedo = c.rgb;o.Alpha = c.a;}ENDCG} FallBack "Diffuse"
}

-------by  wolf96

unity3d shader的软高光的金属效果相关推荐

  1. 【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 amp; 纹理混合...

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接: http://hpw123.net/a/C__/kongzhitaichengxu/2014/1117/120.html 作者:毛星 ...

  2. 【Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 纹理混合

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

  3. 【Unity3D Shader编程】之七 静谧之秋篇: 表面着色器的写法(二)—— 自定义光照模式

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

  4. 【Unity3D Shader编程】之七 静谧之秋篇 表面着色器的写法 二 —— 自定义光照模式

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  5. Unity3D Shader编程】之七 静谧之秋篇: 表面着色器的写法(二)—— 自定义光照模式

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

  6. 【浅墨Unity3D Shader编程】之七 静谧之秋篇: 表面着色器的写法(二)—— 自定义光照模式

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

  7. 【浅墨Unity3D Shader编程】之七 静谧之秋篇: 表面着色器的写法(二)——自定义光照模式

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://hpw123.net/plus/view.php?aid=183 作者:毛星云(浅墨)    微博:http://weibo ...

  8. 【Unity3D Shader编程】之五 圣诞夜篇 Unity中Shader的三种形态对比 混合操作合辑

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  9. 【游戏渲染】【译】Unity3D Shader 新手教程(1/6)

    http://gad.qq.com/article/detail/7175490 该文章来自用户转载 点击阅读原文 刚开始接触Unity3D Shader编程时,你会发现有关shader的文档相当散, ...

最新文章

  1. 构建Flex数据服务程序
  2. mysql删除重复记录
  3. 04、Vue.js---自定义过滤器
  4. (转)Three challenges you’re going to face when building a chatbot
  5. Python的交互式界面 编写 .
  6. 【原创】MVC+ZTree实现权限树的功能
  7. Java服务GC参数调优案例
  8. 怎么检测声音频率和幅值_【电缆小课堂】国网天津电缆公司电缆带电检测团队介绍及典型案例分析...
  9. QT每日一练day1:第一个程序
  10. 1432: 【蓝桥杯】:剪格子(迷宫问题变体)
  11. 当AD19原理图导出位PCB图时报错UnkownPin和Failed to add class member可能的解决办法
  12. tcp欢动窗口机制_Linux网络编程面试--滑动窗口的实现机制
  13. coolpad大神f2Android,酷派大神F2全高清版(8675-FHD Android 5.0)刷Recovery教程
  14. 李国庆PK刘强东:最失败是品类战略
  15. iOS 开发 申请299美金企业开发账号
  16. android动态开场,Android 开场动画
  17. 被墙了究竟是什么意思?
  18. 【Go】Go Ubuntu 安装 gvm:Go 版本管理工具
  19. 一名渗透工程师所必备的技能(一)
  20. ByteBuffer总结

热门文章

  1. 关于计算机二进制编码的游戏,信息编码游戏二进制教学案例
  2. JSONObject简介
  3. csdn最牛最全的使用python自动发送邮件
  4. 内网穿透原理,以及用花生壳实现内网穿透
  5. 设置QT软件的字体字库
  6. 3升桶和5升桶,倒出4升的水
  7. Python中with语句的作用
  8. 在线ps、在线平面设计以及图片无损放大
  9. 【案例4-5】图形的面积与周长计算程序
  10. 设备管理器如何改成锁定计算机,解决方案:为什么不能设置计算机指纹解锁设置?...