GLUT(freeglut)으로 간단한 OpenGL 예제 만들기
OpenGL 2019. 11. 24. 18:33 |freeglut을 설치하고 간단한 OpenGL 예제를 만들어 보자.
http://freeglut.sourceforge.net/ 에서 MSVC용 Prepackaged Release 를 다운 받아 원하는 폴더에 설치 한다.
빈 Console 프로젝트를 만든다.
freeglut 라이브러리의 dll 파일이 있는 폴더를 Environment에 지정 한다.
Include 디렉토리를 지정 한다.
sprintf() 사용을 위해 SDL checks를 No로 바꾼다. Yes로 된 경우 비표준 함수인 sprintf_s()를 써야 한다.
SDL checks: Adds recommended Security Development Lifecycle (SDL) checks. These checks include extra security-relevant warnings as errors, and additional secure code-generation features.
Library 디렉토리를 지정 한다.
외부 라이브러리 사용시 위 사진과 같이 라이브러리 파일들을 추가해야 하지만 freeglut_std.h에 필요한 라이브러리가 모두 추가 되어 있으므로 하지 않아도 된다.
<freeglut_std.h>
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 | # include <windows.h> /* Windows static library */ # ifdef FREEGLUT_STATIC #error Static linking is not supported with this build. Please remove the FREEGLUT_STATIC preprocessor directive, or download the source code from http://freeglut.sf.net/ and build against that. /* Windows shared library (DLL) */ # else # define FGAPIENTRY __stdcall # if defined(FREEGLUT_EXPORTS) # define FGAPI __declspec(dllexport) # else # define FGAPI __declspec(dllimport) /* Link with Win32 shared freeglut lib */ # if FREEGLUT_LIB_PRAGMAS # pragma comment (lib, "freeglut.lib") # endif # endif # endif /* Drag in other Windows libraries as required by FreeGLUT */ # if FREEGLUT_LIB_PRAGMAS # pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */ # pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */ # pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */ # pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */ # pragma comment (lib, "user32.lib") /* link Windows user lib */ # endif #else /* Non-Windows definition of FGAPI and FGAPIENTRY */ # define FGAPI # define FGAPIENTRY #endif |
windows.h 도 포함 되어 있다.
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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | #include <gl/glut.h> #include <cstdio> GLfloat locationX = 0.0f, locationY = 0.0f; const GLfloat step = 0.02f; const GLfloat size = 0.2f; int winId; void Menu(int value); void Keyboard(unsigned char key, int x, int y); void Special(int key, int x, int y); void Mouse(int button, int state, int x, int y); void Display(); int main(int argc, char** argv) { glutInit(&argc, argv); winId = glutCreateWindow("OpenGL"); glutKeyboardFunc(Keyboard); glutSpecialFunc(Special); glutMouseFunc(Mouse); // Sub menu GLint SubMenu = glutCreateMenu(Menu); glutAddMenuEntry("Red", 4); glutAddMenuEntry("Green", 5); glutAddMenuEntry("Blue", 6); // Menu glutCreateMenu(Menu); glutAddMenuEntry("White", 1); glutAddMenuEntry("Black", 2); glutAddMenuEntry("Gray", 3); // Add sub menu glutAddSubMenu("Triangle Color", SubMenu); glutAttachMenu(GLUT_RIGHT_BUTTON); glutDisplayFunc(Display); glutMainLoop(); return 0; } void Menu(int value) { switch (value) { case 1: glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // 배경 흰색 break; case 2: glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 배경 검정색 break; case 3: glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // 배경 회색 break; case 4: glColor3f(1.0f, 0.0f, 0.0f); // 삼감형 빨간색 break; case 5: glColor3f(0.0f, 1.0f, 0.0f); // 삼감형 녹색 break; case 6: glColor3f(0.0f, 0.0f, 1.0f); // 삼감형 파란색 break; default: break; } glutPostRedisplay(); } void Keyboard(unsigned char key, int x, int y) { switch (key) { case 'r': case 'R': glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // 배경 빨간색 break; case 'g': case 'G': glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // 배경 녹색 break; case 'b': case 'B': glClearColor(0.0f, 0.0f, 1.0f, 1.0f); // 배경 파란색 break; case 27: glutDestroyWindow(winId); // ESC키 프로그램 종료 exit(0); break; default: break; } glutPostRedisplay(); } void Special(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: // step 만큼 x감소 locationX -= step; break; case GLUT_KEY_RIGHT: // step 만큼 x증가 locationX += step; break; case GLUT_KEY_UP: // step 만큼 y증가 locationY += step; break; case GLUT_KEY_DOWN: // step 만큼 y감소 locationY -= step; break; } char title[128] = {0,}; sprintf(title, "Triangle location (%.2f, y=%.2f)", locationX, locationY); glutSetWindowTitle(title); // 제목표시줄에 삼각형 좌표 표시 glutPostRedisplay(); } void Mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { glColor3f(0.0f, 1.0f, 1.0f); // 삼각형 하늘색 char title[128] = { 0, }; sprintf(title, "Click (x: %d, y: %d)", x, y); glutSetWindowTitle(title); // 제목표시줄에 클릭 좌표 표시 glutPostRedisplay(); } else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP){ glColor3f(1.0f, 1.0f, 0.0f); // 삼각형 노란색 glutPostRedisplay(); } } void Display() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); glVertex2f(locationX, locationY + size); glVertex2f(locationX - size, locationY - size); glVertex2f(locationX + size, locationY - size); glEnd(); glFinish(); } |
코드를 입력하고 실행 한다.
오른쪽 버튼을 클릭하면 메뉴가 나온다.
삼각형이 빨간색으로 바뀌었다.
r,g,b, 방향키, ESC키 등을 눌러 본다.
SubSystem을Console에서 Widows로 바꾼다.
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 | #include <gl/glut.h> void Menu(int value) { switch (value) { case 1: glClearColor(1.0f, 1.0f, 1.0f, 1.0f); break; case 2: glClearColor(0.0f, 0.0f, 0.0f, 1.0f); break; case 3: glClearColor(0.5f, 0.5f, 0.5f, 1.0f); break; case 4: glColor3f(1.0f, 0.0f, 0.0f); break; case 5: glColor3f(0.0f, 1.0f, 0.0f); break; case 6: glColor3f(0.0f, 0.0f, 1.0f); break; default: break; } glutPostRedisplay(); } void display() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); glVertex2f(0.0f, 0.5f); glVertex2f(-0.5f, -0.5f); glVertex2f(0.5f, -0.5f); glEnd(); glFinish(); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { glutCreateWindow("OpenGL"); // Sub menu GLint SubMenu = glutCreateMenu(Menu); glutAddMenuEntry("Red", 4); glutAddMenuEntry("Green", 5); glutAddMenuEntry("Blue", 6); // Menu glutCreateMenu(Menu); glutAddMenuEntry("White", 1); glutAddMenuEntry("Black", 2); glutAddMenuEntry("Gray", 3); // Add sub menu glutAddSubMenu("Triangle Color", SubMenu); glutAttachMenu(GLUT_RIGHT_BUTTON); glutDisplayFunc(display); glutMainLoop(); return 0; } |
위 코드와 같이 Windows 프로그램에 맞게 바꾸고 빌드하면 에러없이 빌드는 되지만 아무것도 실행 되지는 않는다.
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 106 107 108 109 110 111 112 113 114 115 116 | #include <Windows.h> #include <gl/gl.h> # pragma comment (lib, "opengl32.lib") # pragma comment(lib, "glu32.lib") HINSTANCE g_hInst; HWND hWndMain; LPCTSTR lpszClass = TEXT("OpenGL"); HDC hdc; HGLRC hrc; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void Display(); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { HWND hWnd; MSG Message; WNDCLASS WndClass; g_hInst = hInstance; WndClass.cbClsExtra = 0; WndClass.cbWndExtra = 0; WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClass.hInstance = hInstance; WndClass.lpfnWndProc = WndProc; WndClass.lpszClassName = lpszClass; WndClass.lpszMenuName = NULL; WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; RegisterClass(&WndClass); hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); while (GetMessage(&Message, NULL, 0, 0)) { TranslateMessage(&Message); DispatchMessage(&Message); } return (int)Message.wParam; } void Display() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_TRIANGLES); glVertex2f(0.0f, 0.5f); glVertex2f(-0.5f, -0.5f); glVertex2f(0.5f, -0.5f); glEnd(); glFinish(); } LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { case WM_CREATE: hWndMain = hWnd; PIXELFORMATDESCRIPTOR pfd; int nPixelFormat; hdc = GetDC(hWnd); memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 32; nPixelFormat = ChoosePixelFormat(hdc, &pfd); SetPixelFormat(hdc, nPixelFormat, &pfd); hrc = wglCreateContext(hdc); wglMakeCurrent(hdc, hrc); return 0; case WM_PAINT: Display(); SetTextColor(hdc, RGB(255, 255, 0)); SetBkMode(hdc, TRANSPARENT); TextOutA(hdc, 10, 10, "Windows OpenGL", 14); ValidateRect(hWnd, NULL); return 0; case WM_SIZE: glViewport(0, 0, LOWORD(lParam), HIWORD(lParam)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1, 1, -1, 1, 1, -1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return 0; case WM_DESTROY: wglMakeCurrent(hdc, NULL); wglDeleteContext(hrc); ReleaseDC(hWnd, hdc); PostQuitMessage(0); return 0; } return(DefWindowProc(hWnd, iMessage, wParam, lParam)); } |
glut을 사용하지 않고 Windows에서 지원하는 OpenGL 관련 wgl함수를 이용해 작성한 코드이다.
※ Reference
http://soen.kr/lecture/library/opengl/opengl-5.htm
'OpenGL' 카테고리의 다른 글
Boundary and nonboundary edge flags 다각형의 경계선 설정하기 (0) | 2019.12.20 |
---|---|
Simple Solar System 간단한 태양계 그리기 (4) | 2019.12.17 |
Rotation 회전 (0) | 2019.12.13 |
Keeping the aspect ratio 종횡비 유지하기 (0) | 2019.12.12 |