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

Author Topic: Issue with full screen switching  (Read 3008 times)

0 Members and 1 Guest are viewing this topic.

clasher114

  • Newbie
  • *
  • Posts: 2
    • View Profile
Issue with full screen switching
« on: November 11, 2023, 11:22:28 am »
Google translate
I'm writing a 3D game in OpenGL and C++. I am using SFML for window management, event handler. etc, also I use the "glad" library for rendering 3D graphics and glm for calculating matrices.
Now I'm facing a problem when you create a new window (sf::RenderWindow::create()) to toggle fullscreen mode, all the already created VAOs (Vertex Array Objects) stop rendering, only the new VAO renders properly. At the same time, SFML sends some errors to the console that I haven't found a solution for.
Here's a code example, F - to switch to full screen mode, Space - to recreate the cube
#include <SFML/Graphics.hpp>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

const char* title = "Test";

float size = 1.f;

static const int attributes[] = {
    3, 3, 3, 0
};

static const GLfloat vertices[] = {
    //    x     y      z      r       g       b
        -size, -size, -size, 0.583f,  0.771f,  0.014f, 0.0f, 0.0f,-1.0f,
         size, -size, -size, 0.609f,  0.115f,  0.436f, 0.0f, 0.0f,-1.0f,
         size,  size, -size, 0.327f,  0.483f,  0.844f, 0.0f, 0.0f,-1.0f,
         size,  size, -size, 0.822f,  0.569f,  0.201f, 0.0f, 0.0f,-1.0f,
        -size,  size, -size, 0.435f,  0.602f,  0.223f, 0.0f, 0.0f,-1.0f,
        -size, -size, -size, 0.310f,  0.747f,  0.185f, 0.0f, 0.0f,-1.0f,

        -size, -size,  size, 0.597f,  0.770f,  0.761f, 0.0f, 0.0f, 1.0f,
         size, -size,  size, 0.559f,  0.436f,  0.730f, 0.0f, 0.0f, 1.0f,
         size,  size,  size, 0.359f,  0.583f,  0.152f, 0.0f, 0.0f, 1.0f,
         size,  size,  size, 0.483f,  0.596f,  0.789f, 0.0f, 0.0f, 1.0f,
        -size,  size,  size, 0.559f,  0.861f,  0.639f, 0.0f, 0.0f, 1.0f,
        -size, -size,  size, 0.195f,  0.548f,  0.859f, 0.0f, 0.0f, 1.0f,

        -size,  size,  size, 0.014f,  0.184f,  0.576f,-1.0f, 0.0f, 0.0f,
        -size,  size, -size, 0.771f,  0.328f,  0.970f,-1.0f, 0.0f, 0.0f,
        -size, -size, -size, 0.406f,  0.615f,  0.116f,-1.0f, 0.0f, 0.0f,
        -size, -size, -size, 0.676f,  0.977f,  0.133f,-1.0f, 0.0f, 0.0f,
        -size, -size,  size, 0.971f,  0.572f,  0.833f,-1.0f, 0.0f, 0.0f,
        -size,  size,  size, 0.140f,  0.616f,  0.489f,-1.0f, 0.0f, 0.0f,

         size,  size,  size, 0.997f,  0.513f,  0.064f, 1.0f, 0.0f, 0.0f,
         size,  size, -size, 0.945f,  0.719f,  0.592f, 1.0f, 0.0f, 0.0f,
         size, -size, -size, 0.543f,  0.021f,  0.978f, 1.0f, 0.0f, 0.0f,
         size, -size, -size, 0.279f,  0.317f,  0.505f, 1.0f, 0.0f, 0.0f,
         size, -size,  size, 0.167f,  0.620f,  0.077f, 1.0f, 0.0f, 0.0f,
         size,  size,  size, 0.347f,  0.857f,  0.137f, 1.0f, 0.0f, 0.0f,

        -size, -size, -size, 0.500f,  0.953f,  0.042f, 0.0f,-1.0f, 0.0f,
         size, -size, -size, 0.714f,  0.505f,  0.345f, 0.0f,-1.0f, 0.0f,
         size, -size,  size, 0.783f,  0.290f,  0.734f, 0.0f,-1.0f, 0.0f,
         size, -size,  size, 0.722f,  0.645f,  0.174f, 0.0f,-1.0f, 0.0f,
        -size, -size,  size, 0.302f,  0.455f,  0.848f, 0.0f,-1.0f, 0.0f,
        -size, -size, -size, 0.225f,  0.587f,  0.040f, 0.0f,-1.0f, 0.0f,

        -size,  size, -size, 0.517f,  0.713f,  0.338f, 0.0f, 1.0f, 0.0f,
         size,  size, -size, 0.053f,  0.959f,  0.120f, 0.0f, 1.0f, 0.0f,
         size,  size,  size, 0.393f,  0.621f,  0.362f, 0.0f, 1.0f, 0.0f,
         size,  size,  size, 0.673f,  0.211f,  0.457f, 0.0f, 1.0f, 0.0f,
        -size,  size,  size, 0.820f,  0.883f,  0.371f, 0.0f, 1.0f, 0.0f,
        -size,  size, -size, 0.982f,  0.099f,  0.879f, 0.0f, 1.0f, 0.0f
};

