程式碼吸貓 | 用 OpenGL 影象渲染的養貓計劃

語言: CN / TW / HK

一起用程式碼吸貓!本文正在參與【喵星人徵文活動】

在掘金上看到最近的新活動 "程式碼吸貓",技術類文章只要和貓有關就行。

對於沒有養貓的程式設計師,這不是為難人嘛。

不過沒關係,用 OpenGL 影象渲染給自己造一隻貓吧!!!

模型構造

首先需要構造出貓的模型,有能力的話可以直接在三維軟體裡面造一個。

或者像我一樣直接下載免費的貓模型,然後把它匯入 Blender 3D 軟體中。

在 Blender 中可以預覽貓模型,或者對它做一下調整,最後在把這個模型匯出。

模型載入

匯出的 obj 檔案裡面就記錄了模型的頂點資訊,接下來就要用 OpenGL 將它繪製出來。

這裡要用到 assimp 開源庫,它支援多種模型檔案的解析操作,通過它將模型解析成一個個 Mesh 。

Mesh 的定義如下:

cpp class Mesh { public: /* Mesh Data */ vector<Vertex> vertices; vector<unsigned int> indices; vector<Texture> textures; unsigned int VAO; // 省略部分程式碼 }

Mesh 相當於繪製模型上的一個個網格或者說面片,它包含了該網格的頂點、紋理資訊和繪製索引。

而模型 Model 就是由這一系列網格 Mesh 組成的。

如上圖所示,貓模型是由一個個小矩陣組成的,小矩陣就可以理解成 mesh 網格了。

Model 的定義如下:

cpp class Model { public: /* Model Data */ vector<Texture> textures_loaded; vector<Mesh> meshes; // 省略部分程式碼 }

在實際繪製的時候,也是由一個一個 Mesh 最終繪製成的。

cpp // draws the model, and thus all its meshes void Draw(Shader shader) { for(unsigned int i = 0; i < meshes.size(); i++) meshes[i].Draw(shader); }

從圖中也可以看到,貓模型的網格數量是很多的,導致載入的時候會很很慢了,載入方法如下:

```cpp void loadModel(string const &path) { // 使用 assimp 庫進行載入 const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace); // 檢查是否有錯 if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero { cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl; return; } // 獲取模型所在資料夾 directory = path.substr(0, path.find_last_of('/'));

// 從根節點一個一個節點開始處理
processNode(scene->mRootNode, scene);

} ```

使用 assimp 處理後會得到一個根節點,然後順著根節點一個一個往下處理就好了。

cpp   void processNode(aiNode *node, const aiScene *scene)   {     for(unsigned int i = 0; i < node->mNumMeshes; i++)     {       aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; // 處理得到的 aiMesh 並組裝成定義好的 Mesh 資料結構       meshes.push_back(processMesh(mesh, scene));     } // 處理子節點     for(unsigned int i = 0; i < node->mNumChildren; i++)     {       processNode(node->mChildren[i], scene);     }   }

可以看到處理過程大量的 for 迴圈操作,所以後續才會針對模型檔案的優化,加快其載入速度。

模型渲染

得到了最終的 Model 之後,就可以對它做渲染顯示了。

cpp // model 矩陣調整模型顯示位置和方向     glm::mat4 model = glm::mat4(1.0f);     model = glm::translate(model, glm::vec3(tranx_x, tranx_y, tranx_z));     model = glm::rotate(model,glm::radians(90.0f),glm::vec3(0.0,0.0,1.0));     model = glm::scale(model, glm::vec3(0.5f, 0.5f, 0.5f));         shader.setMatrix4fv("model", glm::value_ptr(model));     ourModel.Draw(shader);

由於模型自身就帶了一個位置和方向,顯示的時候不一定是我們想要的觀察方位,所以還是要調整一個模型矩陣。

最後渲染就可以看到 貓模型 效果啦。

小結

為了便於觀察,可以處理一下鍵盤或者滑鼠事件,修改模型矩陣的值,從不同角度擼貓。

目前的貓模型還只是靜態的,調整的話也只能用鍵盤調整,而且還只是改了 移動、縮放、旋轉這些屬性,貓本身是沒有動的。

想要貓自身能動的話,還需要模型裡面有對應的骨骼動畫才可以了,等後面有了這樣的模型,再繼續迭代。

關注微信公眾號 音視訊開發進階,看更多擼貓後續內容...