라이브러리 속성 설정 및 // 복붙용
요거 할때 debug나 release만 하면 안되고 두개 다
// 01_renderWindow.cpp : 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include "01_renderWindow.h"
#include <gl/GL.h>
#include <gl/GLU.h>
#define MAX_LOADSTRING 100
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
TCHAR szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
TCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
//우리가 추가
HGLRC hRC = NULL; //렌더링 컨텍스트(3d)
HDC hDC = NULL; //핸들 디바이스 컨텍스트 ....GDI 장치 컨텍스트
float angle = 0.0f;
// 이 코드 모듈에 들어 있는 함수의 정방향 선언입니다.
ATOM MyRegisterClass(HINSTANCE hInstance); //HINSTANCE 운영체제(윈도우) 객체
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
////////////////////요기가 복붙한거 //////////////////////////////
//렌더링 컨텍스트를 만드는 함수
bool initRC(HWND hWnd)
{
static PIXELFORMATDESCRIPTOR pfd =
// pfd는 윈도우즈에게 우리가 원하는 픽셀포맷을 알려준다
{
sizeof( PIXELFORMATDESCRIPTOR ),
// 이 픽셀포맷 설명자의 크기
1, // 버전
PFD_DRAW_TO_WINDOW |
// 포맷이 반드시 윈도우를 지원해야 함
PFD_SUPPORT_OPENGL |
// 포맷이 반드시 OpenGL을 지원해야 함
PFD_DOUBLEBUFFER,
// 반드시 더블 버퍼링을 지원해야함
PFD_TYPE_RGBA,
// RGBA 포맷을 요청
32,
// 색상깊이를 선택
0, 0, 0, 0, 0, 0,
// 색상비트 무시
0,// 알파버퍼 없음
0,// 쉬프트 비트 무시
0,// Accumulation 버퍼 없음
0, 0, 0, 0, // Accumulation 비트 무시
24, // 24비트 Z-버퍼 (깊이 버퍼)
0, // 스텐실 버퍼 없음
0, // Auxiliary 버퍼 없음
PFD_MAIN_PLANE, // 메인 드로잉 레이어
0, // 예약됨
0, 0, 0 // 레이어 마스크 무시
};
hDC = GetDC( hWnd ); //gdi 컨텍스트를 가져오고 이게 있으면 그림을 그릴 수 있음
if( NULL == hDC ) // 장치 컨텍스트를 얻었는지 확인
{
::MessageBox(NULL, L"GL 장치 컨텍스트를 만들 수 없음", L"오류", MB_OK|MB_ICONEXCLAMATION );
return false;
}
int pixelFormat = ChoosePixelFormat( hDC, &pfd ); // 일치하는 포맷을 찾은 결과를 가진다
if( NULL == pixelFormat ) // 일치하는 픽셀 포맷을 찾았는지 확인
{
::MessageBox(NULL, L"적절한 PixelFormat을 찾을 수 없음", L"오류", MB_OK|MB_ICONEXCLAMATION );
return false;
}
if( !SetPixelFormat( hDC, pixelFormat,&pfd ) ) // 픽셀 포맷을 설정할 수 있는지 확인
{
MessageBox( NULL, L"PixelFormat을 설정할 수 없습니다.", L"오류", MB_OK|MB_ICONEXCLAMATION);
return false; // FALSE를 반환
}
hRC = wglCreateContext( hDC ); //여기까지 오면 오픈쥐일이랑 캔버스가 연결된거
if ( NULL == hRC ) // 렌더링 컨텍스트를 가져올 수 있는지 확인
{
MessageBox( NULL, L"GL 렌더링 컨텍스트를 생성할 수 없습니다.", L"오류", MB_OK|MB_ICONEXCLAMATION );
return false; // FALSE를 반환
}
if( !wglMakeCurrent( hDC, hRC ) ) // 렌더링 컨텍스트를 활성화하려고 시도
{
MessageBox( NULL, L"GL 렌더링 컨텍스트를 활성화할 수 없습니다.", L"오류", MB_OK|MB_ICONEXCLAMATION);
return false; // FALSE를 반환
}
return true;
}
//연결을 해주고 지우는 함수
void releaseRC()
{
if(!wglDeleteContext(hRC))
{
::MessageBox(NULL,L"렌터링 컨텍스트 지우기에 실패함",L"오류", MB_OK|MB_ICONEXCLAMATION);
}
}
void reSizeGLScene(int width, int height)
{
if(height == 0)
{
height = 1;
}
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); //단위행렬...
//창의 비율을 계산
gluPerspective(45.0f, //FOV ... 카메라, 사람눈에서도 쓰이는 렌즈가 빛을 받아들일 수 있는 각도(field of view)
(float)width / (float)height, //Aspect Ratio 가로세로비를 윈도우즈 넓이? 에 맞춰서
0.1f, //Near Plane
100.0f); //Far Plane
//리소스의 한계...32bit의 한계..시험 끝나고 특강할듯..
//요 4개로 시야 절두체? 만들 수 있음 머리가 없어서 시야 절두체
//모델은 월드좌표, 뷰는 카메라 좌표 오픈쥐엘은 이걸 한번에 처리함
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void initGL()
{
glShadeModel(GL_SMOOTH); //나중에 개념나옴
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //백그라운드 지우는 컬러
glClearDepth(1.0f); //나중
glEnable(GL_DEPTH_TEST); //나중
glDepthFunc(GL_LEQUAL); //나중
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void drawGLScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-3.0f, 0.0f, -10.0f);
glRotatef(angle, 0,1,0);
glBegin(GL_TRIANGLES);//요기 찍은게 그래픽 카드로 넘어감
glColor3f( 0.5f, 0.3f, 0.72f );
glVertex3f( 0.0f, 1.0f, 0.0f );
glVertex3f(-1.0f,-1.0f, 0.0f );
glVertex3f( 1.0f,-1.0f, 0.0f );
glEnd();
glLoadIdentity();
glTranslatef( 3.0f, 0.0f, -10.0f );
glRotatef( angle, 0, 0, 1 );
glBegin(GL_QUADS);
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3f( -1.0f, 1.0f, 0.0f );
glColor3f( 0.0f, 1.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, 0.0f );
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex3f( 1.0f, -1.0f, 0.0f );
glColor3f( 0.5f, 0.5f, 0.5f );
glVertex3f( -1.0f, -1.0f, 0.0f );
glEnd();
++angle;
}
/////////////////////////////////////////요 위가 복붙한거 ////////////////////////////////////////
int APIENTRY _tWinMain(HINSTANCE hInstance, //요 함수가 메인함수...중요함 _tWinMain()
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 여기에 코드를 입력합니다.
MSG msg;//메세지...윈도우즈는 메시지 기반으로 모든게 움직이니깐
HACCEL hAccelTable;
//중간고사 전까지 요 프로젝트로 씀
// 전역 문자열을 초기화합니다.
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MY01_RENDERWINDOW, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 응용 프로그램 초기화를 수행합니다.
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY01_RENDERWINDOW));
// 기본 메시지 루프입니다.
bool done = true;
//렌더링 idle loop 기본적인 3d...
// idle = 윈도우 메시지가 없을때...0
while( done )
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //메시지가 없으면 그냥 다음으로 넘어감 peek메시지
{
if(msg.message == WM_QUIT)
{
releaseRC();
done = false;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
drawGLScene();
SwapBuffers(hDC);
}
}
return (int) msg.wParam;
}
//
// 함수: MyRegisterClass()
//
// 목적: 창 클래스를 등록합니다.
//
// 설명:
//
// Windows 95에서 추가된 'RegisterClassEx' 함수보다 먼저
// 해당 코드가 Win32 시스템과 호환되도록
// 하려는 경우에만 이 함수를 사용합니다. 이 함수를 호출해야
// 해당 응용 프로그램에 연결된
// '올바른 형식의' 작은 아이콘을 가져올 수 있습니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY01_RENDERWINDOW));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MY01_RENDERWINDOW);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 함수: InitInstance(HINSTANCE, int)
//
// 목적: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
// 설명:
//
// 이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
// 주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
if(!initRC(hWnd)) //렌더링 생성 1.
{
return FALSE;
}
initGL(); //초기값 셋팅 해주는거 2.
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 목적: 주 창의 메시지를 처리합니다.
//
// WM_COMMAND - 응용 프로그램 메뉴를 처리합니다.
// WM_PAINT - 주 창을 그립니다.
// WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//about 아니라 요가
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_SIZE:
reSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // 요기 추가됨
break;
//////////////////////////////////////////////////////////////
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 메뉴 선택을 구문 분석합니다.
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 그리기 코드를 추가합니다.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}