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

Author Topic: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.  (Read 5214 times)

0 Members and 3 Guests are viewing this topic.

Order

  • Newbie
  • *
  • Posts: 8
    • View Profile
SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« on: July 16, 2014, 02:01:03 pm »
Hi Guys,

I'm struggling to draw some sf::Text to the sf::RenderWindow when used alongside OpenGL glDraw commands.

I've tried working through the resolution in http://en.sfml-dev.org/forums/index.php?topic=14622.0, however I think a few crucial lines of code and their order may be omitted from the solution.

I think the issue is in the draw procedure towards the bottom of the code, more specifically :
   window.pushGLStates();
      window.draw(instructions);
   window.popGLStates();

Any pointers as to where I'm going wrong?

Wall of text incoming :


#include <GL/glew.h>

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

#include <iostream>
#include <string>
#include <vector>


// globals
int screenWidth = 600;
int screenHeight = 600;
bool running = true;

sf::Font ambleFont;
sf::Text instructions;

GLuint
vaoId,
vboId,
indexBufferId[1],
vertexShaderId,
fragmentShaderId,
programId,
currentIndexBuffer = 0;

const GLchar* vertexShader = {
        "#version 400\n"\

        "layout(location=0) in vec4 in_Position;\n"\
        "layout(location=1) in vec4 in_Color;\n"\
        "out vec4 ex_Color;\n"\

        "void main(void)\n"\
        "{\n"\
        "  gl_Position = in_Position;\n"\
        "  ex_Color = in_Color;\n"\
        "}\n"
};

const GLchar* FragmentShader =
{
        "#version 400\n"\

        "in vec4 ex_Color;\n"\
        "out vec4 out_Color;\n"\

        "void main(void)\n"\
        "{\n"\
        "  out_Color = ex_Color;\n"\
        "}\n"
};

sf::RenderWindow window;

bool init();
bool load();
void unload();
bool createBuffers();
void destroyBuffers();
bool createShaders();
void destroyShaders();
void handleEvents();
void draw();

typedef struct {
        float XYZW[4];
        float RGBA[4];
} Vertex;

// helper to check and display for shader compiler errors
bool check_shader_compile_status(GLuint obj) {
        GLint status;
        glGetShaderiv(obj, GL_COMPILE_STATUS, &status);
        if (status == GL_FALSE) {
                GLint length;
                glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
                std::vector<char> log(length);
                glGetShaderInfoLog(obj, length, &length, &log[0]);
                std::cerr << &log[0];
                return false;
        }
        return true;
}

// helper to check and display for shader linker error
bool check_program_link_status(GLuint obj) {
        GLint status;
        glGetProgramiv(obj, GL_LINK_STATUS, &status);
        if (status == GL_FALSE) {
                GLint length;
                glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
                std::vector<char> log(length);
                glGetProgramInfoLog(obj, length, &length, &log[0]);
                std::cerr << &log[0];
                return false;
        }
        return true;
}

int main() {

        if (!init()) running = false;

        while (running) {

                handleEvents();
                draw();
        }

        unload();
        return 0;
}

bool init() {
        window.create(sf::VideoMode(800, 600), "OpenGL Test", sf::Style::Default, sf::ContextSettings(24U, 8U, 4U, 4U, 0U));
        window.setVerticalSyncEnabled(true);
        std::cout << "Initializing OpenGL v" << window.getSettings().majorVersion << "." << window.getSettings().minorVersion << std::endl;

        glewExperimental = GL_TRUE;
        GLenum error = glGetError();
        if (error != GL_NO_ERROR) {
                std::cout << "Error initializing an OpenGL context with the current window." << std::endl;
                return false;
        }

        GLenum ret = glewInit();
        if (ret != GLEW_NO_ERROR) {
                std::cout << "Error, couldn't initialize Glew." << std::endl;
                return false;
        }

        if (!load()) return false;

        glClearColor(0.f, 0.f, 0.f, 255.f);

        return true;
}

bool load() {
        if (!createShaders()) return false;
        if (!createBuffers()) return false;

        return true;
}

