iPhone 에서 OpenGL 로 AR 기능을

  사용하려고 하면 필수적으로 OpenGL 의 

  모델 도형을 투명한 배경위에 보여줘야 합니다.

  그래서 설정해야 할 것들이 몇가지 있습니다.

  우선 기본 설정에서 RGBA8 로 해주고, 

  배경의 색깔을 모두 지운 후 alpha 에 투명값을 

  설정하는 겁니다. "0" 으로 말이죠.

  다시 정리하면 아래 코드를 볼 수 있습니다.

// 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])) {

CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;

eaglLayer.opaque = NO;//no - transparent

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;

}

animating = FALSE;

displayLinkSupported = FALSE;

animationFrameInterval = 1;

displayLink = nil;

animationTimer = nil;

// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer

// class is used as fallback when it isn't available.

NSString *reqSysVer = @"3.1";

NSString *currSysVer = [[UIDevice currentDevice] systemVersion];

if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)

displayLinkSupported = TRUE;

[self setupView];

}

return self;

}


해당 코드는 일반적으로 제공되는 OpenGL 코드인데, eaglLayer.opaque = NO 로 설정해야 투명한 배경을


얻을 수 있습니다. 또한 도형을 그리는 부분에서는 배경화면의 색깔을 투명으로 지정해야 합니다.


        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


여기서 glClear(Red, Green, Blue, alpha) 값을 보시면 모두 0 으로 설정하면 됩니다.


그런데 이렇게 하고서 투명처리가 안되어 무지 고생을 했습니다.


알고 봤더니 인터페이스 빌더에서 해당 OpenGL 을 그리는 View 의 배경색이 흰색으로 설정되어 있었습니다.





그래서 위와 같이 View 를 선택한 뒤, 배경색 팔레트에서 Opacity 값을 0 으로 설정하면 


View 자체가 투명한 색을 가지게 됩니다.


그러면 아래와 같은 투명배경의 도형을 카메라와 같이 볼 수 있게 됩니다.




Interesting/iPhone | Posted by hyena0 2010. 1. 22. 22:55

