2023年3月30日 星期四

Custom Projection Matrix to fit Vulkan default viewport

➡️ 前篇


客製化Projeciton Matrix

為了fit Vulkan奇怪的NDC

需要

Mb * Ma = Projection Matrix

Ma怎麼來?

Ma

Mb怎麼來?

當NDC的z落在-1~1之間 🐞
Mb

Fix 🐞

vulkan NDC的z落在0~1之間才對
OpenGL才是落在-1~1之間

vulkan tutorial裡有1行
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
就是在指定NDC要用0~1

code from GLM setup.hpp

這樣一來

Mb其實是
A = F/(F-N)
B= -NF/(F-N)
 

比較一下

(MbMa)和GLM的perspectiveRH_ZO
只差在 Result[1][1]的正負

這代表

➡️ 前篇 的結果2修正後的結果3
其實是同個投影矩陣!?


Vulkan在clip space做Face culling嗎?

➡️ 前篇


clip space就是projection space


A X B = n 
n和Vc_to_eye的夾角沒有 > 90度的話
這個三角面可以顯示

用這種方法,三角形應該要顯示
結果1沒有
所以Vulkan不是這樣做的

從 NDC 變換到 view port space

➡️ 前篇


Flipping the Vulkan viewport


設定完viewport的屬性後
Vulkan會自行計算Red、Green、Center這些參數
再用這些參數把NDC座標變換到viewport

DX、OpenGL、Vulkan在那做Face cullng?

 

開場

設定逆時鐘方向是三角形的正面


這是我們的三角形和camera設定

使用glm::lookAt,預設是右手的Camera

為什麼3角形沒有出來?

結果1
程式碼來自vulkan tutorial

但是他的可以

結果2
程式碼來自vulkan tutorial

然後改成這樣也行?

結果3


to NDC space


肉眼可見DirectX、openGL、Vulkan
大家在NDC三角形都是逆時針

如果vulkan是在這裡做face culling
結果1就會看到三角形

結果1並沒看到
所以不是在這裡做!

viewport space

變換到viewport space


判定順時鐘、逆時鐘的座標系必須是
x軸從銀幕左往右
y軸從銀幕下往上

所以我們先自己鏡射一下
如果是在這裡做face culling
Vulkan是逆時鐘
結果1就會看到三角形

結果1並沒看到
所以也不是在這裡做!

那麼現在

假設存在1個 Face cullng space

用來判定face culling

這樣一來
DirectX和OpenGL都是逆時鐘,看得到三角形
而Vulkan是順時鐘,看不到
結果1相符

結果2

代表在camera space先沿著y軸方向鏡射

再乘上projection matrix
Vulkan是順時針
所以不是在NDC做

Vulkan在Screen Spcae是順時鐘
Vulkan在face culling space是逆時鐘

所以結果2看的到

這是一個負負得正的結果

結果3

客製化Projeciton Matrix

去fit這種奇怪的NDC



在Screen Space是順時鐘
在face culling space是逆時鐘

所以結果3看的到

參考資料


Sascha的方法

我們使用右手的Camera

 

直接修改viewport

相當於下面的紅色區塊

在Face culling space是逆時鐘方向

所以能正常顯示

不需要變換到Face culling space

仔細看完VkFrontFace Manual Page
發現它使用的是矩阵求三角形面积的結果再*(-1) 

VkFrontFace Manual Page

因為
viewport space和Face culling space判定的結果就是差1個負號

2023年3月26日 星期日

快速配置vulkan學習環境

安裝C++ Compiler

Microsoft C++ Compiler

安裝scoop、xmake ➡️ 教學

vscode 裝上面2個插件

用xmake生成專案

xmake create -t console hello_world

用xmake安裝glfw、glm ➡️ 教學

xrepo install glfw
xrepo install glad

設定xmake.lua ➡️ 教學

是不是比Visual Studio的設定簡單?

生成compile_commands

xmake project -k compile_commands

複製貼上程式碼 ➡️ main.cpp


編譯和執行exe

xmake build
xmake run
exe跑起來了,只是現在還有毛毛蟲

重開VSCode

現在要不要?


就自動幫你生成c_cpp_properties.json

再執行1次
xmake project -k compile_commands

毛毛蟲消失了
自動完成也能正常運作

編輯時使用c++17

會用到c++17才有的std::optional

載入圖片

image篇載入圖片會用到stb_image.h

安裝庫
xrepo install stb

載入模型

image篇載入圖片會用到tiny_obj_loader.h

安裝庫
xrepo install tinyobjloader

更新xmake.lua

更新compile_commands
xmake project -k compile_commands

毛毛蟲才會不見

2023年3月17日 星期五

速覽SH for glossy transport

今天本來不想卷的,但

上次看GAMES202

有個部分沒想通,做個記錄

