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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 06.09.2010, 20:50   #1
Koshmarovsky
Пользователь
 
Аватар для Koshmarovsky
 
Регистрация: 09.05.2009
Сообщений: 25
По умолчанию Проблемы с OpenGL

Доброе время суток!

Пишу программку на С++, юзаю OpenGL. Необходимо, что бы создавалась куча небольших GL'евских окошек, в которых отрисовка происходила вне зависимости от действий над окнами и во всех сразу.

Код следующий:

Регистрация класса:
Код:
WNDCLASSEX	wc;												// Windows Class Structure
	wc.cbSize			= sizeof(WNDCLASSEX);
	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	
	wc.lpfnWndProc		= (WNDPROC) WndProc;					
	wc.cbClsExtra		= 0;									
	wc.cbWndExtra		= 0;									
	wc.hInstance		= GetModuleHandle(NULL);							
	wc.hIcon			= LoadIcon(NULL, MAKEINTRESOURCE(IDI_DEALS));			
	wc.hIconSm		= LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_SMALL));
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);			
	wc.hbrBackground	= NULL;									
	wc.lpszMenuName	= NULL;									
	wc.lpszClassName		= szWindowClass;								

	RegisterClassEx(&wc);
Создание окна:
Код:
if (!(hWnd=CreateWindowEx(	WS_EX_TOOLWINDOW,		// Это что бы окно не отображалось на панели задач
							reinterpret_cast<LPCWSTR>(L"DEALS"),	
							reinterpret_cast<LPCWSTR>(title),		
							WS_POPUP,		//Это что бы у окна не было рамки и системного меню.
							WindowRect.left, WindowRect.top,				
							WindowRect.right-WindowRect.left,	
							WindowRect.bottom-WindowRect.top,	
							NULL,							
							NULL,							
							hInstance,						
							NULL)))							
	{
		ErrorMessage(L"CreateWindowEx()");
		return FALSE;											
	}
Обработчик сообщений:

Код:
LRESULT CALLBACK GLCore::WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static bool LBPressed = false;
	static WORD StartX;
	static WORD StartY;
	switch (message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_PAINT:
		DrawGLScene();
		SwapBuffers(GetDC(hWnd));//Предположитьельно проблема здесь
		break;
	case WM_LBUTTONDOWN:
		StartX = LOWORD(lParam);
		StartY = HIWORD(lParam);
		LBPressed = true;
		break;
	case WM_LBUTTONUP:
		LBPressed = false;
		break;
	case WM_MOUSEMOVE:
		if (LBPressed)
		{
			WINDOWPLACEMENT lpwndpl;
			GetWindowPlacement (hWnd, &lpwndpl);
			SetWindowPos (hWnd, HWND_TOP, 
				lpwndpl.rcNormalPosition.left+LOWORD(lParam)-StartX, 
				lpwndpl.rcNormalPosition.top +HIWORD(lParam)-StartY, 0, 0, SWP_NOSIZE);
		}
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
Так вот. Если создаю несколько окон, то прорисовка происходит только в последнем. Тем не менее окна реагируют на сообщения WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE, то есть по идее и WM_PAINT до них доходит. И функция DrawGLScene() соответственно выполняется. По этому грешу на Device Context (DC), по тому как не совсем понимаю принцип его работы, и толкового описания не нашел.
В общем, ай нид хелп.
Заранее спасибо =)
Иногда мне кажется, что компилятор просто игнорирует все мои комментарии. (с) Bash.org.ru

Последний раз редактировалось Koshmarovsky; 06.09.2010 в 21:44.
Koshmarovsky вне форума Ответить с цитированием
Старый 06.09.2010, 21:46   #2
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

А где и как происходит инициализация openGL rendering context (wglCreateContext, wglMakeCurrent)?
Инструкция говорит, что один и тот же rendering context не может быть текущим для нескольких потоков одновременно. И уж тем более, rendering context созданный в одном процессе будет недействительным в другом. Может тут проблема?
f.hump вне форума Ответить с цитированием
Старый 06.09.2010, 22:07   #3
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

