OpenGL
Silicon Graphics社が中心となって開発された、グラフィックス処理のためのプログラミングインターフェース(出典:IT用語辞典)。
MacOSXでOpenGLを使う
- xcodeを機動する。
- メニューの[ファイル][新規プロジェクト]から、[Application][Cocoa Application]を選択して[次へ]。
- プロジェクト名を「cocoaGL」にして[完了](ディレクトリはどこか適当な場所へ)。
- [グループとファイル]の[Frameworks][Linked Frameworks]を右クリックして、コンテキストメニューから[追加][既存のフレームワーク]を選択して、以下のフレームワークを追加する。
- OpenGL.framework
- GLUT.framework(必要であれば)
- 続いて、Interface Builderでの作業。
- [グループとファイル]の[Resources][MainMenu?.nib]をダブルクリックして、Interface Builderを機動。
- [MainMenu?.nib(English)]ウインドウの[Classes]タブを選択。
- [NSObject][NSResponder][NSView][NSOpenGLView]を右クリックして、コンテキストメニューから[SubClass? NSOpenGLView]を選択してNSOpenGLViewのサブクラスを作る。
- [MyOpenGLView]を右クリックして、コンテキストメニューから[Crate File for MyOpenGLView]を選択すると、xcodeのプロジェクトにMyOpenGLView.hとMyOpenGLView.mが作成される。
- [MainMenu?.nib(English)]ウインドウの[Instances]タブを選択して、[Window]アイコンをダブルクリックしてアプリケーションウインドウを表示する。
- メニューの[Tools][Palettes][Show Paletts]を選択して、パレットを表示する。
- パレットの[Cocoa-Containers]から[CustomView?]を選択して、先ほど開いたアプリケーションウインドウにドラッグ&ドロップする。
- メニューの[Tools][Show Inspector]を選択して、[Custom Class]から、先ほど作成したMyOpenGLViewを選択して、CustomView?にMyOpenGLViewを割り当てる。
- xcodeの作業に戻る。
- MyOpenGLView.hに次のコードを記述。
#import <Cocoa/Cocoa.h> #import <OpenGL/OpenGL.h> #import <OpenGL/gl.h> #import <OpenGL/glu.h> @interface MyOpenGLView : NSOpenGLView { NSTimer *timer; } - (void) awakeFromNib; - (id) initWithFrame:(NSRect)frameRect; - (void) reshape; - (void) loop; - (void) drawRect:(NSRect)rect; - (void) dealloc; @end
- MyOpenGLView.mに次のコードを記述。
#import "MyOpenGLView.h" @implementation MyOpenGLView - (void)awakeFromNib { timer = [ [ NSTimer scheduledTimerWithTimeInterval: 0.03 target:self selector:@selector(loop) userInfo:nil repeats:YES ] retain ]; } -(id)initWithFrame:(NSRect)frameRect { //OPEN GL draw context NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAAccelerated, NSOpenGLPFAColorSize, 32.0, NSOpenGLPFADepthSize, 32.0, 0 }; NSOpenGLPixelFormat* pixFmt = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease]; self = [super initWithFrame:frameRect pixelFormat:pixFmt]; [ [ self openGLContext ] makeCurrentContext ]; return self; } - (void)loop { glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt( 0, 0, 1, 0, 0, 0, 0, 1, 0 ); // draw opengl [ [ self openGLContext ] flushBuffer ]; } - (void)drawRect:(NSRect)aRect { [self loop]; } - (void)reshape { NSRect bounds = [self bounds]; glViewport( (int)bounds.origin.x, (int)bounds.origin.y, (int)bounds.size.width, (int)bounds.size.height ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 45, (float)bounds.size.width / (float)bounds.size.height, 1.0, 500.0 ); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } - (void) dealloc { [super dealloc]; } @end
- んで、[アクティブなビルド構成]で[Release]を選択して、ビルドして完了。
参考
MacOSX環境のOpenGLで日本語文字列の描画
詳しくは、GLTexString?.hとGLTexString?.mを参照。
こんな↓感じで、日本語文字列の描画が出来る。
GLTexString *texStr; - (void)initGL { glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClearDepth( 1.0f ); glDisable(GL_CULL_FACE); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); NSString *string = [NSString stringWithCString:"こんにちは、世界!"]; texStr = [[GLTexString alloc] initWithString:string]; } - (void)loop { glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt( 0, 0, 8, 0, 0, 0, 0, 1, 0 ); glPushMatrix(); glTranslatef( -4.5, -0.5, 0 ); glColor3f( 1, 1, 1 ); [texStr draw]; glPopMatrix(); [ [ self openGLContext ] flushBuffer ]; }
GLTexString?.h
#import <Cocoa/Cocoa.h> #import <OpenGL/gl.h> #import <OpenGL/OpenGL.h> #define TEX_WIDTH 128 #define TEX_HEIGHT 128 #define FONT_NAME @"HiraKakuPro-W6" /* * HiraKakuPro-W3 * HiraKakuPro-W6 * HiraKakuStd-W8 * HiraMaruPro-W4 * HiraMinPro-W3 * HiraMinPro-W6 */ @interface GLTexString : NSObject { NSString *string; NSAttributedString *attrString; GLuint *texId; } - (id) initWithString:(NSString*)aString; - (void) draw; - (void) dealloc; @end
GLTexString?.m
#import "GLTexString.h" @implementation GLTexString - (id) initWithString:(NSString*)aString { [super init]; int i, strSize; float fontSize; NSFont *font; NSDictionary *attrsDictionary; NSAttributedString *singleChar; NSImage **images; NSBitmapImageRep **imageReps; NSImage* img; NSPoint point; NSSize size, screenResolution; // copy to string from aString string = [NSString stringWithString:aString]; // alloc texture id and image buffer strSize = [string length]; texId = (GLuint*)malloc( sizeof(GLuint)*strSize ); images = (NSImage**)malloc( sizeof(NSImage*)*strSize ); imageReps = (NSBitmapImageRep**)malloc( sizeof(NSBitmapImageRep*)*strSize ); for( i = 0; i < strSize; i++ ){ images[i] = [[NSImage alloc] initWithSize:NSMakeSize( TEX_WIDTH, TEX_HEIGHT )]; } // font settings screenResolution = [[[[NSScreen mainScreen] deviceDescription] objectForKey:NSDeviceResolution] sizeValue]; fontSize = TEX_WIDTH * 72.0/screenResolution.width; font = [NSFont fontWithName:FONT_NAME size:fontSize]; attrsDictionary = [NSDictionary dictionaryWithObjectsAndKeys: font, NSFontAttributeName, [NSColor whiteColor], NSForegroundColorAttributeName, [NSColor clearColor], NSBackgroundColorAttributeName, nil ]; // alloc attributed string attrString = [[NSAttributedString alloc] initWithString:string attributes:attrsDictionary]; // create texture id glEnable( GL_TEXTURE_2D ); glGenTextures( strSize, texId ); // build texture image for( i = 0; i < strSize; i++ ){ img = images[i]; singleChar = [attrString attributedSubstringFromRange:NSMakeRange(i,1)]; // setting background color [img setBackgroundColor:[NSColor clearColor]]; // calc center position size = [singleChar size]; point = NSMakePoint( (TEX_WIDTH-size.width)/2, (TEX_HEIGHT-size.height)/2 ); // draw character to image [img lockFocus]; [singleChar drawAtPoint:point]; [img unlockFocus]; // alloc bitmap image from NSImage imageReps[i] = [[NSBitmapImageRep alloc] initWithData:[img TIFFRepresentation]]; // texture settings glBindTexture( GL_TEXTURE_2D, texId[i] ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, TEX_WIDTH, TEX_HEIGHT, 0, [imageReps[i] hasAlpha] ? GL_RGBA :GL_RGB, GL_UNSIGNED_BYTE, [imageReps[i] bitmapData] ); glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glBindTexture( GL_TEXTURE_2D, 0 ); } glDisable( GL_TEXTURE_2D ); // release for( i = 0; i < strSize; i++ ){ [imageReps[i] release]; [images[i] release]; } free( imageReps ); free( images ); return self; } - (void) draw { int i, strSize; strSize = [string length]; glEnable( GL_TEXTURE_2D ); for( i = 0; i < strSize; i++ ){ glBindTexture( GL_TEXTURE_2D, texId[i] ); glBegin(GL_POLYGON); glTexCoord2f( 0, 1 ); glVertex3f( i*1, 0, 0 ); glTexCoord2f( 1, 1 ); glVertex3f( i*1+1, 0, 0 ); glTexCoord2f( 1, 0 ); glVertex3f( i*1+1, 1, 0 ); glTexCoord2f( 0, 0 ); glVertex3f( i*1, 1, 0 ); glEnd(); } glDisable( GL_TEXTURE_2D ); } - (void) dealloc { glDeleteTextures( [string length], texId ); free( texId ); [attrString release]; [super dealloc]; } @end
GL_TEXTURE_RECTANGLE_EXTで、テクスチャに使う画像の幅・高さを任意のサイズに
// import library #import <OpenGL/gl.h> #import <OpenGL/glext.h> #import <OpenGL/OpenGL.h> // define (!)texture width and height are not 2^n. #define TEX_WIDTH 163 #define TEX_HEIGHT 97 // build texture glEnable( GL_TEXTURE_2D ); glEnable( GL_TEXTURE_RECTANGLE_EXT ); glBindTexture( GL_TEXTURE_RECTANGLE_EXT, textureId ); glTexImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapData ); glDisable( GL_TEXTURE_RECTANGLE_EXT ); glDisable( GL_TEXTURE_2D ); // draw glEnable( GL_TEXTURE_2D ); glEnable( GL_TEXTURE_RECTANGLE_EXT ); glBindTexture( GL_TEXTURE_RECTANGLE_EXT, textureId ); lBegin(GL_POLYGON); glTexCoord2f( 0, TEX_HEIGHT ); glVertex3f( 0, 0, 0 ); glTexCoord2f( TEX_WIDTH, TEX_HEIGHT ); glVertex3f( 1, 0, 0 ); glTexCoord2f( TEX_WIDTH, 0 ); glVertex3f( 1, 1, 0 ); glTexCoord2f( 0, 0 ); glVertex3f( 0, 1, 0 ); glEnd(); glDisable( GL_TEXTURE_RECTANGLE_EXT ); glDisable( GL_TEXTURE_2D );
参考
テクスチャ関連
テクスチャの置き換え
void glTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels );
アルファ値を利用したポリゴンの切り抜き
TGA画像の読み込み
#define TEX_HEIGHT 256 #define TEX_WIDTH 512 GLubyte image[TEX_HEIGHT][TEX_WIDTH][4]; void initTexture(void) { FILE *fp; int x, z; /* texture file open */ if((fp=fopen("test.tga", "rb"))==NULL){ fprintf(stderr, "texture file cannot open\n"); return; } fseek(fp, 18, SEEK_SET); for(x=0;x<TEX_HEIGHT;x++){ for(z=0;z<TEX_WIDTH;z++){ image[x][z][2]=fgetc(fp);/* B */ image[x][z][1]=fgetc(fp);/* G */ image[x][z][0]=fgetc(fp);/* R */ image[x][z][3]=fgetc(fp);/* alpha */ } } fclose(fp); }
RAW画像の読み込み
#define TEXWIDTH 256 #define TEXHEIGHT 256 GLubyte texture[TEXHEIGHT][TEXWIDTH][3]; void initTexture(void) { if ((fp = fopen("tire.raw", "rb")) != NULL) { fread(texture, sizeof texture, 1, fp); fclose(fp); } }
フォント関連
glutBitmapCharacter
※テクスチャが有効だと表示されないようだ。
void drawString( void* font, char* str ){ int i = 0; while( str[i] != '\0' ){ glutBitmapCharacter( font, (int)('a') ); i++; } }
glDisable(GL_TEXTURE_2D); glColor3f( 1, 1, 1 ); glRasterPos3f( 0, 0, 0 ); drawString( GLUT_BITMAP_TIMES_ROMAN_10, "hello" );
- GLUT_BITMAP_8_BY_13
- GLUT_BITMAP_9_BY_15
- GLUT_BITMAP_TIMES_ROMAN_10
- GLUT_BITMAP_TIMES_ROMAN_24
- GLUT_BITMAP_HELVETICA_10
- GLUT_BITMAP_HELVETICA_12
- GLUT_BITMAP_HELVETICA_18
wglUseFontBitmap?, wglUseFontOutline?
Bitmap Font Builder
GLUT関連
フルスクリーンにする
glutFullScreen(); /* フルスクリーン表示 */
メモ
チュートリアル(入門にお奨め)
- GLUTによる「手抜き」OpenGL入門
- GLUT on MacOSX
- OpenGL入門
- OpenGL 入門講座
- NuWiki
- OpenGLプログラム
- Xcode on MacOS X 10.3でGLUTのコードをコンパイルする