프로그래밍/Cocos2D2012. 2. 9. 02:13

plist 프레임 키값을 알아서 가져오는 방법입니다.
 TexturePacker를 사용하여 생성된 plist 프레임 키값을 가져올 때 사용하였습니다. 
        

 NSMutableArray *animFrames = [NSMutableArray array];
        
 NSString *framePath = [[NSBundle mainBundle] pathForResource:@"1st_bad_animation" ofType:@"plist"];
 NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:framePath];
 NSDictionary *framesDict = [dictionary objectForKey:@"frames"];

 // Dictionary는 순서가 뒤섞여 있어서 정렬하기 위해 Array에 새로 담습니다.
 NSMutableArray *sortFrames = [[NSMutableArray alloc] initWithCapacity:[framesDict count]];
        
 for (NSString *frameDictKey in framesDict) 
 {
       [sortFrames addObject:frameDictKey];
 }
        
 [sortFrames sortUsingSelector:@selector(compare:)]; // 정렬 
  // compare 는 기본으로 제공되는 함수이고 커스텀이 가능합니다.
        
  for(NSString *frameDictKey in sortFrames) 
  {
       CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:frameDictKey];
       [animFrames addObject:frame];
  }
Posted by windship
프로그래밍/Cocos2D2012. 2. 8. 01:15
1. CCActionGrid.m 파일의
    
"Incompatible pointer types assigning "CCActionInterval*" from "CCAction*" 에러

other = [action retain]; 부분을
other = (CCActionInterval*) [action retain]; 로 변경  
  



2. ZAttributedString.m 파일의 에러

