for*_*ars 0 c++ opengl buffer glm-math
我正在使用一个带有一堆GLfloats的OpenGL缓冲区作为顶点缓冲区,一切都很顺利.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);
Run Code Online (Sandbox Code Playgroud)
现在这段代码是有效的,我想知道OpenGL如何知道如何用glm :: vec3而不是GLfloats填充缓冲区.然后我想知道,当我从缓冲区读回数据时,使用:
std::vector<glm::vec3> data;
glGetBufferSubData(mTarget, offset, vertexCount * sizeof(glm::vec3), &data[0]);`
Run Code Online (Sandbox Code Playgroud)
这会产生一堆glm :: vec3吗?所以问题是,OpenGL如何填充缓冲区glm::vec3,并且它(如果是这样,如何)读取缓冲区?
根据OpenGL的文档,glBufferData()需要一个指向data(即数组,即顶点坐标)的指针.
我们先来看看它glm::vec3的实现.
如果你看看GLM的GitHub库,你会发现,这取决于你的编译标志,glm::vec3是typedef的highp_vec3这是typedef的tvec3<float, highp>.
tvec3在type_vec3.hpp中声明(由vec3.hpp包含),类(模板)方法在type_vec3.inl中定义.
特别是,operator[]定义是:
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];
}
Run Code Online (Sandbox Code Playgroud)
给定这段代码,可以假设这x是包含坐标的"数组"的第一个元素glm::vec3.但是,当我们回到type_vec3.h时,我们发现:
union { T x, r, s; };
union { T y, g, t; };
union { T z, b, p; };
Run Code Online (Sandbox Code Playgroud)
所以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;
}
Run Code Online (Sandbox Code Playgroud)
在我的机器上打印哪些:
sizeof(v) : 12
sizeof(xyz): 12
sizeof(v) == sizeof(xyz) : true
Run Code Online (Sandbox Code Playgroud)
因此,glm::vec3商店只的(x, y, z)坐标.
现在,如果我们创建一个std::vector<glm::vec3> vertices;,可以肯定地说,指向的数据布局&vertices[0](在C++ 11中vertices.data())是:
vertices == [vertice1 vertice2 ...]
== [vertice1.x vertice1.y vertice1.z vertice2.x vertice2.y vertice2.z ...]
Run Code Online (Sandbox Code Playgroud)
回到原始问题 - glBufferData()的要求:当你通过&vertices[0]时,实际上正在传递地址(即指针)data,正如预期的那样glBufferData().同样的逻辑适用于glGetBufferSubData().