How can I use a dynamically sized texture array with glTexImage2D?

流过昼夜 提交于 2019-12-03 21:37:20

You can use

int width = 1024;
int height = 1024;
GLubyte * texture = new GLubyte[4*width*height];
...
glTexImage2D(
    GL_TEXTURE_2D, 0, GL_RGBA,
    width, height,
    0, GL_RGBA, GL_UNSIGNED_BYTE, textureArray);
delete [] texture;         //remove the un-needed local copy of the texture;

However you still need to specify the width and height to OpenGL in glTexImage2D call. This call copies texture data and that data is managed by OpenGL. You can delete, resize, change your original texture array all you want and it won't make a different to the texture you specified to OpenGL.

Edit: C/C++ deals with only 1 dimensional arrays. The fact that you can do texture[a][b] is hidden and converted by the compiler at compile time. The compiler must know the number of columns and will do texture[a*cols + b].

Use a class to hide the allocation, access to the texture.

For academic purposes, if you really want dynamic multi dimensional arrays the following should work:

int rows = 16, cols = 16;
char * storage = new char[rows * cols];
char ** accessor2D = new char *[rows];
for (int i = 0; i < rows; i++)
{
    accessor2D[i] = storage + i*cols;
}
accessor2D[5][5] = 2;
assert(storage[5*cols + 5] == accessor2D[5][5]);
delete [] accessor2D;
delete [] storage;

Notice that in all the cases I'm using 1D arrays. They are just arrays of pointers, and array of pointers to pointers. There's memory overhead to this. Also this is done for 2D array without colour components. For 3D dereferencing this gets really messy. Don't use this in your code.

Ok since this took me ages to figure this out, here it is:

My task was to implement the example from the OpenGL Red Book (9-1, p373, 5th Ed.) with a dynamic texture array.

The example uses:

static GLubyte checkImage[checkImageHeight][checkImageWidth][4];

Trying to allocate a 3-dimensional array, as you would guess, won't do the job. Someth. like this does NOT work:

GLubyte***checkImage;
checkImage = new GLubyte**[HEIGHT];

for (int i = 0; i < HEIGHT; ++i)
{
  checkImage[i] = new GLubyte*[WIDTH];

  for (int j = 0; j < WIDTH; ++j)
    checkImage[i][j] = new GLubyte[DEPTH];
}

You have to use a one dimensional array:

unsigned int depth = 4;

GLubyte *checkImage = new GLubyte[height * width * depth];

You can access the elements using this loops:

for(unsigned int ix = 0; ix < height; ++ix)
{
  for(unsigned int iy = 0; iy < width; ++iy)
  {
    int c = (((ix&0x8) == 0) ^ ((iy&0x8)) == 0) * 255;

    checkImage[ix * width * depth + iy * depth + 0] = c;   //red
    checkImage[ix * width * depth + iy * depth + 1] = c;   //green
    checkImage[ix * width * depth + iy * depth + 2] = c;   //blue
    checkImage[ix * width * depth + iy * depth + 3] = 255; //alpha
  }
}

Don't forget to delete it properly:

delete [] checkImage;

Hope this helps...

You could always wrap it up in a class. If you are loading the image from a file you get the height and width out with the rest of the data (how else could you use the file?), you could store them in a class that wraps the file loading instead of using preprocessor defines. Something like:

class ImageLoader
{
...
  ImageLoader(const char* filename, ...);
...
  int GetHeight();
  int GetWidth();
  void* GetDataPointer();
...
};

Even better you could hide the function calls to glTexImage2d in there with it.

class GLImageLoader
{
...
  ImageLoader(const char* filename, ...);
...
  GLuint LoadToTexture2D(); // returns texture id
...
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!