void unload() {
        destroyShaders();
        destroyBuffers();
}

bool createBuffers() {
        ambleFont.loadFromFile("../resources/Amble-Bold.ttf");
        instructions.setFont(ambleFont);
        instructions.setString("Press 'T' to swap indices.");
        instructions.setPosition(50, 50);
        instructions.setColor(sf::Color::White);

        Vertex vertices[] = {
                        { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } },
                        // Top
                        { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
                        { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
                        { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
                        { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
                        // Bottom
                        { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
                        { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
                        { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
                        { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
                        // Left
                        { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
                        { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
                        { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
                        { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
                        // Right
                        { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } },
                        { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
                        { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } },
                        { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }
        };

        GLubyte indices[] = {
                // Top
                0, 1, 3,
                0, 3, 2,
                3, 1, 4,
                3, 4, 2,
                // Bottom
                0, 5, 7,
                0, 7, 6,
                7, 5, 8,
                7, 8, 6,
                // Left
                0, 9, 11,
                0, 11, 10,
                11, 9, 12,
                11, 12, 10,
                // Right
                0, 13, 15,
                0, 15, 14,
                15, 13, 16,
                15, 16, 14
        };

        GLubyte alternateIndices[] = {
                // Outer square border:
                3, 4, 16,
                3, 15, 16,
                15, 16, 8,
                15, 7, 8,
                7, 8, 12,
                7, 11, 12,
                11, 12, 4,
                11, 3, 4,

                // Inner square
                0, 11, 3,
                0, 3, 15,
                0, 15, 7,
                0, 7, 11
        };

        GLenum errCheckVal = glGetError();

        glGenVertexArrays(1, &vaoId);
        glBindVertexArray(vaoId);

        glGenBuffers(1, &vboId);
        glBindBuffer(GL_ARRAY_BUFFER, vboId);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (char*)0 + 0 * sizeof(GLfloat));
        glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (void*)sizeof(vertices[0].XYZW));
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);

        glGenBuffers(2, indexBufferId);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[0]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[1]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(alternateIndices), alternateIndices, GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[0]); // rebind to the first

        errCheckVal = glGetError();
        if (errCheckVal != GL_NO_ERROR) {
                std::cout << "Error: Couldn't create a VBO:" << gluErrorString(errCheckVal) << std::endl;
                return false;
        }

        return true;

}

void destroyBuffers() {
        GLenum errCheckVal = glGetError();

        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glDeleteBuffers(0, &vboId);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glDeleteBuffers(2, indexBufferId);

        glBindVertexArray(0);
        glDeleteVertexArrays(1, &vaoId);

        errCheckVal = glGetError();
        if (errCheckVal != GL_NO_ERROR) {
                std::cout << "Error: Couldn't destroy the VBO:" << gluErrorString(errCheckVal) << std::endl;
        }
}

bool createShaders() {
        GLenum errCheckVal = glGetError();

        vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexShaderId, 1, &vertexShader, nullptr);
        glCompileShader(vertexShaderId);
        if (!check_shader_compile_status(vertexShaderId)) {
                return false;
        }

        fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragmentShaderId, 1, &FragmentShader, nullptr);
        glCompileShader(fragmentShaderId);
        if (!check_shader_compile_status(fragmentShaderId)) {
                return false;
        }

        programId = glCreateProgram();
        glAttachShader(programId, vertexShaderId);
        glAttachShader(programId, fragmentShaderId);
        glLinkProgram(programId);
        if (!check_program_link_status(programId)) {
                return false;
        }
        glUseProgram(programId);

        errCheckVal = glGetError();
        if (errCheckVal != GL_NO_ERROR) {
                std::cout << "Error: Couldn't create the shaders:" << gluErrorString(errCheckVal) << std::endl;
                return false;
        }
        return true;
}

void destroyShaders() {
        GLenum errCheckVal = glGetError();

        //glUseProgram(0);

        glDetachShader(programId, vertexShaderId);
        glDetachShader(programId, fragmentShaderId);

        glDeleteShader(vertexShaderId);
        glDeleteShader(fragmentShaderId);

        glDeleteProgram(programId);

        errCheckVal = glGetError();
        if (errCheckVal != GL_NO_ERROR) {
                std::cout << "Error: Couldn't destroy the shaders:" << gluErrorString(errCheckVal) << std::endl;
        }
}

void handleEvents() {
        sf::Event event;
        while (window.pollEvent(event)) {
                switch (event.type) {
                case sf::Event::Closed:
                        running = false;
                        break;
                case sf::Event::Resized:
                        glViewport(0, 0, event.size.width, event.size.height);
                        break;
                case sf::Event::KeyPressed:
                        switch (event.key.code) {
                        case sf::Keyboard::Escape:
                                running = false;
                                break;
                        case sf::Keyboard::T:
                                currentIndexBuffer = !currentIndexBuffer;
                                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId[currentIndexBuffer]);
                                break;
                        }
                }
        }
}

void draw() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       
        glUseProgram(programId);
        glBindVertexArray(vaoId);

        //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        if (currentIndexBuffer == 0) {
                glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, nullptr);
        }
        else {
                glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, nullptr);
        }

        //glBindBuffer(GL_ARRAY_BUFFER, 0);
        //glDisableVertexAttribArray(1);
        //glDisableVertexAttribArray(0);

        window.pushGLStates();
                window.draw(instructions);
        window.popGLStates();

        window.display();

}
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #1 on: July 16, 2014, 02:48:48 pm »
A complete and minimal code that just reproduces the problem would be better than a wall of code that contains tons of irrelevant stuff ;)
Laurent Gomila - SFML developer

