[SOLVED] Clearing problem in Red/Cyan Anaglyph Stereo?

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

[SOLVED] Clearing problem in Red/Cyan Anaglyph Stereo?

Post by Guillaum »

Hello,

I'm currently developping a research project using Irrlicht engine for 3D display. I follow the Irrlicht forum for many days and found lot of revealing informations and helped me to develop lot of things. However, right now, i really do not manage to make stereo vision work.

In order to build a working example of Red/Cyan Anaglyph Stereovision (see source code below), I've been inspired by the following topics of the forum:
2009: http://irrlicht.sourceforge.net/forum/v ... p?p=185215
2009: http://irrlicht.sourceforge.net/forum/v ... =9&t=33463
2008: http://irrlicht.sourceforge.net/forum/v ... hp?t=28893
It seams these examples are working according to their authors. When creating device with EDT_SOFTWARE driver, examples don't work at all, but with EDT_OPENGL it begins to work. However it is like buffer are not correctly cleaned or if overriding material is not working well.

I'm running a Debian 8 Jessie Linux distribution, with Irrlicht 1.8, and compiling with g++
The NVIDIA proprietary display driver (nvidia-driver) is correctly installed.
The graphic card is a NVidia Quadro NVS 3100M (GT218M).

When loading the Quake 3 map example, it is working (with both OpenGL native primitives or Irrlicht primitives):
Image

But, when having an animated mesh, it is dirty:
using Irrlicht primitives
Image
or using OpenGL primitives
Image

And also when having a moving mesh, it is dirty:
Image

Here is my source code:

Code: Select all

 
/* File: stereo.cpp
 
Red/Cyan anaglyph stereovision using Irrlicht engine under Linux width video::EDT_OPENGL driver.
 
Directly inspired by:
http://irrlicht.sourceforge.net/forum/viewtopic.php?p=185215
 
And for Irrlich primitives by
http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=33463
 
COMPILATION:
$ g++ -o irrsteroexample main.cpp stereo.cpp -I/usr/include/irrlicht/ -I/usr/include/GL/ -lIrrlicht -lGL
 
DOWNLOAD MEDIA NEEDED FOR RUNTIME:
$ mkdir ./media/
$ cd ./media/
$ wget https://github.com/zaki/irrlicht/blob/master/media/map-20kdm2.pk3
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.bmp
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.md2
 
USAGE:
$ ./irrsteroexample quake irr
$ ./irrsteroexample sydney irr
$ ./irrsteroexample quake gl
$ ./irrsteroexample sydney gl
 
*/
 
#include <irrlicht.h>
#include <iostream>
#include <gl.h>
 
#include "stereo.hpp"
 
using namespace irr;
 
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
 
/********************
 * Functions to prepare left and right eyes
 * and then restore when finished
 * with OPENGL primitives.
 ****/
 
void prepareLeftEye_OPENGL (unsigned long ulLEyeKey) {
  glClear( GL_DEPTH_BUFFER_BIT ); 
  glMatrixMode( GL_MODELVIEW ); 
  glLoadIdentity(); 
  glColorMask( 0 != ( ulLEyeKey & 0x00ff0000 ), 
               0 != ( ulLEyeKey & 0x0000ff00 ), 
               0 != ( ulLEyeKey & 0x000000ff ), 
               0 != ( ulLEyeKey & 0xff000000 ) ); 
}
 
void prepareRightEye_OPENGL (unsigned long ulREyeKey) {
  glMatrixMode( GL_MODELVIEW ); 
  glLoadIdentity(); 
  glColorMask( 0 != ( ulREyeKey & 0x00ff0000 ), 
               0 != ( ulREyeKey & 0x0000ff00 ), 
               0 != ( ulREyeKey & 0x000000ff ), 
               0 != ( ulREyeKey & 0xff000000 ) ); 
}
 
void restore_OPENGL () {
  glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); 
}
 
/********************
 * Functions to prepare left and right eyes
 * and then restore when finished
 * with IRRLICHT primitives.
 ****/
 
void prepareRightEye_IRRLICHT (irr::video::IVideoDriver *pDriver) {
  pDriver->getOverrideMaterial().Material.ColorMask=ECP_GREEN+ECP_BLUE; // ECP_GREEN+ECP_BLUE
  pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK;
  pDriver->getOverrideMaterial().EnablePasses=
    ESNRP_SKY_BOX
    +ESNRP_SOLID
    +ESNRP_TRANSPARENT
    +ESNRP_TRANSPARENT_EFFECT
    +ESNRP_SHADOW;
}
 
void prepareLeftEye_IRRLICHT (irr::video::IVideoDriver *pDriver) {
  pDriver->getOverrideMaterial().Material.ColorMask=ECP_RED;
  pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK;
  pDriver->getOverrideMaterial().EnablePasses=
    ESNRP_SKY_BOX
    +ESNRP_SOLID
    +ESNRP_TRANSPARENT
    +ESNRP_TRANSPARENT_EFFECT
    +ESNRP_SHADOW;
}
 
void restore_IRRLICHT (irr::video::IVideoDriver *pDriver) {
  pDriver->getOverrideMaterial().Material.ColorMask=ECP_ALL;
  pDriver->getOverrideMaterial().EnableFlags=0;
  pDriver->getOverrideMaterial().EnablePasses=0;
}
 