const char* vertexShader =
"#version 460\n"

"layout(location = 0) in vec3 vertex_position;\n"
"layout(location = 1) in vec3 vertex_color;\n"
"layout(location = 2) in vec3 vertex_normal;\n"

"uniform mat4 matrix;\n"
"uniform mat4 matrix_transpose_inverse;\n"
"uniform mat4 projview;\n"

"out vec3 color;\n"
"out vec3 Normal;\n"
"out vec3 FragPos;\n"

"void main() {\n"
"    color = vertex_color;\n"
"    gl_Position = projview * matrix * vec4(vertex_position, 1.0);\n"
"    Normal = mat3(matrix_transpose_inverse) * vertex_normal;\n"
"    FragPos = vec3(matrix * vec4(vertex_position, 1.0));\n"
"}\n";

const char* fragmentShader =
"#version 460\n"

"uniform float u_ambient; \n"
"uniform vec3 u_lightColor; \n"
"uniform vec3 lightPos; \n"

"out vec4 frag_color; \n"
"in vec3 color; \n"
"in vec3 Normal; \n"
"in vec3 FragPos; \n"

"void main() {\n"
"    vec3 norm = normalize(Normal); \n"
"    vec3 lightDir = normalize(lightPos - FragPos); \n"
"    float diff = max(dot(norm, lightDir), 0.0); \n"
"    vec3 diffuse = diff * u_lightColor; \n"
"    vec3 result = (u_ambient + diffuse) * color; \n"
"    frag_color = vec4(result, 1.0); \n"
"}\n";

class Cube {
public:
    Cube();
    ~Cube();

    void draw();
private:
    GLuint vbo = 0;
    GLuint vao = 0;
};

Cube::Cube() {
    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);

    GLsizei vertexSize = 0;
    for (int i = 0; attributes[i]; i++) {
        vertexSize += attributes[i];
    }

    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);

    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * sizeof(vertices) / sizeof(GLfloat), vertices, GL_STATIC_DRAW);

    // attributes
    int offset = 0;
    for (int i = 0; attributes[i]; i++) {
        int size = attributes[i];
        glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float)));
        glEnableVertexAttribArray(i);
        offset += size;
    }

    glBindVertexArray(0);
}

Cube::~Cube() {
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
}

void Cube::draw() {
    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);
}

