问题描述
我使用一个OpenGL缓冲区和一堆GLfloats作为顶点缓冲区,一切都很好。 GLfloats的格式为 [x1,y1,z1,x2,y2,z2,...] 。
但是,在遵循的同时,它会告诉我改用 glm :: vec3 :
glBufferData GL_ARRAY_BUFFER,vertices.size()* sizeof(GLfloat),& vertices [0],GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER,vertices.size()* sizeof(glm :: vec3),& vertices [0],GL_STATIC_DRAW);
现在这个代码是有效的,我不知道OpenGL怎么知道如何填充glm :: vec3而不是GLfloats。然后我不知道,当我从缓冲区读回数据,使用:
std :: vector< glm :: vec3&数据;
glGetBufferSubData(mTarget,offset,vertexCount * sizeof(glm :: vec3),& data [0]);`
这会造成一堆glm :: vec3吗?所以问题是, OpenGL如何用 glm :: vec3 填充缓冲区,并且(如果是这样,它是如何读取的)
根据, glBufferData()需要一个指向数据
让我们先来看看 glm :: vec3 的实现。如果您签出,你会看到,取决于你的编译标志, glm :: vec3 是一个,这是。
tvec3 在(由提供)和类(模板)方法在中定义。
特别是是:
template< typename T,precision P>
GLM_FUNC_QUALIFIER T& tvec3 :: operator [](typename tvec3 :: length_type i)
{
assert(i> = 0& static_cast< detail :: component_count_t> ;(i)< detail :: component_count(* this));
return(& x)[i];
}
给定这段代码,可以假设 x 是包含坐标 glm :: vec3 的数组的第一个元素。但是,当我们回到时,我们find:
union {T x,r,s; };
union {T y,g,t; };
union {T z,b,p; };
因此 x , y 和 z 是单独的属性。但是,由于,它们可以被视为单个数组,从& x 。
我们现在知道, glm :: vec3 (实际上 tvec3 )以连续方式存储坐标。但是它还存储其他属性?
好,我们可以继续深入代码,或使用一个简单的程序给我们的答案:
#include< iostream>
#include< ios>
#include< glm / vec3.hpp>
int main()
{
const glm :: vec3 v;
const size_t sizeof_v = sizeof(v);
const size_t sizeof_xyz = sizeof(v.x)+ sizeof(v.y)+ sizeof(v.z);
std :: cout<< sizeof(v):< sizeof_v< std :: endl;
std :: cout<< sizeof(xyz):< sizeof_xyz< std :: endl;
std :: cout<< sizeof(v)== sizeof(xyz):< std :: boolalpha< (sizeof_v == sizeof_xyz)< std :: endl;
}
在我的机器上打印:
sizeof(v):12
sizeof(xyz):12
sizeof(v)== sizeof(xyz):true
因此, glm :: vec3
现在,如果我们创建一个(x,y,z) std :: vector< glm :: vec3>顶点; ,可以安全地说,由& vertices [0] 指向的数据的布局是)是:vertices == [vertice1 vertice2 ...]
== [vertice1.x vertice1.y vertice1。 z vertice2.x vertice2.y vertice2.z ...]
回到原始问题 - - glBufferData()的要求:当你传递& vertices [0] data ,正如 glBufferData()所期望的那样。相同的逻辑适用于 glGetBufferSubData()。
I was using an OpenGL buffer with a bunch of GLfloats as a vertex buffer and all was well. The format of the GLfloats being [x1, y1, z1, x2, y2, z2, ...].
But then, while following this tutorial, it tells me to use glm::vec3 instead:
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
Now this code is valid, and I wonder how would OpenGL know how to fill in the buffer with glm::vec3 instead of GLfloats. Then I wonder, when I read the data back from the buffer, using:
std::vector<glm::vec3> data; glGetBufferSubData(mTarget, offset, vertexCount * sizeof(glm::vec3), &data[0]);`
Will this make a bunch of glm::vec3? So the question is, how does OpenGL fill buffers with glm::vec3, and does (and if so, how does) it read it back?
According to OpenGL's documentation, glBufferData() needs a pointer to the data (i.e. an array, i.e. the coordinates of the vertices).
Let's first have a look at glm::vec3's implementation.
If you check out glm's Github repo, you'll see that, depending on your compilation flags, glm::vec3 is a typedef of highp_vec3 which is a typedef of tvec3<float, highp>.
tvec3 is declared in type_vec3.hpp (included by vec3.hpp) and the class (template) methods are defined in type_vec3.inl.
In particular, operator[]'s definition is:
template <typename T, precision P> GLM_FUNC_QUALIFIER T & tvec3<T, P>::operator[](typename tvec3<T, P>::length_type i) { assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); return (&x)[i]; }
Given that piece of code, one would assume that x is the first element of the "array" containing the coordinates of glm::vec3. However, when we go back to type_vec3.h, we find:
union { T x, r, s; }; union { T y, g, t; }; union { T z, b, p; };
So x, y and z are separate attributes. But thanks to how class/struct members are laid out, they can be viewed as a single array starting from &x.
We know now, that glm::vec3 (actually tvec3) stores the coordinates in a contiguous manner. But does it also store other attributes ?
Well, we can continue to dive into the code, or use a simple program to give us the answer:
#include <iostream> #include <ios> #include <glm/vec3.hpp> int main() { const glm::vec3 v; const size_t sizeof_v = sizeof(v); const size_t sizeof_xyz = sizeof(v.x) + sizeof(v.y) + sizeof(v.z); std::cout << "sizeof(v) : " << sizeof_v << std::endl; std::cout << "sizeof(xyz): " << sizeof_xyz << std::endl; std::cout << "sizeof(v) == sizeof(xyz) : " << std::boolalpha << (sizeof_v == sizeof_xyz) << std::endl; }
Which prints, on my machine:
sizeof(v) : 12 sizeof(xyz): 12 sizeof(v) == sizeof(xyz) : true
Therefore, glm::vec3 stores only the (x, y, z) coordinates.
Now, if we create a std::vector<glm::vec3> vertices;, it is safe to say that the layout of the data pointed by &vertices[0] (which, in C++11 is vertices.data()) is:
vertices == [vertice1 vertice2 ...] == [vertice1.x vertice1.y vertice1.z vertice2.x vertice2.y vertice2.z ...]
Going back to the original issue -- glBufferData()'s requirements: when you pass &vertices[0] you are actually passing the address (i.e. pointer) of the data, just as expected by glBufferData(). The same logic applies to glGetBufferSubData().
这篇关于OpenGL如何填充缓冲区并读取它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!