Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 10

Thread: Render one scene to multiple windows with same context

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    64

    Lightbulb Render one scene to multiple windows with same context

    Hello,

    I read some articles how to draw for example in my case one triangle to two different top-level windows. They are both sharing context.
    My hierarchy is following:
    > Application > MainWindow > GraphicsWindow1 > Triangle
    > GraphicsWindow2 (contains link to GraphicsWindow1)

    Problem:
    When GraphicsWindow2 renders he take Triangle from GW1 and calls Draw. I suppose that should be all. But there is not drawed triangle in GW2.

    My goals: render in GW2 same thing as in GW1 but with different camera. Also I tried to build this with some efficient like few lines of code.

    Source code is available on github: https://github.com/glararan/Qt-OpenGL

    GraphicsWindow inherits from GLWindow which inherits from QOpenGLWindow.

    GraphicsWindow location: https://github.com/glararan/Qt-OpenG...hicswindow.cpp
    Triangle location: https://github.com/glararan/Qt-OpenG...e/triangle.cpp
    Shaders are located here: https://github.com/glararan/Qt-OpenG.../shaders/basic

    I have to missing something, just I don't know what.

    Thanks for help!

  2. #2
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    64
    Well I figured out, that problem is located in Triangle.cpp file in Draw function. It seems VAO can't be shared for multiple windows?

    Code :
    void Triangle::Draw(const QMatrix4x4& mvp){
        qDebug() << "Triangle target1:\t" << QOpenGLContext::currentContext()->surface() << "\t" << functions->glGetError(); // returns Triangle target1:	 0x10d6a98 	 0
     
     
        shader->bind();
        qDebug() << "Triangle target2:\t" << QOpenGLContext::currentContext()->surface() << "\t" << functions->glGetError(); // returns Triangle target2:	 0x10d6a98 	 0
        {
            shader->setUniformValue(mvpLoc, mvp);
     
     
            qDebug() << "Triangle target3:\t" << QOpenGLContext::currentContext()->surface() << "\t" << functions->glGetError(); // returns Triangle target3:	 0x10d6a98 	 0
            //glBindVertexArray(vao);
            vao.bind(); // when I move qDebug() "target3" it returns glGetErrors() 1282
     
     
            functions->glDrawArrays(GL_TRIANGLES, 0, 3);
            vao.release();
     
     
            qDebug() << "Triangle target4:\t" << QOpenGLContext::currentContext()->surface() << "\t" << functions->glGetError(); // returns Triangle target4:	 0x10d6a98 	 1282
        }
        shader->release();
    }

    How would you solve this?

    When I want to draw same scene in two windows.. always create vao for each sub-object?

    Thanks

  3. #3
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,926
    Quote Originally Posted by glararan View Post
    It seems VAO can't be shared for multiple windows?
    VAOs aren't shared between contexts. More generally, objects which contain references to other objects aren't shared (more details here).

    Quote Originally Posted by glararan View Post
    How would you solve this?
    The simplest way is not to use a different context for each window. But that isn't an option if the windows may be on different physical displays, or if you need to render from multiple threads concurrently.

    If you need to use multiple contexts, then create a copy of the VAO for each context. Note that you can't force them to have the same name (handle) in different contexts, so you'll need some way to find the correct VAO for a given context.

  4. #4
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    64
    Quote Originally Posted by GClements View Post
    VAOs aren't shared between contexts. More generally, objects which contain references to other objects aren't shared (more details here).


    The simplest way is not to use a different context for each window. But that isn't an option if the windows may be on different physical displays, or if you need to render from multiple threads concurrently.

    If you need to use multiple contexts, then create a copy of the VAO for each context. Note that you can't force them to have the same name (handle) in different contexts, so you'll need some way to find the correct VAO for a given context.
    Ok so, I'm currently sharing context so I have to recreate for second window vao.

    EDIT:

    So for let this working I had to make this edit:
    Code :
    void Triangle::Draw(const QMatrix4x4& mvp, bool copy){
        shader->bind();
        {
            shader->setUniformValue(mvpLoc, mvp);
     
     
            if(!copy)
            {
                //glBindVertexArray(vao);
                vao.bind();
     
     
                functions->glDrawArrays(GL_TRIANGLES, 0, 3);
                vao.release();
            }
            else
            {
                vbo.bind();
     
     
                QOpenGLVertexArrayObject _vao;
                _vao.create();
                _vao.bind();
     
     
                shader->enableAttributeArray(0);
                shader->enableAttributeArray(1);
                shader->setAttributeBuffer(0, GL_FLOAT, 0, 2, 0);
                shader->setAttributeBuffer(1, GL_FLOAT, 6 * sizeof(GLfloat), 3, 0);
     
     
                _vao.bind();
     
     
                functions->glDrawArrays(GL_TRIANGLES, 0, 3);
     
     
                _vao.release();
                vbo.release();
            }
        }
        shader->release();
    [FONT=Verdana]}[/FONT][COLOR=#000000][/COLOR]


    Any idea how to make this better?
    Last edited by glararan; 07-18-2016 at 08:28 AM.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,926
    Quote Originally Posted by glararan View Post
    Code :
                vbo.bind();
     
                QOpenGLVertexArrayObject _vao;
                _vao.create();
                _vao.bind();
    First, binding the VBO serves no purpose here, because attribute array bindings are stored in the current VAO.

    Second, you shouldn't be creating a new VAO for each call to the Draw method; you should be storing it. Currently, GLObject has a member variable, vao of type QOpenGLVertexArrayObject, whereas it should probably have a vector/map/etc of such, with the context (or some context-related property) as the key. Or the window class should have a vector/map/etc, with the object as a key.

    But unless you actually need multiple contexts, you should just use a single context for all windows. Ignore the context which Qt creates and explicitly use makeCurrent() to make the global context current.

  6. #6
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    64
    Quote Originally Posted by GClements View Post
    First, binding the VBO serves no purpose here, because attribute array bindings are stored in the current VAO.

    Second, you shouldn't be creating a new VAO for each call to the Draw method; you should be storing it. Currently, GLObject has a member variable, vao of type QOpenGLVertexArrayObject, whereas it should probably have a vector/map/etc of such, with the context (or some context-related property) as the key. Or the window class should have a vector/map/etc, with the object as a key.

    But unless you actually need multiple contexts, you should just use a single context for all windows. Ignore the context which Qt creates and explicitly use makeCurrent() to make the global context current.

    1) When I dont bind VBO while creating VAO app crashes. But I dont want to have multiple vao
    2) Yes I know but it was fast debug, sorry GLObject variable vao is for main window where scene is rendered correctly, while I bind same vao while drawing on second window, nothing is rendered.
    3) I am using single context, the one created by main window. makeCurrent using in GLWindow::renderNow() look below.

    Code :
    void GLWindow::renderNow(){
        if(!isExposed())
            return;
     
     
        if(!painted)
            return;
     
     
        painted = false;
     
     
        QOpenGLWindow::makeCurrent();
     
     
        QOpenGLWindow::update();
     
     
        context()->swapBuffers(this);
     
     
        if(draw && !pendingUpdate)
        {
            pendingUpdate = false;
     
     
            QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
        }
    }

    So if I correct understand, I should create one global context before I even create mainwindow and use it for both windows.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •