lambert
- Unity shader lambert光照模型与漫反射
- 一、漫反射简介
- 漫反射的特点
- 二、漫反射光照模型-Lambert(兰伯特)光照模型
- Lambert 余弦定理
- 三、自定义UnityShader实现漫反射(Diffuse)效果
- 写法
- 效果展示
- 参考
- 一、漫反射简介
Unity Shader Lambert光照模型与漫反射
一、漫反射简介
一束平行光入射到凹凸不平的表面上,光线被反射向四面八方的现象叫做漫反射。
当一束平行光触及光滑物体表面时,光线则发生规律性反射,反射后的光线也相互平行,这种规律性反射称为光的单向反射或镜面反射。但物体的光滑程度是相对的,而一般物体的表面多粗糙不平,入射线虽然为平行光线,但反射后的光线则向各个方向分散,此种现象为光的漫反射。
现实中的物体,如植物、墙壁、衣服等,其表面粗看起来似乎是平滑,但用放大镜仔细观察,就会看到其表面是凹凸不平的,人眼之所以能看清物体的全貌,主要是靠漫反射光在眼内的成像。
漫反射的特点
- 光照强度与观察角度没有关系
从各个角度观看灯光时,它都具有相同明显的强度
- 光照强度跟灯光的入射角有关系
如果改变光的入射光方向可以看到模型表面的光照强度发生了变化
二、漫反射光照模型-Lambert(兰伯特)光照模型
lambert光照模型属于经验模型,主要用来简单模拟粗糙物体表面的光照现象
此模型假设物体表面为理想漫反射体(也就是只产生漫反射现象,也成为Lambert反射体),同时,场景中存在两种光,一种为环境光,一种为方向光,然后我们分别计算这两种光照射到粗糙物体表面所产生的光照现象,最后再将两个结果相加,得出反射后的光强值。
首先是计算环境光的公式:
I_indirectionDiffuse = K_d * I_a;
其中,K_d为粗糙物体表面材质对光的反射系数,这个系数由程序编写者在宿主程序中给出,I_a为环境光的光强,也就是环境光的颜色数值,一般是一个float3型的变量
然后是计算方向光的公式:
I_directionDiffuse = K_d * I_l * max(0,dot(N, L));
其中I_l为方向光的光强,也就是其颜色值;N为顶点的单位法向量;L为入射光的单位法向量(注意,光照向量是从顶点指向光源的向量;也就是,它与线的传播方向正好相反)。
这个公式与计算环境光的不同,对于环境光,我们不关心它的方向,因为环境光也没有方向,它给予物体的光照在各个顶点处均是一样的。而方向光则需要关注其方向,例如一个聚光灯,灯从不同的角度来照射物体所产生的效果也是不一样的,光线方向越靠近法线,漫反射出来的光就越强,反之则越弱。 方向光的漫反射强度遵循Lambert余弦定理。
综上,得出漫反射后的光强为:
I_diff = K_d * I_a + K_d * I_l * max(0,dot(N, L));
Lambert 余弦定理
模型表面的明亮度直接取决于光线向量(light vector)和表面法线(normal)两个向量将夹角的余弦值。
f(θ) = max(cosθ,0) = max(L•n,0)
关于Lambert余弦定理的推导可参考:DirectX11 兰伯特余弦定理(Lambert)
三、自定义UnityShader实现漫反射(Diffuse)效果
写法
Shader "hidden/NewImageEffectShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_DiffusePower("Diffuse Power", Float) = 1.0
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct APPdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 normalDir : TEXCOORD1;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
// 将物体法线从物体坐标系转换到世界坐标系
o.normalDir = UnityObjectToWorldNormal(v.normal);
return o;
}
sampler2D _MainTex;
float _DiffusePower;
fixed4 frag (v2f i) : SV_Target
{
// 法线方向
float3 normalDirection = normalize(i.normalDir);
// 灯光方向
float lightDirection = normalize(_WorldSpaceLightPos0.xyz);
// 灯光颜色
float3 lightcolor = _LightColor0.rgb;
// 计算灯光衰减
float attenuation = LIGHT_ATTENUATION(i);
float3 attenColor = attenuation * _LightColor0.xyz;
// 基于兰伯特模型计算灯光
float NdotL = max(0,dot(normalDirection,lightDirection));
// 方向光
float3 directionDiffuse = pow(NdotL, _DiffusePower) * attenColor;
// 环境光
float3 inDirectionDiffuse = float3(0,0,0)+UNITY_LIGHTMODEL_AMBIENT.rgb;
// 灯光与材质球表面颜色进行作用
float3 texColor = tex2D(_MainTex, i.uv).rgb;
float3 diffuseColor = texColor *(directionDiffuse+inDirectionDiffuse);
float4 finalColor = float4(diffuseColor,1);
return finalColor;
}
ENDCG
}
}
}
效果展示
参考
Unity Shader-兰伯特光照模型与Diffuse Shader
相关阅读
关于Unity3D开发三星Gear VR的初步尝试(一):已实现打包
这两天老师催我把前段时间买的三星GearVR在Unity3D尝试打包,不然就白买了,到现在已经成功实现了打包。我把记录贴下来,以免未来可能
首先,说一下这款软件。。。 如果您的开发环境中只能使用正版软件,而又因种种原因无法获得专业级的建模工具,正苦苦寻找一个好用
Unity Shader-深度相关知识总结与效果实现(LinearDepth
前言 前言废话依旧比较多,感觉我是个写游戏体验评测的,233。最近想起了《恶灵附身》这款游戏的几个效果: 《恶灵附身》整款游戏
利用Animator实现骨骼动画: 1> 确保人物能够正常移动、Camera能够正常跟随 2> 使用WSAD对人物不同运动状态进行切换与连接 3> Le
http://blog.csdn.net/qinyuanpei/article/details/32355267 博主今天想和大家分享的是Unity3D中的动态阴影,昨天博主重温了一