SFML community forums

Help => Window => Topic started by: nicoraf on August 18, 2013, 10:41:28 pm

Title: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 18, 2013, 10:41:28 pm
Hi,

I am trying to execute the following example (OpenGL Core profile) and when I try to draw a text it displays the following error at the console:

"An internal OpenGL call failed in RenderTarget.cpp (218) : GL_INVALID_OPERATION,
 the specified operation is not allowed in the current state"

The question is:

I have read in other threads that some features are not available for OpenGL core/

Is it posible to use SFML Text using opengl core profile?


Thanks,
Nicolas

#define GLEW_STATIC

#include <GL/glew.h>

#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/RenderWindow.hpp>

#include <glm/glm.hpp>
using glm::mat4;
using glm::vec3;
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform2.hpp>

#include <fstream>
#include <sstream>
#include <string>

#include "GLSLProgram.h"

GLuint theProgram;



int main()
{
        sf::ContextSettings contextSettings;
        contextSettings.depthBits = 32;
        contextSettings.stencilBits = 8;
        contextSettings.antialiasingLevel = 4;
        contextSettings.majorVersion = 0;
        contextSettings.minorVersion = 1;

        // Create the main window
        sf::RenderWindow window(sf::VideoMode(640, 480), "SFML window with OpenGL", sf::Style::Default, contextSettings);

        // Make it the active window for OpenGL calls
        window.setActive();

        GLenum err = glewInit();
        if( GLEW_OK != err )
        {
                fprintf(stderr, "Error initializing GLEW: %s\n", glewGetErrorString(err) );
        }

        const GLubyte *renderer = glGetString( GL_RENDERER );
        const GLubyte *vendor = glGetString( GL_VENDOR );
        const GLubyte *version = glGetString( GL_VERSION );
        const GLubyte *glslVersion =
                glGetString( GL_SHADING_LANGUAGE_VERSION );
        GLint major, minor;
        glGetIntegerv(GL_MAJOR_VERSION, &major);
        glGetIntegerv(GL_MINOR_VERSION, &minor);
        printf("GL Vendor : %s\n", vendor);
        printf("GL Renderer : %s\n", renderer);
        printf("GL Version (string) : %s\n", version);
        printf("GL Version (integer) : %d.%d\n", major, minor);
        printf("GLSL Version : %s\n", glslVersion);

                // Create some text to draw on top of our OpenGL object
    sf::Font font;

    if (!font.loadFromFile("resources/sansation.ttf"))
        return EXIT_FAILURE;
   
        sf::Text text("SFML / OpenGL demo", font);
    text.setColor(sf::Color(255, 255, 255, 170));
    text.setPosition(250.f, 250.f);
        // Bind the texture
    glEnable(GL_TEXTURE_2D);

        // Compile and link Shaders
        GLSLProgram prog;
        if( ! prog.compileShaderFromFile("shaders/basic_affinetransform.vert",GLSLShader::VERTEX) )
        {
                printf("Vertex shader failed to compile!\n%s",
                        prog.log().c_str());
                exit(1);
        }
        if( ! prog.compileShaderFromFile("shaders/basic_affinetransform.frag",GLSLShader::FRAGMENT))
        {
                printf("Fragment shader failed to compile!\n%s",
                        prog.log().c_str());
                exit(1);
        }
        if( ! prog.link() )
        {
                printf("Shader program failed to link!\n%s",
                        prog.log().c_str());
                exit(1);
        }

        float matrix[] = {
                1.0f, 0.0f, 0.0f, 0.0f, // first column
                0.0f, 1.0f, 0.0f, 0.0f, // second column
                0.0f, 0.0f, 1.0f, 0.0f, // third column
                0.5f, 0.0f, 0.0f, 1.0f // fourth column
        };

        int matrix_location = glGetUniformLocation (prog.getHandle(), "matrix");
        glUseProgram (prog.getHandle());
        glUniformMatrix4fv (matrix_location, 1, GL_FALSE, matrix);

        prog.use();

        /////////////////// Create the VBO ////////////////////

        float positionData[] = {
        -0.8f, -0.8f, 0.0f,
         0.8f, -0.8f, 0.0f,
         0.0f, 0.8f, 0.0f };

        float colorData[] = {
                1.0f, 0.0f, 0.0f,
                0.0f, 1.0f, 0.0f,
                0.0f, 0.0f, 1.0f };


        // Create and populate the buffer objects
        GLuint vboHandles[2];

        // Create the buffer objects
        glGenBuffers(2, vboHandles);
        GLuint positionBufferHandle = vboHandles[0];
        GLuint colorBufferHandle = vboHandles[1];

        // Populate the position buffer
        glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
        glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);

        // Populate the color buffer
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
        glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);

        // Create and set-up the vertex array object
        GLuint vaoHandle;
        glGenVertexArrays( 1, &vaoHandle );
        glBindVertexArray(vaoHandle);

        // Enable the vertex attribute arrays
        glEnableVertexAttribArray(0); // Vertex position
        glEnableVertexAttribArray(1); // Vertex color

        // Map index 0 to the position buffer
        glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
        glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );

        // Map index 1 to the color buffer
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
        glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );

        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glClearColor(0.0,0.0,0.0,1.0);
        glEnable(GL_DEPTH_TEST);

        // Configure the viewport (the same size as the window)
        glViewport(0, 0, window.getSize().x, window.getSize().y);

        // Create a clock for measuring the time elapsed
        sf::Clock clock;

        // Start the game loop
        while (window.isOpen())
        {
                // Process events
                sf::Event event;
                while (window.pollEvent(event))
                {
                        // Close window: exit
                        if (event.type == sf::Event::Closed) {
                                window.close();
                                return EXIT_SUCCESS;
                        }

                        // Escape key: exit
                        if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) {
                                window.close();
                                return EXIT_SUCCESS;
                        }

                        // Resize event: adjust the viewport
                        if (event.type == sf::Event::Resized) {
                                glViewport(0, 0, event.size.width, event.size.height);
                        }
                }

                //// Clear the color and depth buffers
                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                //matrix[12] += 0.0001f;
                //glUniformMatrix4fv (matrix_location, 1, GL_FALSE, matrix);


                //glBindVertexArray(vaoHandle);
                //glDrawArrays(GL_TRIANGLES, 0, 3 );

                // Draw some text on top of our OpenGL object
        window.pushGLStates();
        window.draw(text);
        window.popGLStates();

                window.display();

        }



        return EXIT_SUCCESS;
}
 

