最近準備抽空研究下圖形中的光照渲染,先做一個小的demo,然後慢慢加不同的效果
文章來源於 learnOpenGL ,是一個非常好的教程
這篇文章的意義在於將整個過程中的關鍵點以及遇到的錯誤心得彙總並記錄
UI
這裏使用了 Dear Imgui 作爲顯示組件,用來動態改變渲染的效果,其使用也非常簡單,直接將相關的 .h 和 .cpp 文件添加即可,GitHub 上有詳細介紹。
當前設置如下:
- rotation 改變模型沿着 y 軸的旋轉
- position 改變模型在 x,y 軸上的位移
- scale 改變模型的縮放
- color 用來簡單地對模型混合顏色
- rate 控制混合比例
需要的設置 - 設置 imgui 上下文,渲染風格,設置平臺並渲染綁定
- 在渲染循環中將渲染 gui,添加需要的組件,賦值
- 將 ui 上的值作爲 uniform 傳入 shader 中即可
示例如下:
/* imgui 初始化 */
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
const char* glsl_version = "#version 460";
ImGui_ImplOpenGL3_Init(glsl_version);
/* imgui 初始化結束 */
/* 渲染循環 */
while() {
// 將輸入給imgui,並開始新的一幀
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
......
// 設置 imgui 的控件
ImGui::Begin("Operations");
static float rate = 0.0;
ImGui::SliderFloat("rate", &rate, 0.0, 1.0);
ImGui::End();
......
shader.setFloat("rate", rate);
......
// 將gui渲染到平面上
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
// 釋放imgui的資源
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
transform
這裏需要注意的就是矩陣運算的順序
位移矩陣 · 旋轉矩陣 · 縮放矩陣 · 位置
其原因在於如果先計算位移矩陣,在其他矩陣的作用下,位移向量被改變,無法得到正確的組合效果。
例如
當最後計算位移矩陣時,改變 x 軸方向的值效果如下,可以看到模型在世界座標水平方向上正確的移動(還沒加光照,所以黑乎乎的)
但如果將平移矩陣和旋轉矩陣交換順序,模型的平移就會在旋轉的基礎上進行,就是局部座標系下的平移
模型
模型加載一直是關鍵步驟,如果有時間還是建議自己實現下 obj 格式的讀寫,會有很大幫助。
由於模型不是關注的重點,這裏直接使用 assimp 庫來用於模型的加載, 其格式如下。
由於 mesh 中包含了渲染所有的數據,所以節點直接以 mesh 爲單位存儲,這樣也可以方便後期動畫的生成。
爲了方便使用,需要將 assimp 的模型數據轉換爲我們定義的 mesh 格式,這一步 learnopengl 中提供了詳細的源碼。
在這個過程中遇到了一個 cmake 問題,編譯後只能找到 .lib 文件,無法找到 .dll 文件,如果有知道原因的希望在評論區留言
筆記
- 圖片長寬需要是2的冪才行,不然 stb_image 會報錯
- 如果三個維度的縮放係數相同時,縮放矩陣和旋轉矩陣順序可以互換