Shader 點光源和自陰影

2021-05-28 18:09:18 字數 2775 閱讀 6455

本教程基於教程4-法線對映。在實現乙個點光源前你無需知道法線對映,所以如果你只想知道如何實現乙個點光源,可以暫時無需理解教程4的知識。

這個教程只解釋什麼是點光源以及如何實現它,你可以在本教程使用的演算法之後新增法線對映或其他你需要的shader。

只要你理解了教程1,2,3,這個教程不是很難。

點光源(point lights,在某些渲染工具中也叫做omni light)的光線是從3d空間中的乙個點向四周發出的。

不像前面教程中的單向光,點光源有乙個作用範圍,光線傳播一段距離後會衰減為零,這叫做衰減因子(attenuation factor):

attenuation=1-((x/r )2+(y/r )2+(z/r )2)

公式中的r為衰減距離,公式也可表達為:

attenuation=1-(l/r )•(l/r )

如果用1減去v1=l/r和v2=l/r的點乘,就能獲得衰減因子。

在點光源光照範圍之外的物體只有環境光顏色,所以最後的光照方程如下:

i = a + diffuse*specular*attenuation

自陰影使用上述光照方程會遇到的乙個問題是:在漫反射和鏡面高光計算時會有一些顯示錯誤,當光線向量和視線向量方向相反時畫素也會被照亮,而且,如果光源距物體表面過近,也會有顯示錯誤。

解決上述問題的乙個方法是使用自陰影(self-shadowing),它可以避免不應該被照亮的畫素獲得光照。

當物體被遮擋或不應該獲得光照時,自陰影因子為零或接近於零,如果畫素被照亮,則這個因子大於零。

那麼如何實現呢?只需計算表面法線和光照方向的點乘即可:

s = saturate( n.l );

但是這裡的臨界值過低,所以將它乘以4才可以獲得正確的臨界值。

現在我們可以用s乘以漫反射和鏡面高光反射的顏色,這樣當s為零時顏色也為零!我們的新光照方程如下:

i = a + s*(diffuse*specular*attenuation)

這個方程可以進行優化,方法是只有當s大於零時才計算漫反射和鏡面高光反射,否則顏色就為零:if( s > 0) .

當使用法線對映時,我們是在切線空間中進行計算的。這個演算法讓我們可以使用光線向量的z分量,因為切線空間中的這個z分量就等於n•l. 所以有以下方程:

s = 4 * lightdirection.z;

首先我們需要宣告光照範圍:

view source

print?

1floatlightrange;

然後在頂點著色器中計算光照,將衰減值放在光源w分量,光線方向放在l向量中:

view source

print?

1// calculate distance to light in world space

2float3 l = veclightpos - posworld;

3

4// transform light to tangent space

5out.light.xyz = normalize(mul(worldtotangentspace, l));// l, light

6

7// add range to the light, attenuation

8out.light.w = saturate( 1 - dot(l / lightrange, l / lightrange));

剩下的事情就是在光照方程中使用衰減值和施加自陰影,這是在畫素著色器中進行處理的:

view source

print?

1floatshadow = saturate(4.0 * lightdir.z);

2....

3....

4return0.2 * color + shadow*((color * d * lightcolor + s*lightcolor) * (l.w));

如你所見,點光源與前面我們使用的單向光源區別不大,當使用光照時,自陰影值也可以用於前面的示例。

除了需要設定光照範圍和光源位置代替前面教程中的光線方向,xna**沒有其他變化:

view source

print?

1effect.parameters["veclightpos"].setvalue(vlightposition);

2effect.parameters["lightrange"].setvalue(100.0f);

3effect.parameters["lightcolor"].setvalue(vlightcolor);

shader之 多光源漫反射以及陰影

shader unlit mullight subshader cgprogram pragma vertex vert pragma fragment frag include unitycg.cginc pragma target 3.0 衰減與陰影的實現 include autolight.c...

點光源小孔成像matlab

模擬的r射線,不用考慮散 function spheresource h input source to collimator h input source to detector r input hole diameter d1 input pinhole1 parameter x y axis ...

opengl 教程 20 點光源

前面的教程中,我們在方向光的前提下,研究了基本的光照模型 環境光,漫反射光,高光 方向光沒有起點,所有光線都是沿著乙個方向,它的強度不會隨著距離的增加有任何變化。本篇教程中,我們開始研究點光源,點光源是起始於乙個點,向四面照射,會隨著傳輸距離增加而衰減,所以在點光源屬性中,我們會增加乙個光源位置。通...