Кстати, это не по теме вопроса, но может стоит после SwapBuffers поставить ValidateRect(hwnd,0), а то WM_PAINT будет стоять в очереди постоянно.
f.hump вне форума Ответить с цитированием
Старый 06.09.2010, 22:22   #4
Koshmarovsky
Пользователь
 
Аватар для Koshmarovsky
 
Регистрация: 09.05.2009
Сообщений: 25
По умолчанию

Цитата:
Сообщение от f.hump Посмотреть сообщение
А где и как происходит инициализация openGL rendering context (wglCreateContext, wglMakeCurrent)?
сразу после CreateWindowEX:

Код:
hDC = GetDC(hWnd);
PixelFormat = ChoosePixelFormat(hDC,&pfd);
SetPixelFormat(hDC,PixelFormat,&pfd);	
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC,hRC);

Цитата:
Инструкция говорит, что один и тот же rendering context не может быть текущим для нескольких потоков одновременно. И уж тем более, rendering context созданный в одном процессе будет недействительным в другом. Может тут проблема?
Вся работа с DC идет в одном потоке. Из отдельного потока я в качестве теста только отправлял WM_PAINT во все окна по очереди.
Провел еще один тест: выводил, для какого из окон пришло WM_PAINT прямо при обработке сообщения в WndProc. WM_PAINT приходит только активному окну, но даже если какое-либо не последнее окно активно, то отрисовки не происходит (даже в последнем). У меня уже мозг вскипел...
Пойду посплю, может поможет... =)
Иногда мне кажется, что компилятор просто игнорирует все мои комментарии. (с) Bash.org.ru

Последний раз редактировалось Koshmarovsky; 06.09.2010 в 22:31.
Koshmarovsky вне форума Ответить с цитированием
Старый 06.09.2010, 22:58   #5
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

Есть мнение, что все окна создаются в одном (главном) потоке процесса. Т.е. текущим контекстом потока устанавливается контекст окна созданного последним.
Предлагаю сразу за созданием контекста окна поставить следующее, сразу после
Код:
hRC = wglCreateContext(hDC);
поставить
Код:
SetWindowLong(hWnd,GWL_USERDATA,(LONG)hRC);
убрать
Код:
wglMakeCurrent(hDC,hRC);
а в WM_PAINT написать так:
Код:

HGLRC hRC = (HGLRC)GetWindowLong(hWnd,GWL_USERDATA);
HDC hDC = GetDC(hWnd);

wglMakeCurrent(hDC,hRC);

DrawGLScene();
SwapBuffers(hDC);

Последний раз редактировалось f.hump; 06.09.2010 в 23:01.
f.hump вне форума Ответить с цитированием
Старый 07.09.2010, 05:30   #6
Koshmarovsky
Пользователь
 
Аватар для Koshmarovsky
 
Регистрация: 09.05.2009
Сообщений: 25
По умолчанию

Смысл понял, сделал.
Результат: при запуске каждое окно прорисовывается только 1 раз.
Если убрать ValidateRect(hWnd,0); (которая послед SwapBuffers()), то постоянно прорисовывается активное окно. Только прорисовывается не до конца.
Вот код функции DrawGLScene():
Код:
bool GLCore::DrawGLScene ()										
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glColor3f(0.0f,1.0f,0.0f);
	double move = sin(M_PI*GetTickCount()/1000);
	glBegin(GL_QUADS);
		glVertex2d(140+135*move, 5);
		glVertex2d(140+135*move, 25);
		glVertex2d(160+135*move, 25);
		glVertex2d(160+135*move, 5);
	glEnd();
	return true;	
}
То есть в окошке туда сюда двигается зеленый квадрат (временная фича, что бы было видно, что окно действительно прорисовывается). До последних изменений квадрат рисовался только в последнем созданном окне, остальные не рисовались ввобще, то есть на них оставался рисунок последнего находящегося над ними окна. Теперь при активации о'кна заливаются черным цветом, но квадрат не рисуется.

Опять же, при бесконечной посылке из отдельного потока всем окнам WM_PAINT рисуются только черные прямоугольники, без квадрата. Этот эффект вообще не ясен...