[iPhone] OpenGL 프로그래밍 ...5


  

  [iPhone] OpenGL 프로그래밍 ...5


  마지막으로 다루어볼 도형 그리는 법을 알아보겠습니다.

  3. glVertexPointer, glNormalPointer, glTexCoordPointer, 
   glDrawArrays 이용

  여기서는 glTexCoordPointer 함수가 추가된 형태입니다.

  이 함수는 Texture 를 추가적으로 입력하기 위한 배열을 포함하고 있습니다.

  이것을 적용하기 위해서는 두 가지 작업이 필요한데, 우선은 Texture 를 

  3D 도형에 맞추어서 배열 값을 얻는 것과 이미지를 별도로 등록시키는 것입니다.

  아래의 예제를 봅시다.

  - (void)drawView {

// Our new object definition code goes here

    const GLfloat cubeVertices[] = {

        

        // Define the front face

        -1.0, 1.0, 1.0,             // top left

        -1.0, -1.0, 1.0,            // bottom left

        1.0, -1.0, 1.0,             // bottom right

        1.0, 1.0, 1.0,              // top right

        

        // Top face

        -1.0, 1.0, -1.0,            // top left (at rear)

        -1.0, 1.0, 1.0,             // bottom left (at front)

        1.0, 1.0, 1.0,              // bottom right (at front)

        1.0, 1.0, -1.0,             // top right (at rear)

        

        // Rear face

        1.0, 1.0, -1.0,             // top right (when viewed from front)

        1.0, -1.0, -1.0,            // bottom right

        -1.0, -1.0, -1.0,           // bottom left

        -1.0, 1.0, -1.0,            // top left

        

        // bottom face

        -1.0, -1.0, 1.0,

        -1.0, -1.0, -1.0,

        1.0, -1.0, -1.0,

        1.0, -1.0, 1.0,

        

        // left face

        -1.0, 1.0, -1.0,

        -1.0, 1.0, 1.0,

        -1.0, -1.0, 1.0,

        -1.0, -1.0, -1.0,

        

        // right face

        1.0, 1.0, 1.0,

        1.0, 1.0, -1.0,

        1.0, -1.0, -1.0,

        1.0, -1.0, 1.0

    };

    const GLshort squareTextureCoords[] = {

        // Front face

        0, 1,       // top left

        0, 0,       // bottom left

        1, 0,       // bottom right

        1, 1,       // top right

        

        // Top face

        0, 1,       // top left

        0, 0,       // bottom left

        1, 0,       // bottom right

        1, 1,       // top right

        

        // Rear face

        0, 1,       // top left

        0, 0,       // bottom left

        1, 0,       // bottom right

        1, 1,       // top right

        

        // Bottom face

        0, 1,       // top left

        0, 0,       // bottom left

        1, 0,       // bottom right

        1, 1,       // top right

        

        // Left face

        0, 1,       // top left

        0, 0,       // bottom left

        1, 0,       // bottom right

        1, 1,       // top right

        

        // Right face

        0, 1,       // top left

        0, 0,       // bottom left

        1, 0,       // bottom right

        1, 1,       // top right

    };

    [EAGLContext setCurrentContext:context];    

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

    glViewport(0, 0, backingWidth, backingHeight);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

// Our new drawing code goes here

rota += 0.5;

    glLoadIdentity();

    glTranslatef(0.0, 0.0, -6.0);

    glRotatef(rota, 1.0, 1.0, 1.0);

    glVertexPointer(3, GL_FLOAT, 0, cubeVertices);

    glEnableClientState(GL_VERTEX_ARRAY);


    glTexCoordPointer(2, GL_SHORT, 0, squareTextureCoords);

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

// Draw the front face in Red

        glColor4f(1.0, 0.0, 0.0, 1.0);

        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

// Draw the top face in green

glColor4f(0.0, 1.0, 0.0, 1.0);

glDrawArrays(GL_TRIANGLE_FAN, 4, 4);

// Draw the rear face in Blue

glColor4f(0.0, 0.0, 1.0, 1.0);

glDrawArrays(GL_TRIANGLE_FAN, 8, 4);

// Draw the bottom face

glColor4f(1.0, 1.0, 0.0, 1.0);

glDrawArrays(GL_TRIANGLE_FAN, 12, 4);

// Draw the left face

glColor4f(0.0, 1.0, 1.0, 1.0);

glDrawArrays(GL_TRIANGLE_FAN, 16, 4);

// Draw the right face

glColor4f(1.0, 0.0, 1.0, 1.0);

glDrawArrays(GL_TRIANGLE_FAN, 20, 4);

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

    [context presentRenderbuffer:GL_RENDERBUFFER_OES];

[self checkGLError:NO];

}


  위의 코드에서 처럼 glTexCoordPointer 함수가 추가되어 있는 것을 알 수 있습니다.

   squareTextureCoords[] 배열 값에 Texture 를 어떻게 입력할 것인지하는 정보가 있습니다.

  이 부분은 정사각형의 좌표를 각각 표현한 내용입니다.

  Texture 관련 부분은 Blender부분에서 자세히 다루도록 하겠습니다.

  기본적으로 알면 좋긴 하지만, Blender 로 Export하게 되면 값이 나오게 되므로

  배열값을 보고 알 수 없는 경우도 있기 때문에 지금은 그냥 넘어가겠습니다.

  그래도 궁금하신 분들은 여기를 보시기 바랍니다.

  위의 코드에서 빠진 부분은 texture 를 선택하는 부분인데 아래와 같습니다.

- (void)loadTexture {

    CGImageRef textureImage = [UIImage imageNamed:@"checkerplate.png"].CGImage;

    if (textureImage == nil) {

        NSLog(@"Failed to load texture image");

return;

    }

    NSInteger texWidth = CGImageGetWidth(textureImage);

    NSInteger texHeight = CGImageGetHeight(textureImage);

GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);

    CGContextRef textureContext = CGBitmapContextCreate(textureData,

                                                         texWidth, texHeight,

                                                         8, texWidth * 4,

                                                         CGImageGetColorSpace(textureImage),

                                                         kCGImageAlphaPremultipliedLast);

CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), textureImage);

CGContextRelease(textureContext);

glGenTextures(1, &textures[0]);

glBindTexture(GL_TEXTURE_2D, textures[0]);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

free(textureData);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glEnable(GL_TEXTURE_2D);

}  

  checkerplate.png 파일을 호출해서 textures 배열에 넣고 바인딩 시켜주는 과정입니다.

  물론 이 메소드를 실행해 주어야만 동작합니다.

  [self loadTexture];

  실제 실행 캡처 화면은 아래와 같습니다.


  



  이제 3차원 도형을 그리는 세가지 방법에 대해 다 알아봤습니다.

  다음 포스팅에서는 3차원 도형을 그리는 툴인 Blender 를 사용해 보고, export 하여 배열로 만든 뒤

  아이폰에서 그려보는 작업을 해 보겠습니다.

Interesting/iPhone | Posted by hyena0 2010. 1. 21. 00:40

[iPhone] OpenGL 프로그래밍 ...4


  

  [iPhone] OpenGL 프로그래밍 ...4


  drawView 방식의 두번째를 다루어 보겠습니다.

  2. glVertexPointer, glNormalPointer, glDrawArrays 이용

  이 세가지 함수를 이용하는 것인데, 이전 포스트에서 본 것처럼

  도형의 꼭지점 배열에 대해 glVertexPointer 에서 선택을 하고 glDrawArrays 함수로

  그리는 방식을 취했습니다. 

  두 번째 방식은 glNormalPointer 까지 가세한 것이지요.

  normalPointer 값은 도형의 면에 대한 normal vector값을 가지고 추가로 도형을 표현하고자
  
  하는 것입니다. 이 때에는 normal vector 의 배열값이 추가로 필요합니다.

  그런데 "왜 이것이 필요할까?" 라고 생각할 수 있을 겁니다. 그 이유는 사실적으로 보이려고 하면

  나중에 광원을 가지고 그림자를 지게 할 것인데, 이 normal vector 값이 없으면 그 효과를 적용할 수 없기 때문이지요.

  아래 예를 보겠습니다.

- (void)drawView {


    [EAGLContext setCurrentContext:context];    

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glViewport(0, 0, backingWidth, backingHeight);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);


    glLoadIdentity();

    glTranslatef(0.0, 0.0, 0.0);//6.0

   

    glEnableClientState(GL_VERTEX_ARRAY);

    glEnableClientState(GL_NORMAL_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, Vertices);

    glNormalPointer(GL_FLOAT, 0, Normals);

    glDrawArrays(GL_TRIANGLES, 0, 100);//100 -> size of vertices


    glDisableClientState(GL_VERTEX_ARRAY);

    glDisableClientState(GL_NORMAL_ARRAY);

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

    [context presentRenderbuffer:GL_RENDERBUFFER_OES];

}


예제에서는 Vertices 배열과 Normals 배열을 각각 선택하고 glDrawArrays 를 이용하여 배열의 0에서 크기 만큼(100)

그리도록 되어 있습니다. 

normal pointer 배열을 적용하고 안하고는 조명을 적용하고 안하고를 따져보면 알 수 있습니다. 





  상단의 이미지는 normal pointer 를 적용한 경우이고, 아래의 그림은 미적용이므로 차이를 알 수 있습니다.

  빛에 대해 반응하는 차이가 보이지요.

  여기서 한가지 의문이 들 것으로 보입니다. 오늘의 포스팅에서는 배열의 내용을 설명하지 않고 있지요.

  과연 위의 그림과 같은 도형이 어떻게 나왔는지 궁금하실거 같네요.

  제가 참조한 사이트에서는 Blender 라는 공개소프트웨어를 이용해서 도형을 그린뒤 export하여 

  도형의 정보를 배열에 담아서 보여주고 있습니다. 

  세번째 방법까지 다룬 뒤 Blender로 도형을 그리고 export 하여 원하는 모양을 OpenGL ES 에서 보이는 방법을 

  보여드리도록 하겠습니다.

  

  [Next] OpenGL 프로그래밍..5