SFML community forums

Help => Window => Topic started by: LucasShadow on July 15, 2012, 07:51:12 pm

Title: [SOLVED] RenderWindow::PreserveOpenGLStates
Post by: LucasShadow on July 15, 2012, 07:51:12 pm
I am still getting used to SFML 2.0 and was wondering how the 2.0 version of RenderWindow::PreserveOpenGLStates can be invoked to make sure that OpenGL content can work with SFML content so that this doesnt happen:

(http://puu.sh/IM4X)

That white stuff is an sf::Text, and the green is a textured quad.  Im hoping that by preserving the OpenGLStates I can make the text appear as normal, but I can't find the appropriate reference in the 2.0 docs.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: Laurent on July 15, 2012, 08:58:04 pm
See the pushGLStates and popGLStates functions.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: LucasShadow on July 16, 2012, 01:01:03 am
I tried what you suggested, but still have not had any success. Here is some minimal code that reproduces what I am seeing:

#include <windows.h>
#include <SFML/Graphics.hpp>
#include <math.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>

#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glut.h>

class Scene {
public:
        Scene() {
                // Init OpenGL states
                glEnableClientState( GL_VERTEX_ARRAY );
                glEnableClientState( GL_TEXTURE_COORD_ARRAY );
                glEnable( GL_TEXTURE_2D );
        }
        ~Scene() {
                // Reset OpenGL states
                glDisableClientState( GL_VERTEX_ARRAY );
                glDisableClientState( GL_TEXTURE_COORD_ARRAY );
                glDisable( GL_TEXTURE_2D );
        }
        void resize( int w, int h ) {
                // OpenGL Reshape
                glViewport( 0, 0, w, h );
                glMatrixMode( GL_PROJECTION );
                glLoadIdentity();
                gluPerspective( 120.0, (GLdouble)w/(GLdouble)h, 0.5, 500.0 );
                glMatrixMode( GL_MODELVIEW );
        }
};


float angle = 0.0f;
float lx = 0.0f, lz = -1.0f;
float x = 0.0f, z = 15.0f;
float deltaAngle = 0.0f;
float deltaMove = 0;

using namespace std;

int main(int argc, char **argv) {

    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "SFML/OpenGL Tester");

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

    Scene scene;
    scene.resize(800,600);

    sf::Image img1;
    img1.loadFromFile("texture.bmp");
    GLuint texture1;
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, img1.getSize().x, img1.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)img1.getPixelsPtr() );

    sf::Text text1("Some test text colored red");
    text1.setPosition(230,550);
    sf::Color Red(255,0,0);
    text1.setColor(Red);

    sf::Texture tex1;
    tex1.loadFromFile("hud.png");
    sf::Sprite sprite1;
    sprite1.setTexture(tex1);
    sprite1.setPosition(50,50);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
    glEnable(GL_COLOR_MATERIAL);
    glShadeModel(GL_SMOOTH);

    float Y = 1.0f;

    while( window.isOpen() ) {
        sf::Event event;
        while( window.pollEvent( event ) ) {
            if( event.type == sf::Event::Closed )
                window.close();
        }

        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(50.0, 1.0, 1.0, 70.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(      x, Y, z,//eye's position
                    x + lx, Y,  z + lz, //where the eye is looking (point)
                    0.0f, 1.0f,  0.0f);//translations

        glColor3f(0.5, 0.2, 0.2);

        glBegin(GL_QUADS);
            glEnable(GL_TEXTURE_2D);
            glBindTexture( GL_TEXTURE_2D, texture1 );

            glTexCoord2d(0.0,0.0);
            glVertex3f(0,0,0);
            glTexCoord2d(1.0,0.0);
            glVertex3f(0,1,0);
            glTexCoord2d(1.0,1.0);
            glVertex3f(1,1,0);
            glTexCoord2d(0.0,1.0);
            glVertex3f(1,0,0);

            glDisable(GL_TEXTURE_2D);
        glEnd();

                window.pushGLStates();
                window.draw(text1);
                window.draw(sprite1);
                window.popGLStates();

        window.display();
    }
    return 1;
}
 

This minimal code produces this:
(http://puu.sh/IOLg)

Sprite 1, the non-green picture, where-ever you see white is actually supposed to be transparent. Text 1 also seems to have some problems aswell, as though where the transparent parts should be are colored what the text color is set to. The green square is a textured quad.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: binary1248 on July 16, 2012, 06:50:06 am
In the order they appear in the code:

1. Don't use GLUT and SFML at the same time, SFML is a superset of GLUT and should be used by itself.
2. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) is messing SFML texturing up. pushGLStates and popGLStates pushes the texture environment but resetGLStates doesn't reset it AFAIR. Right now you would have to take care of resetting it back to the default yourself whenever you use SFML to draw some textured stuff.
3. Not sure but the same might apply for glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION) as well.
4. pushGLStates only pushes the current OpenGL state onto the stack. It doesn't clean it up so SFML can work properly. After pushGLStates you would need to call resetGLStates as well. Additionally you would need to reset the states I already mentioned back to default.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: Laurent on July 16, 2012, 08:04:01 am
Quote
2. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) is messing SFML texturing up. pushGLStates and popGLStates pushes the texture environment but resetGLStates doesn't reset it AFAIR. Right now you would have to take care of resetting it back to the default yourself whenever you use SFML to draw some textured stuff.
3. Not sure but the same might apply for glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION) as well.
This is a problem. Do you see a solution other than resetting the entire set of OpenGL states in resetGLStates? :-\

