Шаг 16 - Doc - View + OpenGL

В предыдущих шагах мы делали шаги на 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.

Шпаргалка

  1. создать MFC проект.
  2. изенить стили в C...View::PreCreateWindow(...)
  3. изменить формат пикселя и получить контекст рендеринга в OnCreate(...)
  4. удалить контекст рендеинга в OnDestoy(...)
  5. Нарисовать что-нибудь в OnDraw(...)
  6. Скомпилировать, запустить, долго смотреть на точки, прийти к выводу, что хватит, бросить все, пойти спать.

Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Kirill V. Ratkin.