我正在開發一個未來將支持 3D 的 2D 游戲引擎。在當前的開發階段,我正在研究批處理渲染器。你們中的一些人可能知道,當將圖形一起批處理時,對顏色 (RGBA)、紋理坐標、紋理 ID(紋理索引)和模型轉換矩陣的統一支持會超出視窗,而是通過頂點緩沖區傳遞。現在,我已經實作了將模型的位置、顏色、紋理坐標和紋理 ID 傳遞到頂點緩沖區。我的頂點緩沖區格式現在看起來像這樣:
float* v0 = {x, y, r, g, b, a, u, v, textureID};
float* v1 = {x, y, r, g, b, a, u, v, textureID};
float* v2 = {x, y, r, g, b, a, u, v, textureID};
float* v3 = {x, y, r, g, b, a, u, v, textureID};
我即將使用變換矩陣集成計算物件在世界空間中的位置。這使我提出以下問題:
轉換矩陣應該乘以 CPU 或 GPU 上的模型頂點位置嗎?
需要記住的是,如果我將它傳遞給頂點緩沖區,我將不得不為每個頂點上傳一次變換矩陣(每個精靈 4 次),這對我來說似乎是浪費記憶體。另一方面,與 GPU 的并發能力相比,將模型頂點位置乘以 CPU 上的變換矩陣似乎會更慢。
如果我在 GPU 上計算變換,我的頂點緩沖區格式如下所示:
float* v0 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};
float* v1 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};
float* v2 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};
float* v3 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};
這個問題主要是理論驅動的。因此,非常感謝理論上和技術上的回答。但作為參考,這里是代碼。
uj5u.com熱心網友回復:
轉換應該在 CPU 還是 GPU 上進行?
這真的取決于手頭的情況。如果您每幀都重新提交頂點,最好對最適合您的情況進行基準測驗。如果您想在不重新提交所有頂點的情況下制作影片,您別無選擇,只能將其應用到 GPU 上。
不管是什么原因,如果您決定在 GPU 上應用轉換,除了為每個頂點復制矩陣之外,還有更好的方法可以做到這一點。我將轉換矩陣放在SSBO 中:
layout(std430, binding=0) buffer Models {
mat4 MV[]; // model-view matrices
};
并在 VAO 的每個頂點中存盤一個索引:
float* v0 = {x, y, r, g, b, a, u, v, textureID, model};
float* v1 = {x, y, r, g, b, a, u, v, textureID, model};
float* v2 = {x, y, r, g, b, a, u, v, textureID, model};
float* v3 = {x, y, r, g, b, a, u, v, textureID, model};
頂點著色器可以根據索引屬性去獲取完整的矩陣:
layout(location = 0) in vec4 in_pos;
layout(location = 1) flat in int in_model;
void main() {
gl_Position = MV[in_model] * in_pos;
}
您甚至可以將其與其他每個物件的屬性結合使用,例如textureID.
編輯:您可以通過實體化和多次繪制來實作類似的效果。雖然它可能會更慢。
uj5u.com熱心網友回復:
我不確定您的引擎代碼實際上是什么樣子,但我認為它看起來像任何其他 OpenGL 程式。
如果是這樣,根據我的經驗,變換矩陣通常應該傳遞給頂點著色器,并在繪制場景時在 GPU 上應用給定的頂點資訊。例如:
//MVP matrix
GLuint MatrixID = glGetUniformLocation(shaderProgID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
但是如果你想找到特定組的所有頂點的世界坐標,在渲染功能之外,你可能需要在 CPU 上完成,或者你將需要使用一些并行編程技術,如 OpenCL 來完成這項作業在 GPU 上。
最重要的是,你為什么特別想要繪制程式之外的世界坐標資訊?如果您只想找到模型的世界坐標,您可以簡單地為場景中的每個模型設定一個中心坐標,并且只跟蹤該單個坐標而不是整個網格組。
頂點資訊應始終在模型坐標中并存盤在頂點緩沖區中而無需接觸,除非您想對它們進行一些修改。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/364596.html
