1 Getting started 3 Hello Window - JJhuk/LearnOpenGL GitHub Wiki

LearnOpenGL - Hello Window

url: https://learnopengl.com/Getting-started/Hello-Window ์ƒ์„ฑ์ผ: 2020๋…„ 12์›” 21์ผ ์˜ค์ „ 2:14

GLFW๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋จผ์ € ์‚ดํ‘œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋จผ์ € .cpp ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ์ƒˆ๋กœ ๋งŒ๋“  ํŒŒ์ผ์˜ ๋งจ ์œ„์— ๋‹ค์Œ include๋“ค์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

#include <glad/glad.h>
#include <GLFW/glfw3.h>

GLFW ์•ž์— GLAD๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. GLAD์šฉ ์ธํด๋ฃจ๋“œ ํŒŒ์ผ์—๋Š” ์žฅ๋ฉด ๋’ค์—์„œ ํ•„์š”ํ•œ OpenGL ํ—ค๋”(์˜ˆ๋ฅผ ๋“ค๋ฉด GL/gl.h) ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ OpenGL (์˜ˆ๋ฅผ ๋“ค์–ด GLFW)์ด ํ•„์š”ํ•œ ๋‹ค๋ฅธ ํ—ค๋” ํŒŒ์ผ๋ณด๋‹ค GLAD๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ, GLFW์ฐฝ์„ ์ธ์Šคํ„ด์Šคํ™” ํ•  ์ฃผ์š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //์ฃผ ๋ฒ„์ „
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); //๋ถ€ ๋ฒ„์ „
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //Core-Profile
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Mac OS
  
    return 0;
}

mainํ•จ์ˆ˜์—์„œ ๋จผ์ € glfwInit() ์œผ๋กœ GLFW๋ฅผ ์ดˆ๊ธฐํ™” ํ•œ ๋‹ค์Œ glfwWindowHint ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GLFW๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์”๋‹ˆ๋‹ค. glfwWindowHint ์˜ ์ฒซ๋ฒˆ์งธ ์ธ์ž๋Š” ๊ตฌ์„ฑํ•˜๋ ค๋Š” ์˜ต์…˜์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ GLFW_ ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™์€ ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์˜ ํฐ ์—ด๊ฑฐ ํ˜•์—์„œ ์˜ต์…˜์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ์˜ต์…˜ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์˜ต์…˜ ๋ฐ ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์˜ ๋ชฉ๋ก์€ GLFW ์ฐฝ ์ฒ˜๋ฆฌ ๋ฌธ์„œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ ์ •์˜๋˜์ง€ ์•Š์€ ๋งŽ์€ ์ฐธ์กฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด GLFW ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ฑ…์˜ ์ดˆ์ ์€ OpenGL ๋ฒ„์ „ 3.3์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์— GLFW์— ๋ฒ„์ „ 3.3์ด ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋ ค๋Š” OpenGL ๋ฒ„์ „์ž„์„ ์•Œ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์‹์œผ๋กœ GLFW๋Š” OpenGL ์ปจํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ค ๋•Œ ์ ์ ˆํ•œ ์ค€๋น„๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์ ˆํ•œ OpenGL ๋ฒ„์ „์ด ์—†์„ ๋•Œ GLFW๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ฃผ ๋ฒ„์ „๊ณผ ๋ถ€ ๋ฒ„์ „์„ ๋ชจ๋‘ 3.3์œผ๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ GLFW์— core-profile์„ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค. GLFW์— core-profile์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๊ณ  ๋งํ•˜๋ฉด ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์€ ์ด์ „ ๋ฒ„์ „๊ณผ ํ˜ธํ™˜๋˜๋Š” ๊ธฐ๋Šฅ ์—†์ด OpenGL ๊ธฐ๋Šฅ์˜ ๋” ์ž‘์€ ์ง‘ํ•ฉ์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Mac OS X์—์„œ๋Š” ์ดˆ๊ธฐํ™” ์ฝ”๋“œ์—glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹œ์Šคํ…œ/ํ•˜๋“œ์›จ์–ด์— OpenGL ๋ฒ„์ „ 3.3 ์ด์ƒ์ด ์„ค์น˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์ถฉ๋Œํ•˜๊ฑฐ๋‚˜ ์ •์˜๋˜์ง€ ์•Š์€ ๋™์ž‘์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ปดํ“จํ„ฐ์—์„œ OpenGL ๋ฒ„์ „์„ ์ฐพ์œผ๋ ค๋ฉด Linux ์ปดํ“จํ„ฐ์—์„œ glxinfo ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ Windows์˜ ๊ฒฝ์šฐ OpenGL Extension Viewer ์™€ ๊ฐ™์€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ง€์›๋˜๋Š” ๋ฒ„์ „์ด ๋” ๋‚ฎ์œผ๋ฉด ๋น„๋””์˜ค ์นด๋“œ๊ฐ€ OpenGL 3.3+๋ฅผ ์ง€์›ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  (๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ •๋ง ์˜ค๋ž˜๋œ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.) ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์‹ญ์‹œ์˜ค.

