SFML community forums

Help => Graphics => Topic started by: Andarann on June 02, 2017, 03:57:01 am

Title: [Solved] VBO creates bug ?
Post by: Andarann on June 02, 2017, 03:57:01 am
Hello everyone, I hope your projects are all working fine. Because mine, not so much.

I recently started adding OpenGL to my project, to do the 3d rendering while SFML is supposed to manage the windowing and GUI parts. The GUI system itself works very fine without OpenGL, but since I added it graphical bugs have risen.

Some pin-pointing and debugging led me to the conclusion that the command "glBindBuffer" is responsible for my misery, because without it my GUI system works like usual.

Here are the important code chunks :

1)The drawing function of the Container class. This class contains other widgets/parts of the GUI system and renders them if asked. With VBO generated, it only has the color given in"myRenderTexture.get()->clear(sf::Color(0,0,0,200));"
void Container::draw(sf::RenderTarget& target) const
{
    if (updated)//We only do that if there is a need to re-draw the Container
    {
        background.setPosition(sf::Vector2f(0,0));

        myRenderTexture.get()->clear(sf::Color(0,0,0,200));
        background.draw(*myRenderTexture.get());

        for (auto it = allWidgets.begin() ; it != allWidgets.end() ; it++)
            if (it->second.hideState == false)
                renderWidgetDirection(*((it->second).widget), *myRenderTexture.get());

        myRenderTexture.get()->display();

        renderSprite.setTexture(myRenderTexture.get()->getTexture());
    }
    target.draw(renderSprite);
}

2)Most of the Container class declaration
class Container : public Widget{//Ok
public:
     /** Irrelevant stuff */

    virtual void update(sf::RenderWindow& window, sf::Vector2f origin = sf::Vector2f(0,0));
    virtual void draw(sf::RenderTarget& target) const;

private:

    /** Irrelevant stuff */

    sf::Sprite renderSprite;
    std::shared_ptr<sf::RenderTexture> myRenderTexture;

};