#include "glslprogram.h"

#include <fstream>
using std::ifstream;
using std::ios;

#include <sstream>
using std::ostringstream;

#include <sys/stat.h>

GLSLProgram::GLSLProgram() : handle(0), linked(false) { }

bool GLSLProgram::compileShaderFromFile( const char * fileName,
                                         GLSLShader::GLSLShaderType type )
{
    if( ! fileExists(fileName) )
    {
        logString = "File not found.";
        return false;
    }

    if( handle <= 0 ) {
        handle = glCreateProgram();
        if( handle == 0) {
            logString = "Unable to create shader program.";
            return false;
        }
    }

    ifstream inFile( fileName, ios::in );
    if( !inFile ) {
        return false;
    }

    ostringstream code;
    while( inFile.good() ) {
        int c = inFile.get();
        if( ! inFile.eof() )
            code << (char) c;
    }
    inFile.close();

    return compileShaderFromString(code.str(), type);
}

bool GLSLProgram::compileShaderFromString( const string & source, GLSLShader::GLSLShaderType type )
{
    if( handle <= 0 ) {
        handle = glCreateProgram();
        if( handle == 0) {
            logString = "Unable to create shader program.";
            return false;
        }
    }

    GLuint shaderHandle = 0;

    switch( type ) {
    case GLSLShader::VERTEX:
        shaderHandle = glCreateShader(GL_VERTEX_SHADER);
        break;
    case GLSLShader::FRAGMENT:
        shaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
        break;
    case GLSLShader::GEOMETRY:
        shaderHandle = glCreateShader(GL_GEOMETRY_SHADER);
        break;
    case GLSLShader::TESS_CONTROL:
        shaderHandle = glCreateShader(GL_TESS_CONTROL_SHADER);
        break;
    case GLSLShader::TESS_EVALUATION:
        shaderHandle = glCreateShader(GL_TESS_EVALUATION_SHADER);
        break;
    default:
        return false;
    }

    const char * c_code = source.c_str();
    glShaderSource( shaderHandle, 1, &c_code, NULL );

    // Compile the shader
    glCompileShader(shaderHandle );

    // Check for errors
    int result;
    glGetShaderiv( shaderHandle, GL_COMPILE_STATUS, &result );
    if( GL_FALSE == result ) {
        // Compile failed, store log and return false
        int length = 0;
        logString = "";
        glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &length );
        if( length > 0 ) {
            char * c_log = new char[length];
            int written = 0;
            glGetShaderInfoLog(shaderHandle, length, &written, c_log);
            logString = c_log;
            delete [] c_log;
        }

        return false;
    } else {
        // Compile succeeded, attach shader and return true
        glAttachShader(handle, shaderHandle);
        return true;
    }
}