๋‹ค์Œ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ์ฐฝ ๊ฐœ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฐฝ ๊ฐœ์ฒด๋Š” ๋ชจ๋“  ์ฐฝ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์œ ํ•˜๋ฉฐ ๋Œ€๋ถ€๋ถ„์˜ GLFW์˜ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค


//800 600 "Learn OpenGL" ์ด๋ผ๋Š” ์ฐฝ์˜ ์œˆ๋„์šฐ. ํ•จ์ˆ˜๊ฐ€ ๊ทธ ๊ฐœ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•จ
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
    std::cout << "Failed to create GLFW window" << std::endl;
    glfwTerminate(); //์ข…๋ฃŒ
    return -1;
}
glfwMakeContextCurrent(window); //ํ˜„์žฌ ์Šค๋ ˆ๋“œ์˜ ๊ธฐ๋ณธ ์ปจํ…์ŠคํŠธ

glfwCreateWindow ํ•จ์ˆ˜๋Š” ๊ฐ๊ฐ ์ฒ˜์Œ ๋‘๊ฐœ์˜ ์ธ์ˆ˜๋กœ ์ฐฝ ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์„ธ๋ฒˆ์งธ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฐฝ์˜ ์ด๋ฆ„์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ "LearnOpenGL" ์ด๋ผ๊ณ  ๋ถ€๋ฅด์ง€๋งŒ, ์›ํ•˜๋Š”๋Œ€๋กœ ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ 2๊ฐœ์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ๋‚˜์ค‘์— ๋‹ค๋ฅธ GLFW ์ž‘์—…์— ํ•„์š”ํ•œ GLFWwindow ๊ฐœ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„ GLFW์—๊ฒŒ ์ฐฝ์˜ ์ปจํ…์ŠคํŠธ๋ฅผ ํ˜„์žฌ ์Šค๋ ˆ๋“œ์˜ ๊ธฐ๋ณธ ์ปจํ…์ŠคํŠธ๋กœ ๋งŒ๋“ค๋„๋ก ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค.

GLAD

์ด์ „ ์ฑ•ํ„ฐ์—์„œ GLAD๊ฐ€ OpenGL์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” OpenGL ํ•จ์ˆ˜๋“ค์„ ํ˜ธ์ถœํ•˜๊ธฐ ์ด์ „์— GLAD๋ฅผ ์ดˆ๊ธฐํ™” ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.


if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
    std::cout << "Failed to initialize GLAD" << std::endl;
    return -1;
}    

OS๋ณ„ OpenGL ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์˜ ์ฃผ์†Œ๋ฅผ ๋กœ๋“œ ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ GLAD์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. GLFW๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ปดํŒŒ์ผ ํ•˜๋Š” OS์— ๋”ฐ๋ผ ์˜ฌ๋ฐ”๋ฅธ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” glfwGetProcAddress๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Viewport

๋ Œ๋”๋ง์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋งˆ์ง€๋ง‰์œผ๋กœ ํ•ด์•ผ ํ•  ์ผ์ด ์žˆ์”๋‹ˆ๋‹ค. OpenGL์ด ์ฐฝ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ์™€ ์ขŒํ‘œ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ๋ Œ๋”๋ง ์ฐฝ์˜ ํฌ๊ธฐ๋ฅผ OpenGL์— ์•Œ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค. glViewport ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ด๋Ÿฌํ•œ ์น˜์ˆ˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

glViewport(0, 0, 800, 600);

