# texture arrays

## Recommended Posts

Rui    122
hey! here's the problem: i want to load 6 images using devil end put them in a texture array. i guess i could do it one by one, basically repeating the same code 6 times (one for each image), but im trying to do it in a way that uses less lines of code. so here's what i have:
 void load_img_devil () {
int width, height, format, il_img;

ilInit ();
iluInit();
ilutRenderer(ILUT_OPENGL);

for(int i=0;i<6;i++){
ilGenImages (1, (ILuint*)&il_img); // get an unique ID
ilBindImage(il_img); // Bind this image name.
width = ilGetInteger (IL_IMAGE_WIDTH);
height = ilGetInteger (IL_IMAGE_HEIGHT);
il_imgData[i] = ilGetData();
format = ilGetInteger(IL_IMAGE_FORMAT);

// create GL texture
glGenTextures (1, (GLuint *)&texID[i]); // get texture unique ID
glBindTexture (GL_TEXTURE_2D, texID[i]); // bind it

// associate with data read with DevIL
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format,
GL_UNSIGNED_BYTE, il_imgData[i]);

// Release data space created with DevIL
ilDeleteImages(1, (const ILuint *)&il_img);
}

// Parameterise Texture
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}


the thing is.. it doesnt work. to test it i made a square and textured it with texID[0], it appears white; as with any other index. Note 1: texID and il_imgData are global variables; arrays with lenght 6. Note 2: if i open brackets after 'if(i==0)' and close it after the ilDeleteImages call, it works.(for the first image)

##### Share on other sites
DevFred    840
I'm pretty sure you cannot cast like that:
(const wchar_t *)"F:\\Side1.png"

##### Share on other sites
Zahlman    1682
Use L"something here" to create a string literal using wchars.

##### Share on other sites
Rui    122
@DevFred: i can. i dont get any compiler errors or warnings. in fact, that's why i did the cast in the first place, otherwise i'd get a compiler error. plus, if i try to load only one texture, it works. my guess is the problem is somewhere in the loop.

@Zahlman: i'm not sure what you mean but i think it's more or less what DevFred said, so...

Thanks for the replies.

##### Share on other sites
erissian    727
That for loop seems like an excellent candidate for a function. Then you can just call it six times, once for each file.

##### Share on other sites
LogicalError    293
Quote:
 Original post by Rui@DevFred: i can. i dont get any compiler errors or warnings. in fact, that's why i did the cast in the first place, otherwise i'd get a compiler error. plus, if i try to load only one texture, it works. my guess is the problem is somewhere in the loop.@Zahlman: i'm not sure what you mean but i think it's more or less what DevFred said, so...Thanks for the replies.

No, DevFred is right. you're casting one type of pointer (char*) to (wchar_t* )..
One is an 8-bit ascii string, the other is a 16-bit unicode string, something which is valid C++ (so no compiler error) but in this case it's still a bug.
Use L"F:\\Side1.png" to create a 16-bit unicode string.

##### Share on other sites
dashurc    236
Quote:
 Original post by Rui@DevFred: i can. i dont get any compiler errors or warnings. in fact, that's why i did the cast in the first place, otherwise i'd get a compiler error. plus, if i try to load only one texture, it works. my guess is the problem is somewhere in the loop.@Zahlman: i'm not sure what you mean but i think it's more or less what DevFred said, so...Thanks for the replies.

While casting like that isn't a compiler error, it's a logical error and most likely explains why you're getting untextured triangles.

To use wide character strings use a capital L before the quotation mark.

##### Share on other sites
LogicalError    293
Quote:
 Original post by dashurcWhile casting like that isn't a compiler error, it's a logical error and most likely explains why you're getting untextured triangles.

Hey, i resent that! ;)

##### Share on other sites
DevFred    840
Quote:
 Original post by Rui@DevFred: i can. i dont get any compiler errors or warnings. in fact, that's why i did the cast in the first place, otherwise i'd get a compiler error.

So if you give meat to a vegetarian and he complains "I don't like meat", what do you do? Simply tell him "Don't worry, just pretend it's a vegetable"?

##### Share on other sites
Rui    122
k, thanks everyone. i see now why that's an error. devfred really put it in perspective for me lol..

(following erissian's advice it works perfect, with 'const wchar_t*')

any ideas why that might be?

##### Share on other sites
erissian    727
Quote:
 Original post by Ruik, thanks everyone. i see now why that's an error. devfred really put it in perspective for me lol.. but replacing '(const wchar_t*) "F:\\Side1.pgn"' for 'L"Side1.pgn"' made ilLoadImage exit though..(following erissian's advice it works perfect, with 'const wchar_t*')any ideas why that might be?

You can use ilGetError() to find out what's going wrong.

Anyways, to understand the problem you had before, you need to realize how the character arrays are kept in memory. A regular ascii character array looks like:

'H','e','l','l','o',' ','w','o','r','l','d',0

Because the individual characters are a single byte. Wide character arrays, on the other hand, are two bytes in length, so the equivalent array looks like:

0,'H',0,'e',0,'l',0,'l',0,'o',0,' ',0,'w',0,'o',0,'r',0,'l',0,'d',0

So while you can use a wide character pointer to reference an ascii character array, what it ends up seeing is:

'He','ll','o ','wo','rl','d\0',...

plus whatever is in memory after that until it comes across 0x00.

For fun, "F:\\Side1.png" translates to: "䘺屓楤攱⹰湧" which is probably not what you were looking for :)

##### Share on other sites
Zahlman    1682
Quote:
 Original post by Rui@DevFred: i can. i dont get any compiler errors or warnings.

Just because the compiler doesn't complain about something doesn't mean you "can do" it. You can write programs that are basically guaranteed to crash immediately, without the compiler saying a thing. Such is C++. That's one of the main reasons we try to steer new programmers away from it.

Quote:
 plus, if i try to load only one texture, it works. my guess is the problem is somewhere in the loop.

Things "seeming to work once" is a common symptom of code that does something wrong that the compiler can't catch. Again, such is C++, etc.

Quote:
 @Zahlman: i'm not sure what you mean

I don't know how much clearer I could make it, but let me try saying exactly what it should look like:

if (i==0) if(!ilLoadImage(L"F:\\Side1.png")) exit(0); // Load the image

The L"something here" construct is built into the language. It tells the compiler that you are creating a wide-character literal. This means that a chunk of memory is set up with a size of (number of characters in the string) * (number of bytes needed for a wide character), and each character of the string is a wide character.

An ordinary string literal uses a chunk of memory with a size of (number of characters in the string) * (number of bytes needed for an ordinary character, i.e. 1). By casting the pointer, you do not affect this chunk of memory. Instead, you instruct the compiler to regard the chunk of memory as if it were a sequence of (size of a wide character)-sized elements, which (a) obviously contains fewer elements than intended, and (b) groups the bytes of the string literal together in nonsensical ways.

##### Share on other sites
Rui    122
Quote:
 That's one of the main reasons we try to steer new programmers away from it.

Quote:
 Again, such is C++, etc.

Granted I dont have much experience, but it's not that i'm a new programmer, i'm just new to C++. I never had a class to learn C++ like I did C or Java for example, and yet I need it for the Computer Graphics class project.

Quote:
 I don't know how much clearer I could make it, but let me try saying exactly what it should look like:if (i==0) if(!ilLoadImage(L"F:\\Side1.png")) exit(0); // Load the image

i had never seen that construct before, hence the confusion.