白話陰影繪製(Shadow Mapping)

2021-10-04 09:11:55 字數 2018 閱讀 6223

今天下午翻閱之前的**,然後翻到了繪製陰影,感覺陰影的實現過程應該有乙個類似於白話的說明易於理解,所以就拿出時間來寫寫,與大家共勉。好了我們閒話少敘,直入正題。

先宣告一下示例**主要來自於《webgl程式設計指南》

在這裡我們主要講思想:

1. 陰影是如何產生的

我們從生活中的常識講起,在生活中陰影是如何 產生的呢?光在直線傳播的過程**現了「遮擋物」, 因此遮擋物的下面光線就稍微弱一些,顯得稍微暗一些,從而就產生了陰影。

2. 原理結合三維圖形學

從陰影產生的常識性原理中我們可以得知,要判斷**是陰影就需要知道**產生了遮擋,而遮擋物又是如何產生的呢?我們細看會發現距離光源最近的物體就是遮擋物,那麼這個近該如何度量呢?這就是圖形學中的深度。所以我們就需要獲取光源視點下的***最近的物體***的深度。說到了這裡大家應該會想到乙個詞彙「深度圖 」

var shadow_vshader_source =

'attribute vec4 a_position;\n'

+'uniform mat4 u_mvpmatrix;\n'

+'void main() \n'

;// fragment shader program for generating a shadow map

var shadow_fshader_source =

'#ifdef gl_es\n'

+'precision mediump float;\n'

+'#endif\n'

+'void main() \n'

;

3.比較深度,確定陰影範圍。有了描述遮擋物的深度之後,問題來了我們應該怎麼樣確定陰影覆蓋範圍呢?細想一下接收陰影的物件是誰呢?這個不難發現是地面。因此我們也就得出了要把地面轉化到光源座標系下進行對比的操作,這裡有人可能會要問了,為什麼說是「轉化」呢?這裡就要涉及到另乙個視點的問題了,因為我們對於陰影實現的過程是乙個「旁觀者」的位置,所以這個渲染是基於觀察者座標系的,為了進行比較需要將這個比較從觀察者座標系轉化到光源座標系。在轉化到同一座標系後根據常識我們也知道如何確定陰影範圍了。

var vshader_source =

'attribute vec4 a_position;\n'

+'attribute vec4 a_color;\n'

+'uniform mat4 u_mvpmatrix;\n'

+'uniform mat4 u_mvpmatrixfromlight;\n'

+'varying vec4 v_positionfromlight;\n'

+'varying vec4 v_color;\n'

+'void main() \n'

;// fragment shader program for regular drawing

var fshader_source =

'#ifdef gl_es\n'

+'precision mediump float;\n'

+'#endif\n'

+'uniform sampler2d u_shadowmap;\n'

+'varying vec4 v_positionfromlight;\n'

+'varying vec4 v_color;\n'

+'void main() \n'

;

**解釋:

因為著色器中有一些隱含的渲染管線小知識,為了初學者便於理解在這裡解釋一下:

gl_fragcoord.z 片元著色器中的深度值 ,範圍[0-1]

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

v_positionfromlight除以w透視除法,經過透視除法後x y z變化到[-1-1]範圍內,為了與深度圖中的[0-1]之間的深度進行比較,需要將其轉化到[0-1]之間。

ShadowMap渲染陰影方法及問題

shadowmap基於的原理 sm演算法是乙個2 pass繪製演算法,第一pass從光源視點繪製場景,生成sm紋理,第2pass從視點檢視按常規方法繪製場景 從光源的位置觀察場景,這時候我們看不到的地方就是該有陰影的地方,於是可以使用比較畫素到光源距離的方法來確定某個畫素是否在陰影之中。於是我們需要...

ShadowMap實現軟陰影,使用整數紋理

陰影貼圖技術一般都是使用浮點紋理,這樣有足夠的精度來儲存深度值,不過,為了在不支援浮點紋理的顯示卡上使用陰影貼圖 比如很多整合顯示卡 就只好使用整數紋理,對效果的影響不是很大.於是,使用a8r8g8b8格式的紋理來儲存深度值,將深度值壓縮進rgba通道,方法如下 float4 floor fdept...

Canvas陰影繪製

陰影的繪製主要依賴以下四個屬性 const canvas document.getelementbyid canvas const ctx canvas.getcontext 2d 陰影的x偏移 ctx.shadowoffsetx 10 陰影的y偏移 ctx.shadowoffsety 10 陰影顏...