glViewport์˜ ์ฒซ ๋‘ ์ธ์ž๋Š” ์ฐฝ์˜ ์™ผ์ชฝ ํ•˜๋‹จ ๋ชจ์„œ๋ฆฌ์˜ ์œ„์น˜๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์„ธ ๋ฒˆ์งธ์™€ ๋„ค ๋ฒˆ์งธ ๋งค๊ฐœ ๋ณ€์ˆ˜๋Š” ๋ Œ๋”๋ง ์ฐฝ์˜ ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ํ”ฝ์…€ ๋‹จ์œ„๋กœ ์„ค์ •ํ•˜๋ฉฐ GLFW์˜ ์ฐฝ ํฌ๊ธฐ์™€ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ๋ทฐํฌํŠธ์˜ ํฌ๊ธฐ๋ฅผ GLFW์˜ ํฌ๊ธฐ๋ณด๋‹ค ์ž‘์€ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ชจ๋“  OpenGL ๋ Œ๋”๋ง์ด ๋” ์ž‘์€ ์ฐฝ์— ํ‘œ์‹œ๋˜๊ณ  ์˜ˆ๋ฅผ ๋“ค์–ด OpenGL ๋ทฐํฌํŠธ ์™ธ๋ถ€์— ๋‹ค๋ฅธ ์š”์†Œ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์”ฌ ๋’ค์— OpenGL์€ glViewport๋ฅผ ํ†ตํ•ด ์ง€์ •๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ 2D์ขŒํ‘œ๋ฅผ ํ™”๋ฉด์˜ ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ฒ˜๋ฆฌ ๋œ ์œ„์น˜ (-0.5,0.5) ๋Š” (์ตœ์ข… ๋ณ€ํ™˜์œผ๋กœ) ํ™”๋ฉด ์ขŒํ‘œ์—์„œ (200, 450) ์— ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค. OpenGL์—์„œ ์ฒ˜๋ฆฌ ๋œ ์ขŒํ‘œ๋Š” -1๊ณผ 1 ์‚ฌ์ด์ด๋ฏ€๋กœ (-1 ~ 1) ์ด (0, 800)๊ณผ (0,600)๊นŒ์ง€์˜ ๋ฒ”์œ„๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ฐฝ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•˜๋Š” ์ˆœ๊ฐ„ ๋ทฐํฌํŠธ๋„ ์กฐ์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฐฝ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” ์ฐฝ์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํฌ๊ธฐ ์กฐ์ • ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”„๋กœํ†  ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค.

void framebuffer_size_callback(GLFWwindow* window, int width, int height);  

ํ”„๋ ˆ์ž„ ๋ฒ„ํผ ํฌ๊ธฐ ํ•จ์ˆ˜๋Š” GLFWwindow๋ฅผ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๊ณ , ์ƒˆ ์ฐฝ ํฌ๊ธฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋‘ ๊ฐœ์˜ ์ •์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฐฝ ํฌ๊ธฐ๊ฐ€ ๋ณ€๊ฒฝ ๋  ๋•Œ๋งˆ๋‹ค GLFW๋Š” ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์ฒ˜๋ฆฌ ํ•  ์ ์ ˆํ•œ ์ธ์ž๋ฅผ ์ฑ„์›๋‹ˆ๋‹ค.

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}  

์šฐ๋ฆฌ๋Š” GLFW์— ๋“ฑ๋กํ•˜์—ฌ ๋ชจ๋“  ์ฐฝ ํฌ๊ธฐ ์กฐ์ •์—์„œ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ธธ ์›ํ•œ๋‹ค๊ณ  ์•Œ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.


glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);  

์ฐฝ์ด ์ฒ˜์Œ ํ‘œ์‹œ๋˜๋ฉด framebuffer_size_callback ์ด ๊ฒฐ๊ณผ ์ฐฝ ํฌ๊ธฐ์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๋ ˆํ‹ฐ๋‚˜ ๋””์Šคํ”Œ๋ ˆ์ด์˜ ๊ฒฝ์šฐ ๋„ˆ๋น„์™€ ๋†’์ด๋Š” ์›๋ž˜ ์ž…๋ ฅ ๊ฐ’ ๋ณด๋‹ค ํ›จ์”ฌ ๋†’์•„์ง‘๋‹ˆ๋‹ค.

