unity3d shader的软高光的金属效果
来源:互联网 发布:数据分析方面的证书 编辑:程序博客网 时间:2024/04/29 15:25
学了书里的这一章有很多知识我也很不了解,于是查了一些资料,渐渐的明朗了一些,,一下结合书里的知识和网上的资料与我的理解来说明
主要原理是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的软高光的金属效果
- unity3d shader缔造金属各向异性效果
- unity3d的shader
- unity3d的shader编程
- Unity3D的Shader基本结构
- unity3d设置材质的shader
- Unity3D开发之Unity5版本自写Shader没有雾的效果问题
- unity3d shader之浮雕效果
- 金属字体的制作
- 金属材质的参数
- 腐蚀的金属字
- 基于shader的效果框架
- 基于shader的效果框架
- Unity3d Shader 内置的_Time的意思
- Unity3D中CG/GLSL shader与iPhone shader的区别
- [Unity3D] [Shader] 实现基于NDC的Sprite渐隐Shader
- unity3d shader学习(2)-unity shader的结构
- unity3d Shader学习(3)-unity shader的形式
- ios国际化-NSLocalizedString
- 连锁超市系统 欢迎咨询:QQ:460396970 超市内训群 群号:226057379 电话:13304839600 《待续》
- typedef和枚举、类类型
- Validate Binary Search Tree
- 整型数据在内存当中的存放形式
- unity3d shader的软高光的金属效果
- 23种设计模式全解析
- 2、titanuim studio添加按钮事件和信息输出
- Expression:(stream!=Null)问题
- weblogic制作证书实现HTTPS 完整版
- 预处理器变量
- 超市连锁软件 超市联盟大家园论坛
- OC概述
- CentOS 6.2系统详细启动流程