- 아래 코드들은 인프런의 게임 개발자를 위한 3D 그래픽스, 쉐이더, OpenGL 의 강의에서 사용한 코드들입니다
- 모든 저작권은 드립커피 + 한모금더 님께 있습니다
1. hello-glfw.c
#include <GLFW/glfw3.h> // GLFW 라이브러리를 사용하기 위한 헤더 파일 포함
#pragma comment(lib, "glfw3.lib") // 링크할 라이브러리 지정
const unsigned int WIN_W = 500; // 창의 너비 (픽셀 단위)
const unsigned int WIN_H = 500; // 창의 높이 (픽셀 단위)
int main(void) {
// GLFW 초기화
glfwInit();
// 새로운 창 생성 (너비, 높이, 창 제목, 모니터, 공유 컨텍스트)
GLFWwindow* window = glfwCreateWindow(WIN_W, WIN_H, "Hello GLFW", NULL, NULL);
// 생성한 창의 컨텍스트를 현재 컨텍스트로 설정
glfwMakeContextCurrent(window);
// 메인 루프
while (!glfwWindowShouldClose(window)) {
// 이벤트 처리
glfwPollEvents();
}
// GLFW 종료 및 자원 해제
glfwTerminate();
return 0; // 프로그램 정상 종료
}
### 코드 해석
1. **헤더 파일 포함 및 라이브러리 링크**
- `#include <GLFW/glfw3.h>`: OpenGL을 사용하기 위해 필요한 GLFW 라이브러리의 헤더 파일을 포함합니다.
- `#pragma comment(lib, "glfw3.lib")`: 링크할 라이브러리를 지정합니다. 이 지시어는 특정 라이브러리를 링커에 포함시킵니다.
2. **윈도우 크기 상수 정의**
- `const unsigned int WIN_W = 500;`: 창의 너비를 500 픽셀로 설정합니다.
- `const unsigned int WIN_H = 500;`: 창의 높이를 500 픽셀로 설정합니다.
3. **`main` 함수**
- `glfwInit()`: GLFW 라이브러리를 초기화합니다.
- `glfwCreateWindow(WIN_W, WIN_H, "Hello GLFW", NULL, NULL)`: 주어진 너비와 높이로 창을 생성하고, 제목을 "Hello GLFW"로 설정합니다. 모니터와 공유 컨텍스트는 `NULL`로 설정합니다.
- `glfwMakeContextCurrent(window)`: 생성한 창의 OpenGL 컨텍스트를 현재 컨텍스트로 만듭니다.
- `while (!glfwWindowShouldClose(window))`: 창이 닫히지 않는 동안 반복하는 루프입니다. 이 루프 내에서 이벤트를 처리합니다.
- `glfwPollEvents()`: 모든 대기 중인 이벤트를 처리합니다.
- `glfwTerminate()`: GLFW를 종료하고 할당된 자원을 해제합니다.
- `return 0;`: 프로그램을 정상 종료합니다.
이 코드는 기본적으로 500x500 픽셀 크기의 창을 생성하고, 사용자가 창을 닫기 전까지 이벤트를 계속 처리하는 간단한 GLFW 프로그램입니다. OpenGL 렌더링이나 그래픽 작업을 추가하기 위한 기본 틀로 사용될 수 있습니다.
2. hello-glew.c
#include <GL/glew.h> // GLEW 라이브러리를 사용하기 위한 헤더 파일 포함
#include <GLFW/glfw3.h> // GLFW 라이브러리를 사용하기 위한 헤더 파일 포함
#pragma comment(lib, "opengl32.lib") // OpenGL 라이브러리 링크
#pragma comment(lib, "glew32.lib") // GLEW 라이브러리 링크
#pragma comment(lib, "glfw3.lib") // GLFW 라이브러리 링크
#include <stdio.h> // 표준 입출력 라이브러리 포함
const unsigned int WIN_W = 500; // 창의 너비 (픽셀 단위)
const unsigned int WIN_H = 500; // 창의 높이 (픽셀 단위)
int main(void) {
// GLFW 초기화
glfwInit();
// 새로운 창 생성 (너비, 높이, 창 제목, 모니터, 공유 컨텍스트)
GLFWwindow* window = glfwCreateWindow(WIN_W, WIN_H, "Hello GLEW", NULL, NULL);
// 생성한 창의 컨텍스트를 현재 컨텍스트로 설정
glfwMakeContextCurrent(window);
// GLEW 초기화
glewInit();
// OpenGL 버전 확인 (선택적)
const char* strVersion = (const char*)(glGetString(GL_VERSION));
printf("version = %s\n", strVersion); // OpenGL 버전 출력
fflush(stdout); // 출력 버퍼 비우기
// 메인 루프
while (!glfwWindowShouldClose(window)) {
// 화면 지우기
glClear(GL_COLOR_BUFFER_BIT);
// 프레임 버퍼 교환
glfwSwapBuffers(window);
// 이벤트 처리
glfwPollEvents();
}
// GLFW 종료 및 자원 해제
glfwTerminate();
return 0; // 프로그램 정상 종료
}
### 코드 해석
1. **헤더 파일 포함 및 라이브러리 링크**
- `#include <GL/glew.h>`: GLEW 라이브러리를 사용하기 위한 헤더 파일을 포함합니다.
- `#include <GLFW/glfw3.h>`: GLFW 라이브러리를 사용하기 위한 헤더 파일을 포함합니다.
- `#pragma comment(lib, "opengl32.lib")`: OpenGL 라이브러리를 링커에 포함시킵니다.
- `#pragma comment(lib, "glew32.lib")`: GLEW 라이브러리를 링커에 포함시킵니다.
- `#pragma comment(lib, "glfw3.lib")`: GLFW 라이브러리를 링커에 포함시킵니다.
- `#include <stdio.h>`: 표준 입출력 라이브러리를 포함합니다.
2. **윈도우 크기 상수 정의**
- `const unsigned int WIN_W = 500;`: 창의 너비를 500 픽셀로 설정합니다.
- `const unsigned int WIN_H = 500;`: 창의 높이를 500 픽셀로 설정합니다.
3. **`main` 함수**
- `glfwInit()`: GLFW 라이브러리를 초기화합니다.
- `glfwCreateWindow(WIN_W, WIN_H, "Hello GLEW", NULL, NULL)`: 주어진 너비와 높이로 창을 생성하고, 제목을 "Hello GLEW"로 설정합니다. 모니터와 공유 컨텍스트는 `NULL`로 설정합니다.
- `glfwMakeContextCurrent(window)`: 생성한 창의 OpenGL 컨텍스트를 현재 컨텍스트로 만듭니다.
- `glewInit()`: GLEW 라이브러리를 초기화합니다.
- `glGetString(GL_VERSION)`: 현재 OpenGL 버전을 문자열로 가져옵니다.
- `printf("version = %s\n", strVersion)`: OpenGL 버전을 출력합니다.
- `fflush(stdout)`: 출력 버퍼를 비웁니다.
- `while (!glfwWindowShouldClose(window))`: 창이 닫히지 않는 동안 반복하는 메인 루프입니다.
- `glClear(GL_COLOR_BUFFER_BIT)`: 컬러 버퍼를 지웁니다.
- `glfwSwapBuffers(window)`: 프레임 버퍼를 교환하여 화면에 그린 내용을 표시합니다.
- `glfwPollEvents()`: 모든 대기 중인 이벤트를 처리합니다.
- `glfwTerminate()`: GLFW를 종료하고 할당된 자원을 해제합니다.
- `return 0;`: 프로그램을 정상 종료합니다.
이 코드는 500x500 픽셀 크기의 창을 생성하고, GLEW와 GLFW를 초기화한 뒤, OpenGL 버전을 출력합니다. 메인 루프에서는 컬러 버퍼를 지우고, 프레임 버퍼를 교환하며, 이벤트를 처리합니다. 사용자가 창을 닫을 때까지 이러한 작업을 반복합니다. OpenGL을 이용한 그래픽 작업을 추가하기 위한 기본 틀로 사용될 수 있습니다.
- #include 와 #pragment의 차이
- **`#include`**: 헤더 파일을 포함시켜 함수 선언과 타입을 사용할 수 있게 합니다.
- **`#pragma comment(lib, "라이브러리명")`**: 링커에게 특정 라이브러리를 포함시키라고 지시합니다.
예를 들어:
- `#include <GL/glew.h>`: GLEW 함수와 타입을 사용할 수 있게 합니다.
- `#pragma comment(lib, "glew32.lib")`: GLEW 함수의 실제 구현을 포함시킵니다.
즉, `#include`는 코딩을 위해 필요한 함수 선언을 가져오고, `#pragma comment(lib, ...)`는 실행 파일을 만들기 위해 필요한 함수 구현을 포함시킵니다.
- fflush (stdout) 이해
`fflush(stdout)`는 출력 버퍼를 비우는 역할을 합니다. 프로그램에서 무언가를 출력할 때, 그 내용이 실제로 화면에 표시되기 전에 잠시 기다리는 과정이 있어요. 이때, 출력 함수를 호출하면 내용이 버퍼에 저장되어 기다리게 됩니다. 그래서 이 내용을 즉시 화면에 출력하고 싶을 때 사용되는게 `fflush(stdout)`입니다. 그렇게 하면 버퍼에 있는 내용이 즉시 화면에 출력되어요.
간단한 예시를 들어보면, "Hello"라는 메시지를 출력한 후 바로 "World!"를 출력하고 싶을 때 사용할 수 있어요. 만약 `fflush(stdout)`를 사용하지 않으면 "Hello"와 "World!"가 함께 출력될 것이에요. 하지만 `fflush(stdout)`를 사용하면 "Hello"가 먼저 출력되고, 바로 다음에 "World!"가 출력됩니다.
- glfwSwapBuffers(window) 이해
`glfwSwapBuffers(window)` 함수는 더블 버퍼링(Double Buffering)을 사용하는 그래픽 애플리케이션에서 중요한 역할을 합니다.
1. **백 버퍼에 그림 그리기**:
- 우리는 실제 화면에 표시되는 프론트 버퍼가 아닌 백 버퍼에 그림을 그립니다. 이렇게 하면 사용자는 화면에서 깜빡임 없이 부드러운 그림을 볼 수 있습니다.
2. **프론트와 백 버퍼 교환**:
- `glfwSwapBuffers(window)` 함수를 호출하면 백 버퍼의 내용이 프론트 버퍼로 옮겨지게 됩니다. 이제 그린 그림이 실제 화면에 표시됩니다.
3. **새로운 그림 그리기**:
- 이제 백 버퍼는 비어있게 되었고, 우리는 새로운 그림을 백 버퍼에 그릴 준비를 할 수 있습니다.
간단히 말하자면, `glfwSwapBuffers(window)` 함수는 그린 그림을 실제 화면에 보여주는 역할을 합니다. 이 과정을 반복하면 사용자는 화면에 부드럽게 업데이트되는 그림을 볼 수 있습니다.
3. refresh.c
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#pragma comment(lib, "opengl32.lib") // Windows에서 OpenGL 라이브러리를 링크하기 위한 pragma
#pragma comment(lib, "glew32.lib") // GLEW 라이브러리를 링크하기 위한 pragma
#pragma comment(lib, "glfw3.lib") // GLFW 라이브러리를 링크하기 위한 pragma
#pragma warning(disable: 4711 4710 4100) // 경고를 무시하기 위한 pragma
#include <stdio.h>
#include <string.h> // strrchr() 함수를 사용하기 위한 헤더 파일
const unsigned int WIN_W = 500; // 창의 너비 (픽셀 단위)
const unsigned int WIN_H = 500; // 창의 높이 (픽셀 단위)
const unsigned int WIN_X = 100; // 창의 X 좌표 (픽셀 단위)
const unsigned int WIN_Y = 100; // 창의 Y 좌표 (픽셀 단위)
void refreshFunc(GLFWwindow* window) {
// 화면을 새로 고칠 때 호출되는 콜백 함수
printf("새로고침 호출됨\n"); // 디버그용 메시지 출력
fflush(stdout); // 표준 출력 버퍼를 비워줌
glClear(GL_COLOR_BUFFER_BIT); // 색상 버퍼를 지워 이전 프레임의 내용을 지움
glFinish(); // 모든 OpenGL 명령이 완료될 때까지 기다림
glfwSwapBuffers(window); // 프레임 버퍼를 스왑하여 이전 프레임의 내용을 화면에 표시
}
int main(int argc, char* argv[]) {
// 프로그램 이름 가져오기
#if defined(_WIN32) || defined(_WIN64)
char* win_name = (strrchr(argv[0], '\\') == NULL) ? argv[0] : (strrchr(argv[0], '\\') + 1);
#else // Unix, Linux, MacOS
char* win_name = (strrchr(argv[0], '/') == NULL) ? argv[0] : (strrchr(argv[0], '/') + 1);
#endif
// GLFW 및 GLEW 시작
glfwInit(); // GLFW 라이브러리 초기화
GLFWwindow* window = glfwCreateWindow(WIN_W, WIN_H, win_name, NULL, NULL); // 창 생성
glfwSetWindowPos(window, WIN_X, WIN_Y); // 창 위치 설정
glfwMakeContextCurrent(window); // OpenGL 컨텍스트 생성
glewInit(); // GLEW 초기화
// 준비 작업
glfwSetWindowRefreshCallback(window, refreshFunc); // 화면 새로 고침 콜백 함수 설정
glClearColor(0.5F, 0.8F, 0.8F, 1.0F); // 화면을 지울 색상 설정 (RGBA)
// 메인 루프
while (!glfwWindowShouldClose(window)) { // 창이 닫힐 때까지 반복
glClear(GL_COLOR_BUFFER_BIT); // 색상 버퍼를 지워 이전 프레임의 내용을 지움
glFinish(); // 모든 OpenGL 명령이 완료될 때까지 기다림
glfwSwapBuffers(window); // 프레임 버퍼를 스왑하여 이전 프레임의 내용을 화면에 표시
glfwPollEvents(); // 이벤트를 처리하고 상태를 업데이트
}
// 완료
glfwTerminate(); // GLFW 종료
return 0;
}
OpenGL과 GLFW를 사용하여 창을 생성하고 그 창에 색을 채우는 간단한 프로그램입니다.
- **라이브러리 및 헤더 파일 포함**: OpenGL 및 GLFW 라이브러리를 사용하기 위한 헤더 파일을 포함하고 있습니다.
- **상수 정의**: 창의 크기와 위치를 상수로 정의하고 있습니다.
- **refreshFunc 함수**: 이 함수는 화면을 새로 고칠 때 호출됩니다. 화면을 지우고 새로 고친 후 바뀐 내용을 화면에 표시합니다.
- **메인 함수**:
- 프로그램 이름을 가져오고, GLFW 및 GLEW를 초기화하며, 창을 생성하고 위치를 설정합니다.
- 화면을 지울 색상을 설정하고, 화면 새로 고침 콜백 함수를 등록합니다.
- 메인 루프에서는 창이 닫힐 때까지 화면을 지우고 새로 고친 후 이벤트를 처리합니다.
- 마지막으로 GLFW를 종료하고 프로그램을 종료합니다.
이 코드는 OpenGL을 사용하여 간단한 그래픽 애플리케이션을 작성하는 기본적인 방법을 보여줍니다.
'컴퓨터 그래픽스 > OpenGL' 카테고리의 다른 글
OpenGL ft. Visual Studio Community (0) | 2024.04.10 |
---|---|
OpenGL ft. Visual Studio Code (0) | 2024.04.10 |
OpenGL 강의 (0) | 2024.04.10 |
OpenGL 블로그 정리 (0) | 2024.04.06 |
OpenGL 실습 환경 만들기 (0) | 2024.03.19 |