Quote
4. pushGLStates only pushes the current OpenGL state onto the stack. It doesn't clean it up so SFML can work properly. After pushGLStates you would need to call resetGLStates as well. Additionally you would need to reset the states I already mentioned back to default.
pushGLStates calls resetGLStates; otherwise it would be mentioned in the doc.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: binary1248 on July 16, 2012, 06:20:12 pm
Quote
2. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) is messing SFML texturing up. pushGLStates and popGLStates pushes the texture environment but resetGLStates doesn't reset it AFAIR. Right now you would have to take care of resetting it back to the default yourself whenever you use SFML to draw some textured stuff.
3. Not sure but the same might apply for glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION) as well.
This is a problem. Do you see a solution other than resetting the entire set of OpenGL states in resetGLStates? :-\
If the user wants to use their own OpenGL state set, then they will have to manage it themselves... But then again they won't know what to set it to for SFML unless they look in the source :) I guess they can assume everything that resetGLStates doesn't touch should be set back to default for SFML. Maybe a list of stuff that resetGLStates resets in the docs would save them the trip through source ;)
Quote
4. pushGLStates only pushes the current OpenGL state onto the stack. It doesn't clean it up so SFML can work properly. After pushGLStates you would need to call resetGLStates as well. Additionally you would need to reset the states I already mentioned back to default.
pushGLStates calls resetGLStates; otherwise it would be mentioned in the doc.
The name is kind of misleading don't you think? It would be like glPushMatrix() also calling glLoadIdentity() :) The doc also doesn't explicitly mention that resetGLStates is called. It only mentions saving the current states but not what becomes current. I think it would be nice if the user could use them in inverse order as well, for whatever reason they might have:
// OpenGL code here...
 window.popGLStates();
 window.draw(...);
 window.draw(...);
 window.pushGLStates();
 // OpenGL code here...
That way they can just set their stuff up every frame instead of making SFML set it's stuff up every frame. Depending on the ratio of states that the user and SFML set up this can be faster and easier to manage in some cases.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: Laurent on July 16, 2012, 08:49:43 pm
Quote
Maybe a list of stuff that resetGLStates resets in the docs would save them the trip through source
Good idea :)

Quote
The name is kind of misleading don't you think? It would be like glPushMatrix() also calling glLoadIdentity()
It's misleading... only if you compare with OpenGL functions. Wanyway, what would you suggest as a better name?

Quote
I think it would be nice if the user could use them in inverse order as well
That's what I wanted initially, but it was more tricky than expected. I don't remember why, though ;D
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: binary1248 on July 16, 2012, 09:23:34 pm
Quote
The name is kind of misleading don't you think? It would be like glPushMatrix() also calling glLoadIdentity()
It's misleading... only if you compare with OpenGL functions. Wanyway, what would you suggest as a better name?

Quote
I think it would be nice if the user could use them in inverse order as well
That's what I wanted initially, but it was more tricky than expected. I don't remember why, though ;D
Make the user call resetGLStates() explicitly? There is theoretically 0 performance loss and allows for more flexibility. Then push would do what push implies and nothing more. It would also give more purpose to resetGLStates since now nobody who means to save the states because they want to reset them even bothers calling it. Since we use Git we can get inspiration from there. What about stashGLStates? :P
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: Laurent on July 16, 2012, 10:24:02 pm
If a function must always be followed by another one (pushGLStates + resetGLStates), I feel bad not to merge them. You define two separate functions but doing anything else than calling them together will fail. It feels wrong.

But I know that this is not a perfect solution, I'm still not satisfied with the way SFML and OpenGL are mixed together in user code.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: LucasShadow on July 17, 2012, 02:45:59 am
1. Don't use GLUT and SFML at the same time, SFML is a superset of GLUT and should be used by itself.
Ah, okay. Didnt know SFML was a superset of GLUT.

2. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) is messing SFML texturing up. pushGLStates and popGLStates pushes the texture environment but resetGLStates doesn't reset it AFAIR. Right now you would have to take care of resetting it back to the default yourself whenever you use SFML to draw some textured stuff.
3. Not sure but the same might apply for glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION) as well.
Well how would you reset it completely then if resetGLStates (popGLStates) doesnt do the job?

Quote
Maybe a list of stuff that resetGLStates resets in the docs would save them the trip through source
Good idea :)
I second that  ;)
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: binary1248 on July 17, 2012, 03:14:15 am
Well how would you reset it completely then if resetGLStates (popGLStates) doesnt do the job?
For every state that doesn't get reset by SFML, you would have to look up the OpenGL documentation and see what the default value should be such as in the page for glTexEnv (http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml) it says:
Quote
GL_TEXTURE_ENV_MODE defaults to GL_MODULATE and GL_TEXTURE_ENV_COLOR defaults to (0, 0, 0, 0).
It might seem tedious, but the work involved always stays relative to the amount of special non-SFML-handled states you make use of yourself which shouldn't be too many hopefully :).
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: Laurent on July 17, 2012, 08:06:58 am
Maybe you can capture the OpenGL states in a display list after sf::RenderWindow is created, and apply it whenever you switch from OpenGL to SFML. I don't remember if you can make such a snapshot, last time I used display lists was a long time ago.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: binary1248 on July 17, 2012, 03:34:29 pm
Display lists are only queues of commands. You would still have to tell them what exactly you want to do every frame. Therefore this is semantically no different from resetting all the special states yourself.
Title: Re: RenderWindow::PreserveOpenGLStates
Post by: Laurent on July 17, 2012, 04:55:07 pm
So you can't get a "snapshot" of the current states. Too bad. As far as I remember, Direct3D can do it.
Title: Re: [SOLVED] RenderWindow::PreserveOpenGLStates
Post by: LucasShadow on July 17, 2012, 11:07:46 pm
Thank you both for helping me out. By setting the glTexEnvf settings back to their default state, the graphical errors cleared up :)