Forest Hale wrote:
I believe you need to set these before glTexImage2D:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // if using a format other than GL_RGBA
glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch); // not sure if surface->pitch is the best thing to put here
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, surface->h);
But I’ve never tried uploading an image this way before, I normally would pad the surface size to a power of 2 and then upload that, rather than pulling tricks with unpack settings - also I’m not sure
if these unpack settings exist on iOS.
If you look at the latest http://lackeyccg.com/code/FontGlyphClass.cpp file, I got it to work without using any GL_UNPACK settings. I’m not sure if that method would work on iOS, but I tested that with the method I am currently using, it does (at least on the simulator which I am assuming implies it will work on the device). You think an GL_UNPACK method would be superior? One thing I am currently not sure of is if all of the code I just added to get things to work is needed or optimal. One of the things I am doing now is removing some of the new code and seeing if things still work on iOS.
Here is the code that loads the FontGlyph:
Code:
FontGlyphClass::FontGlyphClass(SDL_Surface surface)
{
int WidthInNearestPowOf2 = nextPowerOfTwo(surface->w);
int HeightInNearestPowOf2 = nextPowerOfTwo(surface->h);
SetTexMinX(0.0f); / Min X /
SetTexMinY(0.0f); / Min Y /
SetTexMaxX((GLfloat)surface->w / WidthInNearestPowOf2); / Max X /
SetTexMaxY( (GLfloat)surface->h / HeightInNearestPowOf2); / Max Y */
SetWidth(surface->w); //This is the actual width and height of the image, which is not necessarily a power of 2.
SetHeight(surface->h);
SDL_Surface *image = SDL_CreateRGBSurface(
SDL_SWSURFACE,
WidthInNearestPowOf2, HeightInNearestPowOf2,
32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
/* Save the alpha blending attributes */
//Uint8 saved_alpha;
//SDL_GetSurfaceAlphaMod(surface, &saved_alpha);
//SDL_SetSurfaceAlphaMod(surface, 0xFF);
//SDL_BlendMode saved_mode;
//SDL_GetSurfaceBlendMode(surface, &saved_mode);
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);//This is the only line relating to blending and alpha that seems to do anything I could notice.
/* Copy the surface into the GL texture image */
SDL_Rect area;
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);
/* Restore the alpha blending attributes */
//SDL_SetSurfaceAlphaMod(surface, saved_alpha);
//SDL_SetSurfaceBlendMode(surface, saved_mode);
/////////////////////
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WidthInNearestPowOf2, HeightInNearestPowOf2, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if(image)
SDL_FreeSurface(image); /* No longer needed since the data is retained as an OpenGL texture */
}
Forest Hale wrote:
It’s best to create an atlas texture (large texture that you upload many small pieces into) and maintain it as a software surface, and when you have copied some additional text images into it, update
the texture - preferably no more than once a frame (mobile hardware is not fast!), so do this as two passes through your relevant code (preparing the needed text images, then uploading, then drawing
them all).
Regarding a software surface as opposed to an opengl texture, I don’t see any reason to maintain (i.e., retain) anything besides the opengl textures. The opengl textures are the only things I actually need to render the glyphs, and I figure I might as well load all the glyphs once and be done loading. I suppose if I happened to never use a particular glyph, there would be some wasted memory, but I’m not sure that would make it worth it to maintain the software surface and dynamically load only those glyphs I need at the moment. But perhaps I am not understanding your point. You seem to be advocating updating the texture very frequently which I would think would result in worse performance.
Regarding a single atlas texture, currently how I am doing it is loading every glyph to an OpenGL texture via glBindTexture(GL_TEXTURE_2D, texture[0]);. This results in a lot of separate opengl texture IDs (which I am not sure is intrinsically bad). I agree that it might be better to load all glyphs to a single texture and have each glyph know its specific UV coordinates on the atlas texture. I did it how I did it because my code was based on http://codepad.org/QS26ciMD from Chris Bush, and that’s how he did it. I’m curious why he decided to load all of the glyphs as separate opengl images. Perhaps he had a reason for it, or perhaps it was simply easier to implement.
Forest Hale wrote:
Note that all OpenGL drivers will greatly prefer that you two pass your render anyway, upload all vertex buffers, textures and anything else of that nature, before you issue your first glDrawElements
of the frame.
I’m not exactly sure what you mean by this. Is this a general comment, or did you look at the code at http://lackeyccg.com/code/ and determine I was doing things in a suboptimal way?