int main() {
        sf::ContextSettings settings(24, 0, 0, 4, 6);
        sf::VideoMode videoMode(WINDOW_WIDTH, WINDOW_HEIGHT);
        sf::RenderWindow window(videoMode, title, sf::Style::Default, settings);
        window.setVerticalSyncEnabled(true);
        window.setKeyRepeatEnabled(false);

    if (!gladLoadGL()) {
        return 1;
    }

    glEnable(GL_DEPTH_TEST);

    Cube* cube = new Cube();

    sf::Shader mainShader;
    mainShader.loadFromMemory(vertexShader, fragmentShader);

        bool fullscreen = false;

        sf::RectangleShape shape(sf::Vector2f(40.f, 40.f));
        shape.setFillColor(sf::Color::Blue);

    float cubeRotation = 0.f;
    // camera
    glm::vec3 front, up, right, dir;

    glm::vec3 position(0.f, 0.f, 5.f);
    float fov = 70.f;
    glm::mat4 rotation(1.f);

    sf::Clock deltaclock;

        while (window.isOpen()) {
        float delta = deltaclock.restart().asSeconds();

        sf::Event e;
        while (window.pollEvent(e)) {
            switch (e.type) {
            case sf::Event::Closed: window.close(); return 0;
            case sf::Event::KeyPressed:
                if (e.key.code == sf::Keyboard::F) {
                    sf::ContextSettings settings(window.getSettings());
                    if (fullscreen) {
                        sf::VideoMode mode(WINDOW_WIDTH, WINDOW_HEIGHT);
                        window.create(mode, title, sf::Style::Default, settings);
                    }
                    else {
                        window.create(sf::VideoMode::getDesktopMode(), title, sf::Style::Fullscreen, settings);
                    }
                    fullscreen = !fullscreen;
                    glEnable(GL_DEPTH_TEST);
                }
                if (e.key.code == sf::Keyboard::Space) {
                    delete cube;
                    cube = new Cube();
                }
                if (e.key.code == sf::Keyboard::Escape) window.close();
                break;
            }
        }

        front = glm::vec3(rotation * glm::vec4(0, 0, -1, 1));
        right = glm::vec3(rotation * glm::vec4(1, 0, 0, 1));
        up = glm::vec3(rotation * glm::vec4(0, 1, 0, 1));
        dir = glm::vec3(rotation * glm::vec4(0, 0, -1, 1));
        dir.y = 0;
        float len = length(dir);
        if (len > 0.0f) {
            dir.x /= len;
            dir.z /= len;
        }

        glClear(GL_DEPTH_BUFFER_BIT);
        window.clear(sf::Color::Transparent);
        window.pushGLStates();
        window.draw(shape);
        window.popGLStates();

        sf::Shader::bind(&mainShader);
        glm::mat4 matrix(1.f);
        float aspect = (float)window.getSize().x / (float)window.getSize().y;
        glm::mat4 projection(glm::perspective(fov, aspect, 0.05f, 1500.0f));
        glm::mat4 view(glm::lookAt(position, position + front, up));
        cubeRotation += delta * 30;
        matrix = glm::rotate(matrix, glm::radians(cubeRotation), glm::vec3(0.f, 1.f, 0.f));
        mainShader.setUniform("matrix", sf::Glsl::Mat4(glm::value_ptr(matrix)));
        mainShader.setUniform("matrix_transpose_inverse", sf::Glsl::Mat4(glm::value_ptr(glm::transpose(glm::inverse(matrix)))));
        mainShader.setUniform("projview", sf::Glsl::Mat4(glm::value_ptr(glm::mat4(projection * view))));
        mainShader.setUniform("u_lightColor", sf::Glsl::Vec3(1.f, 1.f, 1.f));
        mainShader.setUniform("u_ambient", 0.5f);
        mainShader.setUniform("lightPos", sf::Glsl::Vec3(5.f, 5.f, 5.f));
        cube->draw();

                window.display();
        }

    return 0;
}

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Issue with full screen switching
« Reply #1 on: November 14, 2023, 11:06:38 am »
What errors are you getting?

I have little experience with OpenGL, so I just throw out some guesses of things I have vaguely heard of, maybe it can be a starting point in finding out more.
When you switch to fullscreen mode, the window is recreated and probably also the context is recreated. Make sure your resources are in the shared context, otherwise you might need to recreate them on a context switch.
I see you are pushing and popping states. Make sure you're handling any custom states on your side, as SFML just tracks the state the it needs and uses, but not the ones you set.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Issue with full screen switching
« Reply #2 on: November 14, 2023, 05:23:58 pm »
If you're only using SFML for windowing you'll probably be better off with sf::Window rather than sf::RenderWindow which manages a bunch of OpenGL stuff for SFML's graphics module. This way you won't need to push and pop any internal OpenGL state.

You probably won't be able to use SFML's Shader class though, and will have to manage your own shaders - however this is likely better in the long run as experience has taught me that mixing OpenGL with SFML's graphics module can cause problems, such as the one you're describing, anyway.

clasher114

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Issue with full screen switching
« Reply #3 on: November 15, 2023, 09:27:15 am »
What errors are you getting?
An internal OpenGL call failed in Texture.cpp(782).
Expression:
   glBindTexture(GL_TEXTURE_2D, 0)
Error description:
   GL_INVALID_OPERATION
   The specified operation is not allowed in the current state.
Its happening on window.clear()
When you switch to fullscreen mode, the window is recreated and probably also the context is recreated.
So maybe there is a way to create a context and create a window on it?