bool DrawAnaglyph( enum EPrimitives primitives,
                   irr::video::IVideoDriver *pDriver, 
                   irr::scene::ISceneManager *pSm, 
                   irr::scene::ICameraSceneNode *pCamera, 
                   irr::video::SColor colBackground, 
                   float fWidth, float fFocus, int nDriverType, 
                   unsigned long ulREyeKey, unsigned long ulLEyeKey ) 
{ 
  // Right eye 
  irr::core::vector3df reye = pCamera->getPosition(); 
 
  // Left eye 
  irr::core::vector3df v( fWidth, 0, 0 ); 
  irr::core::matrix4 m; 
  m.setRotationDegrees( pCamera->getRotation() + irr::core::vector3df( 90.f, 0, 0 ) ); 
  m.transformVect( v ); 
  irr::core::vector3df leye = reye + v; 
 
  if (primitives == PRIMITIVES_OPENGL) {
    // Setup right eye 
    prepareRightEye_OPENGL (ulREyeKey) ;
  }
 
  //pDriver->beginScene( true, true, colBackground ); 
  pDriver->beginScene( true, true, SColor(0,200,200,255) );
 
  if (primitives == PRIMITIVES_IRRLICHT) {
    // Setup right eye 
    prepareRightEye_IRRLICHT (pDriver) ;
  }
 
  // Tried here (but with no success) some code from: http://irrlicht.sourceforge.net/forum/viewtopic.php?t=28893
  //pDriver->setRenderTarget (video::ERT_STEREO_BOTH_BUFFERS, true, true, video::SColor(0, 0, 0, 1)) ;
  //pDriver->setRenderTarget (video::ERT_STEREO_RIGHT_BUFFER, true, true, video::SColor(0, 0, 0, 1)) ;
 
  // Eye target 
  irr::core::vector3df oldt = pCamera->getTarget(); 
  irr::core::vector3df eyet = ( oldt - reye ).normalize() * fFocus; 
  pCamera->setTarget( eyet ); 
 
  pDriver->clearZBuffer();
 
  pSm->drawAll();  // right eye
 
  if (primitives == PRIMITIVES_OPENGL) {
    // Setup left Eye 
    prepareLeftEye_OPENGL (ulLEyeKey) ;
  }
 
  pDriver->clearZBuffer();
 
  if (primitives == PRIMITIVES_IRRLICHT) {
    // Setup left Eye 
    prepareLeftEye_IRRLICHT (pDriver) ;
  }
 
  pCamera->setPosition( leye ); 
  pCamera->OnRegisterSceneNode(); 
 
  // Tried here (but with no success) some code from: http://irrlicht.sourceforge.net/forum/viewtopic.php?t=28893
  //pDriver->setRenderTarget (video::ERT_STEREO_LEFT_BUFFER, true, true, video::SColor(0, 0, 0, 1)) ;
 
  pSm->drawAll(); // left eye
 
  pDriver->endScene(); 
 
  if (primitives == PRIMITIVES_OPENGL) {
    restore_OPENGL () ;
  }
  else if (primitives == PRIMITIVES_IRRLICHT) {
    restore_IRRLICHT (pDriver) ;
  }
 
  // Restore original position 
  pCamera->setPosition( reye ); 
  pCamera->setTarget( oldt ); 
 
  return true; 
} 
 

Code: Select all

 
// File stereo.hpp
#ifndef STEREO_HPP
#define STEREO_HPP
 
enum EPrimitives { PRIMITIVES_IRRLICHT , PRIMITIVES_OPENGL } ;
 
bool DrawAnaglyph( enum EPrimitives primitives,
                   irr::video::IVideoDriver *pDriver, 
                   irr::scene::ISceneManager *pSm, 
                   irr::scene::ICameraSceneNode *pCamera, 
                   irr::video::SColor colBackground, 
                   float fWidth, float fFocus, int nDriverType, 
                   unsigned long ulREyeKey, unsigned long ulLEyeKey ) ;
 
#endif /* STEREO_HPP */
 

Code: Select all

 
/* File: main.cpp
 
Red/Cyan anaglyph stereovision using Irrlicht engine under Linux width video::EDT_OPENGL driver.
 
Directly inspired by:
http://irrlicht.sourceforge.net/forum/viewtopic.php?p=185215
 
And for Irrlich primitives by
http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=33463
 
COMPILATION:
$ g++ -o irrsteroexample main.cpp stereo.cpp -I/usr/include/irrlicht/ -I/usr/include/GL/ -lIrrlicht -lGL
 
DOWNLOAD MEDIA NEEDED FOR RUNTIME:
$ mkdir ./media/
$ cd ./media/
$ wget https://github.com/zaki/irrlicht/blob/master/media/map-20kdm2.pk3
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.bmp
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.md2
 
USAGE:
$ ./irrsteroexample quake irr
$ ./irrsteroexample sydney irr
$ ./irrsteroexample quake gl
$ ./irrsteroexample sydney gl
 
*/
 
 
/** Example 002 Quake3Map
 
This Tutorial shows how to load a Quake 3 map into the engine, create a
SceneNode for optimizing the speed of rendering, and how to create a user
controlled camera.
 
Please note that you should know the basics of the engine before starting this
tutorial. Just take a short look at the first tutorial, if you haven't done
this yet: http://irrlicht.sourceforge.net/tut001.html 
 
Lets start like the HelloWorld example: We include the irrlicht header files
and an additional file to be able to ask the user for a driver type using the
console.
*/
#include <irrlicht.h>
#include <iostream>
 
