トップページ > Wiki > OpenGL

OpenGL のバックアップ(No.11)


Silicon Graphics社が中心となって開発された、グラフィックス処理のためのプログラミングインターフェース(出典:IT用語辞典)。

MacOSXでOpenGLを使う

  1. xcodeを機動する。
  2. メニューの[ファイル][新規プロジェクト]から、[Application][Cocoa Application]を選択して[次へ]。
  3. プロジェクト名を「cocoaGL」にして[完了](ディレクトリはどこか適当な場所へ)。
  4. [グループとファイル]の[Frameworks][Linked Frameworks]を右クリックして、コンテキストメニューから[追加][既存のフレームワーク]を選択して、以下のフレームワークを追加する。
    • OpenGL.framework
    • GLUT.framework(必要であれば)
  5. 続いて、Interface Builderでの作業。
  6. [グループとファイル]の[Resources][MainMenu?.nib]をダブルクリックして、Interface Builderを機動。
  7. [MainMenu?.nib(English)]ウインドウの[Classes]タブを選択。
  8. [NSObject][NSResponder][NSView][NSOpenGLView]を右クリックして、コンテキストメニューから[SubClass? NSOpenGLView]を選択してNSOpenGLViewのサブクラスを作る。
  9. [MyOpenGLView]を右クリックして、コンテキストメニューから[Crate File for MyOpenGLView]を選択すると、xcodeのプロジェクトにMyOpenGLView.hとMyOpenGLView.mが作成される。
  10. [MainMenu?.nib(English)]ウインドウの[Instances]タブを選択して、[Window]アイコンをダブルクリックしてアプリケーションウインドウを表示する。
  11. メニューの[Tools][Palettes][Show Paletts]を選択して、パレットを表示する。
  12. パレットの[Cocoa-Containers]から[CustomView?]を選択して、先ほど開いたアプリケーションウインドウにドラッグ&ドロップする。
  13. メニューの[Tools][Show Inspector]を選択して、[Custom Class]から、先ほど作成したMyOpenGLViewを選択して、CustomView?にMyOpenGLViewを割り当てる。
  14. xcodeの作業に戻る。
  15. 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
  16. 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
  17. んで、[アクティブなビルド構成]で[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/OpenGL.h>
#import <OpenGL/gl.h>
#import <OpenGL/glu.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;
	GLuint *texId;
	NSImage **images;
	NSBitmapImageRep **imageReps;
}

- (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 *attrString;
	NSAttributedString *singleChar;
	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 )
			] autorelease
		];
	}
	
	// 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
	];
	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];
		
		// create 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 );
	}
	
	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();
	}
}

- (void)dealloc {
	int i, strSize;
	
	strSize = [string length];
	for( i = 0; i < strSize; i++ ){
		[images[i] release];
		[imageReps[i] release];
	}
	
	[string release];
	free( texId );
	free( images );
	free( imageReps );
	
	[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();               /* フルスクリーン表示 */

メモ

チュートリアル(入門にお奨め)

より詳しい情報はこちらから

OpenGLを利用したサンプル

リファレンス

iPhoneDev.null-null.net

RSSフィード

このウィキの更新情報を、XML(RSS)フォーマットで提供しています。
ご利用のRSSリーダーやアプリケーションにRSSフィードを登録してください。

ページの先頭へ戻る


Copyright(c) Daisuke Nogami. All Right Reserved.