Page 1 of 1

Textures and fonts don't work in multiple windows in OpenGL

Posted: Mon Aug 23, 2010 10:52 am
by sylpheed
Hi, first of all sorry for my English.

I'm using wxWidgets and Irrlicht for a multiple graphic window aplication, concretely I'm using 2 Irrlicht Scene Managers in 2 different wxWindows. Everything works fine in Direct3D, but textures (using driver->draw2DImage) and fonts are not shown in OpenGL mode. Textures used in geometry objects are displayed perfectly.

I guess it's an initialization problem, but I can't solve it. Please, could you help me? This is the initialization of the context:

Code: Select all

if (driver->getDriverType () == EDT_OPENGL){		
		if (this->hwnd != hwnd){
			// Libera la memoria del anterior contexto
			if (this->hwnd && hdc)
				ReleaseDC ((HWND)this->hwnd, (HDC)hdc);

			// Crea un nuevo contexto
			hdc = GetDC ((HWND)hwnd);						


			DWORD flags = PFD_SUPPORT_COMPOSITION | PFD_SWAP_EXCHANGE | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
			// Descriptor
			PIXELFORMATDESCRIPTOR pfd = {
				sizeof(PIXELFORMATDESCRIPTOR),             // Size Of This Pixel Format Descriptor
				1,                                         // Version Number
				flags,
				PFD_TYPE_RGBA,                             // Request An RGBA Format
				16,										   // Select Our Color Depth
				0,0,0,0,0,0,							   // Color Bits Ignored
				0,                                         // No Alpha Buffer
				0,                                         // Shift Bit Ignored
				0,                                         // No Accumulation Buffer
				0, 0, 0, 0,	                               // Accumulation Bits Ignored
				16,										   // Z-Buffer (Depth Buffer)
				0,										   // Stencil Buffer Depth
				0,                                         // No Auxiliary Buffer
				PFD_MAIN_PLANE,                            // Main Drawing Layer
				0,                                         // Reserved
				0, 0, 0                                    // Layer Masks Ignored
			};

			


			bool arb_init = false;

			PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat_ARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
			if (wglChoosePixelFormat_ARB){
				// This value determines the number of samples used for antialiasing
				// My experience is that 8 does not show a big
				// improvement over 4, but 4 shows a big improvement
				// over 2.
				int antialias = ((GraphicDeviceIrr*)GraphicDevice::getGraphicDevice ())->getAntialias ();

				f32 fAttributes[] = {0.0, 0.0};
				s32 iAttributes[] =
				{
					WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
					WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
					WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
					WGL_COLOR_BITS_ARB, 24,
					WGL_ALPHA_BITS_ARB, 0,
					WGL_DEPTH_BITS_ARB, 16,
					WGL_STENCIL_BITS_ARB, 0,
					WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
					WGL_STEREO_ARB, GL_FALSE,
#ifdef WGL_ARB_multisample
					WGL_SAMPLE_BUFFERS_ARB, 1,
					WGL_SAMPLES_ARB, antialias,
#elif defined(WGL_EXT_multisample)
					WGL_SAMPLE_BUFFERS_EXT, 1,
					WGL_SAMPLES_EXT,AntiAlias, // 20,21
#elif defined(WGL_3DFX_multisample)
					WGL_SAMPLE_BUFFERS_3DFX, 1,
					WGL_SAMPLES_3DFX,AntiAlias, // 20,21
#endif
					WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
					// other possible values:
					// WGL_ARB_pixel_format_float: WGL_TYPE_RGBA_FLOAT_ARB
					// WGL_EXT_pixel_format_packed_float: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT
					0,0
				};

				s32 pixelFormat=0;
				u32 numFormats=0;
				const s32 valid = wglChoosePixelFormat_ARB ((HDC)hdc, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
				BOOL res = SetPixelFormat((HDC)hdc, pixelFormat, &pfd);
				

				if (valid && res){
					#ifdef WGL_ARB_create_context
						PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs_ARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
						if (wglCreateContextAttribs_ARB)
						{
							int iAttribs[] =
							{
								WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
								WGL_CONTEXT_MINOR_VERSION_ARB, 1,
								0
							};

							// Crea el contexto de renderizado si no existe ninguno
							if (((GraphicDeviceIrr*)GraphicDevice::getGraphicDevice ())->hrc == NULL)
								((GraphicDeviceIrr*)GraphicDevice::getGraphicDevice ())->hrc = wglCreateContextAttribs_ARB((HDC)hdc, 0, iAttribs);								
							arb_init = true;
						}
					#endif
				}
			}


			if (!arb_init){
				int pf = GetPixelFormat ((HDC)hdc);
				DescribePixelFormat((HDC)hdc, pf, sizeof (PIXELFORMATDESCRIPTOR), &pfd);			
				pf = ChoosePixelFormat((HDC)hdc, &pfd);
				SetPixelFormat((HDC)hdc, pf, &pfd);
				// Crea el contexto de renderizado si no existe ninguno
				if (((GraphicDeviceIrr*)GraphicDevice::getGraphicDevice ())->hrc == NULL)
					((GraphicDeviceIrr*)GraphicDevice::getGraphicDevice ())->hrc = wglCreateContext ((HDC)hdc);									
			}
		}
	}

Posted: Mon Aug 23, 2010 2:15 pm
by hybrid
You need to create the context such that it is shared with the one that Irrlicht creates. Please check example 14 (better in SVN, changes could be in Irrlicht 1.7 though) where I might have added a line to show how to do this. Otherwise google how to create shared contexts.

Posted: Thu Aug 26, 2010 12:16 pm
by sylpheed
hybrid wrote:You need to create the context such that it is shared with the one that Irrlicht creates. Please check example 14 (better in SVN, changes could be in Irrlicht 1.7 though) where I might have added a line to show how to do this. Otherwise google how to create shared contexts.
Thanks hybrid, now it works ;). By the way, some misterious things happened.

