▼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



−戻る−