ztest failing when rendering to two winform panels - bug?

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
floriang
Posts: 13
Joined: Mon Jul 14, 2014 12:03 pm

ztest failing when rendering to two winform panels - bug?

Post by floriang »

Hi all,
I am trying to render to two windows panel (using irrlicht 1.8 ), and I don't understand why but it looks like the Z test is failing on the second panel.
I am using openGL driver (opengl is required because i want to use irrlicht inside an application that otherwise uses opengl), and I get window handles from the panels with

Code: Select all

panel1->Handle.ToPointer()


The whole code:

Code: Select all

 
void RenderThread() {
            PIXELFORMATDESCRIPTOR pfd;
            int pf;
            struct SExposedVideoData irrdeviceVideoInfo;
            struct SExposedVideoData nativeVideoInfo1;
            struct SExposedVideoData nativeVideoInfo2;
            irr::SIrrlichtCreationParameters params;
            params.WindowId = _WinId1;         //I point this to the MDI windows.
            params.DriverType = video::EDT_OPENGL;
            params.EventReceiver = 0;
            params.AntiAlias = 0;
            IrrlichtDevice* device = createDeviceEx(params);      //The device is create but it is hidden.
            _IrDevice = device;
            
            // setup 2 windows
            irrdeviceVideoInfo = _IrDevice->getVideoDriver()->getExposedVideoData();
            
            memset( &pfd,0, sizeof(pfd) );
            pfd.nSize = sizeof(pfd);
            pf = GetPixelFormat((HDC)irrdeviceVideoInfo.OpenGLWin32.HDc);
            DescribePixelFormat((HDC)irrdeviceVideoInfo.OpenGLWin32.HDc,pf, sizeof(pfd), &pfd);
            pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
            pfd.cDepthBits=16;
            nativeVideoInfo1.OpenGLWin32.HWnd = _WinId1;
            nativeVideoInfo1.OpenGLWin32.HDc = GetDC((HWND)nativeVideoInfo1.OpenGLWin32.HWnd);
            pf = ChoosePixelFormat( (HDC)nativeVideoInfo1.OpenGLWin32.HDc, &pfd );
            SetPixelFormat( (HDC)nativeVideoInfo1.OpenGLWin32.HDc, pf, &pfd );
            nativeVideoInfo1.OpenGLWin32.HRc = wglCreateContext( (HDC)nativeVideoInfo1.OpenGLWin32.HDc );
            wglShareLists((HGLRC)irrdeviceVideoInfo.OpenGLWin32.HRc, (HGLRC)nativeVideoInfo1.OpenGLWin32.HRc);
 
            
            memset( &pfd,0, sizeof(pfd) );
            pfd.nSize = sizeof(pfd);
            pf = GetPixelFormat((HDC)irrdeviceVideoInfo.OpenGLWin32.HDc);
            DescribePixelFormat((HDC)irrdeviceVideoInfo.OpenGLWin32.HDc,pf, sizeof(pfd), &pfd);
            pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
            pfd.cDepthBits=16;
            nativeVideoInfo2.OpenGLWin32.HWnd = _WinId2;
            nativeVideoInfo2.OpenGLWin32.HDc = GetDC((HWND)nativeVideoInfo2.OpenGLWin32.HWnd);
            pf = ChoosePixelFormat( (HDC)nativeVideoInfo2.OpenGLWin32.HDc, &pfd );
            SetPixelFormat( (HDC)nativeVideoInfo2.OpenGLWin32.HDc, pf, &pfd );
            nativeVideoInfo2.OpenGLWin32.HRc = wglCreateContext( (HDC)nativeVideoInfo2.OpenGLWin32.HDc );
            wglShareLists((HGLRC)irrdeviceVideoInfo.OpenGLWin32.HRc, (HGLRC)nativeVideoInfo2.OpenGLWin32.HRc);
 
            // setup drawing
            IVideoDriver* driver = device->getVideoDriver();
            ISceneManager* smgr = device->getSceneManager();
            IGUIEnvironment* guienv = device->getGUIEnvironment();
 
            irr::core::vector3df position;
 
            position.X = 0;
            position.Y = 0;
            position.Z = 0;
 
            scene::IMeshSceneNode* node = smgr->addCubeSceneNode(3.0f, 0, -1, position);
 
            scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(core::vector3df(0.0f, 0.3f,0));
            node->setPosition(core::vector3df(0,0,0));
            node->setMaterialFlag(video::EMF_LIGHTING, false);
            node->setMaterialType(video::EMT_SOLID);
            //node->setMaterialFlag(video::EMF_WIREFRAME, true);
            node->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
            node->addAnimator(anim);
            anim->drop();
 
            IMeshBuffer* mb = node->getMesh()->getMeshBuffer(0);
            u32 count = mb->getVertexCount();
            
            video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices();
            for( int i=0; i<count; i++ ) {
                switch( i%6 )
                {
                case 0: vertices[i].Color = SColor(0xFF,0xFF,0,0); break;
                case 1: vertices[i].Color = SColor(0xFF,0,0xFF,0); break;
                case 2: vertices[i].Color = SColor(0xFF,0,0,0xFF); break;
                case 3: vertices[i].Color = SColor(0xFF,0,0xFF,0xFF); break;
                case 4: vertices[i].Color = SColor(0xFF,0xFF,0xFF,0xFF); break;
                case 5: vertices[i].Color = SColor(0xFF,0xFF,0xFF,0); break;
                }
            }
             
            scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
            cam->setPosition(core::vector3df(0,0,10.0));
            cam->setTarget(core::vector3df(0,0,0));
 
            while(true)
            {
                device->run();
                driver->beginScene(true, true, video::SColor(0,0,180,255), nativeVideoInfo2);
                smgr->setActiveCamera(cam);
                smgr->drawAll();
                driver->endScene();
 
                driver->beginScene(true, true, video::SColor(0,100,180,255), nativeVideoInfo1);
                smgr->setActiveCamera(cam);
                smgr->drawAll();
                driver->endScene();                 
            }
 
            device->drop();
        }
 