Ready your engines

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹จ์ผ ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋ฆฐ ๋‹ค์Œ ์ฆ‰์‹œ ์ข…๋ฃŒํ•˜๊ณ  ์ฐฝ์„ ๋‹ซ๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ๋ช…์‹œ์ ์œผ๋กœ ์ค‘์ง€ํ•˜๋ผ๋Š” ์ง€์‹œ๋ฅผ ๋ฐ›์„ ๋•Œ๊นŒ์ง€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๊ณ„์† ์ฒ˜๋ฆฌํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ด์œ ๋กœ ์šฐ๋ฆฌ๋Š” GLFW์—๊ฒŒ ์ค‘์ง€ํ•˜๋ผ๊ณ  ๋งํ•  ๋•Œ๊นŒ์ง€ ๊ณ„์† ์‹คํ–‰๋˜๋Š” ๋ Œ๋” ๋ฃจํ”„๋ผ๊ณ  ๋ถ€๋ฅด๋Š” while ๋ฃจํ”„๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•œ ๋ Œ๋”๋ง ๋ฃจํ”„๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

while(!glfwWindowShouldClose(window))
{
    glfwSwapBuffers(window);
    glfwPollEvents();    
}

glfwWindowShouldClose ํ•จ์ˆ˜๋Š” GLFW๊ฐ€ ๋‹ซํžˆ๋„๋ก ์ง€์‹œ๋˜์—ˆ๋Š”์ง€ ๊ฐ ๋ฃจํ”„ ๋ฐ˜๋ณต์˜ ์‹œ์ž‘์—์„œ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๊ทธ๋ ‡๋‹ค๋ฉด ํ•จ์ˆ˜๋Š” true ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ Œ๋”๋ง ๋ฃจํ”„ ์‹คํ–‰์ด ์ค‘์ง€ ๋œ ํ›„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

glfwPollEvents ํ•จ์ˆ˜๋Š” (ํ‚ค๋ณด๋“œ ์ž…๋ ฅ ๋˜๋Š” ๋งˆ์šฐ์Šค ์ด๋™ ์ด๋ฒคํŠธ์™€ ๊ฐ™์€) ์ด๋ฒคํŠธ๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์ฐฝ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉฐ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค (์ฝœ๋ฐฑ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Œ). glfwSwapBuffers๋Š” ์ด ๋ Œ๋”๋ง ๋ฐ˜๋ณต์ค‘์— ๋ Œ๋”๋งํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ƒ‰์ƒ ๋ฒ„ํผ(GLFW ์ฐฝ์˜ ๊ฐ ํ”ฝ์…€์— ๋Œ€ํ•œ ์ƒ‰์ƒ ๊ฐ’์„ ํฌํ•จํ•˜๋Š” ํฐ 2D ๋ฒ„ํผ)๋ฅผ ๊ณ ์ฒดํ•˜๊ณ  ํ™”๋ฉด์— ์ถœ๋ ฅ์œผ๋กœ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

Double buffer ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ๋‹จ์ผ ๋ฒ„ํผ์— ๊ทธ๋ฆด ๋•Œ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€์— ๊นœ๋ฐ•์ž„ ๋ฌธ์ œ๊ฐ€ ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฒฐ๊ณผ ์ถœ๋ ฅ ์ด๋ฏธ์ง€๊ฐ€ ์ˆœ์‹๊ฐ„์— ๊ทธ๋ ค์ง€์ง€ ์•Š๊ณ  ํ”ฝ์…€ ๋‹จ์œ„๋กœ ๊ทธ๋ ค์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์™ผ์ชฝ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ, ์œ„์—์„œ ์•„๋ž˜๋กœ ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค. ์ด ์ด๋ฏธ์ง€๋Š” ๋ Œ๋”๋ง๋˜๋Š” ๋™์•ˆ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฆ‰์‹œ ํ‘œ์‹œ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ฒฐ๊ณผ์— ์•„ํ‹ฐํŒฉํŠธ(๋ˆˆ์— ๋ณด์ผ ์ •๋„๋กœ ์ด์ƒํ•œ๊ฑฐ)๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์”๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์œˆ๋„์šฐ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ๋ Œ๋”๋ง์— ์ด์ค‘ ๋ฒ„ํผ๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ ๋ฒ„ํผ์—๋Š” ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ์ตœ์ข… ๊ฒฐ๊ณผ๋งŒ ๊ทธ๋ ค์ฃผ๊ณ , ๋ชจ๋“  ๋ Œ๋”๋ง ๋ช…๋ น์€ ๋ฐฑ ๋ฒ„ํผ๋กœ ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ Œ๋”๋ง ๋ช…๋ น์ด ์™„๋ฃŒ ๋˜์ž๋ง์ž ๋ฒก ๋ฒ„ํผ๋ฅผ ํ”„๋ก ํŠธ ๋ฒ„ํผ๋กœ ๊ต์ฒดํ•˜์—ฌ ์ด๋ฏธ์ง€๊ฐ€ ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๊ณ  ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ๋„๋ก ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๋ชจ๋“  ์•„ํ‹ฐํŒฉํŠธ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

