WebGL 陰影的實現

2021-09-18 09:10:35 字數 1951 閱讀 4977

原理:根據光源與物體之間的距離(也就是物體在光源座標系下的深度z值),來決定物體是否可見。如下圖,同一條光線上有兩個點p1、p2,由於p2的z值大於p1,所以p2在陰影中。

需要使用兩對著色器:(1)一對著色器用來計算光源到物體的距離;(2)另一對根據(1)中計算出的距離繪製場景。

(2)如何使用(1)中的距離❓

使用一張紋理影象把(1)的結果傳入(2)中,這張紋理影象稱為 《陰影貼圖》。

通過陰影貼圖實現陰影的方法稱為 《陰影對映》。

陰影對映的過程:

1⃣️ 將視點移到光源的位置處,並執行(1)中的著色器。這時,那些『將要被繪出』的片元都是被光照射到的,即落在這個畫素上的各個片元中最前面的。並不實際繪製出片元的顏色,而是將片元的z值寫入到陰影貼圖中。

假設p1點z值為1,p2點z值為2,陰影貼圖中資料大概如下:

2⃣️ 將視點移回原來的位置,執行(2)中的著色器繪製場景。此時,計算出每個片元在光源座標系下的座標,並與陰影貼圖中記錄的z值比較,如果前者大於後者,就說明當前片元處在陰影之中,用較深暗的顏色繪製。

(1)、投影矩陣: 

matrix4.setperspective(fov, aspect, near, far)

//  fov - 垂直視角,即可視空間頂面和底面間的夾角,必須大於0.

//  aspect - 指定近裁剪面的寬高比,應當與canvas 保持一致

//  near,far - 近、遠裁剪面的位置。

⚠️ 光源的投影矩陣:aspect   需要使用生成的陰影貼圖的解析度,eg:256*256、1024*1024

⚠️ 正常繪製時的投影矩陣:aspect   使用canvas的解析度

(2)、生成陰影貼圖:

1⃣️ 使用 《光源處》 的檢視投影矩陣,繪製模型(模型可能存在偏移、旋轉等);

2⃣️ 儲存此時的 《光源下的模型檢視投影矩陣》 ;

3⃣️ 將光源視點下的每個頂點的深度值存入到陰影貼圖,儲存在幀緩衝區中。 

gl_fragcoord 的內建變數是vec4型別的,用來表示片元的座標。

gl_fragcoord.x 和 gl_fragcoord.y 是片元在螢幕上的座標,gl_fragcoord.z 是深度值。

它們是通過 (gl_position.xyz / gl_position.w)/2.0+0.5 計算的,並被歸一化到[0.0, 1.0]區間。

(3)、正常繪製模型:

1⃣️ 使用 《視點處》 的檢視投影矩陣,繪製模型(模型可能存在偏移、旋轉等);

2⃣️ 根據 《光源下的模型檢視投影矩陣》 計算模型在光源座標系下的頂點位置,頂點的位置需要進行歸一化;

webgl 中的x和y座標都是在[-1.0, 1.0]區間中的,紋理座標 s和t是在[0.0, 1.0]中的,所以需要將  模型在光源座標系下的頂點的x和y座標 轉化為 s和t座標:

vec3 shadowcoord = (v_positionfromlight.xyz / v_positionfromlight.w)/2.0+0.5;

shadowcoord.x 和 shadowcoord.y ,為當前片元在陰影貼圖中對應紋素的紋理座標,shadowcoord.z 為當前片元在光源座標系中的歸一化的z值。

3⃣️ 根據shadowcoord.x 和 shadowcoord.y,去獲取到陰影貼圖對應點紋素的深度值;

4⃣️ shadowcoord.z > 陰影貼圖對應點紋素的深度值,visibility 為0.5,即此位置的片元為 《陰影部分》;

shadowcoord.z < 陰影貼圖對應點紋素的深度值,visibility 為1.0,即此位置的片元為 《非陰影部分》;

**實現可參考:webgl實現陰影效果

webgl 平面陰影效果

在特定的3d場景中,陰影效果有時還是顯得十分重要的,在一般的3d引擎當中設定陰影可以直接通過對物體設定屬性來實現,十分的方便,這裡我們就用webgl來實現一下平面效果。平面陰影是通過燈光將物體的陰影投射在乙個平面內,但是物體之間沒有陰影的疊加,也就是說a物體的陰影不會投射到b物體上,在本案例中我們主...

WebGL光照陰影對映

經過前面的學習,webgl的基本功能都已經掌握了,我們不僅掌握了著色器的編寫,圖形的繪製,矩陣的變換,新增光照,還通過對webgl的基礎api封裝,編寫出了便利的工具庫.是時候進一步深入學習webgl的高階功能了,我認為要做逼真的3d特效,陰影絕對是乙個必不可少的環節.現在我們就在之前光照的基礎上新...

WebGL光照陰影對映

經過前面的學習,webgl的基本功能都已經掌握了,我們不僅掌握了著色器的編寫,圖形的繪製,矩陣的變換,新增光照,還通過對webgl的基礎api封裝,編寫出了便利的工具庫.是時候進一步深入學習webgl的高階功能了,我認為要做逼真的3d特效,陰影絕對是乙個必不可少的環節.現在我們就在之前光照的基礎上新...