Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Закрытая тема
Ваша тема закрыта, почему это могло произойти? Возможно,
Нет наработок или кода, если нужно готовое решение - создайте тему в разделе Фриланс и оплатите работу.
Название темы включает слова - "Помогите", "Нужна помощь", "Срочно", "Пожалуйста".
Название темы слишком короткое или не отражает сути вашего вопроса.
Тема исчерпала себя, помните, один вопрос - одна тема
Прочитайте правила и заново правильно создайте тему.
 
Опции темы Поиск в этой теме
Старый 13.08.2009, 11:32   #1
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию Новичкам OpenGL

В большинстве учебников по OpenGL в качестве того, что должно быть "Hello, world" приводится монстр на 200 строк из 10 функций (который еще и грузит процессор по максимуму). Когда я со всем этим разбирался, главная задача была - максимально упростить программу, чтобы осталась только суть OpenGL без всякой мишуры.

Хочу поделиться своей нароботкой, сдобренной комментариями. Если что-то не понятно и не прокомментировано - скорее всего, это WinAPI, см. здесь.

Код:
// Программа рисует вращающуюся красную звезду. При клике в окне она остнанавливается / продолжает двигаться.
// Примечание: Project Properties -> Linker -> Input -> Additional Dependencies должно быть "opengl32.lib".


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl/gl.h>	// Программа слишком простая, мы даже не используем glu.h

LRESULT CALLBACK WindowProc (HWND, UINT, WPARAM, LPARAM);

HDC dc;
const GLshort Coord[14] = {	  0,    0,	// Координаты вершин звезды (считаются в Excel-е)
				  0, -100,
				 59,   81,
				-95,  -31,
				 95,  -31,
				-59,   81,
				  0, -100};


int __stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
						// Тут идет создание окна через WinAPI
	WNDCLASS wc;
	PIXELFORMATDESCRIPTOR pfd;
	MSG msg;
	ZeroMemory (&wc, sizeof WNDCLASS);
	wc.style	= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc	= WindowProc;
	wc.hInstance	= hInstance;
	wc.hCursor	= LoadCursor (NULL, IDC_ARROW);
	wc.lpszClassName= L"CMyWnd";
	RegisterClass (&wc);
	HWND hWnd = CreateWindowA ("CMyWnd", "OpenGL sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 308, 334, NULL, NULL, hInstance, NULL);

						// А здесь - инициализация графики... тоже WinAPI
	dc = GetDC (hWnd);
	ZeroMemory (&pfd, sizeof PIXELFORMATDESCRIPTOR);
	pfd.nSize = sizeof PIXELFORMATDESCRIPTOR;
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
	SetPixelFormat (dc, ChoosePixelFormat (dc, &pfd), &pfd);
	HGLRC hrc = wglCreateContext (dc);

						// Инициализация и настройка OpenGL
	wglMakeCurrent		(dc, hrc);
	glEnable			(GL_BLEND);				// Чтобы был Antialiasing
	glEnable			(GL_POLYGON_SMOOTH);
	glHint			(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
	glBlendFunc		(GL_SRC_ALPHA_SATURATE, GL_ONE);	// Лучший вариант антиалиасинга для состыкованных полигонов
	glEnableClientState	(GL_VERTEX_ARRAY);			// Будем использовать массивы вершин
	glVertexPointer		(2, GL_SHORT, 0, Coord);
	glClearColor		(0, 0, 0, 0);				// Цвета
	glColor3ub		(255, 0, 0);

						// И снова WinAPI
	ShowWindow (hWnd, nCmdShow);
	SetTimer (hWnd, 1, USER_TIMER_MINIMUM, NULL);
	while (GetMessage(&msg,NULL,0,0) > 0)
		DispatchMessage (&msg);

	return msg.wParam;
}


LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static bool	Rotate=1;			// Движемся или стоим
	const WORD	Width  = LOWORD(lParam),	// Для красоты кода перенес сюда из под WM_SIZE
			Height = HIWORD(lParam);

	switch (message)
	{
	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:			// Если клик, то останавливаем/продолжаем
		Rotate = !Rotate;
		// no break

	case WM_TIMER:
		if (Rotate)
		{
			glMatrixMode (GL_MODELVIEW);	// 65 раз в секунду поворачиваем объект
			glRotated (1, 0, 0, 1);
		}
		// no break

	case WM_PAINT:
		glClear (GL_COLOR_BUFFER_BIT);		// Очищаем экран
		glDrawArrays (GL_TRIANGLE_FAN, 0, 7);	// Рисуем вершины в режиме Triangle Fan
		SwapBuffers (dc);			// Обновляем окно
		break;

	case WM_SIZE:					// Обрабатываем изменение размера окна
		glViewport (0, 0, Width, Height);
		glMatrixMode (GL_PROJECTION);
		glLoadIdentity();
		glOrtho (-Width/2, Width/2, Height/2, -Height/2, 1, -1);
		break;

	case WM_KEYDOWN:				// Если нажали Escape, то выходим
		if (wParam != VK_ESCAPE)
			break;
		// else no break

	case WM_DESTROY:
		PostQuitMessage (0);
	}

	return DefWindowProc (hWnd, message, wParam, lParam);
}
Поскольку мы рисуем Triangle Fan, нам достаточно использовать вершины звезды (без внутренних углов), и координату центра (0,0).

Особо обращу внимание на glBlendFunc (GL_SRC_ALPHA_SATURATE, GL_ONE);
Эта функция задает, как будут накладываться полупрозрачные объекты (в том числе граничные пиксели антиалиасинга). Возможные варианты аргументов можно посмотреть в MSDN. Некоторые константы можно использовать только в первом аргументе, некоторые - только во втором, и не все сочетания еще допустимы (хотя всего сочетаний довольно много). В хелпах показаны несколько вариантов, но мне иногда приходилось методом тыка перебирать разные сочетания. Вариант (GL_SRC_ALPHA_SATURATE, GL_ONE) используется когда стыкуются некоторые полигоны (которые треугольные, я терминологию точно не помню), и на их стыке не должно быть антиалиасинга - иначе будут появляться щели.

Последний раз редактировалось ds.Dante; 13.08.2009 в 11:37.
ds.Dante вне форума
Старый 13.08.2009, 11:42   #2
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Учить основы OpenGL советую по книге OpenGL Redbook.
P. S. Если можно, закрепите статью.

Комментарий от pproger: для кроссплатформенности используйте либу glaux

MaTBeu: почистил флейм
Тема закрыта. Если есть конструктивная критика или советы по теме - мне в ЛС, открою.

Последний раз редактировалось MaTBeu; 14.08.2009 в 14:52.
ds.Dante вне форума
Старый 14.08.2009, 15:29   #3
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Так вот, на некоторых компьютерах этот код не работает (показывает черный экран). Дело в антиалиасинге. Не знаю, можно ли его использовать на этих компьютерах, но если убрать glEnable (GL_BLEND) и следущие три строки, то все должно заработать.
ds.Dante вне форума
Закрытая тема


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
совсем тупым новичкам..include Yo-yo Помощь студентам 7 12.03.2012 07:27
Новичкам: Насчет халявы MaTBeu Общие вопросы C/C++ 0 23.12.2008 23:38