3)Constructor of the OpenGLRenderer class. This is where the faulty code bits lie
OpenGLRenderer::OpenGLRenderer()
{
    if (gl3wInit())
    {
        std::cerr << "Failed to initialize gl3w\n";
    }

    if (!sf::Shader::isAvailable())
    {
        std::cerr << "Can't use shaders. Maybe your graphic card is too old ? Check your drivers too !\n";
    }

    GLfloat g_vertex_buffer_data[] = {
    0.1, 0.0, 0.5, -0.5f, -0.5f, 0.0f,
    0.5, 0.4, 0.1, 0.5f, -0.5f, 0.0f,
    1.0, 0.7, 0.0, 0.0f,  0.5f, 0.0f
    };

    glGenBuffers(1, &vertexBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

    shader.loadFromFile("src/shaders/vertex_test.txt", "src/shaders/frag_test.txt");
}

I really have no idea why this bug occurs. My understanding is that sfml uses opengl, so maybe there is some deadly overlap somewhere ? If anyone could explain me why this doesn't work, I would be thankful forever !
Title: Re: VBO creates bug ?
Post by: Andarann on June 02, 2017, 06:17:47 pm
Some more pin-pointing made me able to add the following elements : the VBO is not the source of the problem.

What happens is the following : the OpenGL triangle is rendering once, then the GUI is rendered, then the program crashes at the function "glDrawArrays". Any idea why ?
Title: Re: VBO creates bug ?
Post by: dabbertorres on June 02, 2017, 06:21:03 pm
The code you've posted doesn't reflect this, so, have you read this (https://www.sfml-dev.org/tutorials/2.4/window-opengl.php#using-opengl-together-with-the-graphics-module)?

tl;dr:
sf::RenderWindow::popGLStates() (https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1RenderTarget.php#a8d1998464ccc54e789aaf990242b47f7)
sf::RenderWindow::pushGLStates() (https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1RenderTarget.php#ad5a98401113df931ddcd54c080f7aa8e)
sf::RenderWindow::resetGLStates() (https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1RenderTarget.php#aac7504990d27dada4bfe3c7866920765)
Title: Re: VBO creates bug ?
Post by: Andarann on June 02, 2017, 06:34:01 pm
Hello ! Yes, I added those functions to my code (even with an added resetGLStates(), even if pushGlStates() apparently already does that). The rendering code is the following :

void System::Render()
{
    //if (primaryContainer.wasUpdated())
    //{

    windowMain.clear(sf::Color(0,255,127));//Rendering part

        renderOpenGL();

        windowMain.pushGLStates();
        windowMain.resetGLStates();

            renderWidgets();

        windowMain.popGLStates();

        windowMain.display();
    //}

    numberOfFrames++;
}

Again, they all work separately, but together I'm greeted with a seg fault...
Title: Re: VBO creates bug ?
Post by: dabbertorres on June 02, 2017, 06:56:36 pm
You should be using either resetGLStates() alone, OR pushGLStates() and popGLStates(). Not both. Does that make a difference?
Title: Re: VBO creates bug ?
Post by: Andarann on June 02, 2017, 07:05:50 pm
No it doesn't, both these codes result in a seg fault :

windowMain.clear(sf::Color(50,0,0));//Rendering part

        renderOpenGL();

            windowMain.pushGLStates();

            renderWidgets();

            windowMain.popGLStates();

        windowMain.display();

and

windowMain.clear(sf::Color(50,0,0));//Rendering part

        renderOpenGL();

            windowMain.resetGLStates();

            renderWidgets();

        windowMain.display();




Title: Re: VBO creates bug ?
Post by: dabbertorres on June 02, 2017, 07:09:14 pm
Have you used a debugger to trace the source of the seg fault?
Title: Re: VBO creates bug ?
Post by: Andarann on June 02, 2017, 07:37:53 pm
Yes : every time the error leads me to glDrawArrays. The following happens : gl is rendered once, then SFML, then the RenderWindow is displayed, then the gl starts and crashes at glDrawArrays. glGetError() doesn't give any error code before the crash. Maybe the problem comes from the gl states set by SFML ?
Title: Re: VBO creates bug ?
Post by: dabbertorres on June 02, 2017, 08:01:56 pm
What code of yours does it pass through first?
First, let's try to prove it's not your code, before looking at SFML.

Can you paste a stack trace, and any relevant code?
Title: Re: VBO creates bug ?
Post by: Andarann on June 02, 2017, 09:12:05 pm
Ok so here's the OpenGLRender class :
#include "OpenGLRenderer.hpp"

OpenGLRenderer::OpenGLRenderer()
{
    if (gl3wInit())
    {
        std::cout << "FUCK";
    }

    if (!sf::Shader::isAvailable())
    {
        std::cerr << "Can't use shaders. Maybe your graphic card is too old ? Check your drivers too !\n";
    }

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindVertexArray(0);

    shader.loadFromFile("src/shaders/vertex_test.txt", "src/shaders/frag_test.txt");
}

OpenGLRenderer::~OpenGLRenderer()
{

}

void OpenGLRenderer::render(sf::RenderWindow& window)
{
    sf::Shader::bind(&shader);

    glBindVertexArray(VAO);

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    sf::Shader::bind(NULL);
}

The System class contains both the SFML widget to render and an instance of OpenGLRenderer. Here's the part of the constructor concerning those :

System::System() :  oglpart(),//The OpenGLRenderer instance. It also initializes gl3w here
                    windowMain(sf::VideoMode(INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT), "Game", sf::Style::Resize),
                    primaryContainer(sf::Vector2f(50,50), sf::Vector2f(500, 500), "resources/window_background.png")
{
    /** Initialization of other variables. Does not concern SFML or OpenGL so irrelevant*/
}

And again, the render code :
void System::Render()
{
    if (primaryContainer.wasUpdated())
    {
        windowMain.clear(sf::Color(50,0,0));

            renderOpenGL();

                windowMain.pushGLStates();

                    renderWidgets();

                windowMain.popGLStates();

        windowMain.display();
    }

    numberOfFrames++;
}

Thank you for your time btw. Hope we can solve this quickly... I'm pretty sure this is another function I forget to use/didn't use correctly  ;D
Title: Re: VBO creates bug ?
Post by: Andarann on June 02, 2017, 09:53:12 pm
By the way, the Container class renders using a shared_ptr<sf::RenderTexture> and a sf::Sprite. Maybe having sf::RenderTexture as a shared_ptr creates an issue ? I will test & edit, but if the problem comes from here it's a shame because it was effective and convenient.
Code of the Container rendering is here again :
if (updated)//We only do that if there is a need to re-draw the Container
    {
        std::cout << "Drawn\n";
        background.setPosition(sf::Vector2f(0,0));

        myRenderTexture.get()->clear(sf::Color(0,255,0,200));
        background.draw(*myRenderTexture.get());

        for (auto it = allWidgets.begin() ; it != allWidgets.end() ; it++)
            if (it->second.hideState == false)
                renderWidgetDirection(*((it->second).widget), *myRenderTexture.get());

        myRenderTexture.get()->display();

        renderSprite.setTexture(myRenderTexture.get()->getTexture());
    }
    target.draw(renderSprite);

EDIT : Nope, changed to a regular sf::RenderTexture created at each rendering cycle, no change. Now, there's no crash, but the SFML part just doesn't show.
Title: Re: VBO creates bug ?
Post by: dabbertorres on June 03, 2017, 03:17:45 am
Stack trace of the crash?

Nope, changed to a regular sf::RenderTexture created at each rendering cycle, no change. Now, there's no crash, but the SFML part just doesn't show.
Your System::Render(), shouldn't you only be conditionally calling renderWidgets() if the container was updated? Something like:
void System::Render()
{
    windowMain.clear(sf::Color(50,0,0));
 
    renderOpenGL();

    if (primaryContainer.wasUpdated())
    {
        windowMain.pushGLStates();

            renderWidgets();

        windowMain.popGLStates();
    }

    windowMain.display();
 
    numberOfFrames++;
}
Title: Re: VBO creates bug ?
Post by: Andarann on June 03, 2017, 03:54:19 am
No no I can't apply this code, it would cause a lot of problems in the application : the OpenGL rendering would always hide the interface, except when it is updated.

Anyway, I think I've found something really interesting : when I switch to my crappy Integrated graphic card, everything is fine. The crash is only with my "better" Nvidia card.
Title: Re: VBO creates bug ?
Post by: dabbertorres on June 03, 2017, 09:57:45 am
Oh I see how you're using it now, that makes sense. I meant for the drawing to the sf::RenderTexture to go in an if().
Though I don't think you should have an if() at all in System::Render() then?

As for the Intel vs Nvidia case, I'm afraid someone else with some more familiarity with drivers will have to help you, I'm not familiar enough with the drivers to be of much use.

If you get a stack trace, I might be able to help, otherwise you'll have to wait for someone else to come along.
Title: Re: VBO creates bug ?
Post by: eXpl0it3r on June 03, 2017, 10:41:34 am
Provide an MCVE (https://stackoverflow.com/help/mcve) so everyone can see everything that is going on and can actually test your code.
If it's a bug with SFML, then it can be reproduced in a few lines of code. If it can't be minimized to that size, then it often is a user code issue. ;)

Don't forget to test all your code with SFML 2.4.2.
Title: Re: VBO creates bug ?
Post by: binary1248 on June 03, 2017, 12:41:26 pm
You still haven't showed us any of the actual code around your OpenGL glDraw*** commands, which I assume are somewhere in renderOpenGL(). By now it should be more or less known that popGLStates() and pushGLStates() don't take care of almost all states that were introduced in OpenGL 1.2 and later. This includes VAO and VBO bindings. If you are leaving even a single binding or something else in another state than what SFML would expect if you didn't render using OpenGL yourself, it will produce unexpected output. If you are lucky, this would only be an error, if you start to play with buffer bindings then OpenGL won't check whether the data sources it thinks are correct actually point to the correct data (how would it check if an arbitrary pointer is valid if we can't even do it ourselves?).
Title: Re: VBO creates bug ?
Post by: Andarann on June 03, 2017, 03:46:49 pm
There is no problem anymore !
I have just figured that after all the SFML initialization, using a resetGLStates() on the window before initializing the OpenGL part works fine ! I don't know why, and frankly I'm too happy to care.
Thank you for your time everyone !