#include "stereo.hpp"
 
using namespace irr;
 
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
/*
Again, to be able to use the Irrlicht.DLL file, we need to link with the
Irrlicht.lib. We could set this option in the project settings, but to make it
easy, we use a pragma comment lib:
*/
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
enum EModel { MODEL_QUAKE3MAP , MODEL_SYDNEY } ;
 
void usage (const char *program) {
  std::cerr << "Usage: " << program << " <model> <primitives>" << std::endl ;
  std::cerr << "  with model: quake|sydney" << std::endl ;
  std::cerr << "  and primitives: irr|gl" << std::endl ;
  exit (1) ;
}
 
/*
  Ok, lets start. Again, we use the main() method as start, not the WinMain().
*/
int main(int argc, char *argv[])
{
  enum EModel modelChoice ;
  enum EPrimitives primitivesChoice ;
 
  /* Command line treatment */
 
  // Count
  if (argc != 3) {
    usage(argv[0]) ;
  }
 
  // First arg
  if (!strcmp (argv[1], "quake")) {
    modelChoice = MODEL_QUAKE3MAP ;
  }
  else if (!strcmp (argv[1], "sydney")) {
    modelChoice = MODEL_SYDNEY ;
  }
  else {
    usage (argv[0]) ;
  }
 
  // Second arg
  if (!strcmp (argv[2], "irr")) {
    primitivesChoice = PRIMITIVES_IRRLICHT ;
  }
  else if (!strcmp (argv[2], "gl")) {
    primitivesChoice = PRIMITIVES_OPENGL ;
  }
  else {
    usage (argv[0]) ;
  }
 
  // create device and exit if creation failed
 
  IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(640, 480));
 
  if (device == 0)
    return 1; // could not create selected driver.
 
  video::IVideoDriver* driver = device->getVideoDriver();
  scene::ISceneManager* smgr = device->getSceneManager();
 
  device->getFileSystem()->addZipFileArchive("media/map-20kdm2.pk3");
 
  scene::ICameraSceneNode* Cam = smgr->addCameraSceneNodeFPS();
  scene::IAnimatedMesh* mesh = 0;
  scene::IAnimatedMeshSceneNode* node = 0;
 
  if (modelChoice == MODEL_QUAKE3MAP) {
    mesh = smgr->getMesh("20kdm2.bsp");
   
    if (mesh) {
      //node = smgr->addOctTreeSceneNode(mesh->getMesh(0), 0, -1, 1024);
      node = smgr->addAnimatedMeshSceneNode(mesh);
    }
 
    /*
      Because the level was not modelled around the origin (0,0,0), we
      translate the whole level a little bit.
    */
    if (node) {
      node->setPosition(core::vector3df(-1300,-144,-1249));
    }
 
  }
  else { /* modelChoice == MODEL_SYDNEY */
    mesh = smgr->getMesh("media/sydney.md2");
 
    if (mesh)
      node = smgr->addAnimatedMeshSceneNode( mesh );
 
    if (node) {
      node->setMaterialFlag(EMF_LIGHTING, false);
      node->setMD2Animation(scene::EMAT_STAND);
      node->setMaterialTexture( 0, driver->getTexture("media/sydney.bmp") );
    }
 
    Cam->setPosition(vector3df(0,30,-40)) ; 
  }
 
  /*
    The mouse cursor needs not be visible, so we hide it via the
    irr::IrrlichtDevice::ICursorControl.
  */
  device->getCursorControl()->setVisible(false);
 
  while(device->run())
    {
      if (device->isWindowActive())
        {
 
          DrawAnaglyph(
                       primitivesChoice,
                       driver, smgr, Cam,
                       video::SColor(0,200,200,255), // Background color (255,200,200,200)
                       2, // fWidth
                       1000, // fFocus
                       video::EDT_OPENGL,
                       0x000000ff, // ulREyeKey
                       0x00ffff00 // ulLEyeKey
                       );
 
          //driver->beginScene(true, true, video::SColor(255,200,200,200));
          //smgr->drawAll();
          //driver->endScene();
 
        }
      else
        device->yield();
    }
 
  /*
    In the end, delete the Irrlicht device.
  */
  device->drop();
  return 0;
}
 
/*
  That's it. Compile and play around with the program.
**/
 
Do someone has an idea how to make this work properly?

Thanks,
Guillaume
Last edited by Guillaum on Tue Dec 01, 2015 2:35 pm, edited 8 times in total.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: A working example for Red/Cyan Anaglyph Stereovision und

Post by mongoose7 »

The problem with Sydney appears to be that the focal length is not correct.

I wouldn't think that a software renderer would have the necessary functions for this work so don't use it.
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: A working example for Red/Cyan Anaglyph Stereovision und

Post by Guillaum »

Thanks much for your reply.

The problem is not the animated Sydney model, because the problem also appears when only moving an object:

Image

