Skip to main content
GameDev.net gamedev.net
🔒 Locked

Texture Error

Started by BeginGamer Jul 8, 2012 at 2:47 AM 12 replies 1.9k views
Original Post
BeginGamer
BeginGamer
I was battling with my code for today, and I pin-pointed the error of my sdl program instantly closing from error with the generation of my textures...



// in my DrawingGame definition source file
static void uploadImage( std::string & filename, GLuint & id )
{
SDL_Surface * tempt = IMG_Load(filename.c_str());
if(!tempt)
{
id = 0;
}
SDL_Surface * nCopy = SDL_CreateRGBSurface(SDL_SWSURFACE,tempt->w,tempt->h,32,
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
#else
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
#endif
);
SDL_BlitSurface(tempt,NULL,nCopy,NULL);
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
nCopy->w, nCopy->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nCopy->pixels);
SDL_FreeSurface(tempt);
SDL_FreeSurface(nCopy);
}

void gameDraw::Render_2D::getSpriteSheets(const std::vector<std::string> & imagefiles )
{
std::vector<GLuint>::iterator it;
unsigned int nSize = imagefiles.size();
textures.insert(it,nSize, 0);
unsigned int i = 0;
BOOST_FOREACH( std::string image, imagefiles )
{
uploadImage(image, textures);
++i;
}
}

khoadd
khoadd
You should specify the "it" first:
it = textures.begin();

if you want to insert to the beginning of vector :
textures.insert(it, nSize, value); (value : choose by urself)

if not the beginning

textures.insert(it + number, nSize, value) (number: is where you want);
khoadd
khoadd
why u must use it = textures.begin()
Let see this example:

i have a vector which has 2 items value 10:
myvector: | 10 | 10 |

I want to add 2 items (value : 20) to the myvector to form this one:
myvector: | 20 | 20 | 10 | 10 |

I must do : it = myvector.begin();
It means I want a place holder (we dont need to know the size) at the beginning of the myvector
myvector: |....place_holder......| 10 | 10 |
so "it" is your place_holder

then fill the place_holder with value u want
myvector.insert(it, nSize, value);
it means let myvector fills the "it" (the place_holder) with the "value" and "nSize" i want.

Another example:
your vector here:
myvector: | 10 | 10 |
add 2 more items to the middle
it = myvector.begin();
myvector.insert( it + 1, nSize, value);

you will have | 10 | 20 | 20 | 10 |
BeginGamer
BeginGamer
I tried that and still got an error , and I also tried

void gameDraw::Render_2D::getSpriteSheets(const std::vector<std::string> & imagefiles )
{
unsigned int nSize = imagefiles.size();
std::vector<GLuint> SpriteSheets(nSize, 0);
unsigned int i = 0;
BOOST_FOREACH( std::string image, imagefiles )
{
uploadImage(image, SpriteSheets);
++i;
}
textures = SpriteSheets;
}
khoadd
khoadd
Another problem i found in your logic:

if temp is null

how can u call func :
SDL_CreateRGBSurface()

if temp is null, u should return.
khoadd
khoadd
oh sorry,
I found another. vertor operator [] returns a "reference" not an "int".

So my advice is to use a GLint* (int pointer) instead of vector

example:
GLint* SpriteSheep = new GLint[nSize];
then
u can use uploadImage(image, SpriteSheet);
khoadd
khoadd
Try my last solution. I believe that it is
And whether it is right or wrong, Plz reply
BeginGamer
BeginGamer
it compiles and works... with GLuint * texture yet now it's not printing my sprites... but it does print background... if you want to see my rendering code



void gameDraw::Render_2D::Render(glSDL_Config & gConfig )
{
if( gConfig.Draw_Background)
{
GLubyte bk_indices [] = {
0, 1 , 2,
0, 2 , 3
};

glBindTexture(GL_TEXTURE_2D , textures[gConfig.background]);

glSDL_Vertex bk_vRect = gConfig.bk_Vertex;
glSDL_texture bk_tRect = gConfig.bk_texture;
GLfloat bk_vertices[ ] = {
bk_vRect.x , bk_vRect.y + bk_vRect.h, 0,
bk_vRect.x , bk_vRect.y , 0,
bk_vRect.x + bk_vRect.w , bk_vRect.y , 0,
bk_vRect.x + bk_vRect.w , bk_vRect.y + bk_vRect.h, 0
};
GLfloat bk_Texvertices[ ] = {
bk_tRect.x , bk_tRect.y + bk_tRect.num,
bk_tRect.x , bk_tRect.y ,
bk_tRect.x + bk_tRect.num , bk_tRect.y ,
bk_tRect.x + bk_tRect.num , bk_tRect.y + bk_tRect.num
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT,0, bk_Texvertices);
glVertexPointer(3, GL_FLOAT, 0, bk_vertices);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, bk_indices);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
if( gConfig.Draw_Sprite)
{
if( gConfig.foreground != gConfig.background)
{
glBindTexture(GL_TEXTURE_2D, textures[gConfig.foreground]);
}
int nSize = RenderArray.size();
GLfloat vertices[nSize * 12];
GLfloat texvertices[nSize * 8];
glSDL_Vertex vtemp;
glSDL_texture textemp;
unsigned int itv = 0;
unsigned int itex = 0;
BOOST_FOREACH( SpriteData & iter , RenderArray )
{
vtemp = boost::get<0>(iter);
textemp = boost::get<1>(iter);
//buttom left
vertices[itv] = vtemp.x;
vertices[itv + 1] = vtemp.y + vtemp.h;
vertices[itv + 2] = vtemp.layer;
//upper left
vertices[itv + 3] = vtemp.x;
vertices[itv + 4] = vtemp.y;
vertices[itv + 5] = vtemp.layer;
//upper right
vertices[itv + 6] = vtemp.x + vtemp.w;
vertices[itv + 7] = vtemp.y;
vertices[itv + 8] = vtemp.layer;
//lower right
vertices[itv + 9] = vtemp.x + vtemp.w;
vertices[itv + 10] = vtemp.y + vtemp.h;
vertices[itv + 11] = vtemp.layer;
itv += 12;
//buttom left
texvertices[itex] = textemp.x;
texvertices[itex + 1] = textemp.y + textemp.num;
//upper left
texvertices[itex + 2] = textemp.x;
texvertices[itex + 3] = textemp.y;
//upper right
texvertices[itex + 4] = textemp.x + textemp.num;
texvertices[itex + 5] = textemp.y;
//buttom right
texvertices[itex + 6] = textemp.x + textemp.num;
texvertices[itex + 7] = textemp.y + textemp.num;
itex += 8;
}
RenderArray.clear();
unsigned short quadindices[nSize * 6 ];
unsigned short *ndx = quadindices;
for (int i = 0, fv = 0; i < nSize; i++, fv += 4, ndx += 6)
{
ndx[0] = fv;
ndx[1] = fv + 1;
ndx[2] = fv + 2;
ndx[3] = fv;
ndx[4] = fv + 2;
ndx[5] = fv + 3;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//Enable drawing state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT,0, texvertices);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, quadindices);
//Done with drawing state
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);
}
SDL_GL_SwapBuffers();

}


