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

Author Topic: [2.0] RenderWindow, GLStates, and VBOs  (Read 4762 times)

0 Members and 1 Guest are viewing this topic.

Izman

  • Newbie
  • *
  • Posts: 7
    • View Profile
[2.0] RenderWindow, GLStates, and VBOs
« on: April 04, 2013, 02:32:42 am »
I get a crash whenever I call a GLStates() function (pushGLStates(), popGLStates(), resetGLStates()) while drawing using a VBO on a RenderWindow.

I'm trying to teach myself non-deprecated OpenGL by following the online tutorial at http://open.gl

I copy + pasted the code found in the first tutorial (located at: http://open.gl/content/code/c2_triangle_elements.txt)

I Imported
#include <SFML/Graphics/RenderWindow.hpp>
changed the syntax to match SFML 2.0, and changed the rendering code to:

    // Clear the screen to black
        glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
        glClear( GL_COLOR_BUFFER_BIT );
               
        // Draw a rectangle from the 2 triangles using 6 indices
        glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );

        window.pushGLStates();
               
                //RENDER SFML

        window.popGLStates();
        window.display();
        window.resetGLStates();

The program runs for a fraction of a second, then gives me a unhandled exception.

If I comment out 
window.pushGLStates();
window.popGLStates();
window.resetGLStates();
Then the code runs fine.  However, I want to be able to draw text using SFML along side VBOs.

I'm a total noob to VBOs, and I only come from a background of Immediate Mode.  I saw on some other threads that they used
glDisableClientState()
to fix this, but I don't know where to begin.

How can I get the tutorial code to not crash immediately?
« Last Edit: April 04, 2013, 02:40:59 am by Izman »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #1 on: April 04, 2013, 07:32:43 am »
Use glDisableClientState to disable color and/or texture coordinates if you don't use them -- SFML internally keeps them enabled, so it can crash if you don't bind the corresponding buffer.
Laurent Gomila - SFML developer

Izman

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #2 on: April 04, 2013, 07:59:38 am »
Thanks for the reply :)

Sadly, I already tried doing that, but maybe I did it wrong.

Here's the exact source code I'm using.  I added in the glDisableClientState() calls after the RenderWindow

Should compile by linking GLEW statically and SFML 2.0 dynamically.

http://pastebin.com/7hWy91ff

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #3 on: April 04, 2013, 01:08:32 pm »
You must call it after drawing with SFML, not just at init time. And why did you put a call to resetGLStates there? It's useless.
Laurent Gomila - SFML developer

Izman

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #4 on: April 04, 2013, 09:46:15 pm »
Thanks for your assistance,

I put a resetGLStates() call because it's required for my Immediate Mode project (without it all the drawing gets thrown on top of the last SFML call)

I put the glDisableClientState() calls in the render loop, and now it doesn't crash :)  However, it's also not displaying any colour either (well duh, I disabled colour + textures).  However, if I remove the disabling of colour (or textures, or both)

                        //Disable Client States
                        glDisableClientState(GL_COLOR_ARRAY);
                        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

I get an instant crash again. 

Here's the render loop:

            // Clear the screen to black
                glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
                glClear( GL_COLOR_BUFFER_BIT );

                // Draw a rectangle from the 2 triangles using 6 indices
                glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );

                window.pushGLStates();
               
                        //RENDER SFML HERE

                        //Disable Client States
                        glDisableClientState(GL_COLOR_ARRAY);
                        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

                window.popGLStates();
                window.display();

How can I display the colour of the rectangle without crashing?

Edit: Removed SECONDARY_COLOR
« Last Edit: April 04, 2013, 10:18:34 pm by Izman »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #5 on: April 05, 2013, 08:09:00 am »
You just need to disable the components that you don't use. Those that you use won't cause a crash.

And you must call glDisableClientState after popGLStates().
Laurent Gomila - SFML developer

Izman

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #6 on: April 05, 2013, 10:43:14 am »
Thank you for your patience,

Funny enough, the directions seem so simple yet I can't get them to work.  However, I did go through the SFML source code to find where the glEnableClientStates() were.

Turns out the call to resetGLStates() was the root of the problem.  If I copy out the source code without the resetGLStates() call at the end of popGLStates(), the program runs fine and I get colour.

However, that still doesn't solve anything, as I want to draw text using SFML's Text class. 

Note that I did try adding every permutation of
                glDisableClientState(GL_VERTEX_ARRAY);
                glDisableClientState(GL_COLOR_ARRAY);
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);

After the popGLStates() call, and no luck -- I either get a white box, nothing at all, or a crash.


I guess from here the only option is to handle fonts from outside of SFML and use a sf::Window instead.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #7 on: April 05, 2013, 11:49:59 am »
Can you please post a complete and minimal code that reproduces the problem?
Laurent Gomila - SFML developer

Izman

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #8 on: April 05, 2013, 06:51:37 pm »
Sorry for the delay,

Considering I'm a complete beginner at VBOs, I don't really know what I can cut, so this is the smallest I can get the source code:

// Link statically with GLEW
#define GLEW_STATIC

// Headers
#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>

// Shader sources
const char* vertexSource =
        "#version 150\n"
        "in vec2 position;"
        "in vec3 color;"
        "out vec3 Color;"
        "void main() {"
        "       Color = color;"
        "       gl_Position = vec4( position, 0.0, 1.0 );"
        "}";
const char* fragmentSource =
        "#version 150\n"
        "in vec3 Color;"
        "out vec4 outColor;"
        "void main() {"
        "       outColor = vec4( Color, 1.0 );"
        "}";