The encountered problem is not focal lenght or parallax values, but overriding or buffer cleaning.

For example, if the pass ESNRP_SOLID is removed from the overriding material like that:

Code: Select all

void prepareRightEye_IRRLICHT (irr::video::IVideoDriver *pDriver) {
  pDriver->getOverrideMaterial().Material.ColorMask=ECP_GREEN+ECP_BLUE; // ECP_GREEN+ECP_BLUE
  pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK;
  pDriver->getOverrideMaterial().EnablePasses=
    ESNRP_SKY_BOX
//    +ESNRP_SOLID
    +ESNRP_TRANSPARENT
    +ESNRP_TRANSPARENT_EFFECT
    +ESNRP_SHADOW;
}
 
void prepareLeftEye_IRRLICHT (irr::video::IVideoDriver *pDriver) {
  pDriver->getOverrideMaterial().Material.ColorMask=ECP_RED;
  pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK;
  pDriver->getOverrideMaterial().EnablePasses=
    ESNRP_SKY_BOX
//    +ESNRP_SOLID
    +ESNRP_TRANSPARENT
    +ESNRP_TRANSPARENT_EFFECT
    +ESNRP_SHADOW;
}
 
Then i obtain this:
http://www.guillaumeriviere.name/irr/videos/vid1.avi

But when it is activated, this is when the problem happens:
http://www.guillaumeriviere.name/irr/videos/vid2.avi

So, we can see that there is a problem of bad overrinding or cleaning of the frames.
Last edited by Guillaum on Sat Nov 28, 2015 8:03 pm, edited 1 time in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Vectrotek »

My opinion..
There is nothing wrong with what you're doing!
The "dirt" that you see is because you are not "clearing" the buffer and the polygons are moving causing "trails".
Now, you don't want to clear the buffer because you want to "overlay" the Blue
onto the Red or vice versa.
If you render the "Level" in Red, then also render the "Character" in Red,
then, and only then, render the "Level" AND "Character" in Blue again, in that order, then it should be fine.
It is however important that you don't allow the character to undergo any animation before you have rendered
both Blue and Red layers.
Only after all of the above was done and you have advanced your character animation by a frame you clear the buffers
and redo the render keeping in mind that Z Depth remain important throughout the whole process.
In other words..