ZAttributeRun *newRun = [[ZAttributeRun allocinitWithIndex:NSMaxRange(range) attributes:[[_attributes lastObject]attributes]]; 를
ZAttributeRun *newRun = [[ZAttributeRun allocinitWithIndex:NSMaxRange(range) attributes:(NSDictionary*)[(ZAttributeRun *)[_attributes lastObjectattributes]]; 로 변경

ZAttributeRun *newRun = [[ZAttributeRun alloc] initWithIndex:NSMaxRange(range) attributes:[[_attributes objectAtIndex:firstAfter-1] attributes]]; 를

ZAttributeRun *newRun = [[ZAttributeRun allocinitWithIndex:NSMaxRange(range) attributes:(NSDictionary*)[(ZAttributeRun *)[_attributes objectAtIndex:firstAfter-1attributes]]; 로 변경   


3.  CCDirevctorIOS.m 파일의 에러

UIDeviceOrientationPortraitUpsideDown 부분을
UIInterfaceOrientationPortraitUpsideDown 로 변경  

Posted by windship
프로그래밍/Cocos2D2012. 2. 6. 10:52
//
//  HelloWorldLayer.m
//  FontStrokeDemo
//
//  Created by user on 12-2-1.
//  Copyright __MyCompanyName__ 2012亮�. All rights reserved.
//


// Import the interfaces
#import "HelloWorldLayer.h"

// HelloWorldLayer implementation
@implementation HelloWorldLayer

+(CCScene *) scene
{
	// 'scene' is an autorelease object.
	CCScene *scene = [CCScene node];
	
	// 'layer' is an autorelease object.
	HelloWorldLayer *layer = [HelloWorldLayer node];
	
	// add layer as a child to scene
	[scene addChild: layer];
	
	// return the scene
	return scene;
}

-(CCRenderTexture*) createStroke:(CCLabelTTF*) label   
                            size:(float)size   
                           color:(ccColor3B)cor
{
	CCRenderTexture* rt = [CCRenderTexture renderTextureWithWidth:label.texture.contentSize.width+size*2  height:label.texture.contentSize.height+size*2];
	CGPoint originalPos = [label position];
	ccColor3B originalColor = [label color];
	BOOL originalVisibility = [label visible];
	[label setColor:cor];
	[label setVisible:YES];
	ccBlendFunc originalBlend = [label blendFunc];
	[label setBlendFunc:(ccBlendFunc) { GL_SRC_ALPHA, GL_ONE }];
	CGPoint meio = ccp(label.texture.contentSize.width/2+size, label.texture.contentSize.height/2+size);
	[rt begin];
	for (int i=0; i<360; i+=30) // you should optimize that for your needs
	{
		[label setPosition:ccp(meio.x + sin(CC_DEGREES_TO_RADIANS(i))*size, meio.y + cos(CC_DEGREES_TO_RADIANS(i))*size)];
		[label visit];
	}
	[rt end];
	[label setPosition:originalPos];
	[label setColor:originalColor];
	[label setBlendFunc:originalBlend];
	[label setVisible:originalVisibility];
	[rt setPosition:originalPos];
	return rt;
}

// on "init" you need to initialize your instance
-(id) init
{
	// always call "super" init
	// Apple recommends to re-assign "self" with the "super" return value
	if( (self=[super init])) {
		
        //label1
		CCLabelTTF* label = [CCLabelTTF labelWithString:@"FontStrokeDemo"
                                             dimensions:CGSizeMake(305,179) 
                                              alignment:UITextAlignmentLeft
                                               fontName:@"Arial" 
                                               fontSize:38];
        [label setPosition:ccp(240, 160)];
        [label setColor:ccWHITE];
        CCRenderTexture* stroke = [self createStroke:label  
                                                size:3  
                                               color:ccBLUE];
        [self addChild:stroke];
        [self addChild:label];
        
        //label2
		CCLabelTTF* label2 = [CCLabelTTF labelWithString:@"Test String"
                                             dimensions:CGSizeMake(305,179) 
                                              alignment:UITextAlignmentLeft
                                               fontName:@"Arial" 
                                               fontSize:38];
        [label2 setPosition:ccp(240, 100)];
        [label2 setColor:ccWHITE];
        CCRenderTexture* stroke2 = [self createStroke:label2  
                                                size:3  
                                               color:ccRED];
        [self addChild:stroke2];
        [self addChild:label2];
	}
	return self;
}

// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
	// in case you have something to dealloc, do it in this method
	// in this particular example nothing needs to be released.
	// cocos2d will automatically release all the children (Label)
	
	// don't forget to call "super dealloc"
	[super dealloc];
}
@end
Posted by windship
프로그래밍/Cocos2D2012. 2. 5. 15:06
cocos2D에서 레티나, 3GS 2가지 해상도를 지원하기 위해서는

1. retina 사용여부 부분을 주석해제 해야합니다. (appDelegate 안에 주석처리 되어 있음)

// Enables High Res mode(Retina Display) on iPhone 4 and maintains low res on all other devices 
if (! [director enableRetinaDisplay:YES])
 CCLOG(@"Retina Display Not Supported");

2. 이미지는 2가지로 만들어서 넣으면 됩니다.

aaa.png(3GS), aaa-hd.png(레티나)

* @2x는 cocos2d에서는 필요 없습니다. -hd로 대체됩니다. 단 default.png는 default@2x.png로 만들어야 합니다. 
Posted by windship
프로그래밍/Cocos2D2012. 2. 5. 14:16
아이폰 용으로 레티나 디스플래이를 지원할 경우
파일명 뒤에 -hd 를 붙여 사용한다.

이때 아이패드용으로 개발 시 이 레티나용 소스를 사용해서 표현하고 싶다면
ccFileUtils.m  파일을 찾아가

+(NSString*) getDoubleResolutionImage:(NSString*)path

이 함수안에 

if( CC_CONTENT_SCALE_FACTOR() == 2)

위의 부분을 아래와 같이 변경해 주자

if( CC_CONTENT_SCALE_FACTOR() == 2 || (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad))
이는 레티나 디스플래이용으로 설정되었을 때 -hd 파일을 쓴다는 부분인데
뒤에 부가적으로 아이폰 일 경우에도 사용하겠다고 선언해주는 것이다.

UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
이 부분은 현재 인터페이스가 아이패드인지 확인 하는 부분


추가적으로 이렇게 불러오는 리소스와 더불어
포인트도 아이폰용 포인트를 그대로 사용하고 싶다면 아래와 같이 인라인 함수를 하나 만들어 사용하면 편하다.

/** Returns ipad point.
 @return CGPoint
 */
static inline CGPoint
CGPointMakeBothIPad(float iPhonePoint_X, float iPhonePoint_Y) {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
        return CGPointMake(iPhonePoint_X/320*768,iPhonePoint_Y/480*1024);
    else
        return CGPointMake(iPhonePoint_X,iPhonePoint_Y);
}
Posted by windship
프로그래밍/Cocos2D2012. 1. 29. 00:33
* 라이센스 관련

1. 나의 앱은 소스 코드를 공개하지 않으려고 한다. 그래도 Cocos2D를 사용할 수 있는가?
-> 물론이다. Cocos2D는 MIT 라이센스로 관리되고 있다. 궁금한 점이 있다면 라이센스 관련 항목을 읽어보라.

2. 만약 누가 나의 앱을 구입했을 경우 나는 그에게 소스 코드도 제공해야 하는가?
-> 당신의 게임을 구입했다 하더라도 그 게임의 소스 코드를 제공해야 할 의무는 없다.


* 개발 관련

1. Cocos2D에서 3D 오브젝트를 사용할 수 있는가?
-> 아무 문제 없이 2D 게임에도 3D 오브젝트를 넣어서 그래픽 퀄리티를 높일 수 있다. Cocos2D의 기본 투영 행렬 구조는 3D와 같으므로 아마 변경할 필요도 없을 것이다.

2. 버그를 발견하거나 제안할 사항이 있다. 어떻게 하면 되는가?
-> 이슈 추적기를 사용하라. http://code.google.com/p/cocos2d-iphone/issues/list
또한 포럼에 있는 버그/제안사항 쪽에 글을 써도 된다. 하지만 이슈 추적기를 사용하는 것을 권장한다.

3. 엔진의 개선에 참여하고 싶다면?
-> 당신이 코드에 기여하고 싶다면 다음 단계를 따라주기 바란다.
(만약 당신이 새로운 git 또는 GitHub를 가지고 있다면 Pro Git를 읽어야 한다. 특히 Contributing to a project: Small/Large Public Project 부분을 읽어주시길) (*역주 : GIT는 분산 소스코드 관리 프로그램임)

4. 아이폰용 SDK 3.x와 4.x를 위한 게임을 개발할 수 있는가?
-> 물론이다. Cocos2D는 SDK 2.x, 3.x, 4.x를 지원한다.

5. Cocos2D를 아이폰/아이패드/맥에서 사용할 수 있는가?
-> 그렇다. Cocos2D는 모든 애플 디바이스를 잘 지원한다.
- 아이폰/아이팟 터치 1세대
- 아이폰 3G/아이팟 터치 2세대 
- 아이폰 3Gs/아이팟 터치 3세대
- 아이폰 4/아이팟터치 4세대(고해상도 레티나 모드 선택 지원 가능)
- 아이패드
- Mac OSX

6. 텍스처 사이즈는 어떻게 해야 하는가?
-> 두 가지 고려해야 할 사항이 있다. 비압축 텍스처와 PVRTC 텍스처이다.

비압축 텍스처를 위해 텍스처는 3세대 디바이스에서는 2048 이하의 2제곱수를 가진 2차원 텍스처여야 하고, 그 이전 디바이스에서는 1024 이하여야 한다. 따라서 16x256은 OK. 512x512도 OK. 그러나 240x320은 2의 제곱수가 아니므로 안된다.
이 규칙에 맞지 않는 이미지도 사용은 가능하지만, 텍스처로 변환되어 저장될 때 2의 배수로 자동 저장된다는 점을 기억하라. 240x320의 이미지는 텍스처로 변환될 때 256x512로 바뀔 것이다. 
아이폰 3Gs와 같은 새로운 플랫폼에서는 최대 텍스처 사이즈가 2048x2048까지 가능하다. 아이폰 3G 이하라면 1024x1024까지만 가능하다.

PVRTC 압축 텍스처는 2의 제곱수 크기로 정사각형이어야 한다. 예를 들면 4x4, 32x32, 256x256, 1024x1024와 같은 크기여야 한다. 이 포맷으로 로드된 이미지는 GPU상에서 돌아가는 포맷과 밀접하게 매칭되는 특별한 포맷이다. 따라서 2의 제곱수 크기로 정사각형이어야만 한다. 만약 PVRTC 압축 텍스처를 사용했는데 흰 그림만이 나올 경우 이러한 크기와 정사각형이 아닐 확률이 높다.

7. 스프라이트 시트는 무엇이며 왜 사용해야 하는가?
-> 스프라이트 시트는 큰 스프라이트 상에 정렬된 스프라이트들의 모음이다. 이것을 사용하면 두 가지 장점이 있는데, 첫째로 시트 상의 모든 스프라이트가 한 번의 드로우 콜로 그려질 수 있다는 것이다. 이것은 매우 효율적이다. 두번째로는 메모리의 낭비 없이 2의 제곱수 크기가 아닌 텍스처를 사용할 수 있다는 것이다. 스프라이트 시트 상에 스프라이트를 묶는 가장 좋은 실습은 스프라이트 섹션(http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:sprites)을 참고하면 더욱 자세한 정보를 얻을 수 있다.

8. 텍스처 상에 렌더링하기(렌더 투 텍스처) 기술을 사용할 수 있는가?
-> 물론이다. 프레임버퍼 오브젝트를 사용할 수 있다. 이것은 Cocos2D에서 이펙트 구현을 위해 사용되고 있다. Grabber.m 또는 RenderTexture.m 클래스를 참고하라.

9. 라이트나 연기 같은 동적 알파 효과를 사용할 수 있는가?
-> 물론이다. 프레임버퍼 오브젝트와 채널 마스킹 조합으로 오직 알파 채널 상에서 적절한 블렌딩 모드를 사용해 그릴 수 있다. 연기 효과를 위한 iSteam(다른 이미지보다 상위에 그려지는 편집 가능한 연기 레이어), 번개, 스크래치 복원 이펙트와 변경 가능한 플레이 필드. 이러한 렌더 텍스처 클래스를 보고 다음의 스레드(http://groups.google.com/group/cocos2d-iphone-discuss/brouwse_frm/thread/dab9b84cd5262d80/ed15695bb0cb3af5?lnk=gst&q=scratch+off#ed15695bb0cb3af5)를 참고하라. 

10. 내 프로젝트에 사운드를 추가하는 방법은?
-> Cocos2D는 여러 가지의 오디오 프레임워크를 가지고 있다. 당신에게 필요한 것을 잘 골라서 사용하기 바란다. 

SimpleAudioEngine 인터페이스는 Cocos Denshion 오디오 라이브러리의 일부로서, 대부분의 게임 어플리케이션에 사용하기에는 충분할 것이다

3D의 공간감이 느껴지는 사운드가 필요하다면 PASoundMgr 인터페이스를 사용하면 된다. PASoundMgr은 Cocos2D의 expermental/sound-engine 디렉토리에 포함되어 있다.

더 많은 고급 오디오 테크닉이 필요하거나 저수준의 OS 오디오 API에 접근하고 싶다면 CocosDenshion 오디오 라이브러리의 CDAudioManager 인터페이스가 좋은 선택이 될 것이다.

매우 간단한 오디오 기능이 필요하다면 OS 오디오 API를 직접 사용하는 것으로 충분할 수도 있다. 예를 들어 만약 사운드 하나만 플레이하고 싶다면 AVAudioPlayer API로 간단하게 SimpleAudioEngine과 CDAudioManager 인터페이스 내에서 배경음악으로 활용할 수 있을 것이다.


* 문제 해결

1. 이미지를 띄웠는데, 시뮬레이터에서 색상이 엉망으로 보인다.
-> 혹시 PowerPC 기반 맥을 사용하고 있지 않는가? 맞다면 이미 보고된 문제이다. PowerPC는 아이폰 개발에 적합한 플랫폼이 아니다.

2.  테스트는 어떻게 해볼 수 있는가?
-> 1. Cocos2D XCode 프로젝트를 연다.
    2. 다음 순서로 클릭한다. XCode > View > Customize toolbar 
    3. Active Target, Active Executable을 드래그해서 당신의 탑 프로젝트 툴바로 옮긴다.
    4. 테스트하고 싶은 뷰를 선택하고 드롭다운 메뉴에서 Build and Go를 선택한다.

3. PNG 이미지가 포토샵에서 보이는 것처럼 보이지 않는다. 어째서인가? 
-> 만약 PNG 이미지가 포토샵에서처럼 깨끗하게 나오지 않는다면 우선은 32비트 픽셀 포맷을 사용하도록 하자.

 [[CCDirector sharedDirector] setPixelFormat:kRGBA8]; // 기본은 RGB565
 [[CCTexture2D setDefaultAlphaPixelFormat:KCCTexture2DPixelFormat_RGBA8888]; // 기본은 RGBA8888

그래도 여전히 문제가 생긴다면 다음 사항을 체크하자.

 * 디바이스 상에서 이미지가 생성될 때 알파 채널이 미리 적용되었는지 여부
 * 미리 적용된 알파 이미지를 정확하게 렌더링하기 위해, Cocos2D는 이 블렌딩함수를 사용한다.

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

그러나 당신이 만약 다른 블렌딩함수를 사용하고 싶다면 다음과 같이 해야 한다.

// Cocos2D v0.7x는 모든 스프라이트에 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA를 블렌딩 함수로서 사용한다.
// 이 방법은 정확하지 않다. 그러나 만약 당신이 0.7x의 방식을 에뮬레이트하고 싶다면

[sprite setBlendFunc: (ccBlendFunc) {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}];

블렌딩 함수에 대한 더 많은 정보와 미리 곱해진 알파 이미지에 대해서 알고 싶다면 다음을 읽어보기 바란다.

Premultiplied images in Cocos2D (http://www.cocos2d-iphone.org/wiki/doku.php/release_notes0_8#premultiplied_images)

그리고, 이미지가 혹시 하얗게 나올 경우, 이미지가 미리 곱해진 알파를 가지고 있다면 텍스처가 변환될 때 RGB 컴포넌트가 수정될 것이다. 하지만 만약 이것을 오버라이드하고 싶다면 다음과 같이 하라.

[sprite setOpacityModifyRGB:NO];
 
Posted by windship
프로그래밍/OpenGL-ES2011. 1. 22. 13:00

이전글에서 사용한 프로젝트에서 텍스쳐를 붙혀볼랍니다.

프로젝트 첨부하였습니다.(N드라이브에서 파일을 올리니 올려지는구나 ~)







1.우선 사용할 텍스쳐를 추가합니다.

문제는 사용해야할수있는 텍스쳐의 사이즈가 정해져있습니다.

그거슨 2의 제곱....

Icon.png는 72x72의 사이즈 이고

Lena256.png는 파일명대로 256x256 입니다.

텍스쳐 싸이즈가 2의 제곱이 아닐경우 2의 제곱으로 만들어 줘야하나 생략합니다;

(애플 공식샘플에 존재하나 구글에서 찾는게 더 빠르니 nextPOT 으로 검색 )  POT는 -Power Of Two


그리고 텍스쳐를 읽어들이기 위해 CoreGraphics.framework를 추가해야합니다.

혹 CoreGraphics.framework 추가를 까먹고 빌드를 하면

_CG~궁시렁~  이런 에러가 나오는데 

프렘웤이나 라이브러리 추가안햇을경우의 에러출력 방식을 알수있기에 그냥 빌드해보시길 바랍니다;








2.텍스쳐읽어들이는 소스가 좀 길어서 새로 메쏘드를 작성합니다.

그리고 멤버변수인 텍스쳐 오브젝트도 같이 만들어 줍니다.





3.텍스쳐를 읽어들이기 전에 해야할일은

사용한 텍스쳐 삭제하기 입니다.

나중에 하면 까먹는 일이 많으니 제일먼저 해줍니다;






4.텍스쳐 로딩하기

간단하게 텍스쳐를 사용하기위한 멤버변수와 텍스쳐 파일명을 건네줍니다.(66,71라인)

넘겨준 멤버변수에 저장이 되기에 포인터로 넘겨줍니다.

로딩에 실패했을경우 NO가 반납되어

assert()에서 프로그램강제 종료되게 하였습니다.(69,74라인)






5.텍스쳐 로딩 메쏘드

UIImage로 텍스쳐를 가져오고있으나(482라인)

간단하게 하기위해 일단 캐쉬가 남는 imageNamed을 사용.

게임에서 쓸려면 imageWithData를 사용해야합니다.


픽셀 데이터를 저장하기 위해 malloc으로 메모리생성 (489라인)

메모리생성 했으니 반납하는것도 안까먹기 (497,564라인)

아이폰 아이패드용 텍스쳐 로딩처리(491 ~ 521 라인)


OpenGL에서의 텍스쳐 생성과 옵션설정(525 ~ 552 라인)

간혹 필터링 설정을 안하는 샘플이 있는데(529,531 라인)

에뮬레이터에서는 잘되는데 디바이스에서는 안되는 경우가 많습니다.

필터링도 종류가 많으니 옵션을 바꿔가면서 직접 눈으로 확인하는게 좋습니다.

( GL_LINEAR는 고퀄리티 속도저하/ GL_NEAREST는 저퀄리티 속도상승 )


어드레싱에 대해선 다음번에 쓸 atlas에서 쓰기로 하고(536라인)


환경설정은 GL_MODULATE가 디폴트 설정에 사각형 색상 무시 텍스쳐 출력이고(543라인)

GL_DECAL을 사용하면 사각형의 색깔과 텍스쳐의 그림이 같이 출력됩니다.


알파채널을 사용하는 GL_RGBA를 사용하니 블렌딩을 유효화(547라인)


마지막으로 GPU에게 전송하면 텍스쳐를 사용할 준비가 끝납니다.(552라인)





6.텍스쳐 좌표 설정

레나는 왼쪽위에구석을 기준으로 256싸이즈로 출력(197라인)

아이콘은 왼쪽밑에구석을 기준으로 72싸이즈로 출력되게 수정.


저번에 귀찮아서 생략한 색상도 추가하고(230라인)

4개의 정점의 색깔을 흰색으로 수정.


이번에 텍스쳐출력을 위해 텍스쳐좌표를 새롭게 작성.(243라인)

텍스쳐싸이즈가 1024픽쎌이던 32픽쎌이던 1.0이 최대싸이즈 입니다.

이건 다음에 쓸 atlas에서 다시 설명하겠습니다.

텍스쳐도 알기쉽게 퀘변조로의 Z 의 순서로 작성합니다.

소스 코멘트에서도 적었듯이 좌표로 치자면 x,y를(244라인)

다이렉트X에서는 u,v로 쓰고

오픈쥐엘에서는 s,t로 쓰나 둘다 같은놈입니다.


좌표랑 색상쓰려고 했던것처럼 텍스쳐도 똑같이 해줍니다(282라인)


glEnable(GL_TEXTURE_2D)을 써서 텍스쳐를 사용할것이라는걸 알리고(286라인)

텍스쳐생성할때 사용하였던 glBindTexture()를써서 사용할 텍스쳐오브젝트를 선택합니다(289라인)

첨에 mTexture를 바인드해서 사각형을 출력하였고(레나)

그담음엔 mTexture2를 바인드해서 사각형을 출력하였습니다.(아이콘)


기본적으로 렌더링이 끝나면 이 메쏘드에서 렌더링할때 유효화했던 스테이트를 원래상태로 돌려줍니다.(300~305라인)





이걸루 간단하게 텍스쳐를 출력해보았습니다.


위에처럼 텍스쳐를 쭈욱사용할경우 glEnable(GL_TEXTURE_2D)를 

텍스쳐 로딩할때 한번만 써줘서 286라인 생략가능합니다.(블렌드처럼)

그리고 glEnableClientState도 텍스쳐 로딩끝나고 한번만 설정해주면

매번 다시 설정할 필요는 없습니다.


단, 다른곳에서 glDisable을 안할경우에 해당됩니다. ㅎ_ㅎ;


다음엔 간단 텍스쳐 atlas를 해볼랍니다;

Posted by windship
프로그래밍/OpenGL-ES2011. 1. 22. 12:59

아이폰4랑 아이폰3는 해상도는 틀리나

다행히도 화면비율은 같습니다.

아이폰4 -> 640x960 비율 1:1.5 (세로모드일 경우)

아이폰3 -> 320x480 비율 1:1.5 (세로모드일 경우)




1.우선 정사각형으로 만들어 봅시다.

199라인에 있는 glOrthof()를 추가합니다.

gl.h를 보면 ( left, right, bottom, top, zNear, zFar ) 이렇게 6개의 파라메터를 넣으라 합니다.

저도 자세한건 모르니

현재 출력화면(다음부턴 viewport라 하겟슴)을 glOrthof()에 지정한 비율로 출력한다 라고 합시다.

결국 제대로된 정사각형을 출력하기 위해선 비율만 맞춰주면 됩니다.

여지껏 세로가 긴화면을 억지로 1:1의 비율로 출력됬으니 

이걸 1:1.5의 비율로 바꿔주기만 하면 됩니다.

3D공간은 원점이 가운데이고 상하좌우 ±1.0를 사용하여 전체싸이즈가 2.0이나

viewport는 +만써서 1.0의 싸이즈를 사용하니 

상하좌우 각각 ±1:1.5씩을 대입하여 전체싸이즈를 2배로 뿔려줍니다.


161라인의 setFramebuffer는 밑에서 설명.





2.EAGLView에서 viewport가 자동으로 설정됩니다.

디버그창에보이듯이 320x480으로 viewport를 설정되였습니다.

viewport는 여기서 설정됩니다를 위한것이기에 여기선 아무것도 안하고 패스합니다.






3.지대루 정사각형이 출력되어졌습니다.





4.위의 정사각형의 싸이즈는 둘다 1.0입니다.

좌표는 컬러풀이 (-0.5,-0.5)이고 검둠이고 (0,0)입니다.

이런식의 싸이즈와 좌표로는 원하는곳에 원하는 싸이즈의 사각형을 표시할 염두가 안납니다.

그래서 이걸 2D좌표와 2D싸이즈로 변활할 필요가 있습니다.

검둥이를 x160,y240 에 가로 80, 세로 120

컬러풀을 x0,y0 에 가로 240, 세로 360 으로 설정하면 이렇게 됩니다.







5.우선 사각형의 좌표와 싸이즈를 바꿔줍시다.

바꿔주는김에 사각형 그리는 순서도 알기쉽게 바꿔줍니다.

퀘변조로의 Z의 순서로.

179라인의 static const 삭제도 까먹으면 안됩니다.






6.이제 3D좌표를 2D좌표로 바꿔줍니다.

좌표X는 0.0 ~ 320.0  ------>  -1.0 ~ +1.0 으로 변환

좌표Y도 0.0 ~ 480.0  ------>  -1.5 ~ +1.5 으로 변환


-우선 2D좌표를 3D좌표로 바꿔줍니다.(좌표X의 경우)

2D좌표 / 320.0

2D좌표가 0.0 이면 0.0이 되고,

2D좌표가 320.0 이면 1.0이 됩니다.

(2D좌표는 +0.0 ~ +1.0이 되었습니다)


-이걸 2배로 늘려줍니다(2배라고는 하나 사실은 아까 설정한 좌우비율의 2배입니다)

0.0이면 0.0이 되고,

1.0이면 2.0이 됩니다.

(2D좌표는 +0.0 ~ +2.0이 되었습니다)


3D좌표의 -쪽으로 좌우비율의 반만큼 이동시켜줍니다.

0.0 이면 2D좌표 - 1.0 = -1.0이 되고,

2.0 이면 2D좌표 - 1.0 = +1.0이 됩니다.

(2D좌표는 -1.0 ~ +1.0이 되었습니다)


이걸 공식으로 하면

3DPosX = ( 2DPosX / 320.0f ) * ratioWidth - ( ratioWidth * 0.5f );



좌표Y도 이런식으로 바꿔주고 싶은데

OpenGL에서의 viewport좌표의 원점은 화면 왼쪽 밑에 존재하고

아이폰에서의 view좌표의 원점은 화면 왼쪽 위에에 존재하니

2배로 늘려줄때 곱하기 - 해줘서 부호를 반대로 만들어주고

위쪽이 + 가 되므로 상하비율의 반만큼 +쪽으로 이동시켜줍니다.


이걸 공식으로 하면

3DPosY = ( 2DPosY / 480.0f ) * -ratioHeight + ( ratioHeight * 0.5f );







이걸루 OpenGL에서 2D 사용의 기초가 끝났습니다.

샘플을 최대한 수정안하는 방향으로 했기에 실질적으로 사용할려면 이곳저곳 띁어 고쳐야 합니다.

잘못된 곳이 있으면 지적 부탁드립니다 ㅎ_ㅎ;



다음엔 텍스쳐를 붙혀볼랍니다.

Posted by windship
프로그래밍/OpenGL-ES2011. 1. 22. 12:58

아이폰에서 OpenGL|ES 1.0을 사용하여 2D를 사용하기위해

먼저 3D의 기본지식을 설명하려 합니다.

http://en.wikipedia.org/wiki/OpenGL_ES <-외국어로 씌어져 있슴.



사용환경

xcode 3.2.5

iOS sdk 4.2


1.우선 OpenGL프로젝트 생성.

저는 GL2D 란 이름으로 생성함.



2.OpenGL|ES 1.0을 쓰기위해선 자동생성된 ViewController 43번째줄만 바꿔주면 됩니다.

45~48번줄은 삭제하고 kEAGLRenderingAPIOpenGLES2를 kEAGLRenderingAPIOpenGLES1로 바꿔줌.

//opengl|es 1.0 사용

EAGLContext *aContext = [[EAGLContext allocinitWithAPI:kEAGLRenderingAPIOpenGLES1];






3.이번엔 실질적으로 렌더링하는곳을 몇군데 만져줍니다.

알기쉽게 사각형 순서를 코멘트하고,(163라인)

샘플의 사각형의 세로가 0.333 인게 기분나뻐서 0.5로 변경,(170~174라인)

3D좌표 설명용으로 검정색 정사각형을 하나로 추가하고(175~178라인)

배경색이 어두운게 기운이 안나서 서울지하철2호선색상으로 변경,(191라인)

2.0용 쉐이더 사용하는곳을 지워주고,(193라인근방)

위아래로 움직이는게 멀미할것 같으니 삭제,(200라인근방)

마지막으로 검정색 정사각형을 렌더링합니다.(207라인)-코멘트에 5번부터라고 써있는데 오타임;





4.빌드하고 실행하면 나오는 결과물입니다.

배경은 서울지하철 2호선 색상이고,

원래 샘플의 사각형보단 약간 길쭉하게 표시되고 정가운데에서 멈춰있으며,

제가 추가한 검정색 정사각형이 보입니다.

거기에 제가 코멘트에 적은 사각형 순서번호를 그렸습니다.




5.제가 추가한 사각형은 가로세로 1.0의 사이즈의 정사각형인데 직사각형으로 나옵니다.

원래 샘플의 사각형도 -0.5~0.5의 사이즈면 결국 1.0의 사이즈인데 마찬가지로 직사각형으로 나옵니다.

허나 이건 틀린게 아닙니다.





세로가 길던 가로가 길던 기본적인 3D좌표는 

가운데가 원점 

위아래(+1.0 ~ -1.0)

좌우(-1.0 ~ +1.0) 입니다.

( Z축은 왼손좌표일경우 앞뒤 +1.0 ~ -1.0 오른손좌표일경우 앞뒤 -1.0 ~ +1.0 )

제가 추가한 사각형은 사이즈가 1.0이니 위로 길죽하지만 

원점을 기준으로 정확하게 1.0의 사이즈로 출력되었고,

원래 샘플의 정사각형도 원점을 기준으로 위아래좌우로 0.5씩의 사이즈로 출력되었습니다.

그러므로 결론은 여기까진 아무문제 없다 입니다.





다음번엔 소스코드에 한줄만 추가해서 정사각형으로 만들고,

알기쉬운 2D좌표를(왼쪽위가 원점)써서 출력을 해볼까 합니다;

Posted by windship
프로그래밍/OpenGL-ES2010. 8. 3. 00:42
/**
 *  @file SurfaceView.h
 *  A View that implements a CoreSurface buffer
 *  The buffer is created automatically in initWithFrame: with the size
 *  passed to it and 5-6-5 RGB format.
 *  The memory can be accessed with the pixels property, and after modifying
 *  it you must call setNeedsDisplay on it for it to update.
 */
 
#import <UIKit/UIKit.h>
#import <CoreSurface/CoreSurface.h>
 
@interface SurfaceView : UIView
{
    CALayer *surfaceLayer;
    unsigned short *pixels;
    CoreSurfaceBufferRef surfaceBuffer;
}
 
@property (nonatomic, readonly) unsigned short *pixels;
 
@end
 
 
 
/**
 *  @file SurfaceView.m
 *  Implementation of SurfaceView
 */
 
#import "SurfaceView.h"
 
@implementation SurfaceView
 
- (id)initWithFrame:(CGRect)frame {
    frame.origin.x /= 2;
    frame.origin.y /= 2;
   
    if (self = [super initWithFrame:frame]) {
        // Create Surface
        int w = frame.size.width, h = frame.size.height;
        surfaceBuffer = CoreSurfaceBufferCreate((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
            [NSNumber numberWithInt:w],         kCoreSurfaceBufferWidth,
            [NSNumber numberWithInt:h],         kCoreSurfaceBufferHeight,
            [NSNumber numberWithInt:'L565'],    kCoreSurfaceBufferPixelFormat,
            [NSNumber numberWithInt:2*w*h],     kCoreSurfaceBufferAllocSize,
            [NSNumber numberWithBool:YES],      kCoreSurfaceBufferGlobal,
            [NSNumber numberWithInt:2*w],       kCoreSurfaceBufferPitch,
            @"PurpleGFXMem",                    kCoreSurfaceBufferMemoryRegion,
            nil]);
       
        // Create layer for surface
        CGRect frame2 = CGRectMake(frame.origin.x, frame.origin.y,
                                   frame.size.width+1, frame.size.height+1);
        CoreSurfaceBufferLock(surfaceBuffer, 3);
        surfaceLayer = [[CALayer layer] retain];
        [surfaceLayer setMagnificationFilter:0];
        [surfaceLayer setEdgeAntialiasingMask:0];
        [surfaceLayer setFrame:frame2];
        [surfaceLayer setContents:surfaceBuffer];
        [surfaceLayer setOpaque:YES];
        [[self _layer] addSublayer:surfaceLayer];
        CoreSurfaceBufferUnlock(surfaceBuffer);
       
        // Get base address
        pixels = CoreSurfaceBufferGetBaseAddress(surfaceBuffer);
    }
    return self;
}
 
- (void)dealloc {
    [surfaceLayer release];
    [super dealloc];
}
 
- (void)drawRect:(CGRect)rect {
    // It will break if you remove this empty function
}
 
- (unsigned short*)pixels {
    return pixels;
}
@end

/** 
 *  @file SurfaceView.h
 *  A View that implements a CoreSurface buffer
 *  The buffer is created automatically in initWithFrame: with the size
 *  passed to it and 5-6-5 RGB format.
 *  The memory can be accessed with the pixels property, and after modifying
 *  it you must call setNeedsDisplay on it for it to update.
 */
 
#import <UIKit/UIKit.h>
#import <CoreSurface/CoreSurface.h>

@interface SurfaceView : UIView 
{
    CALayer *surfaceLayer;
    unsigned short *pixels;
    CoreSurfaceBufferRef surfaceBuffer;
}

@property (nonatomic, readonly) unsigned short *pixels;

@end



/** 
 *  @file SurfaceView.m
 *  Implementation of SurfaceView
 */
 
#import "SurfaceView.h"

@implementation SurfaceView

- (id)initWithFrame:(CGRect)frame {
    frame.origin.x /= 2;
    frame.origin.y /= 2;
    
    if (self = [super initWithFrame:frame]) {
        // Create Surface
        int w = frame.size.width, h = frame.size.height;
        surfaceBuffer = CoreSurfaceBufferCreate((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
            [NSNumber numberWithInt:w],         kCoreSurfaceBufferWidth,
            [NSNumber numberWithInt:h],         kCoreSurfaceBufferHeight,
            [NSNumber numberWithInt:'L565'],    kCoreSurfaceBufferPixelFormat,
            [NSNumber numberWithInt:2*w*h],     kCoreSurfaceBufferAllocSize,
            [NSNumber numberWithBool:YES],      kCoreSurfaceBufferGlobal,
            [NSNumber numberWithInt:2*w],       kCoreSurfaceBufferPitch,
            @"PurpleGFXMem",                    kCoreSurfaceBufferMemoryRegion,
            nil]);
        
        // Create layer for surface
        CGRect frame2 = CGRectMake(frame.origin.x, frame.origin.y, 
                                   frame.size.width+1, frame.size.height+1);
        CoreSurfaceBufferLock(surfaceBuffer, 3);
        surfaceLayer = [[CALayer layer] retain];
        [surfaceLayer setMagnificationFilter:0];
        [surfaceLayer setEdgeAntialiasingMask:0];
        [surfaceLayer setFrame:frame2];
        [surfaceLayer setContents:surfaceBuffer];
        [surfaceLayer setOpaque:YES];
        [[self _layer] addSublayer:surfaceLayer];
        CoreSurfaceBufferUnlock(surfaceBuffer);
        
        // Get base address
        pixels = CoreSurfaceBufferGetBaseAddress(surfaceBuffer);
    }
    return self;
}

- (void)dealloc {
    [surfaceLayer release];
    [super dealloc];
}

- (void)drawRect:(CGRect)rect {
    // It will break if you remove this empty function
}

- (unsigned short*)pixels {
    return pixels;
}
@end
Posted by windship