Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SFML + Qt + render to QImage problem  (Read 4612 times)

0 Members and 1 Guest are viewing this topic.

Hronom

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
SFML + Qt + render to QImage problem
« on: December 13, 2013, 03:10:51 pm »
Hello guys!
I need your help. I didnt good at OpenGL and maybe I asked not in approriate topic. But I have some problem with using SFML in pair with Qt, and maybe you can point me the way where problem happens.

Screenshot with problem in attachment.

Here code of my main.cpp file:

main.cpp
#include "MyQmlGUIWin.h"

#include "SFMLItem.h"
#include "SFMLEngine.h"
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <QQmlContext>
#include <QApplication>
#include <QDebug>


int main(int argc, char **argv)
{
    QApplication *app;
    app = new QApplication(argc, argv);

    SFMLEngine *engine;
    engine = new SFMLEngine();

    sf::Font font;
    font.loadFromFile("data/fonts/DejaVuSans.ttf");

    sf::Text text;
    text.setFont(font);
    text.setString("Hello world");
    text.setCharacterSize(24);
    text.setColor(sf::Color::Red);
    text.setStyle(sf::Text::Bold | sf::Text::Underlined);

    sf::CircleShape shape(50);
    shape.setFillColor(sf::Color(150, 50, 250));
    shape.setRadius(40);
    shape.setPosition(100, 100);

    // set a 10-pixel wide orange outline
    shape.setOutlineThickness(10);
    shape.setOutlineColor(sf::Color(250, 150, 100));

    engine->clear();
    engine->draw(text);
    engine->draw(shape);
    engine->display();

    engine->saveOnHDD();


    int returnCode;
    //returnCode = app->exec();

    delete app;

    return 0;
}
 

SFMLEngine is custom sf::RenderTarget. And here is code.

SFMLEngine.h
#ifndef SFMLEngine_H
#define SFMLEngine_H

#include <SFML/Graphics/RenderTarget.hpp>
#include <QOpenGLContext>
#include <QOpenGLFramebufferObjectFormat>
#include <QSGTexture>
#include <QQuickWindow>
#include <QOffscreenSurface>

class SFMLEngine: public QObject, public sf::RenderTarget
{
    Q_OBJECT
private:
    QOffscreenSurface *m_surface;
    QOpenGLContext *m_sfmlContext;
    QOpenGLFramebufferObject *m_fbo;

public:
    SFMLEngine();
    ~SFMLEngine();

    GLuint getTextureID();

    void saveOnHDD();

    void display();

protected:
    virtual sf::Vector2u getSize() const;
    virtual bool activate(bool par_active);
};

#endif
 

SFMLEngine.cpp
#include "SFMLEngine.h"

#include "SFMLItem.h"
#include "SFMLEngine.h"

#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QDebug>

SFMLEngine::SFMLEngine(): QObject(0)
{
    qmlRegisterType<SFMLItem>("SFML", 1, 0, "SFMLItem");
    qmlRegisterType<SFMLEngine>("SFML", 1, 0, "SFMLEngine");  

    QSurfaceFormat surfaceFormat;
    surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);

    m_surface = new QOffscreenSurface();
    m_surface->create();

    m_sfmlContext = new QOpenGLContext();
    m_sfmlContext->setFormat(surfaceFormat);
    if(m_sfmlContext->create() == false)
        qDebug()<<Q_FUNC_INFO<<"Shit happens with QOpenGLContext create";

    if(m_sfmlContext->makeCurrent(m_surface) == false)
        qDebug()<<Q_FUNC_INFO<<"Shit happens with QOpenGLContext makeCurrent";

    QOpenGLFramebufferObjectFormat fboFormat;
    //fboFormat.setSamples(16);
    fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);

    m_fbo = new QOpenGLFramebufferObject(800, 600, fboFormat);
    if(m_fbo->bind() == false)
        qDebug()<<Q_FUNC_INFO<<"Shit happens with QOpenGLFramebufferObject bind";
}

SFMLEngine::~SFMLEngine()
{
    delete m_sfmlContext;
}

GLuint SFMLEngine::getTextureID()
{
    return m_fbo->texture();
}

void SFMLEngine::saveOnHDD()
{
    m_fbo->toImage().save("test.png");
}

void SFMLEngine::display()
{
    m_sfmlContext->swapBuffers(m_surface);
}

sf::Vector2u SFMLEngine::getSize() const
{
    qDebug()<<"SFMLEngine::getSize";

    sf::Vector2u size;
    size.x = 800;
    size.y = 600;

    return size;
}

