Wednesday, November 28, 2007

Screen Space Ambient Occlusion

Crysis大受注目後, SSAO也開始紅了起來, 因此我上網查了一下資料, 想說寫一個DX10.1的sample, 藉此來展示一下新的multi-sample depth buffer的存取功能. 在網路上找到幾篇不錯的資料, 大致上找到三種作法.

第一種就是Crysis的做法, 使用depth buffer中的資料, 將pixel還原至世界座標, 然後在周圍空間中的點中取樣, 將取樣點的Z值跟viewport中對應pixel的Z值比較來決定出遮蔽的比例. 基本上這個做法物理上完全不正確, 但他可以在面的交接處產生陰影, 讓人"感覺"好像有AO. 我目前是使用這個方法, 之後還會再試試其它做法. 再這裡有完整的實作介紹. Crytek的原始文件可以在這裡找到, 不過只有短短18行, 所有些東西還是得自己try.

第二個做法則是類似deferred shader的做法, 使用兩個buffer來紀錄每個pixel的位置及法向量, 然後根據附近pixel的資料, 距離以及法向量的夾角, 求出相對應的遮蔽的比例. 接下來我會試驗看看這個方法, 在這裡有完整的實作介紹. 這個方法我感覺比較接近真正的AO, 也許效果會更好一些 . 不過跟第一種方法比就是要多花一些記憶體空間.

第三種做法則是將問題分為兩部分, 高頻與低頻. 高頻代表的就是物體面與面之間的交物作用, 也就是local的部分. 這部分可以使用SSAO解決, 上面兩種方法都可以. 至於彽頻部分則是物件與物件的交互作用部分, 也就是global的部分. 這部分則是使用object space的方式使用proxy來解決. 這個做法聽起來挺不錯的, 而且scaleable, 對於配備低的電腦就只用SSAO.這裡可以找到詳細的說明.

即時AO的好處除了節省記憶體外, 另一個最大好處就是可以做到動態AO. 另外在網路上也發現到一篇關於即時動態AO的文章, 有興趣的在這裡可以找到更詳細資料.

放上一段使用第一種方法在動態物件上的影片, 效果不是非常的滿意, 我想還需要再多做一些試驗. 之前有用R2VB做過動態AO, 但效能太差, 不太可能應用再真實遊戲上. 我覺得視覺上的70%正確比起物理上的90%正確更符合遊戲的需要.

8 comments:

Anonymous said...

Crysis真的是好強
不過看到B主,你的Engine
感覺到台灣的驕傲也

你寫的Normal Map讓我學到很多

Anonymous said...

前輩您好

小弟目前剛好也在實做SSAO
有些問題想要請教

根據小弟的了解
SSAO是將ScreenSpace的頂點反推回ViewSpace
然後查詢附近的頂點深度與DepthMap的值作比較

問題在於
如果將上面結果直接繪出
會發現畫面上的灰色的深淺會根據攝影機改變 而產生變化
不知道這是否是正常的現象

另外
在ScreenSpace反推回ViewSpace時
我目前所用的矩陣都是取Shader預設的矩陣
這方法是否正確

先感謝前輩撥冗指教

fallingCAT said...

因為是Screen Space AO, 因為攝影機移動而產生一些差異是正常的.

至於reconstruct view space position, 我使用的方法是在四個vertex中輸入攝影機到四個端點的向量, 在ps中直接將此向量乘上深度值就可以得到view space position, 你可以參考看看.

Unknown said...

前輩您好

您提到的"四個vertex中輸入攝影機到四個端點的向量",所謂四個vertex是指隨意的四個點嗎?還是有其他的意思呢?

感謝前輩指點迷津 ^^

fallingCAT said...

因為是Screen Space, 這四點指的是Screen Quad的四個端點.

Anonymous said...

您好~ 初次拜訪,第一個想問的就是... 什麼是AO呢? :P 一下子想不到這是什麼的縮寫...

以後會常來逛的!

fallingCAT said...

AO -> Ambient Occlusion

Anonymous said...

前輩您好:
小弟目前也在實作SSAO,參考的資料是ShaderX7裡6.1章節的SSAO的文章,不過作法因該是跟Crysis的作法一樣,可是小弟一直搞不懂文章裡用的Sampling的方法,文章裡是用"randomly rotated kernel of sample vector"的方式,看他的Pixel shader code 裡面是將rotate vector 存在一張4X4的貼圖哩,之後再從裡面取得rotated vector並且轉成rotated matrix,不過小弟怎麼推都推不出結果,所以才想請問前輩關於這個部分的理論。
謝謝!