首先是关于直接移植一维阵列解决方案的一些话:
首先,正如Mortennobel在他的评论中所说,最大纹理大小很可能不是 3397
,这只是枚举值(定义该值的opengl.hGL_MAX_TEXTURE_SIZE
标头应该如何知道您的硬件和驱动程序限制?)。要从您的实现中获取实际值,请使用. 但即便如此,这对你来说也可能太小了(可能是 8192 或类似的东西)。int size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
但是要将更大的一维数组放入着色器中,您可以使用缓冲区纹理(自 OpenGL 3 以来它是核心,因此存在于 DX10 类硬件上)。这些是从标准 OpenGL 缓冲区对象中获取数据的纹理。但是这些纹理始终是一维的,由整数 texCoords(可以说是数组索引)访问而不是过滤。所以它们实际上不是真正的纹理,而是一种将缓冲区对象作为着色器内的线性 1D 数组访问的方法,这非常适合您的需求(实际上比普通过滤和标准化的 1D 纹理更适合) .
编辑:您可能还考虑像以前一样使用直接的 3D 纹理,但是对于层次结构的较高部分使用自制的 mipmap 级别(是的,3D 纹理也可以有 mipmap)。所以 mipmap 级别 0 是精细的 256 网格,级别 1 包含较粗的 128 网格,...但是要有效地使用此数据结构,您可能需要在着色器中进行显式 LOD 纹理访问(使用textureLod
,或者甚至更好地不过滤,texelFetch
),这也需要 OpenGL 3。
编辑:如果您不支持 OpenGL 3,我仍然不建议使用 3D 纹理将您的 1D 数组放入,而是使用 2D 纹理,就像Rahul在他的回答中建议的那样(1D-2D 索引魔法不是真的那么难)。但是如果你有 OpenGL 3,那么我要么使用缓冲区纹理直接使用你的线性 1D 数组布局,要么使用带有 mipmaps 的 3D 纹理进行直接八叉树映射(或者可能会提出一个完全不同且更复杂的数据结构首先是体素网格)。
编辑:当然,完全细分的八叉树并没有真正利用八叉树的内存节省特性来发挥其优势。对于将八叉树打包到 3D 纹理中的更动态和内存效率更高的方法,您还可以从这篇关于八叉树纹理的经典 GPU Gems 文章中获得一些灵感。它们基本上将所有八叉树单元作为 2x2x2 网格任意存储到 3D 纹理中,使用内部节点的值作为指向该纹理中子节点的指针。当然,现在您可以对此进行各种改进(因为您似乎也希望内部节点存储数据),例如将整数与浮点数一起存储并使用漂亮的位编码等,但基本思想非常简单。