Results 1 to 3 of 3

Thread: OpenGL offscreen rendering in a thread

  1. #1
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    369
    Thanks
    87
    Thanked 13 Times in 13 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default OpenGL offscreen rendering in a thread

    Hello there!

    I could use a little help with an offscreen rendering procedure that needs to run in its own thread. I have already programmed a function that uses OpenGL commands to render a scene and to read the color and depth buffers into local buffers. However, right now this is all inside the draw() function of a QGLViewer and so the offscreen rendering happens whenever the gui is drawn. I need to figure out a way to separate the offscreen rendering into its own class that would run as a separate thread at a configurable frame rate.

    After some research I can see that there are split opinions whether it makes sense to pursue this goal at all. Some argue that all OpenGL rendering should be in one thread, some argue that they don't, both giving arguments that seem legit. In my case, the configurable frequency is important so I would like it to be independent from the gui thread. On the other hand, this offscreen rendering, which is really an RGB-D camera simulator, is a data acquisition process that belongs into the deepest layers of the software and is as far from the gui as Sydney from New York. It sends a cold shiver down my spine to think I would have to embed this data pipeline into a gui component.

    This was my first naive attempt:

    Qt Code:
    1. // A thread object just to run things.
    2. class SimulatedCameraThread : public QThread
    3. {
    4. SimulatedCamera simulatedCamera; // This is actually a QGLViewer widget
    5. void init();
    6. void run();
    7. };
    8.  
    9. // Initialization function executed once after construction.
    10. void SimulatedCameraThread::init()
    11. {
    12. simulatedCamera.init();
    13. simulatedCamera.show(); // urgh!
    14. }
    15.  
    16. // The loop of the QThread.
    17. void SimulatedCameraThread::run()
    18. {
    19. // Run in an infinite loop and keep rendering.
    20. while (true)
    21. {
    22. simulatedCamera.update();
    23. msleep(100); // Here is where I can configure the frame rate.
    24. }
    25. }
    26.  
    27. // A widget class that encapsulates the OpenGL frame grabbing.
    28. class SimulatedCamera: public QGLViewer
    29. {
    30. void init();
    31. void grab();
    32. void draw();
    33. };
    34.  
    35. void SimulatedCamera::init()
    36. {
    37. glewInit();
    38. }
    39.  
    40. // Grabs a frame using OpenGL and writes it into memory.
    41. void SimulatedCamera::grab()
    42. {
    43. glMatrixMode(GL_PROJECTION);
    44. glPushMatrix();
    45.  
    46. // Bunch of OpenGL code that grabs a frame into a buffer.
    47.  
    48. glPopMatrix();
    49. glPopAttrib();
    50. }
    51.  
    52. // Override QGLViewer.
    53. void SimulatedCamera::draw()
    54. {
    55. grab();
    56. }
    To copy to clipboard, switch view to plain text mode 

    I derived a class from QThread and in its run() method I start an infinite loop where update() is called in succession with a sleep. With this I was aiming at simulating what the gui thread would do: calling update() on the widget whenever it needs to be redrawn. The simulated camera is inside the QThread and derives from QGLViewer, which itself is a subclass of QOpenGLWidget and so we can treat it as if it were a QOpenGLWidget for all purposes. By overriding draw(), I have control over the rendering. All of this works surprisingly well, were it not for having to call show() in the init() function of the QThread.
    I found that if I don't call show(), update() does nothing, presumably because the widget is not visible. If I do call show, weird things happen when the gui opens, but it recovers and tadaa, the offscreen rendering works like a charm.

    Now, guys, please, what do I do to get rid of the show()?

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,775
    Thanks
    262
    Thanked 773 Times in 763 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: OpenGL offscreen rendering in a thread

    If calling show() actually makes something visible on screen, then it doesn't seem like you are running a separate thread at all. All Qt graphics calls must be executed from within the main thread, so if show() works, it implies that you are still in the main thread.

    If you look at the example in the QThread documentation, is your architecture something like that? Do you have a "worker" object that does the rendering under the control of a QThread instance, and is the worker instance actually moved into control of the thread?
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    369
    Thanks
    87
    Thanked 13 Times in 13 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: OpenGL offscreen rendering in a thread

    show() is called by the main thread, this is true. I don't know what happens to the widget then, but I know for sure that then the run() method starts updating the widget at the rate I wanted and the rendering works fine.
    In the meantime I figured out that if I set these flags in the constructor:

    Qt Code:
    1. SimulatedCamera::SimulatedCamera(QWidget *parent) : QGLViewer(parent)
    2. {
    3. setWindowFlags(Qt::CoverWindow);
    4. setAttribute(Qt::WA_DontShowOnScreen);
    5. setAutoBufferSwap(false);
    6. }
    To copy to clipboard, switch view to plain text mode 

    then the widget is not shown and doesn't spam error messages related to the double buffering. I am not sure how many eyes I made roll with this approach, but it does work perfectly as expected now.
    Last edited by Cruz; 26th November 2020 at 09:53.

Similar Threads

  1. Qwt and Offscreen Rendering (Qt 5)
    By bigjoeystud in forum Qwt
    Replies: 0
    Last Post: 9th June 2016, 23:43
  2. OpenGL rendering in separate thread, Qt 5.0.1
    By jaf in forum Qt Programming
    Replies: 3
    Last Post: 28th October 2015, 00:03
  3. Replies: 0
    Last Post: 26th June 2013, 19:23
  4. Do offscreen render(openGL) with Qt5
    By stereoMatching in forum Qt Programming
    Replies: 4
    Last Post: 26th June 2013, 12:34
  5. Rendering offscreen with QGLWidget
    By jcox23 in forum Qt Programming
    Replies: 4
    Last Post: 29th January 2013, 15:37

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.