마지막으로 다루어볼 도형 그리는 법을 알아보겠습니다.
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 하여 배열로 만든 뒤
아이폰에서 그려보는 작업을 해 보겠습니다.