p = q,積分項=1
p ≠ q,積分項 = 0

第6堂:Precomputed Radiance Transfer


第7堂:SH for glossy transport
這個矩陣怎麼來的?

SH一瞥

SH是一組2維基函數

抓前面m個基函數來使用


投影到SH

因為Diffuse和視角無關,上面橘色框框只是1個2維函數F

把F投影到SH上,得到投影系數C1…Cm


Glossy BRDF一瞥

BRDF每個ωo,會對映到多個ωi

等同於每個ωo,都對映到1個2維函數Fn


在球面上取n個方向

令每個方向為ωn

每個ωn,都會對映到1個2維函數Fn


第1次投影:把BRDF投影到SH

對每個ωn,把Fn投影到SH上
得到投影系數Tn1Tnm
(水平方向)

畫成表格就是

    m ➡️  SH系數
  n
⬇️    T11T1m
⬇️    T21T2m
⬇️            :
⬇️    Tn1Tnm
 方
 向


用SH系數重新分組

令 m=1 為一組
可以得到1個2維函數S1

    m ➡️  SH系數
  n
⬇️    T11
⬇️    T21
⬇️       :
⬇️    Tn1
 方
 向

全部分組完,可以得到m個2維函數Sm

第2次投影

把每個2維函數Sm都投影到SH上
最後會得到m組t1m...tMm
(垂直方向)

m = M
    m ➡️  SH系數
 M
⬇️    t11t1m         
⬇️    t21t2m
⬇️           :            
⬇️    tM1tMm   
 SH
 系
 數

到這裡都是預計算(Offline)

還原

已知ωo的方向為 n=2
進行m次基函數的疊加可以還原成

    m ➡️  SH系數
  n
⬇️         
⬇️    T21T2m
⬇️            
⬇️    
 方
 向


再把上面投影片
藍色框框的系數cp和T21T2m做內積
就是最後的光照結果

我叫tMm,這裡叫tij

把上面的過程寫成矩陣乘法

L = ( B t ) l = B ( t l )

和下面是同個意思



2023年3月16日 星期四

速覽全局光照

BRDF, Diffue, Fresnel of Specular(Mirror) And Light


From Direct Light to Indirect Light

四十歲後,不滯於物,草木竹石均可為燈

自此精修,漸進於無燈勝有燈之境



📑 一、什麼是BRDF

假設有1個物體,草木竹石均可(不透明的草)
物體上有1個微小面積dA

光會射入dA,然後從dA離開(射出)
  • 射入Li:dA在Normal半球方向都能接收光
  • 射出Lo:dA在Normal半球方向都可能射出光

描述光如何射入dA,再從dA射出的函數就叫
Bidirectional Reflectance Distribution Function
雙向反射分布函數

不同的物體,有不同的BRDF,形狀都長的不太一樣

眼睛方向

眼睛方向:dA指向eye的向量


Diffuse BRDF

和眼睛方向無關
眼睛動的時候,不會變

光從1個方向射入後,會均均向所有方向射出

cos(θo)衰減會被能量的透視補嘗抵消掉
所以可以當作Lo所有方向都是定值

Sepcular(Mirror) BRDF

眼睛動的時候,會跟著變

Mirror BRDF
從1個方向射入,從另1個方向射出

Specular BRDF
從1個方向射入
但從多個方向射出

BRDF可以做加法
Mirror 是1條線;Specular是1個Lobe狀


Specular(Mirror) BRDF比較 

左:1條線  中:小Lobe 右:大Lobe


牆上會動的高光是:Specular

不會動的是:Diffuse


鏡子:Mirror BRDF


木牆高光:Specular BRDF


白牆:Diffuse BRDF


📑 二、Light 

直接光源間接光源
  • 直接光源:燈、手電筒、手機銀幕
  • 間接光源:Open小將、鏡子、鏡框、書本,草木竹石勻可為燈

直接光源

直接光源:燈

木牆高光:Specular


Fresnel比較

x軸:夾角;y軸:Fresnel值

夾角眼精方向dA平面法向量的夾角

Copper效果最好,難怪古人要用銅鏡


鏡子上的反射:Mirror

應該是水銀(汞)吧?Fresnel值很高


木牆高光:Specular

Fresnel值變化很大,夾角接近90度時,反射最明顯


📑 三、關燈光照

間接光源:從窗子透近來的間接光源

牆上高光,會動:

間接光源打在Specular表面


天花板的光不會動:

間接光源打在Diffuse表面


直接光源:手機銀幕的面光源

牆上靠近手機會動的是:直接光源打在Specular表面

牆上靠近手機不會動的是:直接光源打在Diffuse表面

牆的材質是Combined BRDF


牆上遠離手機會動的是:間接光源打在Specular表面


BGM


拍完收工

可以去吃早餐了? 🤠😋 吃光光