Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Is it possible to set the QOpenGLWidget internal resolution independently from the widget size?



  • I'm using QOpenGLWidget widget in a QGraphicsView/Scene, this widget should be able to display images that can be huge, in QOpenGLWidget this slows down the application immensely since the OpenGL window is at the size of the widget which is at the size of the huge image even though the visible displayed window is always small, equal or less than the size of the screen.

    In other words, is there a way to make the widget rendering resolution the same size as the "physical" widget size on screen instead of always rendering at the potentially huge image size?

    PS: I know I can scale the widget myself, but this will force me to change the size and location of every other widget in the QGraphicsView, I'd like to avoid this if possible. Grabbing the frambuffer to a QImage then scaling that up might be an option, but it is also somewhat slow, I'd like to avoid that too if possible.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    How are you doing the rendering in your OpenGL widget ?



  • A texture on 2 triangles that are drawn directly to the buffer, this is the basic paintGL loop:

    glClear(GL_COLOR_BUFFER_BIT);
    glBindTexture(GL_TEXTURE_2D, texture);
    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glFinish();
    

    Note that even with an empty scene it is still slow, even when rendering nothing, the inefficiency comes from the size of the GL widget.


  • Lifetime Qt Champion

    What size has it ?
    How do you set its size ?
    What kind of graphics card do you have ?



  • It's should be able to display any image as big as OpenGL can handle, but even 2000X2000 is slow. Note that even huge 5000X5000 images work fine and fast in a standalone OpenGL app that has the same logic as the Qt one. the only difference is it has a reasonable window size.

    I set the size by resizing the widget, I need the widget to be the same size as the image in the QGraphicsView,. Ideally I would render the widget at the small displayed size then scale the output if needed, but I couldn't find an option of scaling the widget without altering its resolution or using slow method like QImage grabbing.

    GTX1060, the 6GB version.


  • Lifetime Qt Champion

    Can you show a minimal compilable example that exhibit this behavior ?

    Did you set the viewport of the QGraphicsView to also be a QOpenGLWidget ?



  • Did you set the viewport of the QGraphicsView to also be a QOpenGLWidget ?

    No, QOpenGLWidget is just a widget in the QGraphicsScene, the QGraphicsView has the default viewport. Is this the wrong way to go about displaying an OpenGL texture?


  • Lifetime Qt Champion

    Can you share the code you use to setup that ?
    I am really not sure I am following you correctly.



  • @HUUD said in Is it possible to set the QOpenGLWidget internal resolution independently from the widget size?:

    I'm using QOpenGLWidget widget in a QGraphicsView/Scene, this widget should be able to display images that can be huge

    Are you sure you need to do this? Where is your source OpenGL texture coming from?
    Ultimately, you just want to draw your texture into the same widget as the QGraphicsScene, right? You can use an OpenGL Widget as the viewport of the graphics scene, and just handle drawing that texture yourself. https://doc.qt.io/qt-5/qgraphicsview.html documents how to use an OpenGL Viewport.

    I suspect what's currently happening is

    • You make your texture (Where is that coming from?)

    • You draw it full resolution into the offscreen widget, copying the full size of the texture on the GPU.

    • The contents of that widget get copied into CPU memory, again at full size.

    • The image in memory is used in drawing the QGraphics scene, which round-trips back to the GPU for display after being drawn in CPU memory.

    What you probably want is

    • You have your OpenGL Texture

    • You draw it at whatever size, keeping it on the GPU, and only using write bandwidth for the visible size.

    • Qt draws the rest of the QGraphicsScene into the QOpenGLWidget on the GPU.

    Using a Widget in the scene is a layer of complexity that makes no sense, unless you want actual UI widgets in the scene for the user to interact with.

    Also, consider using QOpenGLTextureBlitter - it's an underrated convenience class that wraps drawing a texture, so you don't have to keep track of a shader just for blitting a texture.



  • Thanks everyone, changing the QGraphicsView's viewport to an QOpenGLWidget and implementing the GLpainting stuff in a QGraphicsItem as described here did the trick:

    https://forum.qt.io/topic/91248/accelerate-qgraphicsview-with-opengl-widget-correct-up-to-date-workflow

    There were user interaction widget in the QGraphicsView that broke from the viewport change, but implementing them in the QOpenGLWidget instead seems to work. Thanks again.


Log in to reply