▼iPhoneプログラミングメモ▼
OpenGLによる2Dグラフィックス
GpenGLによる2Dグラフィックスの描画を行うプログラムを作成する。
フレームワークの準備
QuartzCoreフレームワークとOpenGLESフレームワークを追加。
画像の準備
sorami.png
ソースコードの記述
Graphics2DEx.h #import "Canvas.h" #import "Graphics.h" #import "Image.h" //Graphics2DExの宣言 @interface Graphics2DEx : Canvas { Graphics* _g; Image* _image; } @end
Graphics2DEx.m #import "Graphics2DEx.h" //Graphics2DExの実装 @implementation Graphics2DEx //フレームの初期化 - (id)initWithFrame:(CGRect)frame { if (self=[super initWithFrame:frame]) { //グラフィックスの生成 _g=[[Graphics alloc] init]; //イメージの初期化 _image=nil; //アニメの開始 [self startAnime:100]; } return self; } //メモリ解放 - (void)dealloc { [_g release]; [_image release]; [super dealloc]; } //セットアップ - (void)setup { //グラフィックスのセットアップ [_g initSize:CGSizeMake(self.bgWidth,self.bgHeight)]; //イメージの読み込み _image=[[Image makeImage:[UIImage imageNamed:@"sorami.png"]] retain]; } //定期処理 - (void)onTick { //バッファのクリア [_g clear]; //ラインの描画 [_g setColor:rgb(0,0,255)]; [_g setLineWidth:2]; [_g drawLine_x0:40 y0:10 x1:40 y1:70]; //矩形の描画 [_g setColor:rgb(0,255,0)]; [_g setLineWidth:1]; [_g drawRect_x:10 y:100 w:60 h:60]; //矩形の塗り潰し [_g setColor:rgb(255,255,0)]; [_g setLineWidth:1]; [_g fillRect_x:80 y:100 w:60 h:60]; //円の描画 [_g setColor:rgb(0,255,0)]; [_g drawCircle_x:40 y:210 r:30]; //円の塗り潰し [_g setColor:rgb(0,0,255)]; [_g fillCircle_x:110 y:210 r:30]; //画像の描画 [_g drawImage:_image x:10 y:270]; //テキストの描画 [_g setFontSize:24]; [_g setColor:rgb(0,0,255)]; [_g drawString:@"そらみ" x:30 y:390]; //拡大反転画像の描画 [_g setFlipMode:GRAPHICS_FLIP_HORIZONTAL]; [_g drawScaledImage:_image x:130 y:270 w:161 h:161 sx:0 sy:0 sw:114 sh:114]; [_g setFlipMode:GRAPHICS_FLIP_NONE]; } @end
Canvas.h #import <UIKit/UIKit.h> #import <OpenGLES/EAGL.h> #import <OpenGLES/ES1/gl.h> #import <OpenGLES/ES1/glext.h> //Canvasの実装 @interface Canvas : UIView { @private //描画 EAGLContext* _context; //コンテキスト GLint _bgWidth; //背景幅 GLint _bgHeight; //背景高さ GLuint _viewRenderBuff; //レンダーバッファ GLuint _viewFrameBuff; //フレームバッファ GLuint _depthRenderBuff;//デプスレンダーバッファ BOOL _initFlag; //初期化フラグ //アニメ NSTimer* _animeTimer;//アニメタイマー } //描画 @property(readonly) GLint bgWidth; @property(readonly) GLint bgHeight; //描画 - (void)setup; - (void)onTick; //アニメ - (void)startAnime:(int)interval; - (void)stopAnime; @end
Canvas.m #import#import #import "Canvas.h" #define USE_DEPTH_BUFFER 0 //Canvasのプライベートメソッド @interface Canvas () @property (nonatomic,retain) EAGLContext *context; @property (nonatomic,assign) NSTimer *animeTimer; - (BOOL)createFrameBuff; - (void)destroyFrameBuff; - (void)drawView; @end //Canvasの実装 @implementation Canvas //描画 @synthesize context =_context; @synthesize animeTimer=_animeTimer; @synthesize bgWidth =_bgWidth; @synthesize bgHeight =_bgHeight; //==================== //初期化 //==================== //レイヤーの取得 + (Class)layerClass { return [CAEAGLLayer class]; } //初期化 - (id)init { if ((self=[super init])) { _initFlag=NO; } return self; } //フレームの初期化 - (id)initWithFrame:(CGRect)frame { if (self=[super initWithFrame:frame]) { //レイヤーの生成 CAEAGLLayer* eaglLayer=(CAEAGLLayer*)self.layer; eaglLayer.opaque=YES; eaglLayer.drawableProperties=[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; //コンテキストの生成 _context=[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; if (!_context || ![EAGLContext setCurrentContext:_context]) { [self release]; return nil; } //アニメ _animeTimer=nil; } return self; } //メモリの解放 - (void)dealloc { //描画 if ([EAGLContext currentContext]==_context) { [EAGLContext setCurrentContext:nil]; } [_context release]; //アニメ [_animeTimer release]; [super dealloc]; } //==================== //描画 //==================== //ビューの描画 - (void)drawView { //前処理 [EAGLContext setCurrentContext:_context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES,_viewFrameBuff); //描画 if (!_initFlag) { [self setup]; _initFlag=YES; } [self onTick]; //後処理 glBindRenderbufferOES(GL_RENDERBUFFER_OES,_viewRenderBuff); [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; } //セットアップ(オーバーライド用) - (void)setup { } //定期処理(オーバーライド用) - (void)onTick { } //サブビューのレイアウト - (void)layoutSubviews { [EAGLContext setCurrentContext:_context]; [self destroyFrameBuff]; [self createFrameBuff]; [self drawView]; } //フレームバッファの生成 - (BOOL)createFrameBuff { glGenFramebuffersOES(1,&_viewFrameBuff); glGenRenderbuffersOES(1,&_viewRenderBuff); glBindFramebufferOES(GL_FRAMEBUFFER_OES,_viewFrameBuff); glBindRenderbufferOES(GL_RENDERBUFFER_OES,_viewRenderBuff); [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,GL_RENDERBUFFER_OES,_viewRenderBuff); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,GL_RENDERBUFFER_WIDTH_OES,&_bgWidth); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES,GL_RENDERBUFFER_HEIGHT_OES,&_bgHeight); if (USE_DEPTH_BUFFER) { glGenRenderbuffersOES(1,&_depthRenderBuff); glBindRenderbufferOES(GL_RENDERBUFFER_OES,_depthRenderBuff); glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES,_bgWidth,_bgHeight); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES,GL_RENDERBUFFER_OES,_depthRenderBuff); } if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)!=GL_FRAMEBUFFER_COMPLETE_OES) { return NO; } return YES; } //フレームバッファの破棄 - (void)destroyFrameBuff { glDeleteFramebuffersOES(1,&_viewFrameBuff); _viewFrameBuff=0; glDeleteRenderbuffersOES(1,&_viewRenderBuff); _viewRenderBuff=0; if (_depthRenderBuff) { glDeleteRenderbuffersOES(1,&_depthRenderBuff); _depthRenderBuff=0; } } //==================== //アニメ //==================== - (void)startAnime:(int)interval { [self stopAnime]; self.animeTimer=[NSTimer scheduledTimerWithTimeInterval:interval/1000.0f target:self selector:@selector(drawView)userInfo:nil repeats:YES]; } //アニメの停止 - (void)stopAnime { if (_animeTimer!=nil) { [_animeTimer invalidate]; self.animeTimer=nil; } } @end
Graphics.h#import "Image.h" //テキストバッファ #define TEXT_BUFF 100 //色 #define rgba(red,green,blue,alpha) [Graphics makeColor_r:red g:green b:blue a:alpha] #define rgb(red,green,blue) [Graphics makeColor_r:red g:green b:blue a:255] //色定数 #define GRAPHICS_AQUA rgb(0,255,255) #define GRAPHICS_BLACK rgb(0,0,0) #define GRAPHICS_BLUE rgb(0,0,55) #define GRAPHICS_FUCHSIA rgb(255,0,255) #define GRAPHICS_GRAY rgb(128,128,128) #define GRAPHICS_GREEN rgb(0,128,0) #define GRAPHICS_LIME rgb(0,255,0) #define GRAPHICS_MAROON rgb(128,0,0) #define GRAPHICS_NAVY rgb(0,0,128) #define GRAPHICS_OLIVE rgb(128,128,0) #define GRAPHICS_PURPLE rgb(128,0,128) #define GRAPHICS_RED rgb(255,0,0) #define GRAPHICS_SILVER rgb(192,192,192) #define GRAPHICS_TEAL rgb(0,128,128) #define GRAPHICS_WHITE rgb(255,255,255) #define GRAPHICS_YELLOW rgb(255,255,0) //フリップ定数 #define GRAPHICS_FLIP_NONE -1 #define GRAPHICS_FLIP_HORIZONTAL 0 #define GRAPHICS_FLIP_VERTICAL 2 //色 typedef struct{ int r; int g; int b; int a; } Color; //Graphicsの宣言 @interface Graphics : NSObject { @private //サイズ CGSize _bgSize;//背景サイズ //グラフィックス設定 Color _color; //色 int _flipMode;//フリップ int _originX; //原点X int _originY; //原点Y //文字列設定 int _fontSize;//フォントサイズ NSMutableDictionary* _textMap; //テキストマップ NSMutableArray* _textList;//テキストリスト } //初期化 - (void)initSize:(CGSize)size; - (void)clear; //クリッピング - (void)clipRect_x:(GLfloat)x y:(GLfloat)y w:(GLfloat)w h:(GLfloat)h; - (void)clearClip; //色 - (void)setColor:(Color)color; + (Color)makeColor_r:(int)r g:(int)g b:(int)b a:(int)a; //グラフィックス設定 - (void)setLineWidth:(int)lineWidth; - (void)setFlipMode:(int)flipMode; - (void)setOrigin_x:(int)x y:(int)y; //文字列設定 - (void)setFontSize:(int)fontSize; - (int)getFontSize; - (int)stringWidth:(NSString*)text; - (int)stringHeight:(NSString*)text; //描画 - (void)drawLine_x0:(int)x0 y0:(int)y0 x1:(int)x1 y1:(int)y1; - (void)drawRect_x:(int)x y:(int)y w:(int)w h:(int)h; - (void)fillRect_x:(int)x y:(int)y w:(int)w h:(int)h; - (void)drawCircle_x:(int)x y:(int)y r:(int)r; - (void)fillCircle_x:(int)x y:(int)y r:(int)r; - (void)drawImage:(Image*)image x:(int)x y:(int)y; - (void)drawScaledImage:(Image*)image x:(int)x y:(int)y w:(int)w h:(int)h sx:(int)sx sy:(int)sy sw:(int)sw sh:(int)sh; - (void)drawString:(NSString*)text x:(int)x y:(int)y; @end
Graphics.m #import "Graphics.h" //テクスチャ頂点情報 GLfloat panelVertices[]={ 0, 0, //左上 0, -1, //左下 1, 0, //右上 1, -1, //右下 }; //テクスチャUV情報 const GLfloat panelUVs[]={ 0.0f, 0.0f, //左上 0.0f, 1.0f, //左下 1.0f, 0.0f, //右上 1.0f, 1.0f, //右下 }; //Graphicsの実装 @implementation Graphics //==================== //初期化 //==================== //初期化 - (id)init { if (self=[super init]) { //背景サイズ _bgSize=CGSizeMake(320,460); //色 _color=GRAPHICS_BLACK; //グラフィックス設定 _flipMode=GRAPHICS_FLIP_NONE; _originX =0; _originY =0; //文字列設定 _fontSize=12; _textList=[[NSMutableArray alloc] init]; _textMap =[[NSMutableDictionary alloc] init]; } return self; } //メモリ解放 - (void)dealloc { [_textList release]; [_textMap release]; [super dealloc]; } //初期化 - (void)initSize:(CGSize)size { _bgSize=size; //ビューポート変換 glViewport(0,0,_bgSize.width,_bgSize.height); //投影変換 glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(-_bgSize.width/2,_bgSize.width/2, -_bgSize.height/2,_bgSize.height/2,-100,100); glTranslatef(-_bgSize.width/2,_bgSize.height/2,0); //モデリング変換 glMatrixMode(GL_MODELVIEW); //クリア色の設定 glClearColor(1,1,1,1); //頂点配列の設定 glVertexPointer(2,GL_FLOAT,0,panelVertices); glEnableClientState(GL_VERTEX_ARRAY); //UVの設定 glTexCoordPointer(2,GL_FLOAT,0,panelUVs); //テクスチャの設定 glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_2D); //ブレンドの設定 glEnable(GL_BLEND); glBlendEquationOES(GL_FUNC_ADD_OES); glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); //ポイントの設定 glEnable(GL_POINT_SMOOTH); } //クリア - (void)clear { glClear(GL_COLOR_BUFFER_BIT); } //==================== //クリッピング //==================== //クリッピングの指定 - (void)clipRect_x:(GLfloat)x y:(GLfloat)y w:(GLfloat)w h:(GLfloat)h { GLfloat area0[4]={ 0,-1, 0,-y }; GLfloat area1[4]={ 0, 1, 0, y+h}; GLfloat area2[4]={ 1, 0, 0,-x }; GLfloat area3[4]={-1, 0, 0, x+w}; glClipPlanef(GL_CLIP_PLANE0,area0); glClipPlanef(GL_CLIP_PLANE1,area1); glClipPlanef(GL_CLIP_PLANE2,area2); glClipPlanef(GL_CLIP_PLANE3,area3); glEnable(GL_CLIP_PLANE0); glEnable(GL_CLIP_PLANE1); glEnable(GL_CLIP_PLANE2); glEnable(GL_CLIP_PLANE3); } //クリッピングのクリア - (void)clearClip { glDisable(GL_CLIP_PLANE0); glDisable(GL_CLIP_PLANE1); glDisable(GL_CLIP_PLANE2); glDisable(GL_CLIP_PLANE3); } //==================== //色 //==================== //色の指定 - (void)setColor:(Color)color { _color=color; } //色の生成 + (Color)makeColor_r:(int)r g:(int)g b:(int)b a:(int)a { Color color; color.r=r; color.g=g; color.b=b; color.a=a; return color; } //==================== //グラフィックス設定 //==================== //ライン幅の指定 - (void)setLineWidth:(int)lineWidth { glLineWidth(lineWidth); glPointSize(lineWidth*0.6f); } //フリップモードの指定 - (void)setFlipMode:(int)flipMode { _flipMode=flipMode; } //減点の指定 - (void)setOrigin_x:(int)x y:(int)y { _originX=x; _originY=y; } //==================== //文字列設定 //==================== //フォントサイズの指定 - (void)setFontSize:(int)fontSize { _fontSize=fontSize; } //フォントサイズの取得 - (int)getFontSize { return _fontSize; } //文字列幅の取得 - (int)stringWidth:(NSString*)text { return [text sizeWithFont:[UIFont systemFontOfSize:_fontSize]].width; } //文字列高さの取得 - (int)stringHeight:(NSString*)text { return [text sizeWithFont:[UIFont systemFontOfSize:_fontSize]].height; } //==================== //描画 //==================== //ラインの描画 - (void)drawLine_x0:(int)x0 y0:(int)y0 x1:(int)x1 y1:(int)y1 { GLfloat _vertexs[256*3]; GLbyte _colors[256*4]; //頂点配列情報 _vertexs[0]= x0;_vertexs[1]=-y0;_vertexs[2]=0; _vertexs[3]= x1;_vertexs[4]=-y1;_vertexs[5]=0; //カラー配列情報 for (int i=0;i<2;i++) { _colors[i*4 ]=_color.r; _colors[i*4+1]=_color.g; _colors[i*4+2]=_color.b; _colors[i*4+3]=_color.a; } //ラインの描画 glBindTexture(GL_TEXTURE_2D,0); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3,GL_FLOAT,0,_vertexs); glColorPointer(4,GL_UNSIGNED_BYTE,0,_colors); glPushMatrix(); glTranslatef(_originX,-_originY,0); glDrawArrays(GL_LINE_STRIP,0,2); glPopMatrix(); } //矩形の描画 - (void)drawRect_x:(int)x y:(int)y w:(int)w h:(int)h { GLfloat _vertexs[256*3]; GLbyte _colors[256*4]; //頂点配列情報 _vertexs[0]= x; _vertexs[1] =-y; _vertexs[2] =0; _vertexs[3]= x; _vertexs[4] =-y-h;_vertexs[5] =0; _vertexs[6]= x+w;_vertexs[7] =-y-h;_vertexs[8] =0; _vertexs[9]= x+w;_vertexs[10]=-y; _vertexs[11]=0; //カラー配列情報 for (int i=0;i<4;i++) { _colors[i*4 ]=_color.r; _colors[i*4+1]=_color.g; _colors[i*4+2]=_color.b; _colors[i*4+3]=_color.a; } //ラインの描画 glBindTexture(GL_TEXTURE_2D,0); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3,GL_FLOAT,0,_vertexs); glColorPointer(4,GL_UNSIGNED_BYTE,0,_colors); glPushMatrix(); glTranslatef(_originX,-_originY,0); glDrawArrays(GL_LINE_LOOP,0,4); glPopMatrix(); } //矩形の塗り潰し - (void)fillRect_x:(int)x y:(int)y w:(int)w h:(int)h { GLfloat _vertexs[256*3]; GLbyte _colors[256*4]; //頂点配列情報 _vertexs[0]= x; _vertexs[1] =-y; _vertexs[2] =0; _vertexs[3]= x; _vertexs[4] =-y-h;_vertexs[5] =0; _vertexs[6]= x+w;_vertexs[7] =-y; _vertexs[8] =0; _vertexs[9]= x+w;_vertexs[10]=-y-h;_vertexs[11]=0; //カラー配列情報 for (int i=0;i<4;i++) { _colors[i*4 ]=_color.r; _colors[i*4+1]=_color.g; _colors[i*4+2]=_color.b; _colors[i*4+3]=_color.a; } //三角形の描画 glBindTexture(GL_TEXTURE_2D,0); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3,GL_FLOAT,0,_vertexs); glColorPointer(4,GL_UNSIGNED_BYTE,0,_colors); glPushMatrix(); glTranslatef(_originX,-_originY,0); glDrawArrays(GL_TRIANGLE_STRIP,0,4); glPopMatrix(); } //円の描画 - (void)drawCircle_x:(int)x y:(int)y r:(int)r { GLfloat _vertexs[256*3]; GLbyte _colors[256*4]; int length=100; //頂点配列情報 for (int i=0;i<length;i++) { float angle=2*M_PI*i/length; _vertexs[i*3+0]= x+cos(angle)*r; _vertexs[i*3+1]=-y+sin(angle)*r; _vertexs[i*3+2]=0; } //カラー配列情報 for (int i=0;i<length;i++) { _colors[i*4 ]=_color.r; _colors[i*4+1]=_color.g; _colors[i*4+2]=_color.b; _colors[i*4+3]=_color.a; } //ラインの描画 glBindTexture(GL_TEXTURE_2D,0); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3,GL_FLOAT,0,_vertexs); glColorPointer(4,GL_UNSIGNED_BYTE,0,_colors); glPushMatrix(); glTranslatef(_originX,-_originY,0); glDrawArrays(GL_LINE_LOOP,0,length); glDrawArrays(GL_POINTS,0,length); glPopMatrix(); } //円の塗り潰し - (void)fillCircle_x:(int)x y:(int)y r:(int)r { GLfloat _vertexs[256*3]; GLbyte _colors[256*4]; int length=100+2; //頂点配列情報 _vertexs[0]= x; _vertexs[1]=-y; _vertexs[2]=0; for (int i=1;i<length;i++) { float angle=2*M_PI*i/(length-2); _vertexs[i*3+0]= x+cos(angle)*r; _vertexs[i*3+1]=-y+sin(angle)*r; _vertexs[i*3+2]=0; } //カラー配列情報 for (int i=0;i<length;i++) { _colors[i*4 ]=_color.r; _colors[i*4+1]=_color.g; _colors[i*4+2]=_color.b; _colors[i*4+3]=_color.a; } //ラインの描画 glBindTexture(GL_TEXTURE_2D,0); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3,GL_FLOAT,0,_vertexs); glColorPointer(4,GL_UNSIGNED_BYTE,0,_colors); glPushMatrix(); glTranslatef(_originX,-_originY,0); glDrawArrays(GL_TRIANGLE_FAN,0,length); glPopMatrix(); } //イメージの描画 - (void)drawImage:(Image*)image x:(int)x y:(int)y { if (image==nil) return; int dx=_originX+x; int dy=_originY+y; int dw=image.width; int dh=image.height; if (_flipMode==GRAPHICS_FLIP_HORIZONTAL) { dx+=image.width; dw=-image.width; } else if (_flipMode==GRAPHICS_FLIP_VERTICAL) { dy+=image.height; dh=-image.height; } glBindTexture(GL_TEXTURE_2D,image.name); glVertexPointer(2,GL_FLOAT,0,panelVertices); glDisableClientState(GL_COLOR_ARRAY); glPushMatrix(); glTranslatef(dx,-dy,0); glScalef(dw,dh,1); glDrawArrays(GL_TRIANGLE_STRIP,0,4); glPopMatrix(); } //イメージの描画 - (void)drawScaledImage:(Image*)image x:(int)x y:(int)y w:(int)w h:(int)h sx:(int)sx sy:(int)sy sw:(int)sw sh:(int)sh { if (image==nil) return; if (_flipMode==GRAPHICS_FLIP_HORIZONTAL) { sx=image.width-sw-sx; } else if (_flipMode==GRAPHICS_FLIP_VERTICAL) { sy=image.height-sh-sy; } int dw=image.width*w/sw; int dh=image.height*h/sh; int dx=_originX+x-sx*w/sw; int dy=_originY+y-sy*h/sh; if (_flipMode==GRAPHICS_FLIP_HORIZONTAL) { dx+=dw; dw=-dw; } else if (_flipMode==GRAPHICS_FLIP_VERTICAL) { dy+=dh; dh=-dh; } [self clipRect_x:_originX+x y:_originY+y w:w h:h]; glBindTexture(GL_TEXTURE_2D,image.name); glVertexPointer(2,GL_FLOAT,0,panelVertices); glDisableClientState(GL_COLOR_ARRAY); glPushMatrix(); glTranslatef(dx,-dy,0); glScalef(dw,dh,1); glDrawArrays(GL_TRIANGLE_STRIP,0,4); glPopMatrix(); [self clearClip]; } //テキストイメージの生成 - (Image*)makeTextImage:(NSString*)text { NSString* key=[NSString stringWithFormat:@"%d,%d,%d,%d,%d,%@", _fontSize,_color.r,_color.g,_color.b,_color.a,text]; //イメージの取得 Image* image=[_textMap objectForKey:key]; if (image!=nil) { [_textList removeObject:image]; [_textList insertObject:image atIndex:0]; return image; } //イメージの生成 image=[Image makeTextImage:text font:[UIFont systemFontOfSize:_fontSize*2] color:[UIColor colorWithRed:_color.r/255.0f green:_color.g/255.0f blue:_color.b/255.0f alpha:_color.a/255.0f]]; image.width =image.width/2; image.height=image.height/2; [_textMap setObject:image forKey:key]; [_textList insertObject:key atIndex:0]; //イメージの削除 if (_textList.count>TEXT_BUFF) { key=[_textList objectAtIndex:_textList.count-1]; [_textMap removeObjectForKey:key]; [_textList removeObjectAtIndex:_textList.count-1]; } return image; } //文字列の描画 - (void)drawString:(NSString*)text x:(int)x y:(int)y { [self drawImage:[self makeTextImage:text] x:x y:y]; } @end
Image.h#import <OpenGLES/EAGL.h> #import <OpenGLES/ES1/gl.h> #import <OpenGLES/ES1/glext.h> #import <QuartzCore/QuartzCore.h> //Imageの宣言 @interface Image : NSObject { unsigned char* _data; //データ GLuint _name; //名前 int _width; //幅 int _height;//高さ } //プロパティ @property unsigned char* data; @property GLuint name; @property int width; @property int height; //イメージの生成 + (Image*)makeImage:(UIImage*)image; + (Image*)makeTextImage:(NSString*)text font:(UIFont*)font color:(UIColor*)color; @end
Image.m #import "Image.h" //Imageの実装 @implementation Image //シンセサイズ @synthesize data =_data; @synthesize name =_name; @synthesize width =_width; @synthesize height=_height; //==================== //初期化 //==================== //初期化 - (id)init { if ((self=[super init])) { _data =NULL; _name =0; _width =0; _height=0; } return self; } //メモリ解放 - (void)dealloc { GLuint num=self.name; if (num!=0) glDeleteTextures(1,&num); if (_data!=NULL) free(_data); [super dealloc]; } //==================== //イメージの生成 //==================== //テクスチャの生成 + (BOOL)makeTeture:(UIImage*)image toOutput:(unsigned char**)textureData andImageSize:(int*)pImageSize andImageWidth:(int*)pImageWidth andImageHeight:(int*)pImageHeight { CGImageRef imageRef; NSUInteger i; int textureSize; int imageWidth; int imageHeight; NSUInteger maxImageSize; CGContextRef context; CGColorSpaceRef colorSpace; BOOL hasAlpha; size_t bitsPerComponent; CGImageAlphaInfo info; if (!image) return NO; //イメージ情報の取得 imageRef=[image CGImage]; imageWidth=CGImageGetWidth(imageRef); imageHeight=CGImageGetHeight(imageRef); if (imageWidth>imageHeight) { maxImageSize=imageWidth; } else { maxImageSize=imageHeight; } for (i=2;i<=1024;i*=2) { if (i>=maxImageSize) { textureSize=i; break; } } if (textureSize>512) return NO; *pImageSize =textureSize; *pImageWidth =imageWidth; *pImageHeight=imageHeight; info=CGImageGetAlphaInfo(imageRef); //アルファ成分チェック hasAlpha=((info==kCGImageAlphaPremultipliedLast) || (info==kCGImageAlphaPremultipliedFirst) || (info==kCGImageAlphaLast) || (info==kCGImageAlphaFirst)?YES:NO); colorSpace=CGColorSpaceCreateDeviceRGB(); *textureData=(unsigned char*)malloc(textureSize*textureSize*4); if (!*textureData) { CGColorSpaceRelease(colorSpace); return NO; } if (hasAlpha) { bitsPerComponent=kCGImageAlphaPremultipliedLast; } else { bitsPerComponent=kCGImageAlphaNoneSkipLast; } context=CGBitmapContextCreate(*textureData,textureSize,textureSize, 8,4*textureSize,colorSpace,bitsPerComponent|kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); //画像ファイルの画像サイズ!=テクスチャのサイズの時 if ((textureSize!=imageWidth) || (textureSize!=imageHeight)) { CGContextScaleCTM(context, (CGFloat)textureSize/imageWidth, (CGFloat)textureSize/imageHeight); } CGRect rect=CGRectMake(0,0,CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)); CGContextClearRect(context,rect); CGContextDrawImage(context,rect,imageRef); CGContextRelease(context); return YES; } //イメージの生成 + (Image*)makeImage:(UIImage*)image { unsigned char* textureData; GLuint textureName; GLsizei textureSize; GLsizei textureWidth; GLsizei textureHeight; //テクスチャの生成 if ([Image makeTeture:image toOutput:(unsigned char**)&textureData andImageSize:&textureSize andImageWidth:&textureWidth andImageHeight:&textureHeight]) { //テクスチャの設定 glGenTextures(1,&textureName); glBindTexture(GL_TEXTURE_2D,textureName); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,textureSize,textureSize, 0,GL_RGBA,GL_UNSIGNED_BYTE,textureData); 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); //テクスチャオブジェクトの生成 Image* texture=[[[Image alloc] init] autorelease]; texture.data=textureData; texture.name=textureName; texture.width=textureWidth; texture.height=textureHeight; return texture; } else { return nil; } } //テキストUIイメージの生成 + (UIImage*)makeTextUIImage:(NSString*)text font:(UIFont*)font color:(UIColor*)color bgcolor:(UIColor*)bgcolor { //ラベルの生成 UILabel* label=[[[UILabel alloc] init] autorelease]; CGSize size=[text sizeWithFont:font constrainedToSize:CGSizeMake(512,512) lineBreakMode:UILineBreakModeWordWrap]; [label setFrame:CGRectMake(0,0,size.width,size.height)]; [label setText:text]; [label setFont:font]; [label setTextColor:color]; [label setTextAlignment:UITextAlignmentLeft]; [label setBackgroundColor:bgcolor]; [label setNumberOfLines:0]; //コンテキストの生成 if (size.width<32) size.width=32; if (size.height<32) size.height=32; unsigned char *bmpData; CGContextRef context; CGColorSpaceRef colorSpace; bmpData=malloc(size.width*size.height*sizeof(unsigned char)*4); colorSpace=CGColorSpaceCreateDeviceRGB(); context=CGBitmapContextCreate(bmpData, size.width,size.height,8,size.width*4, colorSpace, kCGImageAlphaPremultipliedFirst); CGContextSetShouldAntialias(context,0); CGContextClearRect(context,CGRectMake(0,0,size.width,size.height)); //コンテキストの設定 UIGraphicsPushContext(context); CGContextTranslateCTM(context,0,size.height); CGContextScaleCTM(context,1,-1); //ラベルの描画 [label.layer renderInContext:context]; CGImageRef imageRef=CGBitmapContextCreateImage(context); UIImage* image=[[[UIImage alloc] initWithCGImage:imageRef] autorelease]; //コンテキストの設定解放 UIGraphicsPopContext(); //コンテキストの解放 CGColorSpaceRelease(colorSpace); CGContextRelease(context); free(bmpData); return image; } //テキストテクスチャの生成 + (Image*)makeTextImage:(NSString*)text font:(UIFont*)font color:(UIColor*)color { UIImage* image=[Image makeTextUIImage:text font:font color:color bgcolor:[UIColor clearColor]]; return [Image makeImage:image]; } @end