OpenGL로 외부 이미지파일을 읽어와서 출력할 때
glDrawPixels()함수를 쓰는 방법과 텍스쳐(texture)를 사용하는 방법이 있는데,
glDrawPixels()는 그릴 때마다 메인 메모리에서 픽셀값들을 읽어들이는 반면
텍스쳐는 생성할 때 그래픽 처리 장치의 메모리에 저장되므로 속도가 더 빠르다.
또한 텍스쳐를 그릴 때 확대/축소와 위치 지정을 자유롭게 할 수 있다.
먼저 테스트용으로 쓸 이미지 배열을 만든다.
여기서는 텍스쳐 포멧으로 RGBA_8888를 사용할 것인데,
Red, Green, Blue, Alpha(불투명도)에 해당하는 정보들을 각각 8비트(1바이트)씩 사용하는 방법이다.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | int w = 100; int h = 100; GLubyte map[100*100*4]; int i,j; for(i=0; i<h; i++) {     for(j=0; j<w; j++) {          map[w*i*4+j*4+0] = 0x99; //Red         map[w*i*4+j*4+1] = 0x99; //Green         map[w*i*4+j*4+2] = 0xCC; //Blue         map[w*i*4+j*4+3] = 0xAA; //Alpha     } } | 
100x100 크기의 0x9999CCAA색 사각형을 나타내는 1차원 배열이 생성된다.
(그릴 때는 2차원으로 처리된다.)
알파 채널을 사용하기 위해 GL_BLEND를 활성화하고, 
텍스쳐id로 텍스쳐를 생성한 뒤 glBindTexture()로 텍스쳐id와 텍스쳐라이징 대상을 연결한다.
그리고 glTexImage2D()로 텍스쳐로 쓸 GLubyte 배열을 쓴다.
glTexParameteri()로 확대/축소시 텍스쳐 필터를 설정하고
glTexEnvi()로 텍스쳐 환경 설정을 한다.(레퍼런스 참고)
| glEnable(GL_BLEND); glTexImage2D( | 
텍스쳐의 너비와 높이가 각각 2의 거듭제곱 꼴일 때 높은 성능을 얻을 수 있다.
(메모리에 2의 거듭제곱 단위로 할당되기 때문에..)
OpenGL ES에서는 아예 2의 거듭제곱꼴만 하용하고 있다.
예시) 64x128, 128x128, 256x64 등
이제 텍스쳐를 그리는 부분이다.
여기서는 평면상에 텍스쳐를 그릴 것인데, 먼저 OpenGL의 좌표계에 대해 알아야 한다.
별도의 설정을 하지 않을 시, 화면의 중앙이 원점이 되며 우측 상단으로 갈 수록 x와 y 값이 각각 증가한다.
우측 상단 꼭지점의 좌표는 (1, 1)이다.
텍스쳐 이미지 자체의 좌표는, 이미지의 좌측하단이 원점이며,
이미지의 우측상단이 (1, 1)이다.
glOrtho()함수를 쓰면 좌표계(클리핑 범위)를 재설정할 수 있다. 형식은 아래와 같다.
glOrtho(왼쪽, 오른쪽, 아래, 위, z축 근거리방향, z축 원거리방향)
2D만 고려할 때, glOrtho(0, 너비, 높이, 0 정도로 지정하면
MFC, JS 등에서처럼 좌측상단을 원점으로 쓸 수 있다.
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | 
glTexCoord2f()로 그릴 텍스쳐 영역을 지정할 때 
텍스쳐가 뒤집혀 있는 상태이므로 아래와 같은 순서로 그린 것이다.
아래는 png 이미지를 로드하여 화면에 두 번 표시해본 화면이다.
이미지를 로드하기 위해 SDL2를 사용했는데, SDL2 대신 glut과 pnglib라이브러리를 써도 png 이미지파일을 읽어올 수 있다. (pnglib라이브러리 없이도 BMP파일은 로드 가능.) 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #pragma comment (lib,"SDL2") #pragma comment (lib,"SDL2main") #pragma comment (lib,"SDL2_image") #pragma comment (lib,"opengl32.lib") #include <cstdio> #include <SDL.h> #include <SDL_opengl.h> #include <SDL_image.h> using namespace std; SDL_Renderer *renderer; int main(int argc, char **argv){     int winWidth = 800;     int winHeight = 600;     SDL_Window *win = NULL;     SDL_Renderer *renderer = NULL;     SDL_Surface *image;     SDL_RWops *rwop;     rwop = SDL_RWFromFile("../res/img.png", "rb");     image = IMG_LoadPNG_RW(rwop);     GLubyte *map = (GLubyte*)image->pixels;     int w, h;      w = image->w;     h = image->h;     if (SDL_Init(SDL_INIT_VIDEO) < 0)         return 1;     win = SDL_CreateWindow("gl", 100, 100, winWidth, winHeight, SDL_WINDOW_OPENGL);     renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);     SDL_GLContext context;     context = SDL_GL_CreateContext(win);     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);     glEnable(GL_BLEND);     glEnable(GL_TEXTURE_2D);     GLuint texId;     glGenTextures(1, &texId);     glBindTexture(GL_TEXTURE_2D, texId);     glTexImage2D(         GL_TEXTURE_2D, 0, GL_RGBA,         w, h, 0,         GL_RGBA, GL_UNSIGNED_BYTE,         map     );     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);     while (1) {         SDL_Event e;         if (SDL_PollEvent(&e)) {             if (e.type == SDL_QUIT)                 break;             else if (e.type == SDL_KEYUP && e.key.keysym.sym == SDLK_ESCAPE)                 break;         }         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         glOrtho(0, winWidth, winHeight, 0, -1, 1);         glMatrixMode(GL_PROJECTION);         glLoadIdentity();         glBindTexture(GL_TEXTURE_2D, texId);         glBegin(GL_QUADS);             glTexCoord2f(0.0, 0.0); glVertex2f(0, 0);             glTexCoord2f(1.0, 0.0); glVertex2f(w, 0);             glTexCoord2f(1.0, 1.0); glVertex2f(w, h);             glTexCoord2f(0.0, 1.0); glVertex2f(0, h);         glEnd();         glBegin(GL_QUADS);             glTexCoord2f(0.0, 0.0); glVertex2f(0+30, 0+30);             glTexCoord2f(1.0, 0.0); glVertex2f(w+30, 0+30);             glTexCoord2f(1.0, 1.0); glVertex2f(w+30, h+30);             glTexCoord2f(0.0, 1.0); glVertex2f(0+30, h+30);         glEnd();         SDL_GL_SwapWindow(win);         SDL_Delay(21);     }     SDL_GL_DeleteContext(context);     SDL_DestroyRenderer(renderer);     SDL_DestroyWindow(win);     return 0; } | cs |