2017-12-03 296 views
2

我想到了一些令我困惑的東西,我無法找到答案。當我寫的着色器是這樣的:用於制服和變化的OpenGL和GLSL內存對齊

layout (location = 0) in vec3 inPosition; 
layout (location = 1) in vec3 inNormal; 
layout (location = 2) in vec2 inTexCoords; 

我知道VEC3的不對齊,許多vec4的是,或SIMD兼容的數據類型的16字節。我知道這(我想),因爲我在我的C++代碼數據是:

struct Vertex 
{ 
    vec3 position; 
    vec3 normal; 
    vec2 texCoords; 
}; 

每個矢量彼此位於緊貼地,無填料,尺寸爲8 *的sizeof(浮動),32個字節。我把它傳遞給制服,着色器讀取它很好,所以我知道它們都是對齊的。

但是,當涉及到在GLSL均勻塊,與例如std140標準一個VEC3必須用一個額外的4個字節填充添加另一VEC3或vec4之前:

  1. 如果構件是與耗時N基本機器單元部件三個成分的矢量,基座對準爲4N

但是也可以存儲在VEC3和下一VEC3之間的四字節int或四字節布爾壓實尺寸。那麼這是否意味着頂點佈局的attrib指針值不遵循std140佈局?另外,如果我在我的C++代碼中使用SIMD 16字節對齊的向量,這是否意味着我將不能再將attrib指針值設置爲vec3,vec3,vec2,而是擁有所有vec4的?

而且我看到的文件上以下警告:

警告:實現有時得到std140佈局錯 VEC3組件。建議您手動填充 結構/陣列,並避免使用vec3。

這裏說的是避免使用vec3,但我認爲這是一個聰明的節省空間的技術,在vec3之後打包一個四字節的int或bool。

回答

4

std140佈局僅適用於interface blocks,而不適用於接口塊外的緩衝區或屬性的內容。由於接口塊不能用作頂點着色器的輸入或來自片段着色器的輸出,因此std140不會以任何方式影響如何設置glVertexAttribPointer或頂點數據如何存儲。

關於警告:是的,使用vec3之後的空間來存儲和int/float/bool是一個聰明的技巧。但正如警告所述,驅動程序的實現有時會出錯。所以如果你想確保你的代碼在任何地方都能可靠地運行,你要麼測試很多,要麼根本不使用vec3。再次請注意,這隻在接口塊的情況下才有意義。普通的vec3制服不會被這個感動。

你可以做的是打包存儲3個浮點數和一個int在你的C++端,但通過接口塊中的vec4訪問它。您可以使用floatBitsToInt(myBlock.myVec4.w)來檢索整數。

+0

這很有幫助。該floatBitsToInt完全吹捧我的想法,因爲起初我試圖找到一個u8vec4來存儲0 - 255 RGBA,然後發現glsl根本不處理單字節數據類型,所以我的下一個想法是發送一個int並使用位操作員可以獲得正確的顏色通道。 – Zebrafish

+0

稍等片刻,我仍然不得不做甚至floatBitsToInt我剛纔意識到。如果我的0 - 255顏色是我的vec4.w,我仍然需要移位並提取正確的字節。 – Zebrafish