К тому же в идеал нужно, что бы не активные окна так же постоянно перерисовывались без отдельного спамящего потока. Как это можно сделать?
Иногда мне кажется, что компилятор просто игнорирует все мои комментарии. (с) Bash.org.ru

Последний раз редактировалось Koshmarovsky; 07.09.2010 в 05:33.
Koshmarovsky вне форума Ответить с цитированием
Старый 07.09.2010, 12:56   #7
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

Не совсем понятно, что значит прорисовывается не до конца.
WM_PAINT не то сообщение которое можно рассылать напрямую, для этого есть функции UpdateWindow, RedrawWindow.
Если хочется рассылать сообщение, то рассылать WM_PRINT.

Последний раз редактировалось f.hump; 07.09.2010 в 12:59.
f.hump вне форума Ответить с цитированием
Старый 07.09.2010, 15:47   #8
Koshmarovsky
Пользователь
 
Аватар для Koshmarovsky
 
Регистрация: 09.05.2009
Сообщений: 25
По умолчанию

Цитата:
Не совсем понятно, что значит прорисовывается не до конца.
Я имею в виду, что окно просто закрашивается в черный цвет, как-будто выполняется только фунция glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT). Хотя если поменять цвет в glClearColor(...), то окна все равно закрашиваются в черный.
Раньше (до изменений с wglMakeCurrent(hDC,hRC)) окна не прорисовывались вообще, то есть если расположить какое-либо левое окно поверх GL'евских, а потом свернуть его, то в GL'евских окнах оставались куски свернутого окна. Вот.

UpdateWindow() никакого видимого эффекта не дало.

В принципе могу выложить все исходники проекта (или весь проект), если есть время и/или желание копаться в чужом коде... =)
Иногда мне кажется, что компилятор просто игнорирует все мои комментарии. (с) Bash.org.ru
Koshmarovsky вне форума Ответить с цитированием
Старый 07.09.2010, 15:58   #9
Koshmarovsky
Пользователь
 
Аватар для Koshmarovsky
 
Регистрация: 09.05.2009
Сообщений: 25
По умолчанию

Для ясности:
Окна вообще не прорисовываются (остались куски свернутого Chrome'a)
Окна не прорисовываются вообще (остались куски свернутого Chrome'a).bmp
Окна прорисовываются не до конца:
Окна прорисовываются не до конца.bmp
Последнее окно полностью прорисовывается (зеленый квадрат двигается влево-вправо)
Последнее окно полностью прорисовывается (квадрат двигается влево-вправо).bmp
Иногда мне кажется, что компилятор просто игнорирует все мои комментарии. (с) Bash.org.ru

Последний раз редактировалось Koshmarovsky; 07.09.2010 в 16:00.
Koshmarovsky вне форума Ответить с цитированием
Старый 07.09.2010, 17:02   #10
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

Я вообще-то думал про RedrawWindow, UpdateWindow вызывает WndProc если update region не пуст, так что фиг его знает как оно будет, плюс есть ненулевой шанс завалить или подвесить програму. Попробуй после SwapBuffers поставить
Код:
RedrawWindow(hWnd,0,0,RDW_INTERNALPAINT);
насчет черного фона, не знаю. показывай код. Весь проект не нужен. Инициализация/конфигурация OpenGL, application main loop.

Кстати, причиной может быть то, что OpenGL конфигурируется только в контексте окна созданного последним, а для остальных х.з. Так что проблема скорее всего и даже наверняка не с WP_PAINT.

Последний раз редактировалось f.hump; 07.09.2010 в 17:15.
f.hump вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
OpenGl macintoshka12 Общие вопросы C/C++ 2 21.04.2010 12:59
проблемы с opengl. elenza Помощь студентам 1 19.11.2009 22:54
Opengl Алексадр Компоненты Delphi 4 29.09.2009 17:23
OpenGL Paul_AG C++ Builder 20 14.09.2009 19:07
OpenGL yanl Компьютерное железо 0 16.11.2008 00:52