bool SFMLEngine::activate(bool par_active)
{
    qDebug()<<"SFMLEngine::activate"<<par_active;

    bool returnValue;
    returnValue = false;

    if(par_active)
    {
        qDebug()<<"SFMLEngine::activateSFMLContent";

        returnValue = m_sfmlContext->makeCurrent(m_surface);

        if(!m_fbo->isBound())
        {
            qDebug()<<"SFMLEngine::m_fbo->bind()";
            m_fbo->bind();
        }
    }
    else
    {
        qDebug()<<"SFMLEngine::doneSFMLContent";

        m_fbo->release();
        m_sfmlContext->doneCurrent();
    }

    return returnValue;
}
 

Here what I get at output:
QML debugging is enabled. Only use this in a safe environment.
SFMLEngine::activate true
SFMLEngine::activateSFMLContent
SFMLEngine::activate true
SFMLEngine::activateSFMLContent
SFMLEngine::activate true
SFMLEngine::activateSFMLContent
SFMLEngine::getSize
SFMLEngine::getSize
SFMLEngine::getSize
SFMLEngine::activate true
SFMLEngine::activateSFMLContent
SFMLEngine::activate true
SFMLEngine::activateSFMLContent
 

Entire project you can find at https://github.com/Hronom/GraphicSystem this code from GraphicSystemTest4. I am try to make some integration of SFML in QML. I am using latest SFML version from repo and Qt 5.2. My OS is lubuntu 13.10
« Last Edit: December 13, 2013, 04:43:13 pm by Hronom »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: SFML + Qt + render to QImage problem
« Reply #1 on: December 13, 2013, 04:39:50 pm »
Can you please explain what the problem is? Giving us code and hoping we'd understand everything, is not very wise. ;)

What are you doing? What do you expect to happen? What happens? What seems to be the issue? And where in the code do you think the issue seems to be?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Hronom

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: SFML + Qt + render to QImage problem
« Reply #2 on: December 13, 2013, 04:42:25 pm »
Can you please explain what the problem is? Giving us code and hoping we'd understand everything, is not very wise. ;)

What are you doing? What do you expect to happen? What happens? What seems to be the issue? And where in the code do you think the issue seems to be?
Oh sorry guys i don't write that bad screenshot in attachment. So please look on screenshot. Bad text appears and circle like an ellipse.

And I think that something wrong in SFMLEngine::activate(bool par_active)
« Last Edit: December 13, 2013, 04:47:20 pm by Hronom »

Hronom

  • Newbie
  • *
  • Posts: 6
    • View Profile
    • Email
Re: SFML + Qt + render to QImage problem
« Reply #3 on: December 14, 2013, 01:03:48 pm »
Hello guys!
After several hours of working I found that I dont call method sf::RenderTarget::initialize(); in my class. So I call this method and some glitches are gone. But bug with text remained. I add new screenshot in attachment.

So here new code:

main.cpp
#include "MyQmlGUIWin.h"

#include "SFMLItem.h"
#include "SFMLEngine.h"
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <QQmlContext>
#include <QApplication>
#include <QDebug>


int main(int argc, char **argv)
{
    QApplication *app;
    app = new QApplication(argc, argv);

    SFMLEngine *engine;
    engine = new SFMLEngine();

    sf::Font font;
    font.loadFromFile("data/fonts/DejaVuSans.ttf");

    sf::Text text;
    text.setFont(font);
    text.setString("Hello world");
    text.setCharacterSize(24);
    text.setColor(sf::Color::Red);
    text.setStyle(sf::Text::Bold | sf::Text::Underlined);

    sf::CircleShape shape(50);
    shape.setFillColor(sf::Color(150, 50, 250));
    shape.setRadius(40);
    shape.setPosition(100, 100);

    // set a 10-pixel wide orange outline
    shape.setOutlineThickness(10);
    shape.setOutlineColor(sf::Color(250, 150, 100));

    engine->clear();
    engine->draw(text);
    engine->draw(shape);
    engine->display();

    engine->saveOnHDD();


    int returnCode;
    //returnCode = app->exec();

    delete app;

    return 0;
}
 

SFMLEngine is custom sf::RenderTarget. And here is code.

SFMLEngine.h
#ifndef SFMLEngine_H
#define SFMLEngine_H

#include <SFML/Graphics/RenderTarget.hpp>
#include <QOpenGLContext>
#include <QOpenGLFramebufferObjectFormat>
#include <QSGTexture>
#include <QQuickWindow>
#include <QOffscreenSurface>

class SFMLEngine: public QObject, public sf::RenderTarget
{
    Q_OBJECT
private:
    QOffscreenSurface *m_surface;
    QOpenGLContext *m_sfmlContext;
    QOpenGLFramebufferObject *m_fbo;