bool GLSLProgram::link()
{
    if( linked ) return true;
    if( handle <= 0 ) return false;

    glLinkProgram(handle);

    int status = 0;
    glGetProgramiv( handle, GL_LINK_STATUS, &status);
    if( GL_FALSE == status ) {
        // Store log and return false
        int length = 0;
        logString = "";

        glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &length );

        if( length > 0 ) {
            char * c_log = new char[length];
            int written = 0;
            glGetProgramInfoLog(handle, length, &written, c_log);
            logString = c_log;
            delete [] c_log;
        }

        return false;
    } else {
        linked = true;
        return linked;
    }
}

void GLSLProgram::use()
{
    if( handle <= 0 || (! linked) ) return;
    glUseProgram( handle );
}

string GLSLProgram::log()
{
    return logString;
}

int GLSLProgram::getHandle()
{
    return handle;
}

bool GLSLProgram::isLinked()
{
    return linked;
}

void GLSLProgram::bindAttribLocation( GLuint location, const char * name)
{
    glBindAttribLocation(handle, location, name);
}

void GLSLProgram::bindFragDataLocation( GLuint location, const char * name )
{
    glBindFragDataLocation(handle, location, name);
}

void GLSLProgram::setUniform( const char *name, float x, float y, float z)
{
    int loc = getUniformLocation(name);
    if( loc >= 0 ) {
        glUniform3f(loc,x,y,z);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::setUniform( const char *name, const vec3 & v)
{
    this->setUniform(name,v.x,v.y,v.z);
}

void GLSLProgram::setUniform( const char *name, const vec4 & v)
{
    int loc = getUniformLocation(name);
    if( loc >= 0 ) {
        glUniform4f(loc,v.x,v.y,v.z,v.w);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::setUniform( const char *name, const vec2 & v)
{
    int loc = getUniformLocation(name);
    if( loc >= 0 ) {
        glUniform2f(loc,v.x,v.y);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::setUniform( const char *name, const mat4 & m)
{
    int loc = getUniformLocation(name);
    if( loc >= 0 )
    {
        glUniformMatrix4fv(loc, 1, GL_FALSE, &m[0][0]);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::setUniform( const char *name, const mat3 & m)
{
    int loc = getUniformLocation(name);
    if( loc >= 0 )
    {
        glUniformMatrix3fv(loc, 1, GL_FALSE, &m[0][0]);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::setUniform( const char *name, float val )
{
    int loc = getUniformLocation(name);
    if( loc >= 0 )
    {
        glUniform1f(loc, val);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::setUniform( const char *name, int val )
{
    int loc = getUniformLocation(name);
    if( loc >= 0 )
    {
        glUniform1i(loc, val);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::setUniform( const char *name, bool val )
{
    int loc = getUniformLocation(name);
    if( loc >= 0 )
    {
        glUniform1i(loc, val);
    } else {
        printf("Uniform: %s not found.\n",name);
    }
}

void GLSLProgram::printActiveUniforms() {

    GLint nUniforms, size, location, maxLen;
    GLchar * name;
    GLsizei written;
    GLenum type;

    glGetProgramiv( handle, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
    glGetProgramiv( handle, GL_ACTIVE_UNIFORMS, &nUniforms);

    name = (GLchar *) malloc( maxLen );

    printf(" Location | Name\n");
    printf("------------------------------------------------\n");
    for( int i = 0; i < nUniforms; ++i ) {
        glGetActiveUniform( handle, i, maxLen, &written, &size, &type, name );
        location = glGetUniformLocation(handle, name);
        printf(" %-8d | %s\n",location, name);
    }

    free(name);
}

void GLSLProgram::printActiveAttribs() {

    GLint written, size, location, maxLength, nAttribs;
    GLenum type;
    GLchar * name;

    glGetProgramiv(handle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
    glGetProgramiv(handle, GL_ACTIVE_ATTRIBUTES, &nAttribs);

    name = (GLchar *) malloc( maxLength );

    printf(" Index | Name\n");
    printf("------------------------------------------------\n");
    for( int i = 0; i < nAttribs; i++ ) {
        glGetActiveAttrib( handle, i, maxLength, &written, &size, &type, name );
        location = glGetAttribLocation(handle, name);
        printf(" %-5d | %s\n",location, name);
    }

    free(name);
}

bool GLSLProgram::validate()
{
    if( ! isLinked() ) return false;

    GLint status;
    glValidateProgram( handle );
    glGetProgramiv( handle, GL_VALIDATE_STATUS, &status );

    if( GL_FALSE == status ) {
        // Store log and return false
        int length = 0;
        logString = "";

        glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &length );

        if( length > 0 ) {
            char * c_log = new char[length];
            int written = 0;
            glGetProgramInfoLog(handle, length, &written, c_log);
            logString = c_log;
            delete [] c_log;
        }

        return false;
    } else {
       return true;
    }
}

int GLSLProgram::getUniformLocation(const char * name )
{
    return glGetUniformLocation(handle, name);
}

bool GLSLProgram::fileExists( const string & fileName )
{
    struct stat info;
    int ret = -1;

    ret = stat(fileName.c_str(), &info);
    return 0 == ret;
}
 

#ifndef GLSLPROGRAM_H
#define GLSLPROGRAM_H

#include <string>
using std::string;

#include <GL/glew.h>

#include <glm/glm.hpp>
using glm::vec2;
using glm::vec3;
using glm::vec4;
using glm::mat4;
using glm::mat3;

namespace GLSLShader {
    enum GLSLShaderType {
        VERTEX, FRAGMENT, GEOMETRY,
        TESS_CONTROL, TESS_EVALUATION
    };
};

class GLSLProgram
{
private:
    int handle;
    bool linked;
    string logString;

    int getUniformLocation(const char * name );
    bool fileExists( const string & fileName );

public:
    GLSLProgram();

    bool compileShaderFromFile( const char * fileName, GLSLShader::GLSLShaderType type );
    bool compileShaderFromString( const string & source, GLSLShader::GLSLShaderType type );
    bool link();
    bool validate();
    void use();

    string log();

    int getHandle();
    bool isLinked();

    void bindAttribLocation( GLuint location, const char * name);
    void bindFragDataLocation( GLuint location, const char * name );

    void setUniform( const char *name, float x, float y, float z);
    void setUniform( const char *name, const vec2 & v);
    void setUniform( const char *name, const vec3 & v);
    void setUniform( const char *name, const vec4 & v);
    void setUniform( const char *name, const mat4 & m);
    void setUniform( const char *name, const mat3 & m);
    void setUniform( const char *name, float val );
    void setUniform( const char *name, int val );
    void setUniform( const char *name, bool val );

    void printActiveUniforms();
    void printActiveAttribs();
};

#endif // GLSLPROGRAM_H
 
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: Laurent on August 18, 2013, 10:54:58 pm
sfml-graphics still uses deprecated functions, so it can't be used with a core profile. And it's not just sf::Text (look, the error occurs in RenderTarget.cpp).

But SFML shouldn't be able to create contexts that it cannot use, how do you know that it's a core context and what's your OS?
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 18, 2013, 11:02:53 pm
Hi,

I am not using an opengl core context, I use the SFML context :), but I am programming assuming that I have an opengl core context except when I use SFML features such as Text.
I wonder if it is is possible to do that?

In the example I included in the thread, I had been trying to display a triangle (using OpenGL core features) and after that I am trying to display a text " window.draw(text);".

To display the triangle , I use a raw VBO and VAO. Also I use my custom Vertex and Fragment shaders.

I wonder if it is in some way incompatible to use OpenGl core and SFML Texts , or maybe there is some workaround?

I am working with Windows 7 64 bits, and Visual studio 2012 64 bits compiler.

Thanks,
Nicolas

Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: Laurent on August 18, 2013, 11:18:16 pm
Before investigating, please reduce the code to a complete and minimal program that reproduces the problem. The error could be triggered by anything.
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 18, 2013, 11:34:30 pm
Hi,

I tried to simplify as much as I can :)

If you comment :
        window.pushGLStates();
        window.draw(text);
        window.popGLStates();
it works displaying the triangle but the text is not displayed because is commented. You need to include the font file that is in SFML examples.

With those 3 lines, is displays the
"An internal OpenGL call failed in RenderTarget.cpp (218) : GL_INVALID_OPERATION,
 the specified operation is not allowed in the current state"
error.

Thanks,
Nicolas.

//To summarize, rendering with vertex buffer objects (VBOs) involves the following steps:
//1. Before linking the shader program, define the mappings between generic vertex
//attribute indexes and shader input variables by calling glBindAttribLocation.
//2. Create and populate the buffer objects for each attribute.
//3. Create and define the vertex array object by calling glVertexAttribPointer
//while the appropriate buffer is bound.
//4. When rendering, bind to the vertex array object and call glDrawArrays, or other
//appropriate rendering function (for example, glDrawElements).
#define GLEW_STATIC

#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/RenderWindow.hpp>

GLuint CreateShader(GLenum eShaderType, const std::string &strShaderFile)
{
        GLuint shader = glCreateShader(eShaderType);
        const char *strFileData = strShaderFile.c_str();
        glShaderSource(shader, 1, &strFileData, NULL);

        glCompileShader(shader);

        GLint status;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
        if (status == GL_FALSE)
        {
                GLint infoLogLength;
                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);

                GLchar *strInfoLog = new GLchar[infoLogLength + 1];
                glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);

                const char *strShaderType = NULL;
                switch(eShaderType)
                {
                case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
                case GL_GEOMETRY_SHADER: strShaderType = "geometry"; break;
                case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
                }

                fprintf(stderr, "Compile failure in %s shader:\n%s\n", strShaderType, strInfoLog);
                delete[] strInfoLog;
        }

        return shader;
}

GLuint CreateProgram(const std::vector<GLuint> &shaderList)
{
        GLuint program = glCreateProgram();

        // Bind index 0 to the shader input variable "VertexPosition"
    glBindAttribLocation(program, 0, "VertexPosition");
    // Bind index 1 to the shader input variable "VertexColor"
    glBindAttribLocation(program, 1, "VertexColor");

        //The output variable FragColor in the fragment shader. This variable receives the final output color for each
        //fragment (pixel). Like vertex input variables, this variable also needs to be associated with
        //a location. Of course, we typically would like this to be linked to the back color buffer, which
        //by default (in double buffered systems) is "color number" zero.
        glBindFragDataLocation(program, 0, "FragColor");

        for(size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
                glAttachShader(program, shaderList[iLoop]);

        glLinkProgram(program);

        GLint status;
        glGetProgramiv (program, GL_LINK_STATUS, &status);
        if (status == GL_FALSE)
        {
                GLint infoLogLength;
                glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);

                GLchar *strInfoLog = new GLchar[infoLogLength + 1];
                glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
                fprintf(stderr, "Linker failure: %s\n", strInfoLog);
                delete[] strInfoLog;
        }

        for(size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
                glDetachShader(program, shaderList[iLoop]);

        return program;
}

GLuint theProgram;

const std::string strVertexShader(
        "#version 400\n"
        "in vec3 VertexPosition;\n"
        "in vec3 VertexColor;\n"
        "out vec3 Color;\n"
        "void main()\n"
        "{\n"
        "Color = VertexColor;\n"
        "gl_Position = vec4(VertexPosition,1.0);\n"
        "}\n"
);

const std::string strFragmentShader(
        "#version 400\n"
        "in vec3 Color;\n"
        "out vec4 FragColor;\n"
        "void main() {\n"
        "FragColor = vec4(Color, 1.0);\n"
        "}\n"
);

void InitializeProgram()
{
        std::vector<GLuint> shaderList;

        shaderList.push_back(CreateShader(GL_VERTEX_SHADER, strVertexShader));
        shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, strFragmentShader));

        theProgram = CreateProgram(shaderList);

        std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}


int main()
{
        sf::ContextSettings contextSettings;
        contextSettings.depthBits = 32;
        contextSettings.stencilBits = 8;
        contextSettings.antialiasingLevel = 4;
        contextSettings.majorVersion = 3;
        contextSettings.minorVersion = 1;

        // Create the main window
        sf::RenderWindow window(sf::VideoMode(640, 480), "SFML window with OpenGL", sf::Style::Default, contextSettings);

        // Make it the active window for OpenGL calls
        window.setActive();

        GLenum err = glewInit();
        if( GLEW_OK != err )
        {
                fprintf(stderr, "Error initializing GLEW: %s\n", glewGetErrorString(err) );
        }

        // Create some text to draw on top of our OpenGL object
    sf::Font font;
    if (!font.loadFromFile("resources/sansation.ttf"))
        return EXIT_FAILURE;
    sf::Text text("SFML / OpenGL demo", font);
    text.setColor(sf::Color(255, 255, 255, 170));
    text.setPosition(250.f, 450.f);

        InitializeProgram();

        /////////////////// Create the VBO ////////////////////
           
        float positionData[] = {
        -0.8f, -0.8f, 0.0f,
         0.8f, -0.8f, 0.0f,
         0.0f, 0.8f, 0.0f };
    float colorData[] = {
        1.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 1.0f };


    // Create and populate the buffer objects
    GLuint vboHandles[2];

        // Create the buffer objects
    glGenBuffers(2, vboHandles);
    GLuint positionBufferHandle = vboHandles[0];
    GLuint colorBufferHandle = vboHandles[1];

        // Populate the position buffer
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);

        // Populate the color buffer
    glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);

    // Create and set-up the vertex array object
        GLuint vaoHandle;
    glGenVertexArrays( 1, &vaoHandle );
    glBindVertexArray(vaoHandle);

        // Enable the vertex attribute arrays
    glEnableVertexAttribArray(0); // Vertex position
    glEnableVertexAttribArray(1); // Vertex color

        // Map index 0 to the position buffer
        glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );

        // Map index 1 to the color buffer
    glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
    glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
       
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        // Configure the viewport (the same size as the window)
        glViewport(0, 0, window.getSize().x, window.getSize().y);

        // Create a clock for measuring the time elapsed
        sf::Clock clock;

        // Start the game loop
        while (window.isOpen())
        {
                // Process events
                sf::Event event;
                while (window.pollEvent(event))
                {
                        // Close window: exit
                        if (event.type == sf::Event::Closed)
                                window.close();

                        // Escape key: exit
                        if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                                window.close();

                        // Resize event: adjust the viewport
                        if (event.type == sf::Event::Resized)
                                glViewport(0, 0, event.size.width, event.size.height);
                }

                //// Clear the color and depth buffers
                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                glClear(GL_COLOR_BUFFER_BIT);

                glUseProgram(theProgram);

                // In the render function, bind to the vertex array object
                // and call glDrawArrays to initiate rendering.
                glBindVertexArray(vaoHandle);
                glDrawArrays(GL_TRIANGLES, 0, 3 );

                // Draw some text on top of our OpenGL object
        window.pushGLStates();
        window.draw(text);
        window.popGLStates();

                window.display();
        }

        return EXIT_SUCCESS;
}
 
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: Laurent on August 19, 2013, 07:53:08 am
You should try with SFML calls only, and then add OpenGL calls until the errors occurs again (we don't care if the program works or not, we just want to see the error).
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 19, 2013, 09:03:08 pm
Hi, i will try to figure to reduce it more, take into account that it is necessary to load the fragment and vertx shaders and the triangle data also. The other code is sfml related , if I find a way to reduce more i will post it but it is almost a hello world opengl core example.
Thanks,
Nicolas
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: Laurent on August 19, 2013, 09:23:59 pm
Quote
take into account that it is necessary to load the fragment and vertx shaders and the triangle data also
My guess is that you don't need to draw anything to produce the error. It must be caused by a state that you set.
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 19, 2013, 09:28:23 pm
Yes the issue is caused by using VBO and VAO instead if legacy opengl primitives to display the triangle.
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 20, 2013, 06:19:22 am
Simplified the example as Laurent suggested. There are some commented lines to understand the context.
Any help will be appreciated.



#define GLEW_STATIC

#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/RenderWindow.hpp>

int main()
{
    sf::ContextSettings contextSettings;
    contextSettings.depthBits = 32;
    contextSettings.stencilBits = 8;
    contextSettings.antialiasingLevel = 4;
    contextSettings.majorVersion = 3;
    contextSettings.minorVersion = 1;

    // Create the main window
    sf::RenderWindow window(sf::VideoMode(640, 480), "SFML window with OpenGL", sf::Style::Default, contextSettings);

    // Make it the active window for OpenGL calls
    window.setActive();

    GLenum err = glewInit();
    if( GLEW_OK != err )
    {
        fprintf(stderr, "Error initializing GLEW: %s\n", glewGetErrorString(err) );
    }

    // Create some text to draw on top of our OpenGL object
    sf::Font font;
    if (!font.loadFromFile("resources/sansation.ttf"))
        return EXIT_FAILURE;
    sf::Text text("SFML / OpenGL demo", font);
    text.setColor(sf::Color(255, 255, 255, 170));
    text.setPosition(250.f, 450.f);

    /////////////////// Create the VBO ////////////////////
     
    float positionData[] = {
        -0.8f, -0.8f, 0.0f,
         0.8f, -0.8f, 0.0f,
         0.0f, 0.8f, 0.0f };

    // Create and populate the buffer objects
    GLuint vboHandles[1];

    // Create the buffer objects
    glGenBuffers(1, vboHandles);
    GLuint positionBufferHandle = vboHandles[0];

    // Populate the position buffer
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);

    // Create and set-up the vertex array object
    GLuint vaoHandle;
    glGenVertexArrays( 1, &vaoHandle );
    glBindVertexArray(vaoHandle);

    //// Enable the vertex attribute arrays
    //glEnableVertexAttribArray(0); // Vertex position

    //// Map index 0 to the position buffer
    //glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
    //glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
   
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // Configure the viewport (the same size as the window)
    glViewport(0, 0, window.getSize().x, window.getSize().y);

    // Create a clock for measuring the time elapsed
    sf::Clock clock;

    // Start the game loop
    while (window.isOpen())
    {
        // Process events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Resize event: adjust the viewport
            if (event.type == sf::Event::Resized)
                glViewport(0, 0, event.size.width, event.size.height);
        }

        // Here can be custom OpenGL drawing code


        // Draw some text on top of our OpenGL object
        window.pushGLStates();
        window.draw(text);
        window.popGLStates();

        window.display();
    }

    return EXIT_SUCCESS;
}
 
 
 
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: Laurent on August 20, 2013, 07:44:57 am
So if you remove any of your OpenGL calls, it works?
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 20, 2013, 04:46:30 pm
If I comment glBindVertexArray line it doesnt crash and displays the sfml text for me. Thanks
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: Laurent on August 20, 2013, 04:59:29 pm
Crash? I thought we were talking about an error message in the console (although a crash is more expected in this situation).

To solve the crash, try calling glBindVertexArray(0). But I'd really like to solve this error message ;)
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 21, 2013, 10:01:00 pm
Thanks Laurent, I think that this can be solved if SFML uses some fixed particular VAO and VBO for the textures usef for the fonts. Maybe there is no standard way to support opengl core and opengl legacy primitives at the same time or that is possible to do ?
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: binary1248 on August 22, 2013, 01:03:27 am
Thanks Laurent, I think that this can be solved if SFML uses some fixed particular VAO and VBO for the textures usef for the fonts. Maybe there is no standard way to support opengl core and opengl legacy primitives at the same time or that is possible to do ?
? ? ?

This is not a bug, and as such there is nothing to fix.

SFML already forces the operating system to give it a context that supports the deprecated OpenGL interfaces i.e a compatibility context. You can't get a "core only" context if you use SFML for context management. So if you use an SFML context with a high enough version number there should never be any GL_INVALID_OPERATION errors due to removed functions. The only time that error can occur is when something really does go wrong, and you should look for the source of that error instead of wondering whether it has something to do with deprecation or not.

And no, I don't think Laurent is going to consider using VAOs inside SFML just yet. It would cut off too many users with older hardware who are happily running SFML as it is with pre-3.0 OpenGL right now. Not only that, even if SFML did use VAOs it would not be able to provide any significant performance increase anyway, which would be a complete waste of time.

VAOs are a very very advanced topic. It takes time to understand how they work and what they are for. It takes even more time to understand how you can use them effectively, and even more time to test whether they actually make a difference. If you really want to play around with VAOs and SFML, you should really look at the SFML source a lot more and not just rely on the documentation. It is written to provide as much information as possible for the "normal" user, but for people like you who use newer OpenGL that is really sensitive to anything that is done, knowing exactly what and how SFML uses OpenGL is necessary. One thing that many people are still not aware of is that VAOs are one of the few resources that are not shared between contexts. Guess what happens if you call glBindVertexArray() in the wrong context? GL_INVALID_OPERATION, and have fun debugging. Hopefully Laurent won't linger with this shared context framework for too long. It is not future proof considering newer OpenGL resources probably won't be shareable either.

Oh, and pushGLStates() and popGLStates() won't help you either when using VAOs. You should develop a good habit of cleaning up after yourself and unbinding any arrays and doing attribute housekeeping before letting other people mess with OpenGL. Leaving the same array bound the whole time defeats the purpose of a VAO anyway...
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on August 22, 2013, 03:04:30 am
Thank you for your answer, I will read it more carefully in these days. I understand your point in several aspects you mention.
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on September 01, 2013, 07:37:00 pm
I am back. I would like to take some conclusions together.

If we use raw VAO y VBO it is not possible to display texts as intendend?

I have read more articles and the way to render texts in opengl is loading a texture image with all the characterers, then the texts are generated using that texture and opengl primitives.

I have one question, if I would like to use opengl core to avoid incompatibilities dependent of platform maybe it would be better that SFML provides a Window this is opengl core, I know that currently it isn't available. Does it make senses that SFML has some kind of OPENGL core mode? (without any of the 2d features available), I think that will be great for developers as me, that also use de i/o and other SFML stuff.

Thanks in advance,
Nicolas.


Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: binary1248 on September 01, 2013, 08:19:52 pm
If we use raw VAO y VBO it is not possible to display texts as intendend?
It is still possible, you just need to do it properly. Like I said, learn how SFML text rendering is implemented and if you are capable in OpenGL you should have no problem figuring out how to get it to work with VAOs and VBOs.

I have read more articles and the way to render texts in opengl is loading a texture image with all the characterers, then the texts are generated using that texture and opengl primitives.
There really isn't any other way to do it... which is why everybody does it like that...

I have one question, if I would like to use opengl core to avoid incompatibilities dependent of platform maybe it would be better that SFML provides a Window this is opengl core, I know that currently it isn't available. Does it make senses that SFML has some kind of OPENGL core mode? (without any of the 2d features available), I think that will be great for developers as me, that also use de i/o and other SFML stuff.
? ? ?
OK... I am slowly doubting that you understand what you are saying...

1. There is a difference between "core functionality" and a "core profile". Core functionality is basically OpenGL itself without any of its extensions such as GLU. This core functionality is basically a set of functions that are part of an interface you use to communicate with your GPU. That interface can change depending on the version and the context type you request. In OpenGL 3.0 certain functions were marked as deprecated and were removed from the "core profile" interface in OpenGL 3.1. However from OpenGL 3.2 onwards, in addition to the "core profile" you could also request a "compatibility profile" which lets you use most parts of the old interface again. As such any modern hardware that supports OpenGL 3.2 and above should let SFML create a compatibility context for its purposes. In this sense, SFML is still supported on modern graphics hardware.

2. If you want to support older hardware as well, it makes no sense to use all these fancy features. VAOs will not work if the GPU does not support them. SFML is built to support as much hardware as possible while assuring that it stays relatively future-proof regarding OpenGL. Your code in fact is more "incompatible" than SFML code regarding platform portability.

3. If you want to support the majority of modern devices that are available nowadays (including tablets, mobile devices etc.) you want OpenGL ES support. OpenGL ES is a subset of the OpenGL interface. SFML with OpenGL ES support is being (or will be) worked on.

4. OpenGL does not differentiate between 2D or 3D objects, they are all just data to it. The notion of "removing 2D features" does not make any sense.

5. If you don't use any OpenGL resources in SFML that require a context it will not create one. You can use everything unrelated to graphics and windows and it will not have the slightest to do with OpenGL.
Title: Re: Does sf::Text works in a OpenGL Core profile example?
Post by: nicoraf on September 01, 2013, 09:14:47 pm
Hi,

Thanks for you answer. I will try to figure out how it is implemented.