You can use Quartz to draw 2D paths into an
OpenGL texture, resize the source image, convert from one format to
another, and even generate text. One way of loading textures into OpenGL is
creating a Quartz surface using whatever format you’d like and then
drawing the source image to it, as shown in Example 1. Example 1. Texture loading with CGContextDrawImageTextureDescription LoadImage(const string& file) { NSString* basePath = [NSString stringWithUTF8String:file.c_str()]; NSString* resourcePath = [[NSBundle mainBundle] resourcePath]; NSString* fullPath = [resourcePath stringByAppendingPathComponent:basePath]; UIImage* uiImage = [UIImage imageWithContentsOfFile:fullPath]; TextureDescription description; description.Size.x = CGImageGetWidth(uiImage.CGImage); description.Size.y = CGImageGetHeight(uiImage.CGImage); description.BitsPerComponent = 8; description.Format = TextureFormatRgba; description.MipCount = 1; m_hasPvrHeader = false;
int bpp = description.BitsPerComponent / 2; int byteCount = description.Size.x * description.Size.y * bpp; unsigned char* data = (unsigned char*) calloc(byteCount, 1); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; CGContextRef context = CGBitmapContextCreate(data, description.Size.x, description.Size.y, description.BitsPerComponent, bpp * description.Size.x, colorSpace, bitmapInfo); CGColorSpaceRelease(colorSpace); CGRect rect = CGRectMake(0, 0, description.Size.x, description.Size.y); CGContextDrawImage(context, rect, uiImage.CGImage); CGContextRelease(context); m_imageData = [NSData dataWithBytesNoCopy:data length:byteCount freeWhenDone:YES]; return description; }
|
If you want to try the Quartz-loading code in
the sample app, perform the following steps: Add the following method declaration to
IResourceManager in
Interfaces.hpp: virtual TextureDescription LoadImage(const string& file) = 0;
In the SetPngTexture
method in RenderingEngine.TexturedES2.cpp, change
the LoadPngImage call to
LoadImage. In your render engine’s
Initialize method, make sure your minification
filter is GL_LINEAR and that you’re calling
SetPngTexture.
One advantage of loading images with Quartz is
that you can have it do some transformations before uploading the image to
OpenGL. For example, say you want to flip the image vertically. You could
do so by simply adding the following two lines immediately before the line
that calls CGContextDrawImage: CGContextTranslateCTM(context, 0, description.Size.y); CGContextScaleCTM(context, 1, -1);
Another neat thing you can do with Quartz is
generate new images from scratch in real time. This can shrink your
application, making it faster to download. This is particularly important
if you’re trying to trim down to less than 10MB, the maximum size that
Apple allows for downloading over the 3G network. Of course, you can do
this only for textures that contain simple vector-based images, as opposed
to truly artistic content. For example, you could use Quartz to generate a
256×256 texture that contains a blue filled-in circle, as in Example 2. The code for creating the surface should look
familiar; lines of interest are shown in bold. Example 2. ResourceManager::GenerateCircle()TextureDescription GenerateCircle() { TextureDescription description; description.Size = ivec2(256, 256); description.BitsPerComponent = 8; description.Format = TextureFormatRgba;
int bpp = description.BitsPerComponent / 2; int byteCount = description.Size.x * description.Size.y * bpp; unsigned char* data = (unsigned char*) calloc(byteCount, 1); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; CGContextRef context = CGBitmapContextCreate(data, description.Size.x, description.Size.y, description.BitsPerComponent, bpp * description.Size.x, colorSpace, bitmapInfo); CGColorSpaceRelease(colorSpace); CGRect rect = CGRectMake(5, 5, 246, 246); CGContextSetRGBFillColor(context, 0, 0, 1, 1); CGContextFillEllipseInRect(context, rect);
CGContextRelease(context); m_imageData = [NSData dataWithBytesNoCopy:data length:byteCount freeWhenDone:YES]; return description; }
|
If you want to try the circle-generation code
in the sample app, perform the following steps: Add the following method declaration to
IResourceManager in
Interfaces.hpp: virtual TextureDescription GenerateCircle() = 0;
In the SetPngTexture
method in RenderingEngine.TexturedES2.cpp, change
the LoadImage call to
GenerateCircle. In your render engine’s
Initialize method, make sure your minification
filter is GL_LINEAR and that you’re calling
SetPngTexture.
Quartz is a rich 2D graphics API and could have
a book all to itself, so I can’t cover it here; check out Apple’s online
documentation for more information.
|