2015-02-08 91 views
1

我需要座標軸對齊法線,所以我想要安全的內存併發送它作爲字節而不是alpha通道的位置。緩衝區對象由4個字節組成:glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 4 * sizeof(GLubyte), (void*)0);編碼應該像這樣。如何將字節解壓到vec3中?

//byte in buffer object | unpacked vector 
x+ 0010 1011 == vec3(1, 0, 0) 
x- 0010 1001 == vec3(-1, 0, 0) 
y+ 0010 1110 
y- 0010 0110 
z+ 0011 1010 
z- 0001 1010 

//Lets take vec3(-1, 0, 1) encoded velue looks like 0011 1001 
//    ,(operation) -> (result), 
//Z = >>4 -> 0000 0011, &mask -> 0000 0011, -2 -> 0000 0001 
//Y = >>2 -> 0000 1110, &mask -> 0000 0010, -2 -> 0000 0000 
//X = >>0 -> 0011 1001, &mask -> 0000 0001, -2 -> 1111 1111 

我檢查了gDEBuggerGL中的編碼,它是正確的。問題出現在頂點着色器中,因爲拆箱非常笨拙。

layout(location = 0) in vec4 vertex_position; 
//... 
int byte = int(vertex_position.w); 

const int mask = 0x00000003; 
vec3 v_normal; 
v_normal.x = float(((byte >> 0) & mask) - 2); 
v_normal.y = float(((byte >> 2) & mask) - 2); 
v_normal.z = float(((byte >> 4) & mask) - 2); 

首先:有沒有更好的辦法如何做到這一點?

其次:我把這個法線向量渲染成浮動紋理,發現有些值是錯誤的。他們中的許多人不是{1,0,-1}但接近此。那麼我不認爲這段代碼應該引入任何精度錯誤,那麼爲什麼會發生這種情況呢?

Normals in float texture

更新: 精度誤差在過渡引入從頂點着色器到片段着色器和可通過添加flat關鍵字來解決。 (感謝多德)

+0

'8 * sizeof(GLubyte)'看起來有點嫌疑? – 2015-02-08 23:31:43

+0

對不起,我應該改變它。有兩個4 *字節的緩衝區。但另一個不涉及這個問題。 – Keo 2015-02-08 23:34:29

+0

你知道在頂點着色器和片段着色器之間,你的'v_normal'將被插值,除非你採取其他的步驟...... – 2015-02-09 05:13:23

回答

0
//Lets take vec3(-1, 0, 1) encoded velue looks like 0011 1001  
//X = >> 0 -> 0011 1001, &mask -> 0000 0001, -2 -> ffff ffff 

0xFFFFFF不是-1因爲你使用的是GL_UNSIGNED_BYTE,因此這不是一個2的補碼錶示。

+0

這仍然是錯誤的,因爲您首先將它轉換爲「int」。我會一直在想...; p – 2015-02-08 23:49:48

+0

其實,你可以嘗試使用'GL_BYTE'嗎?這使用2的補碼錶示,並且與您的邏輯一致。 – 2015-02-08 23:53:12

+0

沒有任何變化。 '''Vertex_position.w'''實際上是float,因爲它在vec4中,因爲gpu沒有單獨的字節向量或字節。但是,它被轉換爲整數,其餘的魔法是通過具有2的補碼錶示的int完成的。 – Keo 2015-02-09 00:01:07

相關問題