2015-09-03 31 views
0

我一直試圖從兩個不同的VBO切換到只有一個具有交錯屬性。我可以用C++來完成,但在Scala中證明它非常困難。OpenGL交錯VBO - 如何在Scala中獲取sizeof(Float)?

這是我實現:

class Mesh(positions: Array[Float], textureCoordinates: Array[Float], indices: Array[Int]) 
{ 
    // Create VAO, VBO and a buffer for the indices 
    val vao: Int = glGenVertexArrays 
    val vbo: Int = glGenBuffers 
    val ibo: Int = glGenBuffers 

    setup 

    private def setup(): Unit = 
    { 
     val interleavedBuffer: FloatBuffer = prepareFloatBuffer(positions ++ textureCoordinates) 
     val indicesBuffer: IntBuffer = prepareIntBuffer(indices) 

     // One VAO to bind them all! 
     glBindVertexArray(vao) 
      glBindBuffer(GL_ARRAY_BUFFER, vbo) 
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo) 

      // Fill buffers with data 
      glBufferData(GL_ARRAY_BUFFER, interleavedBuffer, GL_STATIC_DRAW) 
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW) 

      // Set vertex attribute pointers 
      glVertexAttribPointer(0, 3, GL_FLOAT, false, 4*5, 0) // 0 = Position = Vector3(x,y,z) -> 3 (coordinates) * 4 (byte-size of float) 
      glVertexAttribPointer(1, 2, GL_FLOAT, false, 4*5, 4*3) // 1 = Texture Coordinates = Vector2(x,y) -> 2 (coordinates) * 4 (byte-size of float) => stride = 3 (coordinates) + 2 (texture coordinates) = 5 * 4 (byte-size of float); offset = 3 (coordinates) * 4 (byte-size of float) 

      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 
      glBindBuffer(GL_ARRAY_BUFFER, 0) 
     glBindVertexArray(0) 
    } 

    private def prepareIntBuffer(data: Array[Int]): IntBuffer = 
    { 
     val buffer: IntBuffer = BufferUtils.createIntBuffer(data.length) 
     buffer.put(data) 
     buffer.flip // Make the buffer readable 

     buffer 
    } 

    private def prepareFloatBuffer(data: Array[Float]): FloatBuffer = 
    { 
     val buffer: FloatBuffer = BufferUtils.createFloatBuffer(data.length) 
     buffer.put(data) 
     buffer.flip // Make the buffer readable 

     buffer 
    } 

    def render(): Unit = 
    { 
     glBindVertexArray(vao) 
     glBindBuffer(GL_ARRAY_BUFFER, vbo) 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo) 
      glEnableVertexAttribArray(0) // Vertices are in zero 
      glEnableVertexAttribArray(1) // Texture Coords are in one 
      glDrawElements(GL_TRIANGLES, this.indices.length, GL_UNSIGNED_INT, 0) 
      glDisableVertexAttribArray(1) 
      glDisableVertexAttribArray(0) 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 
     glBindBuffer(GL_ARRAY_BUFFER, 0) 
     glBindVertexArray(0) 
    } 
} 

的數據(位置,textureCoordinates)是我之前使用的一樣,用兩個不同的駐國際中心組織他們。

現在:

glVertexAttribPointer(0, 3, GL_FLOAT, false, 4*5, 0) 
glVertexAttribPointer(1, 2, GL_FLOAT, false, 4*5, 4*3) 

如何計算這些進步和偏移你問?

那麼,position是一個Vector3(x,y,z),所以3個浮點數。紋理座標是兩個浮點數。

3 + 2 = 5

浮子的尺寸...好,我認爲它是4個字節。 (根據http://wiki.lwjgl.org/wiki/The_Quad_interleaved它是Java)

這將使20,或4 * 5

的用於紋理座標偏移將被計算的相同(3 * 4)用於位置的每個座標

現在,結果看起來並不太好......

enter image description here

你能猜到它實際上應該是什麼? (擾流板:立方體)

那麼,我認爲我的數學是完全破碎的或者浮點數可能在Scala中有不同的大小?

在Java中,我可以做Float.size,但是Scala沒有任何類似的東西。

在C++中我定義了一個結構,做:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, textureCoordinates)); 
+0

這看起來對我來說很奇怪:'prepareFloatBuffer(位置++ textureCoordinates)'希望這是因爲我無法讀取Scala? –

+1

@ AndonM.Coleman:這是數組連接。也是OP問題的根源。 – datenwolf

回答

5

你的問題不是的sizeof浮動,但在你的緩衝區中的數據佈局。聲明

val interleavedBuffer: FloatBuffer = prepareFloatBuffer(positions ++ textureCoordinates) 

創建佈局的緩衝

xyz[0],xyz[1],…,xyz[n],st[0],st[1],…,st[m] 

但是配置什麼OpenGL的期望是

xyz[0],st[0],xyz[1],st[1],…,xyz[n],st[n] 

您可以適當地交織的屬性在緩衝區中,你的你告訴OpenGL每個屬性的元素是連續的(0步長,或者該屬性的一個元素的大小,即xyz爲3 * 4,st爲2 * 4),並將偏移量傳遞到每個子集開始。

+0

有沒有標準的方式來結合在斯卡拉這樣的兩個數組,是嗎?我將不得不手動建立一個方法呢? – Sorona

+0

@Teolha:是的。這就是所謂的「壓縮」,這是'zip'函數的目的。 – datenwolf

+0

不壓縮創建tupled集合?像Array [(a,b)]? – Sorona