With this code, the panel corresponding to nativeVideoInfo2 displays correctly, but the other one doesn't (panel1=NG, panel2=OK).
Then if I invert the nativeVideoInfo1 and 2 in the drawing loop, I will get inverted results (panel1=OK, panel2=NG).

Any ideas?
I have been struggling with this for hours now, I can't understand what can be the problem.
Is it a bug?

** If i find how to do it, I will post an image.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: ztest failing when rendering to two winform panels - bug

Post by CuteAlien »

Sorry, I'm not on Windows right now so couldn't test. But to post images I'll recommend imgur.com.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
floriang
Posts: 13
Joined: Mon Jul 14, 2014 12:03 pm

Re: ztest failing when rendering to two winform panels - bug

Post by floriang »

Thanks for the tip.
Here is what it looks like when PANEL2 displays correctly (as in the code as posted).
PANEL1 and PANEL2 should display the same thing, but they don't!

Image

When looking at the picture, it looks like a Zbuffer issue to me. But it may be something else
floriang
Posts: 13
Joined: Mon Jul 14, 2014 12:03 pm

Re: ztest failing when rendering to two winform panels - bug

Post by floriang »

Update:
I was able to fix the issue by enabling depth test after changing the context:

Code: Select all

 
                device->run();
                driver->beginScene(true, true, video::SColor(0,0,180,255), nativeVideoInfo2);
                glEnable (GL_DEPTH_TEST);
                smgr->setActiveCamera(cam);
                smgr->drawAll();
                driver->endScene();
 
                driver->beginScene(true, true, video::SColor(0,100,180,255), nativeVideoInfo1);
                glEnable (GL_DEPTH_TEST);
                smgr->setActiveCamera(cam);
                smgr->drawAll();
                driver->endScene(); 
 
It looks like a bug in irrlicht when changing the context with opengl.
I will check if there is an API in irrlicht to enable depth test (I'd like to avoid direct opengl calls if possible).
Also I hope this is the only issue!!!
floriang
Posts: 13
Joined: Mon Jul 14, 2014 12:03 pm

Re: ztest failing when rendering to two winform panels - bug

Post by floriang »

Finally, there is no explicit API to do it, but we can use a trick of displaying a 2dline to force irrlicht enabling the depth test when it switches back to 3d rendering.

Here is the final code in case someone else needs it:

Code: Select all

 
                device->run();
                driver->beginScene(true, true, video::SColor(0,0,180,255), nativeVideoInfo2);
                driver->draw2DLine(position2di(0,0),position2di(0,0), invisible ); // trick: force enabling depth test when going back to 3d drawing
                smgr->setActiveCamera(cam);
                smgr->drawAll();
                driver->endScene();
 
                driver->beginScene(true, true, video::SColor(0,100,180,255), nativeVideoInfo1);
                driver->draw2DLine(position2di(0,0),position2di(0,0), invisible ); // trick: force enabling depth test when going back to 3d drawing
                smgr->setActiveCamera(cam);
                smgr->drawAll();
                driver->endScene(); 
 
 
But I think this should be fixed inside the beginScene.
floriang
Posts: 13
Joined: Mon Jul 14, 2014 12:03 pm

Re: ztest failing when rendering to two winform panels - bug

Post by floriang »

Hello again,
I'm keeping on doing more complex rendering on 2 panels, but it feels very buggy.
For example, I get issues when adding guienv static text items to display the FPS: The code below won't display the static text on any panel:

Code: Select all

 
 
            IGUIStaticText* statictext2 = guienv->addStaticText(L"FPS", rect<s32>(10,10,260,22), true);
 
            while(true)
            {
                device->run();
                driver->beginScene(true, true, video::SColor(0,0,180,255), nativeVideoInfo2);
                guienv->drawAll();
                driver->draw2DLine(position2di(0,0),position2di(0,0), invisible ); // trick: force enabling depth test when going back to 3d drawing
                smgr->setActiveCamera(cam);
                smgr->drawAll();
                driver->endScene();
 
                driver->beginScene(true, true, video::SColor(0,100,180,255), nativeVideoInfo1);
                guienv->drawAll();
                driver->draw2DLine(position2di(0,0),position2di(0,0), invisible ); // trick: force enabling depth test when going back to 3d drawing
                smgr->setActiveCamera(cam2);
                smgr->drawAll();
                driver->endScene(); 
 
                int fps = driver->getFPS();
 
                core::stringw str1;
                if (lastFPS != fps)
                {
                        str1 = L"FPS:";
                        str1 += fps;
                        lastFPS = fps;
                        statictext2->setText(str1.c_str());
                }
                
            }
 
If I move the "guienv->drawAll();" statement I also might get other bugs, like the cubes not being colored (all black) etc...
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: ztest failing when rendering to two winform panels - bug

Post by CuteAlien »

Thanks for all the info. Could be you run into stuff no-one has tried so far (or not reported). Problem right now is that the main maintainer of the drivers hasn't shown up much lately, so I fear it might take a while until someone get's around to fixing this :-(
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply