我正在尝试可视化非常大的点云(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/

10-11 22:09
查看更多