是否有增加GL_MAX_ARRAY_TEXTURE_LAYERS的解决方法?

时间:2018-10-25 14:44:45

标签: opengl glsl opengl-3

我正在使用纹理数组来渲染Minecraft样式的体素地形。效果不错,但最近我注意到GL_MAX_ARRAY_TEXTURE_LAYERSGL_MAX_TEXTURE_SIZE小很多。

我的纹理非常小,为8x8,但我需要能够支持从数百个到数千个的渲染;我只需要将GL_MAX_ARRAY_TEXTURE_LAYERS放大即可。

OpenGL 4.5要求GL_MAX_ARRAY_TEXTURE_LAYERS至少为2048,可能就足够了,但是我的应用程序的目标是OpenGL 3.3,它只能保证256 +。

我正在草拟空白,试图找出针对此限制的审慎解决方法;对我而言,根据支持的纹理层的最大数量划分地形的渲染对我来说根本不是一件小事。

我调查了ARB_sparse_texture是否可以提供帮助,但是GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARBGL_MAX_ARRAY_TEXTURE_LAYERS相同;该扩展只是使用VRAM而不是使用层的一种解决方法。

我是否可以从sampler2DArray阵列访问GLSL着色器? GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS必须至少为80以上,因此80+ * 256+ = 20480+足以满足我的需求。那么,理论上我可以做这样的事情吗?

const int MAXLAYERS = 256;
vec3 texCoord;
uniform sampler2DArray[] tex;
void main()
{
    int arrayIdx = int(texCoord.z + 0.5f) / MAXLAYERS  256
    float arrayOffset = texCoord.z % MAXLAYERS;
    FragColor = texture(tex[arrayIdx],
        vec3(texCoord.x, texCoord.y, arrayOffset));
}

1 个答案:

答案 0 :(得分:2)

最好抛弃数组纹理,而只使用纹理图集(或使用数组纹理,使每一层包含很多子纹理,但正如我将要展示的那样,这是不必要的)。如果使用的分辨率如此低,则可能没有使用线性插值,因此可以轻松避免从相邻纹理像素溢出。即使您在渗色方面遇到麻烦,也可以通过在子纹理之间添加一些空间来轻松解决此问题。

即使子纹理需要为10x10以避免渗出,1024x1024纹理(GL 3.3要求的最小尺寸)也可以为您提供102x102子纹理,即10'404纹理。应该足够。如果不是这样,则使其成为具有所需多层的数组纹理。

一些采样器无法满足您的目的。首先,您不能声明任何大小不定的uniform数组。可以,但是您必须在着色器中的某个位置重新声明其大小,因此未声明大小的声明没有多大意义。您唯一可以容纳的未调整大小的数组位于SSBO中,这是SSBO的最后一个元素。

第二,即使具有大小,用于opaque types 数组的索引也必须是dynamically uniform。而且,由于您试图在一次绘制调用中绘制多维数据集的所有面,并且每个面都可以从不同的图层中进行选择,因此该表达式的值没有动态统一的意图。

第三,即使您使用bindless texturing进行此操作,也会遇到相同的问题:除非您使用NVIDIA硬件,否则您选择的采样器必须是动态统一的采样器。这要求采样器数组中的索引是动态统一的。哪个不是你的。