Order

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #2 on: July 16, 2014, 03:38:57 pm »
True, however on the previous post I refer to the advice was to post the whole chunk :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #3 on: July 16, 2014, 03:42:22 pm »
Indeed. So let's summon binary1248 ;)
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #4 on: July 16, 2014, 05:33:29 pm »
Unbind your shader program and VAO before drawing with SFML...
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Order

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #5 on: July 16, 2014, 05:44:05 pm »
Hi,

Hmmm, OK I did that and I've also tried a few variations on the following :

void draw() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        if (currentIndexBuffer == 0) {
                glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, nullptr);
        }
        else {
                glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, nullptr);
        }

        glUseProgram(0);
        glBindVertexArray(0);

        window.pushGLStates();
                window.draw(instructions);
        window.popGLStates();

        glUseProgram(programId);
        glBindVertexArray(vaoId);

        window.display();

}
 

Yet still no dice. Haha, this is such a small starter example and I seem to be missing something simple yet crucial here! :)

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #6 on: July 16, 2014, 05:58:41 pm »
When you create and bind your buffers to your VAO, they will stay bound... forever. You should never leave things bound forever, it defeats the purpose of a VAO. Once you are done binding, unbind the VAO first then the buffers. The bindings will get saved in the VAO since any binding/unbinding after the VAO is unbound will not affect it.

SFML is already bad enough leaving all client state enabled after completion of a draw call, if you don't bother trying to clean up after yourself as well, it will become too chaotic for GL to function properly. It is hard enough getting both GL and SFML to work at the same time, even when you are careful.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Order

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #7 on: July 16, 2014, 06:00:36 pm »
Hi,

Hold on, Just figured it out, I wasn't unbinding and re-binding the array buffer :

void draw() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        if (currentIndexBuffer == 0) {
                glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, nullptr);
        }
        else {
                glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, nullptr);
        }

        glUseProgram(0);
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        window.resetGLStates();
        window.draw(instructions);

        glUseProgram(programId);
        glBindVertexArray(vaoId);
        glBindBuffer(GL_ARRAY_BUFFER, vboId);

        window.display();

}


Order

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: SFML 2.1 Mixing OpenGL GLEW + RenderWindow drawables.
« Reply #8 on: July 16, 2014, 06:01:59 pm »
Ok, just read your reply Binary1248.

Makes a bunch of sense, useful info to know!

Thanks a bunch for the assistance.

Cheers

Dan