我正在尝试可视化非常大的点云(7亿点),并在glDrawArrays
上调用调试器引发访问冲突写入位置异常。我正在使用相同的代码来渲染较小的云(1亿个),并且一切正常。我也有足够的RAM内存(32GB)来存储数据。
为了存储点云,我使用的是std::vector<Point3D<float>>
,其中Point3D是
template <class T>
union Point3D
{
T data[3];
struct{
T x;
T y;
T z;
};
}
顶点数组和缓冲区初始化:
glBindVertexArray(pxCloudHeader.uiVBA);
glBindBuffer(GL_ARRAY_BUFFER, pxCloudHeader.xVBOs.uiVBO_XYZ);
glBufferData(GL_ARRAY_BUFFER, pxCloudHeader.iPointsCount * sizeof(GLfloat) * 3, &p3DfXYZ->data[0], GL_STREAM_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
绘图电话:
glBindVertexArray(pxCloudHeader.uiVBA);
glDrawArrays(GL_POINTS, 0, pxCloudHeader.iPointsCount); // here exception is thrown
glBindVertexArray(0);
我还检查了是否抛出了OpenGL错误,但没有发现任何错误。
最佳答案
我怀疑您的问题是由于GLsizeiptr
的大小所致。
这是用于表示OpenGL缓冲区对象中的大小的数据类型,通常为32位。
700 million vertices * 4-bytes per-component * 3-components = 8,400,000,000 bytes
如果使用32位指针,则尝试在GL中分配那么多字节存在严重问题:8400000000 & 0xFFFFFFFF = 4,105,032,704 (half as many bytes as you actually need)
如果实现中的sizeof (GLsizeiptr)
为 4 ,那么您别无选择,只能拆分数组。一个32位GLsizeiptr
仅允许您存储4个连续的GiB内存,但是如果改用3个单分量数组,则可以解决此问题。使用顶点着色器,您可以像下面这样重建这3个单独的(足够小的)数组:#version 330
layout (location = 0) in float x; // Vertex Attrib Ptr. 0
layout (location = 1) in float y; // Vertex Attrib Ptr. 1
layout (location = 2) in float z; // Vertex Attrib Ptr. 2
void main (void)
{
gl_Position = vec4 (x,y,z,1.0);
}
性能将很糟糕,但这是用最少的精力解决问题的一种方法。顺便说一句,这里的系统内存量(32 GiB)不是最大的问题。您应该考虑GPU上的VRAM数量,因为理想情况下,缓冲区对象被设计为存储在GPU上。使用时,缓冲区对象的任何部分太大而无法存储在GPU内存中,则必须通过PCIe(这些天)总线进行传输。
关于c++ - glDrawArrays访问冲突写入位置,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27585533/