I should make a test if the vertices and texvertices data have came in ~_~.....
khoadd
khoadd
Yup, at this point, no syntax error, you should debug by yourself. I am sure u will find the answer.
I cant help u now coz that is ur code and just u know how it works.
Syntax error is always easy to find than meaning error. sad.png
Good luck smile.png
BeginGamer
BeginGamer
Thanks for everything.. Apparently, the image wasn't loading.. it had a weird extensions LOL.... *Debugging is key* is there anyway to store Gluint in vector or just simply stick with gluint array? Also, do I need to use glDeletetextures ?
BitMaster
BitMaster

oh sorry,
I found another. vertor operator [] returns a "reference" not an "int".

So my advice is to use a GLint* (int pointer) instead of vector

example:
GLint* SpriteSheep = new GLint[nSize];
then
u can use uploadImage(image, SpriteSheet);


I would advice you to completely ignore that advice. Passing a vector element by reference to uploadImage (and then taking its address for glGenTextures) as in your original code was completely correct and the most natural and least error-prone way to do it. The problem was in the way you filled that vector (not counting possible other bugs in the code). I'm not completely sure what the standard says about passing a default constructed iterator to std::vector::insert but I assume that puts us in the happy land of undefined behavior.

For the way you use the vector I would suggest textures.resize(imagefiles.size()) instead of the wonky insert. If not, a short debugging session or an update of this thread with the current code and behavior should put you much closer to your goal.

I would also advise to take what else KhoaVN said with a lot of grains of salt. I freely admit being biased against excessive user of 1337-speak but at the very least the post I quoted is very much not helpful and shows a serious lack of understanding regarding the issues at hand.

There are two schools of thought about using glDeleteTextures. On the one hand, resources you allocated should be freed again. On the other hand the operating system will free all resources claimed by your application when it terminates. Freeing resources after you are done with them is only required if the program does something else for a while before terminating (for example loading another level, and then another). That said, for anything bigger you need to learn about proper resource management anyway, so why not start now in a project where it will not shoot you in the foot for a while?
khoadd
khoadd


I would also advise to take what else KhoaVN said with a lot of grains of salt. I freely admit being biased against excessive user of 1337-speak but at the very least the post I quoted is very much not helpful and shows a serious lack of understanding regarding the issues at hand.



@BitMaster: You're right. That's my fault.
@BeginGamer: Sorry for bad things.
BeginGamer
BeginGamer

For the way you use the vector I would suggest textures.resize(imagefiles.size()) instead of the wonky insert. If not, a short debugging session or an update of this thread with the current code and behavior should put you much closer to your goal.
[/quote]
Yes! You was absolutely right...

Though, I still have this problem of drawing both images.... It draws the background fine but not the sprite image...

I updated both the renderer and image upload with debug feed back. Usually, it tells me that it couldn't open the certain sprite file from IMG_LOAD.. Though, I have the filename correct and the format isn't wrong, it's just a simple png with transparent background. I even tested with a another sprite that work in another program I made just to make sure... The dlls are correct, because I just copy/paste from another working program.. So, I'm kind of scratching my head why it isn't working... I did test if my program receive the proper vertices and texvertices as well for the render function.. No errors was shown and had the positional values that I wanted..
BitMaster
BitMaster
How does "it tells me that it couldn't open the certain sprite file from IMG_LOAD"? What happens? Are both images PNG files? Because if not, the SDL Wiki entry of IMG_Load [1] suggests that PNG support requires the presence of both the PNG and ZLIB dynamic libraries.

[1] http://sdl.beuc.net/sdl.wiki/SDL_image

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.