One last thing

๋ Œ๋”๋ง ๋ฃจํ”„๋ฅผ ์ข…๋ฃŒํ•˜์ž ๋ง์ž ํ• ๋‹น ๋œ ๋ชจ๋“  GLFW ๋ฆฌ์†Œ์Šค๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ •๋ฆฌ/์‚ญ์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. mainํ•จ์ˆ˜ ๋์—์„œ ํ˜ธ์ถœํ•˜๋Š” glfwTerminateํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

glfwTerminate();
return 0;

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๊ฐ€ ์ •๋ฆฌ๋˜๊ณ  ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์ œ๋Œ€๋กœ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๊ณ  ๋ชจ๋“  ๊ฒƒ์ด ์ž˜๋˜๋ฉด ๋‹ค์Œ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

hellowindow

๋งค์šฐ ์ง€๋ฃจํ•˜๊ณ  ์ง€๋ฃจํ•œ ๊ฒ€์ •์ƒ‰ ์ด๋ฏธ์ง€๋ผ๋ฉด ์ œ๋Œ€๋กœ ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค! ์˜ฌ๋ฐ”๋ฅธ ์ด๋ฏธ์ง€๋ฅผ ์–ป์ง€ ๋ชปํ–ˆ๊ฑฐ๋‚˜ ๋ชจ๋“  ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์กฐํ™”๋ฅผ ์ด๋ฃจ๋Š” ์ง€ ํ˜ผ๋ž€์Šค๋Ÿฌ์šฐ๋ฉด ์ „์ฒด ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋จผ์ € ๋ชจ๋“  ๋ง์ปค ์˜ต์…˜์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋˜์–ด ์žˆ๊ณ  IDE์— ์˜ฌ๋ฐ”๋ฅธ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํฌํ•จํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”(์ด์ „ ์žฅ์— ์žˆ์Œ). ๋˜ํ•œ ์ฝ”๋“œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜์„ธ์š”. ์ „์ฒด ์†Œ์Šค ์ฝ”๋“œ์™€ ๋น„๊ตํ•˜์—ฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Input

๋˜ํ•œ GLFW์—์„œ ์–ด๋–ค ํ˜•ํƒœ์˜ ์ž…๋ ฅ ์ œ์–ด๋ฅผ ์›ํ•˜๋ฉฐ GLFW์˜ ์—ฌ๋Ÿฌ ์ž…๋ ฅ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ฐฝ์„ ํ‚ค์™€ ํ•จ๊ป˜ ์ž…๋ ฅ์œผ๋กœ ์ทจํ•˜๋Š” GLFW์˜ glfwGetKEy ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ์ด ํ‚ค๊ฐ€ ํ˜„์žฌ ๋ˆŒ๋Ÿฌ์ ธ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์ž…๋ ฅ์ฝ”๋“œ๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด processInput ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

