В предыдущих шагах мы делали шаги на Win32 API и очень быстро пробежали по основным возможностям OpenGL.
А как извесно, если быстро бежать, то ничего вокруг не увидишь. Вот теперь, хорошо пробежавшись, начнем медленно и внимательно изучать команды OpenGL.
Но чтобы было не так скучно мы будем использовать не Win32 API, а MFC.
В шаге 15 мы посмотрели как пишется программа c OpenGL+MFC в виде диалога, теперь посмотрим как сделать такую же програмку в модели Doc-View.
Прежде всего создаем проект с помощью MFC Wizard и класс View наследуем от CView (хотя можно и от других классов, но в этом просто нет смысла).
В файл stdafx.h добавим заголовочные файлы OpenGL, а в Project->Settings добавим библиотеки OpenGL. Как вы помните из приложений на Win32 API необходимо задать стиль окна. Это можно сделать в функции PreCreateWindow(...). Например так:
BOOL CExampleView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; return CView::PreCreateWindow(cs); }
Затем нам надо установить формат пикселя и создать контекст рендеринга. Это можно сделать в обработчике WM_CREATE:
int CExampleView::OnCreate(LPCREATESTRUCT lpCreateStruct) { PIXELFORMATDESCRIPTOR pfd; int iPixelFormat; CDC *pDC; if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here pDC = GetDC(); 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.iLayerType = PFD_MAIN_PLANE; pfd.cDepthBits = 16; iPixelFormat = ChoosePixelFormat(pDC->m_hDC, &pfd); SetPixelFormat(pDC->m_hDC, iPixelFormat, &pfd); m_hglrc = wglCreateContext(pDC->m_hDC); wglMakeCurrent(pDC->m_hDC, m_hglrc); ReleaseDC(pDC); return 0; }
Не забудьте в описание класса (желательно в раздел private или protected) добавить переменную:
private: HGLRC m_hglrc;
Как вы понимаете это и есть наш контекст рендеринга.
Перед выходом из программы желательно удалить ранее полученный контекст рендеринга. Давайте сделаем это в обработчике WM_DESTROY:
void CExampleView::OnDestroy() { CView::OnDestroy(); // TODO: Add your message handler code here wglMakeCurrent(NULL, NULL); }
Теперь, если вся подготовка прошла удачно. Начинаем что-нибудь рисовать. Разумнее всего (для статических картинок) это сделать в обработчике OnDraw:
void CExampleView::OnDraw(CDC* pDC) { CRect clientRect; CExampleDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here GetClientRect(&clientRect); glViewport(0, 0, clientRect.right, clientRect.bottom); glClearColor (0.5, 0.5, 0.75, 1.0); // цвет фона glClear (GL_COLOR_BUFFER_BIT); // очистка буфера цвета glPointSize (20); // размер точек glColor3f (1.0, 0.0, 0.5); // текущий цвет примитивов glBegin (GL_POINTS); glVertex2f (-1, -1); glVertex2f (-1, 1); glVertex2f (0, 0); glVertex2f (1, -1); glVertex2f (1, 1); glEnd(); }
Программа рисует 5 "толстых" точек. Легко понять, что толщина точек задается командой glPointSize(GLint iSize);
Если вы не используете специальных команд преобразования видовых координат, то библиотека настраивается так, что система координат начинается в центре экрана и простирается от -1 до +1 по X и от -1 до +1 по Y.