    sf::Vector2u m_size;

public:
    SFMLEngine();
    ~SFMLEngine();

    GLuint getTextureID();

    void saveOnHDD();

    void display();

protected:
    virtual sf::Vector2u getSize() const;
    virtual bool activate(bool par_active);
};

#endif
 

SFMLEngine.cpp
#include "SFMLEngine.h"

#include "SFMLItem.h"
#include "SFMLEngine.h"

#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QDebug>
#include <QOpenGLTexture>

SFMLEngine::SFMLEngine(): QObject(0), RenderTarget()
{
    qDebug()<<"SFMLEngine::SFMLEngine";

    qmlRegisterType<SFMLItem>("SFML", 1, 0, "SFMLItem");
    qmlRegisterType<SFMLEngine>("SFML", 1, 0, "SFMLEngine");  

    QSurfaceFormat surfaceFormat;
    surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
    surfaceFormat.setProfile(QSurfaceFormat::CompatibilityProfile);

    m_surface = new QOffscreenSurface();
    m_surface->setFormat(surfaceFormat);
    m_surface->create();

    m_sfmlContext = new QOpenGLContext();
    m_sfmlContext->setFormat(surfaceFormat);
    if(m_sfmlContext->create() == false)
        qDebug()<<Q_FUNC_INFO<<"Shit happens with QOpenGLContext create";

    if(m_sfmlContext->makeCurrent(m_surface) == false)
        qDebug()<<Q_FUNC_INFO<<"Shit happens with QOpenGLContext makeCurrent";

    QOpenGLFramebufferObjectFormat fboFormat;    
    fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    fboFormat.setTextureTarget(GL_TEXTURE_2D);
    fboFormat.setInternalTextureFormat(GL_RGBA8);

    m_size.x = 800;
    m_size.y = 600;

    m_fbo = new QOpenGLFramebufferObject(m_size.x, m_size.y, fboFormat);
    if(m_fbo->bind() == false)
        qDebug()<<Q_FUNC_INFO<<"Shit happens with QOpenGLFramebufferObject bind";

    sf::RenderTarget::initialize();
}

SFMLEngine::~SFMLEngine()
{
    qDebug()<<"SFMLEngine::~SFMLEngine";

    delete m_sfmlContext;
}

GLuint SFMLEngine::getTextureID()
{
    qDebug()<<"SFMLEngine::getTextureID";

    return m_fbo->texture();
}

void SFMLEngine::saveOnHDD()
{
    qDebug()<<"SFMLEngine::saveOnHDD";

    m_fbo->toImage().save("test.png", "PNG", 100);
}

void SFMLEngine::display()
{
    qDebug()<<"SFMLEngine::display";

    m_sfmlContext->swapBuffers(m_surface);
}

sf::Vector2u SFMLEngine::getSize() const
{
    qDebug()<<"SFMLEngine::getSize";

    return m_size;
}

bool SFMLEngine::activate(bool par_active)
{
    qDebug()<<"SFMLEngine::activate";

    bool returnValue;
    returnValue = false;

    if(par_active)
    {
        qDebug()<<"activate SFML content";

        QOpenGLContext *currentContext;
        currentContext = QOpenGLContext::currentContext();
        if(currentContext != 0)
            currentContext->doneCurrent();

        returnValue = m_sfmlContext->makeCurrent(m_surface);

        if(!m_fbo->isBound())
        {
            qDebug()<<"m_fbo->bind()";
            m_fbo->bind();
        }

        //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    }
    else
    {
        qDebug()<<"done SFML content";

        m_fbo->release();
        m_sfmlContext->doneCurrent();
    }

    return returnValue;
}
 

Here what I get at output:
QML debugging is enabled. Only use this in a safe environment.
SFMLEngine::SFMLEngine
SFMLEngine::getSize
SFMLEngine::getSize
SFMLEngine::activate
activate SFML content
SFMLEngine::activate
activate SFML content
SFMLEngine::activate
activate SFML content
SFMLEngine::getSize
SFMLEngine::getSize
SFMLEngine::getSize
SFMLEngine::activate
activate SFML content
SFMLEngine::activate
activate SFML content
SFMLEngine::display
SFMLEngine::saveOnHDD
 

I call draw method in main:
engine->clear();
engine->draw(text);
engine->draw(shape);
engine->display();
 

And I recieve 5 calls of method bool SFMLEngine::activate(bool par_active) with par_active=true I didnt understand is this right or not. And I didnt understand what can do bug in text like on screenshot in attachment.