I created a simple project with only 2 windows (wxWidgets) containing 2 different Irrlicht scene managers. Following example 14, it worked like a charm.

I tried doing same thing in my main project but no results, textures didn't show. After a lot of tries, I found the mistake, if Antialias is enabled in SIrrlichtCreationParameters then nothing is drawed in the windows. Not only fails in my main project, in the other simple project fails too. But, if I enable Antialias in Example 14, then it renders OK :? Why? Could it be a problem from creating wxWidgets windows? I post the code, it's pretty simple:

Code: Select all

#include "AppMain.h"
#include <wx/frame.h>
#include <wx/window.h>
#include <wx/aui/aui.h>
#include <irrlicht.h>
#include "wglext.h"

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

AppMain::AppMain () {}

bool AppMain::OnInit () {	
	// One frame containing two child windows
	wxFrame *frame = new wxFrame (NULL, wxID_ANY, wxEmptyString, wxPoint (100, 200), wxSize (1000, 500));
	wxWindow *win1 = new wxWindow (frame, wxID_ANY, wxPoint (0, 0), wxSize (500, 500));
	wxWindow *win2 = new wxWindow (frame, wxID_ANY, wxPoint (500, 0), wxSize (500, 500));	



	// Irrlicht device creation
	SIrrlichtCreationParameters param;
	param.DriverType = EDT_OPENGL;
	param.WindowId = frame->GetHandle ();	
	//param.AntiAlias = 4; // If Antialias enabled then fail!
	IrrlichtDevice* device = irr::createDeviceEx(param);

	ISceneManager* smgr1 = device->getSceneManager();
	ISceneManager* smgr2 = smgr1->createNewSceneManager (false);
	IVideoDriver* driver = device->getVideoDriver();	

	SExposedVideoData vData = driver->getExposedVideoData ();
	SExposedVideoData data1;
	SExposedVideoData data2;



	// Create context for window 1
	{		
		data1.OpenGLWin32.HWnd = win1->GetHandle ();
		HDC HDc = GetDC ((HWND)data1.OpenGLWin32.HWnd);	
		PIXELFORMATDESCRIPTOR pfd = {0};
		pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
		int pf = GetPixelFormat (HDc);
		DescribePixelFormat (HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
		pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
		pfd.cDepthBits = 16;
		pf = ChoosePixelFormat(HDc, &pfd);
		SetPixelFormat (HDc, pf, &pfd);
		data1.OpenGLWin32.HDc = HDc;
		data1.OpenGLWin32.HRc = vData.OpenGLWin32.HRc;
	}

	// Create context for window 2
	{
		data2.OpenGLWin32.HWnd = win2->GetHandle ();
		HDC HDc = GetDC ((HWND)data2.OpenGLWin32.HWnd);	
		PIXELFORMATDESCRIPTOR pfd = {0};
		pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
		int pf = GetPixelFormat (HDc);
		DescribePixelFormat (HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
		pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
		pfd.cDepthBits = 16;
		pf = ChoosePixelFormat(HDc, &pfd);
		SetPixelFormat (HDc, pf, &pfd);
		data2.OpenGLWin32.HDc = HDc;
		data2.OpenGLWin32.HRc = vData.OpenGLWin32.HRc;
	}



	frame->Show (true);


	while (device->run()){		
		// Draw in window 1
		driver->beginScene (true, true, SColor (255, 0, 0, 0), data1);
		smgr1->drawAll();
		driver->draw2DImage (driver->getTexture ("../media/textures/smiley.png"), vector2di (0, 0));
		driver->endScene();

		// Draw in window 2
		driver->beginScene (true, true, SColor (255, 0, 0, 0), data2);
		smgr2->drawAll();
		driver->draw2DImage (driver->getTexture ("../media/textures/red_x.png"), vector2di (0, 0));
		driver->endScene();
	}

	return true;
}

IMPLEMENT_APP (AppMain)