OpenGL 交错 VBO - 如何在 Scala 中获取 sizeof(Float)?
OpenGL interleaved VBO - how to get sizeof(Float) in Scala?
我一直在尝试从两个不同的 VBO 切换到一个具有交错属性的 VBO。我可以在 C++ 中完成,但在 Scala 中证明它非常困难。
这是我的实现:
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)
}
}
数据(位置、纹理坐标)与我之前使用的相同,它们有两个不同的 VBO。
现在:
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
对于 position
的每个坐标,纹理坐标的偏移量计算相同 (3 * 4)
现在,结果看起来不太好...
你能猜出它到底应该是什么吗? (剧透:一个立方体)
所以,我认为要么是我的数学完全错误,要么是 Float 在 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));
您的问题不在于 sizeof float,而是缓冲区中的数据布局。语句
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,xyz 为 2* 4 for st) 并将偏移量传递到每个子缓冲区的开始位置。
我一直在尝试从两个不同的 VBO 切换到一个具有交错属性的 VBO。我可以在 C++ 中完成,但在 Scala 中证明它非常困难。
这是我的实现:
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)
}
}
数据(位置、纹理坐标)与我之前使用的相同,它们有两个不同的 VBO。
现在:
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
对于 position
的每个坐标,纹理坐标的偏移量计算相同 (3 * 4)现在,结果看起来不太好...
你能猜出它到底应该是什么吗? (剧透:一个立方体)
所以,我认为要么是我的数学完全错误,要么是 Float 在 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));
您的问题不在于 sizeof float,而是缓冲区中的数据布局。语句
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,xyz 为 2* 4 for st) 并将偏移量传递到每个子缓冲区的开始位置。