1. Turn OFF "clear buffers".. (but keep Z Depth Testing activated if you're not sure which to render first)
2. Set Camera_Position to Eye_Left.
3. Render the Level in Red..
4. Render the Character in Red..
5. Set Camera_Position to Eye_Right but don't touch the Target..
6. Render the Level In Blue..
7. Render the Character in Blue..
8. Clear Buffer..

(you must test Blue versus Red as that depends on the glasses)

I think that's the issue. If you also render the background then the "trails" will disappear.
For renders without clear buffer you need something behind the main object to fill the whole screen even if it is a simple giant triangle.
It's about "What" you do "When".. Simply have something "behind" the object so that a clear is not needed..
Last edited by Vectrotek on Sun Nov 22, 2015 12:38 pm, edited 1 time in total.
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Guillaum »

Wow! Thanks much Vectrotek for your answer.

For the moment, i've moved on another project and have no time to focus on this. But i hope to have some time to spend again on this in December or January.

Well, i'm not concentrated and didn't catch every detail you give, but i get the overall idea. It is a good track to tackkle this problem. I will post my code once i will had the time to try this solution and will let you know.

Thanks much again, so exited to try this, crossing my fingers !!!
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Guillaum »

Hi,

Well, i've spend more time on this past days, tried again different directions, but some problems still happen.

As Vectrotek advice, i took care to the order in which things are done. I tried different order, but with no success.

Then i made one remark to myself: only the objects of the first drawAll() are badly cleared (left eye). But the objects of the second call to drawAll() are correctly cleared (right eye).

Then this is the idea of what i tried:

Code: Select all

bool DrawAnaglyph () {
 
   pDriver->beginScene( true, true, colBackground );
     pCamera->setPosition( leftEye );
     pCamera->setTarget( focusPoint );
     prepareLeftEye_IRRLICHT (pDriver) ;
     pSm->drawAll();
   pDriver->endScene( );
  
   pDriver->beginScene( true, true, colBackground );
     pCamera->setPosition( rightEye );
     pCamera->setTarget( focusPoint );
     prepareRightEye_IRRLICHT (pDriver) ;
     pSm->drawAll();
   pDriver->endScene( );
 
  restore_IRRLICHT (pDriver) ;
  pCamera->setTarget( oldt ); 
}
And then it works !!! The two objects of left and right eye are correctly cleared ! BUT.... it produces a flickering trouble :
http://www.guillaumeriviere.name/irr/videos/vid4.avi

:( :( :( so sad! was so close!!!

I then observe the parameters of the beginScene() method.
The first boolean is to ask for backBuffer clearing,
and the second boolean is to ask for zBuffer clearing.
Then i played with this, and i observed that it is the backBuffer clearing that make the solution (nearly) work.

So, i conclude on two things:
i) I must not call beginScene() and endScene() twice because of flickering effect (pushing two images on the screen at a time makes blinking)
ii) I need to clear the back buffer before rendering

Then, i go back to the documentation and see that i can clear the back buffer and Z buffer using the method setRenderTarget(). Let's go. This is the idea of what i tried :

Code: Select all

bool DrawAnaglyph () {
 
   pDriver->beginScene( true, true, colBackground );
 
     pDriver->setRenderTarget (video::ERT_STEREO_BOTH_BUFFERS, true, true, colBackground) ;
 
     pDriver->setRenderTarget (video::ERT_STEREO_LEFT_BUFFER, true, true, colBackground) ;
     pCamera->setPosition( leftEye );
     pCamera->setTarget( focusPoint );
     prepareLeftEye_IRRLICHT (pDriver) ;
     pSm->drawAll();
 
  
     pDriver->setRenderTarget (video::ERT_STEREO_RIGHT_BUFFER, true, true, colBackground) ;
     pCamera->setPosition( rightEye );
     pCamera->setTarget( focusPoint );
     prepareRightEye_IRRLICHT (pDriver) ;
     pSm->drawAll();
 
   pDriver->endScene( );
 
  restore_IRRLICHT (pDriver) ;
  pCamera->setTarget( oldt ); 
}
With the following device init:

Code: Select all

  //device init
  SIrrlichtCreationParameters params;
  params.AntiAlias = 0;
  params.Bits = 32;
  params.DeviceType = EIDT_X11;
  params.Doublebuffer = true;
  params.DriverType = video::EDT_OPENGL;
  params.EventReceiver = 0;
  params.Fullscreen = false;
  params.HighPrecisionFPU = false;
  params.IgnoreInput = false;
  params.LoggingLevel = ELL_INFORMATION;
  params.Stencilbuffer = true;
  params.Stereobuffer = false;
  params.Vsync = true;
  params.WindowSize.Width = 640;
  params.WindowSize.Height = 480;
  params.WithAlphaChannel = false;
  params.ZBufferBits = 16;
  IrrlichtDevice *device = createDeviceEx(params);
 
But it works as if the setRenderTarget() doesn't clear the back buffer and the problem of not correctly clearing the first draw of the left eye still happen:

http://www.guillaumeriviere.name/irr/videos/vid3.avi

What do i miss ? :x :shock: :roll: :?:
Last edited by Guillaum on Sat Nov 28, 2015 8:03 pm, edited 2 times in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Vectrotek »

What happens when you REPLACE the SECOND (not the first) occurrence of the line..

Code: Select all

pDriver->setRenderTarget (video::EDT_OPENGL --or-- EDT_DIRECT3F9, true, true, colBackground) ;
to

Code: Select all

pDriver->setRenderTarget (video::EDT_OPENGL --or-- EDT_DIRECT3F9, false, true, colBackground) ; // Changed the first "true" to "false"..
That would be the same as only clearing the buffer after the SECOND CAMERA was rendered..(I think)
(If that doesn't work then I'll try sending something if I ever try it..)
Don't give up though, I'm sure its a small problem..

Oh, I'm also not sure, but your Stereo graphic render is not True Stereoscopic render for which you'd need "ERT_STEREO_RIGHT_BUFFER",
try doing your Blue Red trick normally. i.e. to a normal buffer.

I'd love to see this work, so keep discussing this..
(keep sending small screenshots, it always helps)
Maybe even a compileable project or complete code so that we can try duplicate what you're doing..
Last edited by Vectrotek on Fri Nov 27, 2015 3:08 pm, edited 1 time in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Vectrotek »

Try not going the "ERT_STEREO_RIGHT_BUFFER" etc route, because your'e using Blue and Red for your effect..
I think "ERT_STEREO_LEFT_BUFFER" * "ERT_STEREO_RIGHT_BUFFER" only comes into play when you've got Stereoscopic Hardware
like the Occulus Rift.
Try rendering your Red and Blue to the SAME buffer..

It should be a matter of simply rendering to the SAME buffer twice, once without Clearing and once with Clearing (inside a single begin and end).
It MUST BE POSSIBLE, so keep trying. :?
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Guillaum »

I already tried to set params.Stereobuffer to true but the program crashes at runtime, with that message:
No stencilbuffer available, disabling stencil shadows.
No doublebuffering available.
Fatal error, could not get visual.


Setting params.Stereobuffer to true is only for graphic cards with two separate output, as Stereo Hardware. I'm a little bit lost, so i try every possibility ! But you are right, i don't need to use ERT_STEREO_LEFT_BUFFER and ERT_STEREO_RIGHT_BUFFER which are only for Stereo Hardware.

As you proposed, i've tried to use the following call to reset backBuffer:

Code: Select all

pDriver->setRenderTarget (video::EDT_OPENGL, true, true, colBackground) ;
Then, it now works to properly clear the back buffer. But then, everything is cleared. Finally, when i was thinking it was only a problem of clearing the back buffer when trying this solution, because it was nearly working (excepted flickering problem):

Code: Select all

bool DrawAnaglyph () {
 
   pDriver->beginScene( true, true, colBackground );
     pCamera->setPosition( leftEye );
     pCamera->setTarget( focusPoint );
     prepareLeftEye_IRRLICHT (pDriver) ;
     pSm->drawAll();
   pDriver->endScene( );
  
   pDriver->beginScene( true, true, colBackground );
     pCamera->setPosition( rightEye );
     pCamera->setTarget( focusPoint );
     prepareRightEye_IRRLICHT (pDriver) ;
     pSm->drawAll();
   pDriver->endScene( );
 
  restore_IRRLICHT (pDriver) ;
  pCamera->setTarget( oldt ); 
}
http://www.guillaumeriviere.name/irr/videos/vid4.avi

But now i understand that two images were alternatively pushed to the screen and it was only eye persistency (50ms) which made believe that it was close to work.

So, coming back to my first problem, i still don't understand why the second (last) draw (for the right eye) is correctly cleared, and why the first draw (for the left eye) which is not correctly cleared.
Last edited by Guillaum on Sat Nov 28, 2015 8:02 pm, edited 1 time in total.
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Guillaum »

Here is my current code after cleaning previous attemps.

Now, it is closer to this snippet:
http://irrlicht3d.org/wiki/index.php?n= ... hRendering
But, as i've commented here
http://irrlicht.sourceforge.net/forum/v ... d&start=15
a call to

Code: Select all

camera->updateAbsolutePosition();
had to be added in my Irrlicht 1.8 program.

Code: Select all

/* File: stereo.cpp
 
Red/Cyan anaglyph stereovision using Irrlicht engine under Linux width video::EDT_OPENGL driver.
 
Directly inspired by:
http://irrlicht.sourceforge.net/forum/viewtopic.php?p=185215
 
And for Irrlich primitives by
http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=33463
http://irrlicht3d.org/wiki/index.php?n=Main.AnaglyphRendering
 
COMPILATION:
$ g++ -o irrsteroexample main.cpp stereo.cpp -I/usr/include/irrlicht/ -I/usr/include/GL/ -lIrrlicht -lGL
 
DOWNLOAD MEDIA NEEDED FOR RUNTIME:
$ mkdir ./media/
$ cd ./media/
$ wget https://github.com/zaki/irrlicht/blob/master/media/map-20kdm2.pk3
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.bmp
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.md2
 
USAGE:
$ ./irrsteroexample quake
$ ./irrsteroexample sydney
 
*/
 
#include <irrlicht.h>
#include <iostream>
#include <gl.h>
 
#include "stereo.hpp"
 
using namespace irr;
 
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
void DrawAnaglyph3 (
                   irr::video::IVideoDriver *pDriver, 
                   irr::scene::ISceneManager *pSm, 
                   irr::scene::ICameraSceneNode *pCamera, 
                   irr::video::SColor colBackground
)
{
   vector3df oldPosition=pCamera->getPosition();
   vector3df oldTarget=pCamera->getTarget();
   
   pCamera->updateAbsolutePosition(); //== Added this in Irrlicht 1.8
   matrix4 startMatrix=pCamera->getAbsoluteTransformation();
 
   vector3df focusPoint= (pCamera->getTarget()-pCamera->getAbsolutePosition()).setLength(1) + pCamera->getAbsolutePosition() ;
 
   //Left eye move...
   vector3df leftEye;
   matrix4 leftMove;
   leftMove.setTranslation( vector3df(-0.01f,0.0f,0.0f) );
   leftEye=(startMatrix*leftMove).getTranslation();
   u8 leftMask = ECP_RED ;
 
   //Right eye move...
   vector3df rightEye;
   matrix4 rightMove;
   rightMove.setTranslation( vector3df(0.01f,0.0f,0.0f) );
   rightEye=(startMatrix*rightMove).getTranslation();
   u8 rightMask=ECP_GREEN+ECP_BLUE ;
 
   //clear the depth buffer, and color
   pDriver->beginScene( true, true, colBackground );
 
   //Left eye...
 
   pCamera->setPosition( leftEye );
   pCamera->setTarget( focusPoint );
 
   pDriver->getOverrideMaterial().Material.ColorMask=leftMask;
   pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK ;
   pDriver->getOverrideMaterial().EnablePasses=ESNRP_SKY_BOX+ESNRP_SOLID+ESNRP_TRANSPARENT+ESNRP_TRANSPARENT_EFFECT+ESNRP_SHADOW;
 
   pSm->drawAll();
   
   //clear the depth buffer
   pDriver->clearZBuffer();
 
   //Right eye...
 
   pCamera->setPosition( rightEye );
   pCamera->setTarget( focusPoint );
 
   pDriver->getOverrideMaterial().Material.ColorMask=rightMask;
   pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK ;
   pDriver->getOverrideMaterial().EnablePasses=ESNRP_SKY_BOX+ESNRP_SOLID+ESNRP_TRANSPARENT+ESNRP_TRANSPARENT_EFFECT+ESNRP_SHADOW;
 
   pSm->drawAll();
 
   pDriver->endScene();
 
   pDriver->getOverrideMaterial().Material.ColorMask=ECP_ALL;
   pDriver->getOverrideMaterial().EnableFlags=0;
   pDriver->getOverrideMaterial().EnablePasses=0;
 
   pCamera->setPosition( oldPosition );
   pCamera->setTarget( oldTarget );
 
}

Code: Select all

 
// File: stereo.hpp
#ifndef STEREO_HPP
#define STEREO_HPP
 
void DrawAnaglyph3 (
                   irr::video::IVideoDriver *pDriver, 
                   irr::scene::ISceneManager *pSm, 
                   irr::scene::ICameraSceneNode *pCamera, 
                   irr::video::SColor colBackground
                    );
 
#endif /* STEREO_HPP */
 

Code: Select all

/* File: main.cpp
 
Red/Cyan anaglyph stereovision using Irrlicht engine under Linux width video::EDT_OPENGL driver.
 
Directly inspired by:
http://irrlicht.sourceforge.net/forum/viewtopic.php?p=185215
 
And for Irrlich primitives by
http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=33463
http://irrlicht3d.org/wiki/index.php?n=Main.AnaglyphRendering
 
COMPILATION:
$ g++ -o irrsteroexample main.cpp stereo.cpp -I/usr/include/irrlicht/ -I/usr/include/GL/ -lIrrlicht -lGL
 
DOWNLOAD MEDIA NEEDED FOR RUNTIME:
$ mkdir ./media/
$ cd ./media/
$ wget https://github.com/zaki/irrlicht/blob/master/media/map-20kdm2.pk3
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.bmp
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.md2
 
USAGE:
$ ./irrsteroexample quake
$ ./irrsteroexample sydney
 
*/
 
 
/** Example 002 Quake3Map
 
This Tutorial shows how to load a Quake 3 map into the engine, create a
SceneNode for optimizing the speed of rendering, and how to create a user
controlled camera.
 
Please note that you should know the basics of the engine before starting this
tutorial. Just take a short look at the first tutorial, if you haven't done
this yet: http://irrlicht.sourceforge.net/tut001.html 
 
Lets start like the HelloWorld example: We include the irrlicht header files
and an additional file to be able to ask the user for a driver type using the
console.
*/
#include <irrlicht.h>
#include <iostream>
 
#include "stereo.hpp"
 
using namespace irr;
 
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
/*
Again, to be able to use the Irrlicht.DLL file, we need to link with the
Irrlicht.lib. We could set this option in the project settings, but to make it
easy, we use a pragma comment lib:
*/
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
enum EModel { MODEL_QUAKE3MAP , MODEL_SYDNEY } ;
 
void usage (const char *program) {
  std::cerr << "Usage: " << program << " <model>" << std::endl ;
  std::cerr << "  with model: quake|sydney" << std::endl ;
  exit (1) ;
}
 
/*
  Ok, lets start. Again, we use the main() method as start, not the WinMain().
*/
int main(int argc, char *argv[])
{
  enum EModel modelChoice ;
 
  /* Command line treatment */
 
  // Count
  if (argc != 2) {
    usage(argv[0]) ;
  }
 
  // First arg
  if (!strcmp (argv[1], "quake")) {
    modelChoice = MODEL_QUAKE3MAP ;
  }
  else if (!strcmp (argv[1], "sydney")) {
    modelChoice = MODEL_SYDNEY ;
  }
  else {
    usage (argv[0]) ;
  }
 
  //device init
  SIrrlichtCreationParameters params;
  params.AntiAlias = 0;
  params.Bits = 32; // 32
  params.DeviceType = EIDT_X11; // EIDT_X11 EIDT_BEST
  params.Doublebuffer = true;
  params.DriverType = video::EDT_OPENGL; // EDT_OPENGL
  params.EventReceiver = 0;
  params.Fullscreen = false;
  params.HighPrecisionFPU = false;
  params.IgnoreInput = false;
  params.LoggingLevel = ELL_INFORMATION;
  params.Stencilbuffer = true; // true
  params.Stereobuffer = false; //== false
  params.Vsync = true; //== false
  // Specify which window/widget to render to
  //params.WindowId = reinterpret_cast<void*>(winId());
  params.WindowSize.Width = 640;
  params.WindowSize.Height = 480;
  params.WithAlphaChannel = false;
  params.ZBufferBits = 16;
 
 
  // create device and exit if creation failed
 
  IrrlichtDevice *device = createDeviceEx(params); // , core::dimension2d<u32>(640, 480)
 
  if (device == 0)
    return 1; // could not create selected driver.
 
  video::IVideoDriver* driver = device->getVideoDriver();
  scene::ISceneManager* smgr = device->getSceneManager();
 
  device->getFileSystem()->addZipFileArchive("media/map-20kdm2.pk3");
 
  scene::ICameraSceneNode* Cam = smgr->addCameraSceneNodeFPS();
  scene::IAnimatedMesh* mesh = 0;
  scene::IAnimatedMeshSceneNode* node = 0;
 
  if (modelChoice == MODEL_QUAKE3MAP) {
    mesh = smgr->getMesh("20kdm2.bsp");
   
    if (mesh) {
      //node = smgr->addOctTreeSceneNode(mesh->getMesh(0), 0, -1, 1024);
      node = smgr->addAnimatedMeshSceneNode(mesh);
    }
 
    /*
      Because the level was not modelled around the origin (0,0,0), we
      translate the whole level a little bit.
    */
    if (node) {
      node->setPosition(core::vector3df(-1300,-144,-1249));
    }
 
  }
  else { /* modelChoice == MODEL_SYDNEY */
    mesh = smgr->getMesh("media/sydney.md2");
 
    if (mesh)
      node = smgr->addAnimatedMeshSceneNode( mesh );
 
    if (node) {
      node->setMaterialFlag(EMF_LIGHTING, false);
      node->setMD2Animation(scene::EMAT_STAND);
      node->setMaterialTexture( 0, driver->getTexture("media/sydney.bmp") );
    }
 
    Cam->setPosition(vector3df(0,30,-40)) ; 
  }
 
  /*
    The mouse cursor needs not be visible, so we hide it via the
    irr::IrrlichtDevice::ICursorControl.
  */
  device->getCursorControl()->setVisible(false);
 
  while(device->run())
    {
      if (device->isWindowActive())
        {
 
          DrawAnaglyph3(
                       driver, smgr, Cam,
                       video::SColor(0,200,200,255) // Background color
                       );
 
          //driver->beginScene(true, true, video::SColor(255,200,200,200));
          //smgr->drawAll();
          //driver->endScene();
 
        }
      else
        device->yield();
    }
 
  /*
    In the end, delete the Irrlicht device.
  */
  device->drop();
  return 0;
}
 
/*
  That's it. Compile and play around with the program.
**/
 
Last edited by Guillaum on Sat Nov 28, 2015 8:01 pm, edited 1 time in total.
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Guillaum »

I've tried different masks:

u8 leftMask = ECP_RED ;
u8 rightMask=ECP_GREEN+ECP_BLUE ;

u8 leftMask = ECP_RED+ECP_ALPHA ;
u8 rightMask=ECP_GREEN+ECP_BLUE+ECP_ALPHA ;

u8 leftMask = ECP_RED ;
u8 rightMask=ECP_RED ;

u8 leftMask = ECP_GREEN+ECP_BLUE ;
u8 rightMask=ECP_GREEN+ECP_BLUE ;

u8 leftMask = ECP_BLUE ;
u8 rightMask=ECP_BLUE ;

u8 leftMask = ECP_GREEN ;
u8 rightMask=ECP_BLUE ;

Then i observe again that it is the first (left eye) draw which is badly cleared.

I also observe that ECP_ALPHA do not change anything.

I finally observe that the fist draw is correctly cleared when the two left and right masks are the identical.
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Guillaum »

Next try will be to test the code next week on another PC under Linux with a different graphic card.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Vectrotek »

Mmm.. I can see that this problem is not as simple as I'd initially assumed!
For one thing, there will be a need for a small vector between the two camera positions that would mathematically
have to be constantly kept "Perpendicular" to a line that STARTS at the "Center Point" of the two "Camera Positions" and ENDS at the
common "Target" or "Focal Point" of the two Cameras.
This means that two "Camera positions" would not be moved manually but rather be the result of moving
the "Center Point" or "Handle" for the two Cameras. (can get quite complicated).
One serious implication of this is that the old "FPS" method of camera control under Irrlicht can
no longer be used!

I'm currently working on a small app that sends large arrays of lights to HLSL and GLSL Shaders.
When I'm done with that I'll try compiling and running your code. (I'm running Windows XP).
Solving this would be really great for a future in which we can all afford occulus systems so keep going!

If I get any joy with this I'll certainly post it.

Good luck Guillaum and keep us posted on your progress!
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Vectrotek »

I know this is not a solution to your immediate problem
but it is something you may want to consider once you get
the thing working. Here is a diagram to explain what I tried
to say in the last post..

Image
You probably have a THIRD camera at the "Handle" point too
as I assume from your "Quake Level" screen shot earlier..
Guillaum
Posts: 23
Joined: Fri Oct 23, 2015 4:57 pm
Location: France

Re: Overriding or clearing problem in Red/Cyan Anaglyph Ster

Post by Guillaum »

Thanks for your support Vectrotek!

I've done some more investigations on the direction of my hardware and driver.

Let's recall i'm using a NVIDIA Quadro NVS 3100M (GT218M) under Thinkpad T410 laptop.
This laptop is using NVidia Optimus.

Then i've installed bumblebee (which is NVIDIA Optimus support for Linux) and went back to my BIOS to activate Optimus (because until now i was on Integrated graphics). And i played with all the three possibilities half of the afternoon:
* Integrated graphics
* Discrete graphics
* NVIDIA Optimus
Image

Then launching the program with optirun (provided by bumblebee):
$ optirun ./irrsteroexample sydney

I also played with the drivers. I was using the Proprietary NVidia current driver 340.65 (under Debian Jessie 8.2).
I tried the legacy Proprietary NVidia driver (304.125) which is also compatible with my Quadro NVS3100M graphic card.
Finally, i tried to come back to the default Open Source driver xorg-nouveau with acceleration (libgl1-mesa-glx and libgl1-mesa-dri).

I was able to run the program in 3D for each of the previous configurations.
But nothing changed, the problem always happens! :mrgreen:
Was a nice afternoon... :?

So, i keep on the track, and will try on PCs (not laptop) with other (more simple?) graphic cards.

Thanks in advance if you can test under Windows XP, because i'm not very confortable with installing all developping tools under Windows, would take lot of time for me because i have only "empty" Windows because i always develop under Linux. It would be a great information to know if it works under Windows, but also with what hardware configuration (laptop/desktop and Graphic Card).
Last edited by Guillaum on Sat Nov 28, 2015 8:17 pm, edited 3 times in total.
Post Reply