Download presentation
1
그래픽 출력
2
Introduction Quartz 2D OpenGL ES Core Graphics frameworks에 포함됨
Cross-platform library인 OpenGL의 embedded system 버전
3
Quartz approach to drawing
CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(context, 2.0); // 선의 굵기가 2가 되게 함 CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); // stroke color (선 또는 도형의 윤곽선에 사용) 설정. 참고, fill color는 채우는 색 CGConextMoveToPoint(context, 100.0f, 100.0f); // 그리는 위치를 (100, 100)으로 옮김 CGConextAddLineToPoint(context, 200.0f, 200.0f); // (100, 100)에서 (200, 200)으로 그림 CGContextStrokePath(context); // 위의 설정으로 그림을 화면에 출력. // 이 함수 실행전에는 화면에 나타나지 않음
4
좌표계 (0, 0) (100,100) (200, 200) (200, 200) (100,100) (0, 0) Quartz 2D
OpenGL ES
5
Color RGBA 사용 색을 프로그램에서 기술할 때 UIColor 객체의 CGColor reference를 써야 함
Red, Green, Blue + Alpha 각 색은 0 ~ 1.0 사이의 값을 가짐 Alpha는 투명도를 나타냄 OpenGL ES에서는 이 모델만 사용 Quartz 2D는 다른 color model도 사용할 수 있음 색을 프로그램에서 기술할 때 UIColor 객체의 CGColor reference를 써야 함 예 [UIColor redColor].CGColor [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:1.0f];
6
Alpha 값의 역할 = 투명도 조절 RGBA 데이터 RGBA 데이터 Alpha 값이 0에 가까울 수록
투명하게 영상을 그리게 됨 그리기 그리기 Alpha 값이 0.6인 경우 RGB = ( 0.1, 0.8, 0.4) 이미 있던 영상 값의 40% + 새로운 영상 값 60% RGB = ( 0.7, 0.1, 0.4, 0.5) RGBA = ( 0.7* *0.4, 0.1* *0.4, 0.4* *0.4), 즉, (0.46, 0.38, 0.44)
7
이미지 그리기 UIImage *drawImage;
drawImage = [UIImage // resource 목록에 넣은 iphone.png 파일을 로딩 CGFloat horizontalOffset = drawImage.size.width /2; CGFloat verticalOffset = drawImage.size.height/2; CGPoint drawpoint = CGPointMake(100.0f - horitontalOffset, 100.0f-verticalOffset); // (100, 100)에 이미지의 중심이 위치하도록 그리는 위치 설정 [drawImage drawAtPoint: drawPoint]; //화면에 출력
8
참고자료 Quartz 2D programming guide
9
OpenGL이란? OpenGL 그래픽 하드웨어 제어를 위한 소프트웨어 인터페이스 DirectX는 경쟁자
“OpenGL implementation”, 즉, 디바이스 드라이버를 제작하고자 하면 OpenGL 라이선스를 SGI 사에서 받아야 함 그러나 드라이버 사용자는 비용지불 안함 DirectX는 경쟁자
10
OpenGL ES란? OpenGL의 Embedded System (ES) 버전 OpenGL ES 스펙 자료
OpenGL ES 2.0 스팩은 iPhone OS 3.0 이상에서만 지원됨 호환성을 위해서는 OpenGL ES 1.1을 사용해야 함 OpenGL ES 스펙 자료 본 수업에서는 3D는 다루지 않고 2D만을 다룰 것임 iPhone SDK 샘플 코드에 좋은 자료(2D, 3D)가 많이 있으니 이것을 분석하고 변형시켜 보는 것이 효과적임
11
OpenGL ES로 그림 출력 절차 그림그리기 반드시 크기가 2의 배수가 되도록 저장 (포토샵) (*.png)
혹은 GLSprite 예제를 수정 Xcode의 “resources”에 추가하기 다음 슬라이드에 나오는 방식을 기반으로 코드 작성
12
이미지 출력 사전 준비하기 (1) 텍스쳐로 사용할 이미지 데이터를 준비시키키
// 화면 넓이 및 높이가 각각 backingWidth, backingHeight일 때 // 화면 전체를 출력에 사용하는 경우 다음과 같이 설정 glVewport(0, 0, backingWidth, backingHeight); glLoadIdentity(); glOrthof(0.0f, (GLfloat)backingwidth, 0.0, (GLfloat)backingHeight, 1.0, -1.0); glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // clear 색을 blue로 설정 glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // 2D 이미지를 텍스쳐로 쓸 수 있게 만듦 glEnable(GL_TEXTURE_2D); // 기존 이미지와 새로운 이미지가 혼합될 수 있게 함 glEnable(GL_BLEND); // 새로운 이미지로 기존 이미지를 덮어 쓰게 함 glBlendFunc(GL_ONE, GL_SRC_COLOR); // 만일 새로운 이미지를 기존 이미지 위에 alpha 값에 따라 투명하게 하고 // 싶으면 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13
이미지 출력 사전 준비하기 (2) 이미지 마다 위의 행위를 해 주어야 함 텍스쳐로 사용할 이미지 데이터를 준비시키키
// Creates a Core Graphics image from an image file spriteImage = [UIImage // 이미지의 넓이와 높이를 구함. 이 값은 2의 배수여야 함 (2, 4, 8, 16, …) width = CGImageGetWidth(spriteImage); height = CGImageGetHeight(spriteImage); if(spriteImage) { // 이미지 데이터를 저장할 공간 할당. RGBA 모델이므로 1 픽셀당 4 바이트. spriteData = (GLubyte *) malloc(width * height * 4); // core graphics framework에서 제공되는 비트맵 context를 생성 spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast); // 비트맵 context에 이미지를 출력. 결과적으로 spriteData에 그린 결과가 저장 CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), spriteImage); // 메모리 leak 방지를 위해 비트맵 context를 해제 CGContextRelease(spriteContext); } 이미지 마다 위의 행위를 해 주어야 함
14
이미지 출력 사전 준비하기 (3) 이미지 마다 위의 행위를 해 주어야 함 이미지를 텍스쳐로 만들기
// 텍스쳐 이름, 즉, 번호 얻기 glGenTextures(1, &spriteTexture); // 얻은 텍스쳐 번호를 바인딩 하기 glBindTexture(GL_TEXTURE_2D, spriteTexture); // Specify a 2D texture image, provideing the a pointer to the image data in memory glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData); free(spriteData); 이미지 마다 위의 행위를 해 주어야 함
15
이미지 출력 사전 준비하기 (4) 파라미터 설정 // Set the texture parameters to use a minifying filter and a linear filer // (weighted average) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Enable use of the texture glEnable(GL_TEXTURE_2D); // Set a blending function to use glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // Enable blending glEnable(GL_BLEND);
16
이미지 출력 (1) Texture coordinates로 표현 예: Glfloat texCoords[] =
{ 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0 }; (0.0, 1.0) (1.0, 1.0) 1 2 3 4 (0.0, 0.0) Texture (1.0, 0.0) Vertices로 표현 예: Glfloat spriteVertices[] = { 10.0, 20.0, 30.0, 20.0, 10.0, 10.0, 30.0, 10.0 }; 10, 20 30, 20 10, 10 Surface 30, 10
17
이미지 출력 (2) 10, 20 30, 20 10, 10 Surface 30, 10 // 출력될 이미지의 화면 영역 설정
glVertexPointer(2, GL_FLOAT, 0, spriteVertices); // 출력(즉, 매핑)할 때 사용할 이미지 영역 설정 glTexCoordPointer(2, GL_FLOAT, 0, texCoords); // 텍스쳐 이미지 설정. 이 텍스쳐의 texCoords 영역이 텍스쳐 매핑에 사용됨 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgWidth, imgHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData); // 화면에 그리기 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4 );
18
텍스쳐 사용에 대한 좋은 자료
19
EAGLView.h (1/2) 이 코드를 기반으로 추가/변경할 것 #import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h> #import <OpenGLES/ES1/gl.h> #import <OpenGLES/ES1/glext.h> @interface EAGLView : UIView { @private /* The pixel dimensions of the backbuffer */ GLint backingWidth, backingHeight; EAGLContext *context; /* OpenGL names for the renderbuffer and framebuffers used to render to this view */ GLuint viewRenderbuffer, viewFramebuffer; /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ GLuint depthRenderbuffer; /* OpenGL name for the sprite texture */ GLuint spriteTexture; // 이미지 출력을 위해 사용되는 텍스쳐 이 코드를 기반으로 추가/변경할 것
20
EAGLView.h (2/2) NSTimer *animationTimer;
NSTimeInterval animationInterval; } (void)startAnimation; // 애니메이션을 시작 시키는 함수 (void)stopAnimation; // 에니메이션을 중지 시키는 함수 (void)drawView; // 애니메이션 주기마다 호출되는 그리기 함수 // 응용은 주로 이 함수를 변경 @property NSTimeInterval animationInterval; // 에니메이션 주기 @end
21
EAGLView.m (1) #import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h> #import "EAGLView.h" // category 정의임. 향후 설명 @interface EAGLView (EAGLViewPrivate) (BOOL)createFramebuffer; (void)destroyFramebuffer; @end @interface EAGLView (EAGLViewSprite) (void)setupView; @implementation EAGLView @synthesize animationInterval; // You must implement this + (Class) layerClass { return [CAEAGLLayer class]; }
22
EAGLView.m (2) //The GL view is stored in the nib file.
// When it's unarchived it's sent -initWithCoder: (id)initWithCoder:(NSCoder*)coder { if((self = [super initWithCoder:coder])) { // Get the layer CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer; eaglLayer.opaque = YES; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; if(!context || ![EAGLContext setCurrentContext:context] || ![self createFramebuffer]) { [self release]; return nil; } animationInterval = 1.0 / 60.0; // 초당 60 프레임 [self setupView]; [self drawView]; return self;
23
EAGLView.m (3) 스크린 크기 저장 (void)layoutSubviews {
[EAGLContext setCurrentContext:context]; [self destroyFramebuffer]; [self createFramebuffer]; [self drawView]; } (BOOL)createFramebuffer { glGenFramebuffersOES(1, &viewFramebuffer); glGenRenderbuffersOES(1, &viewRenderbuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer]; glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES,&backingHeight); if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); return NO; return YES; 스크린 크기 저장
24
EAGLView.m (4) -(void)destroyFramebuffer {
glDeleteFramebuffersOES(1, &viewFramebuffer); viewFramebuffer = 0; glDeleteRenderbuffersOES(1, &viewRenderbuffer); viewRenderbuffer = 0; if(depthRenderbuffer) { glDeleteRenderbuffersOES(1, &depthRenderbuffer); depthRenderbuffer = 0; } (void)startAnimation { animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self userInfo:nil repeats:YES]; (void)stopAnimation { [animationTimer invalidate]; animationTimer = nil; (void)setAnimationInterval:(NSTimeInterval)interval { animationInterval = interval; if(animationTimer) { [self stopAnimation]; [self startAnimation];
25
EAGLView.m (5) // Sets up an array of values to use as the sprite vertices. const GLfloat spriteVertices[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, }; // Sets up an array of values for the texture coordinates. const GLshort spriteTexcoords[] = { 0, 0, 1, 0, 0, 1, 1, 1,
26
EAGLView.m (6) 2D 그리픽을 설정 sprite.png 파일을 텍스쳐로 로딩 (void)setupView {
CGImageRef spriteImage; CGContextRef spriteContext; GLubyte *spriteData; size_t width, height; // Sets up matrices and transforms for OpenGL ES glViewport(0, 0, backingWidth, backingHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); // Clears the view with black glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Sets up pointers and enables states needed for using vertex arrays and textures glVertexPointer(2, GL_FLOAT, 0, spriteVertices); glEnableClientState(GL_VERTEX_ARRAY); glTexCoordPointer(2, GL_SHORT, 0, spriteTexcoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); 2D 그리픽을 설정 sprite.png 파일을 텍스쳐로 로딩
27
EAGLView.m (7) // Creates a Core Graphics image from an image file
spriteImage = [UIImage // Get the width and height of the image width = CGImageGetWidth(spriteImage); height = CGImageGetHeight(spriteImage); // Texture dimensions must be a power of 2. // If you write an application that allows users to supply an image, // you'll want to add code that checks the dimensions and //takes appropriate action if they are not a power of 2. if(spriteImage) { // Allocated memory needed for the bitmap context spriteData = (GLubyte *) malloc(width * height * 4); // Uses the bitmatp creation function provided by the Core Graphics framework. spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast); // After you create the context, you can draw the sprite image to the context. CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), spriteImage);
28
EAGLView.m (8) // You don't need the context at this point, so you need to release it // to avoid memory leaks. CGContextRelease(spriteContext); // Use OpenGL ES to generate a name for the texture. glGenTextures(1, &spriteTexture); // Bind the texture name. glBindTexture(GL_TEXTURE_2D, spriteTexture); // Specify a 2D texture image, provideing the a pointer to the image data in memory glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData); // Release the image data free(spriteData); // Set the texture parameters to use a minifying filter and a linear filer // (weighted average) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Enable use of the texture glEnable(GL_TEXTURE_2D); // Set a blending function to use glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // Enable blending glEnable(GL_BLEND); }
29
EAGLView.m (9) // Updates the OpenGL view when the timer fires
(void)drawView { // 애니메이션을 위해 변경하는 주요 부분 // Make sure that you are drawing to the current context [EAGLContext setCurrentContext:context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glRotatef(3.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context presentRenderbuffer:GL_RENDERBUFFER_OES]; } // Stop animating and release resources when they are no longer needed. (void)dealloc { [self stopAnimation]; if([EAGLContext currentContext] == context) { [EAGLContext setCurrentContext:nil]; [context release]; context = nil; [super dealloc]; @end
30
실습 OpenGL ES 템플릿으로 OpenGLTest 예제 생성하고 내용 살펴 보기 GLSprite 예제를 살펴 보기
실습: 2개의 이미지를 애니메이션 1개는 화면의 위에서 아래로 1개는 화면의 왼쪽에서 오른쪽으로
31
숙제 Aiolos 예제를 iPhone용으로 변환 가이드 라인 (GLSprite 수정)
전체는 시간과 노력이 많이 걸릴 수 있으므로 다음만 수행 스테이지 1의 배경과 구름만 출력 가이드 라인 (GLSprite 수정) setupView에 1개의 이미지가 아닌 여러 개가 되도록 만듦 drawView 수정
32
drawView 수정 - (void)drawView { glClear(GL_COLOR_BUFFER_BIT);
// Make sure that you are drawing to the current context [EAGLContext setCurrentContext:context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glRotatef(3.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context presentRenderbuffer:GL_RENDERBUFFER_OES]; } - (void)drawView { glClear(GL_COLOR_BUFFER_BIT); RenderBufferScene(); (void)drawView { glClear(GL_COLOR_BUFFER_BIT); RenderBufferScene(); // Make sure that you are drawing to the current context [EAGLContext setCurrentContext:context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context presentRenderbuffer:GL_RENDERBUFFER_OES]; }
33
RenderBufferScene void RenderBufferScene(void) { static int first = 0;
if( first == 0 ) { // 처음 실행될 때 필요한 것 // 즉, Aiolos의 경우 START_EVENT일 때 실행하는 코드 삽입 first = 0; } else { // Aiolos의 TIMEOUT_EVENT 때 실행하는 코드 EVENT_TIMEOUT(); }
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.