sudo apt update
sudo apt upgrade
sudo apt install build-essential
sudo apt install libsdl2-dev
sudo apt install libsdl2-ttf-dev
sudo apt install libgles2-mesa-dev libegl1-mesa-dev
gcc -o app app.c `sdl2-config --cflags --libs` -lSDL2_ttf -lGLESv2
| 라이브러리 | 역할 |
|---|---|
| standard I/O | 콘솔 입출력 |
| SDL2 | 창, 멀티미디어, 입력, 이벤트 |
| SDL2_ttf | 텍스트 렌더링 (TTF 폰트) |
| OpenGL ES 2.0 | 그래픽 |
사실 SDL2 만으로도 그래픽 처리를 할 수 있지만 2D 와 픽셀 기반이라는 제한이 있다. 3D 나 벡터 기반의 그래픽 작업을 위해 OpenGL 을 사용한다.
#include <SDL2/SDL.h>
#include <GLES2/gl2.h>
#include <stdio.h>
int main() {
int w = 0;
int h = 0;
int quit = 0;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL_Init Error: %s\n", SDL_GetError());
return -1;
}
SDL_Event event;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Window* window = SDL_CreateWindow(
"SDL2 + GLES2 (blue clear)",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h,
SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN
);
if (!window) {
printf("SDL_CreateWindow Error: %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
SDL_GetWindowSize(window, &w, &h);
SDL_GLContext ctx = SDL_GL_CreateContext(window);
if (!ctx) {
printf("SDL_GL_CreateContext Error: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
SDL_GL_SetSwapInterval(1);
printf("Current Swap Interval: %d\n", SDL_GL_GetSwapInterval());
glViewport(0, 0, w, h);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN) {
quit = 1;
}
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
}
}
SDL_GL_DeleteContext(ctx);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <GLES2/gl2.h>
#include <stdio.h>
static const char* vs_src =
"attribute vec2 aPos;\n"
"attribute vec2 aUV;\n"
"varying vec2 vUV;\n"
"void main(){ vUV=aUV; gl_Position=vec4(aPos,0.0,1.0); }\n";
static const char* fs_src =
"precision mediump float;\n"
"varying vec2 vUV;\n"
"uniform sampler2D uTex;\n"
"void main(){ gl_FragColor=texture2D(uTex,vUV); }\n";
GLuint compile(GLenum type,const char*src){
GLuint s=glCreateShader(type);
glShaderSource(s,1,&src,NULL);
glCompileShader(s);
return s;
}
int main(){
int w=800,h=600,quit=0;
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,2);
SDL_Window* win=SDL_CreateWindow("Hello GLES2",0,0,w,h,SDL_WINDOW_OPENGL);
SDL_GLContext ctx=SDL_GL_CreateContext(win);
// 프로그램
GLuint vs=compile(GL_VERTEX_SHADER,vs_src);
GLuint fs=compile(GL_FRAGMENT_SHADER,fs_src);
GLuint prog=glCreateProgram();
glAttachShader(prog,vs); glAttachShader(prog,fs);
glBindAttribLocation(prog,0,"aPos");
glBindAttribLocation(prog,1,"aUV");
glLinkProgram(prog);
// 폰트 → Surface
TTF_Font* font=TTF_OpenFont("NanumGothic.ttf",64);
SDL_Color white={255,255,255,255};
SDL_Surface* s1=TTF_RenderUTF8_Blended(font,"Hello, World!",white);
SDL_Surface* s2=SDL_ConvertSurfaceFormat(s1,SDL_PIXELFORMAT_ABGR8888,0);
SDL_FreeSurface(s1);
// 텍스처 생성
GLuint tex; glGenTextures(1,&tex);
glBindTexture(GL_TEXTURE_2D,tex);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,s2->w,s2->h,0,
GL_RGBA,GL_UNSIGNED_BYTE,s2->pixels);
SDL_FreeSurface(s2);
// 중앙 위치 계산
float tw=(float)s2->w, th=(float)s2->h;
float cx=(w-tw)/2.0f, cy=(h-th)/2.0f;
float l=2*cx/w-1, r=2*(cx+tw)/w-1;
float t=1-2*cy/h, b=1-2*(cy+th)/h;
GLfloat verts[]={
l,t, 0,0, r,t,1,0, r,b,1,1,
l,t, 0,0, r,b,1,1, l,b,0,1
};
GLuint vbo; glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glBufferData(GL_ARRAY_BUFFER,sizeof(verts),verts,GL_STATIC_DRAW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
SDL_Event e;
while(!quit){
while(SDL_PollEvent(&e)){
if(e.type==SDL_QUIT||e.type==SDL_KEYDOWN) quit=1;
}
glViewport(0,0,w,h);
glClearColor(0,0,1,1); glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(prog);
glBindTexture(GL_TEXTURE_2D,tex);
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0,2,GL_FLOAT,0,4*sizeof(float),(void*)0);
glVertexAttribPointer(1,2,GL_FLOAT,0,4*sizeof(float),(void*)(2*sizeof(float)));
glDrawArrays(GL_TRIANGLES,0,6);
SDL_GL_SwapWindow(win);
}
// 정리
glDeleteProgram(prog);
glDeleteTextures(1,&tex);
glDeleteBuffers(1,&vbo);
TTF_CloseFont(font);
SDL_GL_DeleteContext(ctx);
SDL_DestroyWindow(win);
TTF_Quit(); SDL_Quit();
return 0;
}
필요 파일: NanumGothic.ttf