int main()
{
        int state = 1;  //IF 0 = PROGRAM ENDS
        sf::RenderWindow window( sf::VideoMode( 800, 600, 32 ), "OpenGL", sf::Style::Titlebar | sf::Style::Close );

        // Initialize GLEW
        glewExperimental = GL_TRUE;
        glewInit();

        // Create Vertex Array Object
        GLuint vao;

        glGenVertexArrays( 1, &vao );
        glBindVertexArray( vao );
       
        // Create a Vertex Buffer Object and copy the vertex data to it
        GLuint vbo;
        glGenBuffers( 1, &vbo );

        float vertices[] = {
                -0.5f,  0.5f, 1.0f, 0.0f, 0.0f, // Top-left
                 0.5f,  0.5f, 0.0f, 1.0f, 0.0f, // Top-right
                 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right
                -0.5f, -0.5f, 1.0f, 1.0f, 1.0f  // Bottom-left
        };

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

        // Create an element array
        GLuint ebo;
        glGenBuffers( 1, &ebo );

        GLuint elements[] = {
                0, 1, 2,
                2, 3, 0
        };

        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ebo );
        glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( elements ), elements, GL_STATIC_DRAW );

        // Create and compile the vertex shader
        GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
        glShaderSource( vertexShader, 1, &vertexSource, NULL );
        glCompileShader( vertexShader );

        // Create and compile the fragment shader
        GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
        glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
        glCompileShader( fragmentShader );

        // Link the vertex and fragment shader into a shader program
        GLuint shaderProgram = glCreateProgram();
        glAttachShader( shaderProgram, vertexShader );
        glAttachShader( shaderProgram, fragmentShader );
        glBindFragDataLocation( shaderProgram, 0, "outColor" );
        glLinkProgram( shaderProgram );
        glUseProgram( shaderProgram );

        // Specify the layout of the vertex data
        GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
        glEnableVertexAttribArray( posAttrib );
        glVertexAttribPointer( posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof( float ), 0 );

        GLint colAttrib = glGetAttribLocation( shaderProgram, "color" );
        glEnableVertexAttribArray( colAttrib );
        glVertexAttribPointer( colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof( float ), (void*)( 2 * sizeof( float ) ) );

        while ( state != 0 )
        {
                sf::Event windowEvent;
                while ( window.pollEvent( windowEvent ) )
                {
                        switch ( windowEvent.type )
                        {
                        case sf::Event::Closed:
                                state = 0;
                                break;
                        }
                }

                // Clear the screen to black
                glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                // Draw a rectangle from the 2 triangles using 6 indices
                glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );

                window.pushGLStates();
                       
                        //RENDER SFML HERE

                window.popGLStates();

                //If disabled, nothing gets drawn and no crash occurs
                glDisableClientState(GL_VERTEX_ARRAY);

                //Both has to be disabled or a crash occurs.  If GL_VERTEX_ARRAY is enabled and
                //GL_COLOR_ARRAY and GL_TEXTURE_COORD_ARRAY are disabled, then a white box is drawn
                glDisableClientState(GL_COLOR_ARRAY);
                glDisableClientState(GL_TEXTURE_COORD_ARRAY);

                window.display();

        }

        glDeleteProgram( shaderProgram );
        glDeleteShader( fragmentShader );
        glDeleteShader( vertexShader );

        glDeleteBuffers( 1, &ebo );
        glDeleteBuffers( 1, &vbo );

        glDeleteVertexArrays( 1, &vao );
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #9 on: April 05, 2013, 08:08:35 pm »
Hum... I don't know how the old API (glEnableClientState) mixes with the new one (glEnableVertexAttribArray), and I can't test OpenGL 3 on my computer so I'm not sure what you should do.

Does the program give the expected result without the SFML drawing?
Laurent Gomila - SFML developer

Izman

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #10 on: April 06, 2013, 11:02:12 am »
Hum... I don't know how the old API (glEnableClientState) mixes with the new one (glEnableVertexAttribArray), and I can't test OpenGL 3 on my computer so I'm not sure what you should do.

Does the program give the expected result without the SFML drawing?

Well the thing is that I'm not actually drawing with SFML yet.  I just added
        window.pushGLStates();
           
            //RENDER SFML HERE

        window.popGLStates();
to state where I would theoretically put my window.draw(text) calls.

Currently, I'm just trying to get VBOs drawing while using sf::RenderWindow's pushGLStates() and popGLStates().  If I do not include those 2 functions, I get the expected result (more specifically, if I remove the resetGLStates() call all together)


On a separate note, I did find something interesting.  sf::Text doesn't draw if I call the function
glBindVertexArray( vao );
I can only see the text if I comment out that line (and the rest of the VBO init).

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #11 on: April 06, 2013, 12:14:19 pm »
About that separate note, there is (was?) a bug (or is it intended?) you have to unbind (bind to 0) your buffers/VAO or your text won't be displayed.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #12 on: April 06, 2013, 12:36:48 pm »
This is exactly what we're talking about here, and yes it is a bug ;)
Laurent Gomila - SFML developer

infinitebox

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: [2.0] RenderWindow, GLStates, and VBOs
« Reply #13 on: August 14, 2013, 01:04:57 pm »
Hi,

Sorry to dig this back up, but currently I'm experiencing the exact problem that the OP ran into. Basically calling pushGLStates() and popGLStates() alone will crash the application. This can be re-mediated by calling
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

The application crashes again if I draw a sf::CircleShape in between pushGLStates() and popGLStates()..
Visual studio returns an "Access violation reading location 0x00000000" error dialog.

I would like to know if there's a work around for this. I am doing an OpenGL unit this semester and I wanted to use SFML instead of Freeglut or GLFW for windowing, and 2D stuff.

I'm using SFML2.1 and OpenGL 3.2.
« Last Edit: August 14, 2013, 01:11:16 pm by infinitebox »