void processInput(GLFWwindow *window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

์—ฌ๊ธฐ์„œ ์‚ฌ์šฉ์ž๊ฐ€ ESC ํ‚ค๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. (๋ˆ„๋ฅด์ง€ ์•Š์œผ๋ฉด glfwGetKey๋Š” GLFW_RELEASE๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค) ์‚ฌ์šฉ์ž๊ฐ€ ESCํ‚ค๋ฅผ ๋ˆŒ๋ €๋‹ค๋ฉด glfwSetWindowShouldClose๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ WindowShouldClose ์†์„ฑ์„ true ๋กœ ์„ค์ •ํ•˜์—ฌ GLFW๋ฅผ ๋‹ซ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ฉ”์ธ while ๋ฃจํ”„์˜ ๋‹ค์Œ ์กฐ๊ฑด ๊ฒ€์‚ฌ๊ฐ€ ์‹คํŒจํ•˜๊ณ  ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ๋‹ซํž™๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ Œ๋”๋ง ๋ฃจํ”„๊ฐ€ ๋ฐ˜๋ณต ๋ ๋•Œ๋งˆ๋‹ค processInput์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

while (!glfwWindowShouldClose(window))
{
    processInput(window);

    glfwSwapBuffers(window);
    glfwPollEvents();
}  

์ด๋ฅผ ํ†ตํ•ด ํŠน์ • ํ‚ค๊ฐ€ ๋ˆŒ๋Ÿฌ์กŒ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ๋ชจ๋“  ํ”„๋ ˆ์ž„์— ๋”ฐ๋ผ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ Œ๋”๋ง ๋ฃจํ”„์˜ ๋ฐ˜๋ณต์€ ์ผ๋ฐ˜์ ์œผ๋กœ ํ”„๋ ˆ์ž„์ด๋ผ๊ณ  ๋ถˆ๋ฆฝ๋‹ˆ๋‹ค.

Rendering

๋ฃจํ”„์˜ ๊ฐ ๋ฐ˜๋ณต ๋˜๋Š” ํ”„๋ ˆ์ž„๋งˆ๋‹ค ๋ชจ๋“  ๋ Œ๋”๋ง ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๋ Œ๋”๋ง ๋ช…๋ น์„ ๋ Œ๋”๋ง ๋ฃจํ”„์— ๋ฐฐ์น˜ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ๊ฒ๋‹ˆ๋‹ค.

// ๋ Œ๋”๋ง ๋ฃจํ”„
while(!glfwWindowShouldClose(window))
{
    // ์ž…๋ ฅ
    processInput(window);

    // ๋ Œ๋”๋ง ์ปค๋งจ๋“œ
    ...

		// ์ด๋ฒคํŠธ๋ฅผ ์ฒดํฌํ•˜๊ณ  ํ˜ธ์ถœํ•˜๊ณ  ๋ฒ„ํผ๋ฅผ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค.
    glfwPollEvents();
    glfwSwapBuffers(window);
}

์‹ค์ œ๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•ด ์„ ํƒํ•œ ์ƒ‰์ƒ์œผ๋กœ ํ™”๋ฉด์„ ์ง€์šฐ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ด์ „ ํ”„๋ ˆ์ž„์˜ ๊ฒฐ๊ณผ๊ฐ€ ๊ณ„์† ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค (์›ํ•˜๋Š” ํšจ๊ณผ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.) glClear๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™”๋ฉด์˜ ์ƒ‰์ƒ ๋ฒ„ํผ๋ฅผ ์ง€์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฒ„ํผ ๋น„ํŠธ๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ์ง€์šธ ๋ฒ„ํผ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋น„ํŠธ๋Š” GL_COLOR_BUFFER_BIT , GL_DEPTH_BUFFER_BIT ๊ทธ๋ฆฌ๊ณ  GL_STENCIL_BUFFER_BIT ์ž…๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์ƒ‰์ƒ ๊ฐ’๋งŒ ๊ณ ๋ คํ•˜๋ฏ€๋กœ ์ƒ์ƒ ๋ฒ„ํผ๋ฅผ ์ง€์›๋‹ˆ๋‹ค.

glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glClearColor๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ™”๋ฉด์„ ์ง€์šฐ๋Š” ์ƒ‰์ƒ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. glClear๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์ƒ์ƒ ๋ฒ„ํผ๋ฅผ ์ง€์šธ ๋•Œ๋งˆ๋‹ค ์ „์ฒด ์ƒ์ƒ ๋ฒ„ํผ๊ฐ€ glClearColor์— ์˜ํ•ด ๊ตฌ์„ฑ๋œ ์ƒ‰์ƒ์œผ๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ง™์€ ์ฒญ๋ก์ƒ‰์ด ๋ฉ๋‹ˆ๋‹ค.

OpenGL ์ฑ•ํ„ฐ์—์„œ ๊ธฐ์–ตํ•  ์ˆ˜ ์žˆ๋“ฏ์ด glClearColor ํ•จ์ˆ˜๋Š” ์ƒํƒœ์ง€์ • ํ•จ์ˆ˜์ด๊ณ  glClear๋Š” ํ˜„์žฌ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ฆฌ์–ด๋ง ์ƒ‰์ƒ์„ ๊ฒ€์ƒ‰ํ•œ๋‹ค๋Š” ์ ์—์„œ ์ƒํƒœ์‚ฌ์šฉ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

hellowindow2

์ „์ฒด ์†Œ์Šค ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ง€๊ธˆ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ์ฑ•ํ„ฐ๋ฅผ ์œ„ํ•œ ๋งŽ์€ ๋ Œ๋”๋ง ํ˜ธ์ถœ๋กœ ๋ Œ๋”๋ง ๋ฃจํ”„๋ฅผ ์ฑ„์šธ ๋ชจ๋“  ์ค€๋น„๋ฅผ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค,