2

Im trying to optimise my code by combining my textures into array textures (I realised I can't use texture atlases because most textures are repeated (over ground etc.)). I am working in PyGame and PyOpenGL, and I have never used shaders before. Is it possible to bind a single array texture with glBindTexture(GL_TEXTURE_2D_ARRAY, texname) and use 3d texture coordinates or something to access the different layers? Is it even possible without shaders?

At the moment I have a call to glDrawArrays for every texture with this function:

def DRAW(im, array):
    glBindTexture(GL_TEXTURE_2D,im)
    glTexCoordPointer(2, GL_FLOAT, 32, array)
    glNormalPointer(GL_FLOAT, 32, array[2:])
    glVertexPointer(3, GL_FLOAT, 32, array[5:])
    glDrawArrays(GL_QUADS,0,len(array)/8)
Matt Majic
  • 381
  • 9
  • 18

2 Answers2

4

Texture arrays can't be used without shaders. They were never part of the fixed-function pipeline. There is no GL_TEXTURE_2D_ARRAY enable bit in the GL.

Fixed function fragment processing is specified in section 16 in the OpenGL 4.5 compatibility profile specification.. Section 16.2 states:

Array and multisample textures are only supported by shaders, and may not be enabled for fixed-function texturing.

In the original GL_EXT_texture_array extension, you will find the following statements:

(2) Should texture arrays be supported for fixed-function fragment processing?

RESOLVED: No; it's not believed to be worth the effort. Fixed-function fragment processing could be easily supported by allowing applications to enable or disable TEXTURE_1D_ARRAY_EXT or TEXTURE_2D_ARRAY_EXT.

Note that for fixed-function fragment processing, there would be issues with texture lookups of two-dimensional array textures with shadow mapping. Given that all texture lookups are projective, a total of five coordinate components would be required (s, t, layer, depth, q).

(3) If fixed-function were supported, should the layer number (T or R) be divided by Q in projective texture lookups?

RESOLVED: It doesn't need to be resolved in this extension, but it would be a problem. There are probably cases where an application would want the divide (handle R more-or-less like S/T); there are probably other cases where the divide would not be wanted. Many developers won't care, and may not even know what the Q coordinate is used for! The default of 1.0 allows applications that don't care about projective lookups to simply ignore that fact.

For programmable fragment shading, an application can code it either way and use non-projective lookups. To the extent that the divide by Q for projective lookups is "free" or "cheap" on OpenGL hardware, compilers may be able to recognize a projective pattern in the computed coordinates and generate code appropriately.

When array textures were promoted a OpenGL core feature, this was not changed.

derhass
  • 43,833
  • 2
  • 57
  • 78
3

As the spec quote in the answer by @derhass shows, array textures are not supported without shaders.

However, you can use 3D textures to do pretty much the same thing. You store each texture in a layer of the 3D texture. Then you use the first 2 texture coordinates as usual, to determine the position within the texture image. The 3rd texture coordinate is used to select the layer within the 3D texture.

To load an image into the 3D texture, you use glTexSubImage3D(). For example, say your textures have size 512x512, and you want to load texture index 20:

glTexSubImage3D(GL_TEXTURE_3D, 0,
    0, 0, 20, 512, 512, 1,
    GL_RGBA, GL_UNSIGNED_BYTE, data);

The only slightly tricky part is calculating the 3rd texture coordinate properly, since texture coordinates are normalized floats. Particularly if you use linear sampling, you have to hit the center of a layer exactly, otherwise you'll get a mix of images.

If you have n layers in your 3D texture, the texture coordinate for layer k is:

(k + 0.5f) / n

For example, with n = 4, the resulting texture coordinates for the 4 layers will be:

0.125f
0.375f
0.625f
0.875f

Note how the values are spaced by 0.25f, as you would expect, and placed symmetrically within the interval [0.0f, 1.0f]

One downside of using 3D textures is that they have smaller size restrictions. With this approach, make sure that you don't exceed MAX_3D_TEXTURE_SIZE.

I would encourage you to learn using shaders. It may look slightly intimidating at first because it's certainly more work for very simple use cases. But you'll find that once you get the hang of it, they actually make things easier when your functionality becomes more complex. It's often much more straightforward to write GLSL code to do exactly what you want, instead of trying to figure out how to properly set a few dozen state values to get the desired results. And of course shaders allow you to implement functionality that is simply impossible in the fixed pipeline.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133