環境光和漫反射光最大的區別在於:漫反射光依賴於光源的方向,而環境光和光源方向完全無關,環境光在場景中是均勻分布的,對場景中的所有物體都有效,而漫反射光在物體朝向光源的一面才有光照效果,在背面則沒有光照效果。
如下圖所示,除了光源方向,漫反射光還和物體表面的法向有關。
假設上圖中2個光束的強度都是一樣的,唯一不同的只是方向,則在左邊的圖中,物體表面光照要亮一些,因為光線是直射,而右邊的圖中,物體表面光照要弱一些,因為有乙個角度。
漫反射光照模型實際上基於
lambert's cosine law
,也就是說物體表面反射的光照強度和與光源方向和物體表面法向有關,光源方向和法向的夾角的越小,則物體表面反射的光強越大。 用公式表示就是光源的強度乘以光源和物體表面法向夾角的余弦值。
在上圖中,有四道光a,b,c,d,注意:物體表面法向和a重合,但方向相反。光線a和法向的夾角是0,余弦值就是1,所以a光速光照的強度最大,b次之,c和法向夾角是90度,所以光照強度是0,而d作用與物體的背面,余弦值是個負值,光照強度不可能是個負值,所以d的光照強度也是0,也就是說,光源要在物體表面有光照效果,光源方向和物體表面法向夾角必須是0-90度之間。
如果物體表面是個平面,那麼法向就是乙個固定的向量,但真實物體表面往往並不是平面,所以物體表面的法向是不斷變化的,如下圖中的兩個法向。
對三角形面來說,可以取它的面法向計算光照,此時三角形面上的光照是均勻的,但這種光照效果並不好,我們通常都是對每個頂點定義法向,而三角形面光柵化後的每個畫素,它的法向是由頂點法向插值得到。這種光照模型稱作
phong shading
, 下面就是頂點法向插值後的效果:
注意在片元shader中計算光照前,我們要把法向轉化到世界座標系中去,這樣得到的光照效果才真實的光照模型。
主要**:
lighting_technique.h
struct directionallight
;新的方向光結構,增加了2個成員變數:乙個是光源在世界座標系中的方向,乙個是漫反射的光照強度。
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texcoord;
layout (location = 2) in vec3 normal;
uniform mat4 gwvp;
uniform mat4 gworld;
out vec2 texcoord0;
out vec3 normal0;
void main()
這是更新後的頂點shader**,我們增加了乙個新的頂點屬性--法向,法向需要從物體的區域性座標系轉化到世界座標系中,所以我們增加了乙個uniform變數,用來傳入世界矩陣,該矩陣乘以法向向量,得到世界座標系中的法向向量,最後把該向量傳入到片元shader中去。注意:該**中一些glsl語法,vec4表示四維向量,.xyz表示取向量的前三維。
in vec2 texcoord0;
in vec3 normal0;
out vec4 fragcolor;
struct directionallight
;片元shader中,首先會接受插值的紋理座標和頂點法向,同時定義了乙個法向光的結構,該結構和c++**中的結構是一致的。
void main()
else
最後把紋理取樣的結果和光照的結果相乘,就是把它們混合起來,得到最終畫素的輸出顏色。
fragcolor = texture2d(gsampler, texcoord0.xy) * (ambientcolor + diffusecolor);
}lighting_technique.cpp
void lightingtechnique::setdirectionallight(const directionallight& light)
上面這個函式設定傳入shader的方向光引數,注意方向光方向會被歸一化。另外也會增加乙個設定世界矩陣的函式。
tutorial18.cpp
struct vertex
vertex(vector3f pos, vector2f tex)
};更新頂點結構,增加了法向,法向初始化為(0.0f, 0.0f, 0.0f)。
void calcnormals(const unsigned int* pindices, unsigned int indexcount, vertex* pvertices, unsigned int vertexcount)
for (unsigned int i = 0 ; i < vertexcount ; i++)
}上面這個函式計算三角形面的面法向,然後把三個頂點的法向都賦值面法向的值。
const matrix4f& worldtransformation = p.getworldtrans();
m_peffect->setworldmatrix(worldtransformation);
...
glenablevertexattribarray(2);
...
glvertexattribpointer(2, 3, gl_float, gl_false, sizeof(vertex), (const glvoid*)20);
...
gldisablevertexattribarray(2);
pipeline類中增加了世界矩陣,它是縮放,旋轉,平移座標的乘積。同時,我還使用了第三個頂點屬性,那就是法向。
程式執行後介面如下,可以通過x和z鍵控制漫反射強度。
Note Unity Shader 漫反射光照模型
公式 逐頂點與標準對比 為了使用在properties中的宣告的屬性,需要定義乙個和該屬性型別相匹配的變數!重點是變數!這是個變數!通過這樣的方式,我們就可以得到漫反射公式所需引數之一,材質的漫反射屬性 逐頂點光照會出現一些鋸齒,對於細分模型較低的模型,逐頂點會出現問題 逐畫素光照會在背光區,模型外...
漫反射光照模型
漫反射光照是用於對那些被物體表面隨機散射到各個方向的輻射的進行建模的,在漫反射中,視角的位置i是不重要的,因為反射是完全隨機的,因此可以認為在任何反射方向上的分布都是一樣的。但是入射光線的角度是很重要的。蘭伯特定律 反射光線的強度與表面法線和光源方向之間夾角的余弦值成正比。diffusecol li...
Unityshader 漫反射光照模型
基本光照漫反射計算公式 c diffuse c light m diffuse max 0,n l c light 為光源顏色和強度,可以由lighting.cginc中的 lightcolor0提供 m diffuse 為材質反射係數,一般自己定義在properties中 n為表面法線,l為光源方...