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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Powereleven

Pages: [1]
1
Hello, SFML Forums.

This post is for people who mix custom OpenGL code with SFML.

It's not new that frameworks (like SFML) don't expose low level functionality to be able to keep the same OpenGL context when creating a new window (https://stackoverflow.com/questions/12881049/recreate-window-without-destroying-the-context).

I'm writing this post to show how I managed to minimally adapt SFML's code to support this feature on Windows.

Before, I used to manually delete all my OpenGL resources, call window.create(), then create then back. This is cumbersome and slow, specially when a lot of gigabytes of data are already sitting in the GPU. OpenGL resources included VAO, VBO, FBO, UBO, Shaders, Textures, etc. Now, after recreating the window, I only have to update stuff that actually depend on the window size, like my FBO's GL_TEXTURE_RECTANGLE's with glTexImage2D. Everything is preserved.

We are going to change some things in sfml-window's project.

Firstly, add the directory src\SFML\Window\Win32 to the project's include path. Then, in src/SFML/Window/Window.cpp, add the header #include <SFML/Window/Win32/WglContext.hpp> just below the other headers in the beginning of the file.

Go to SFML/Window/Win32/WglContext.hpp and make this function public:
// ...
public:
void createSurface(HWND window, unsigned int bitsPerPixel);
private:
// ...
 

Then, simply change the beginning of this function:
////////////////////////////////////////////////////////////
void Window::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
{
        if (m_context)
        {
                delete m_impl;
                m_impl = priv::WindowImpl::create(mode, title, style, settings);
                auto ptr = (sf::priv::WglContext*)m_context;
                ptr->createSurface(m_impl->getSystemHandle(), mode.bitsPerPixel);
                wglMakeCurrent(ptr->m_deviceContext, ptr->m_context);
                initialize();
                return;
        }
        // ...
 

I also noticed that a point for improvement for SFML is remembering the previous state of mouse grabbed, visibility, etc.

Obviously, this is a workaround, and not very pretty. Note that this adaption skips some tests done later in the function, like validating the window's style.

I expect SFML to support this natively in the future, where each platform-specific implementation does its thing.

Cya.

2
Network / Workaround to fix connecting nonblocking tcp sockets on Windows
« on: December 20, 2020, 11:28:48 pm »
Hi,
today I decided to try nonblocking tcp socket so I could have a UI that is able to cancel the connecting operation more realiably than using a small timeout in the blocking socket in the connect function, but I found out that calling connect and checking for Done doesn't work on Windows. I found 2 threads from 2012 that mention this problem. https://en.sfml-dev.org/forums/index.php?topic=7435.0 and https://github.com/SFML/SFML/issues/194
Were they ever fixed? Anyway, I'm no expert on windows winsock, so I empirically tested and found out that sleep() a bit after calling connect was enough to work (by work I mean, trying to send bytes worked, even though connect had returned status NotReady), so I suspect that when you call connect, the internal socket is wrongly rebuilt, so it's as if you were always restarting the operation, and it never gets done, as it takes a few milliseconds to connect. Anyway... I coded a small workaround that seems to work fine. Here's some pseudocode. Instead of the more documentation compliant code:
mySocket.setBlocking(false);
while (mySocket.connect(HOST, PORT) != sf::Socket::Status::Done);
mySocket.setBlocking(true); // I only use nonblocking during the first connection phase
 
I do
mySocket.setBlocking(false);
mySocket.connect(HOST, PORT);
while (!mySocket.isConnected())
{
    if (IWantToCancelConnectAttempt)
    {
        mySocket.disconnect();
        goto wherever...
    }
}
mySocket.setBlocking(true);
...
 
where isConnected is implemented like this, which is basically a small portion of the main connect method that doesn't rebuild the socket, but rather just checks what I need
bool TcpSocket::isConnected()
{
        fd_set selector;
        FD_ZERO(&selector);
        FD_SET(getHandle(), &selector);
        timeval time{};
        return select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time);
}
 
I find this documentation confusing https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select, but apparently timeval == NULL is used for blocking operations, but using it with 0s returns immediately.
That's it. I hope that's useful for anyone having this problem. By the way, where is the most appropriate place to post these kinds of things?

3
Window / Can't declare global window when linking statically
« on: May 04, 2019, 02:48:25 pm »
I get the error "Access violation writing location" when I declare a global sf::RenderWindow, but it works when linking dynamically. What could be happening?

4
SFML projects / Tetris Clone :P
« on: July 07, 2018, 06:07:12 pm »
Hi forums :)
I decided to make a Tetris Clone, because it is considered a beginner project and I had never tried to do it. I know there are hundreds of Tetris Clones out there, so I made mine a bit different. Every piece has a square as its bounding box (rectangles would mess up the rotations) and they are read from a Pieces.txt file. So I can set pieces in this format:

0 1 0
0 1 0
0 1 0

1 1 1
0 1 0
0 1 0

1 1
1 1

In which the piece must be a square.
I know it's not optimized because I didn't worry about it, since Tetris is by itself a very light game.

Source:
https://github.com/Powereleven/Tetris-Clone

Feedback would be nice :)

5
What's the terrible mistake I'm making here?

Minimal code:
#include <SFML/Graphics.hpp>
#include <thread>

void run(sf::RenderWindow &window, sf::CircleShape &shape)
{
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();
                }

                window.clear();
                window.draw(shape);
                window.display();
        }
}

int main()
{
        sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
        sf::CircleShape shape(100.f);
        shape.setFillColor(sf::Color::Green);

        std::thread t1(run, window, shape);
        t1.join();

        return 0;
}
 

Error log:
'sf::RenderWindow::RenderWindow(const sf::RenderWindow &)': attempting to reference a deleted function
 

6
Graphics / I need help handling custom OpenGL with SFML
« on: May 24, 2018, 11:51:55 pm »
I have read https://www.sfml-dev.org/tutorials/2.5/window-opengl.php many times but I still can't get things right.
I made a program that prints a simple rotating cube, and everything was working until I decided to mix with SFML Graphics stuff. I just can't understand how to use window.pushGLStates(), window.popGLStates(); and window.setActive(bool) properly.
I read https://github.com/SFML/SFML/blob/master/examples/opengl/OpenGL.cpp#L46 but even using SFML commands that I listed above as used there I still get the error:
An internal OpenGL call failed in RenderTarget.cpp(301).
Expression:
   glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0)
Error description:
   GL_INVALID_OPERATION
   The specified operation is not allowed in the current state.

An internal OpenGL call failed in RenderTarget.cpp(302).
Expression:
   glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8)
Error description:
   GL_INVALID_OPERATION
   The specified operation is not allowed in the current state.

An internal OpenGL call failed in RenderTarget.cpp(304).
Expression:
   glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12)
Error description:
   GL_INVALID_OPERATION
   The specified operation is not allowed in the current state.


 
How do I fix this code? (Sorry for the big code, but at least now I am sure I provided a "Minimal, Complete, and Verifiable example" :P However it's easy to read because most of it are just coordinates you can ignore)
PS.: The frameworks I used besides SFML shouldn't interfere in anything.
PS2: I am using SFML 2.5.0
#include <glad/glad.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

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

#include <iostream>

int SCR_WIDTH = 800;
int SCR_HEIGHT = 600;

sf::Glsl::Mat4 glm_to_Glsl(glm::mat4 matrix) // converts from glm to glsl for convenience to use with SFML
{
        float m_array[16];
        uint8_t index = 0;
        for (uint8_t i = 0; i < 4; i++)
                for (uint8_t j = 0; j < 4; j++)
                        m_array[index++] = matrix[i][j];
        sf::Glsl::Mat4 matrix_Glsl(m_array);
        return matrix_Glsl;
}

class Resource_manager
{
private:
        sf::RenderTarget &window;
        sf::Font arial;
        sf::Text fps;
        unsigned int fps_counter = 0;
public:
        Resource_manager(sf::RenderTarget &p_window) : window(p_window)
        {
                arial.loadFromFile("arial.ttf");
                fps.setFont(arial);
                fps.setCharacterSize(24);
                fps.setFillColor(sf::Color::Red);
                fps.setString("Hello World"); // for simplicity here
        }
        void show_fps()
        {
                window.draw(fps); // program always breaks here
        }
};

struct Global_variables
{
        static float global_time;
};

float Global_variables::global_time = 0.0f;

class Parallelepiped
{
private:
        unsigned int VAO;
        sf::Shader &shader;
        sf::Texture &texture;
public:
        Parallelepiped(sf::Shader &p_shader, sf::Texture &p_texture) : shader(p_shader), texture(p_texture)
        {
                float vertices[] = {
                        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
                        0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
                        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
                        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
                        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
                        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

                        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
                        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
                        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
                        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
                        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
                        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

                        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
                        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
                        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
                        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
                        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
                        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

                        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
                        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
                        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
                        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
                        0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
                        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

                        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
                        0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
                        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
                        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
                        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
                        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

                        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
                        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
                        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
                        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
                        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
                        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
                };
                unsigned int VBO;
                glGenVertexArrays(1, &VAO);
                glGenBuffers(1, &VBO);
                glBindVertexArray(VAO);
                glBindBuffer(GL_ARRAY_BUFFER, VBO);
                glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
                glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
                glEnableVertexAttribArray(0);
                glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
                glEnableVertexAttribArray(1);

                shader.setUniform("texture1", sf::Shader::CurrentTexture);
        }
        ~Parallelepiped()
        {
                glDeleteVertexArrays(1, &VAO);
        }

        void draw(glm::mat4 &p_projection, glm::mat4 &p_view)
        {
                sf::Shader::bind(&shader);
                sf::Texture::bind(&texture);

                glm::mat4 model;
                model = glm::translate(model, glm::vec3(0.0f, 0.0f, -3.0f));
                model = glm::rotate(model, Global_variables::global_time, glm::vec3(0.5f, 1.0f, 0.0f));
                shader.setUniform("projection", glm_to_Glsl(p_projection));
                shader.setUniform("view", glm_to_Glsl(p_view));
                shader.setUniform("model", glm_to_Glsl(model));

                glBindVertexArray(VAO);
                glDrawArrays(GL_TRIANGLES, 0, 36);
        }
};

int main()
{
        sf::RenderWindow window(sf::VideoMode(SCR_WIDTH, SCR_HEIGHT), "OpenGL", sf::Style::Default, sf::ContextSettings(32));
        window.setActive(true);
        window.setVerticalSyncEnabled(true);
        window.setMouseCursorGrabbed(true);
        window.setMouseCursorVisible(false);
        window.setKeyRepeatEnabled(false);
        sf::Mouse::setPosition(sf::Vector2i(SCR_WIDTH / 2, SCR_HEIGHT / 2), window);

        Resource_manager resources(window); // load resources

        gladLoadGL();
        glEnable(GL_DEPTH_TEST);

        sf::Shader cube_shader;
        cube_shader.loadFromFile("cube.vs", "cube.fs"); // just standard shaders
        sf::Texture cube_texture;
        cube_texture.loadFromFile("background.jpg");

        Parallelepiped cube(cube_shader, cube_texture);

        sf::Clock clock;

        while (window.isOpen())
        {
                float dt = clock.restart().asSeconds();
                Global_variables::global_time += dt;
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                        {
                                window.close();
                        }
                        else if (event.type == sf::Event::Resized)
                        {
                                glViewport(0, 0, event.size.width, event.size.height);
                                SCR_WIDTH = event.size.width;
                                SCR_HEIGHT = event.size.height;
                        }

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

                glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                // Draw ...
                glm::mat4 view;
                glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);

                cube.draw(projection, view);
                //resources.show_fps(); // error :((((((( it works if I comment this line
                window.display();
        }

        // release resources...

        return 0;
}
 

7
Graphics / How do you bind multiple textures to the same shader?
« on: May 24, 2018, 01:03:44 am »
I am aware of
sf::Texture::bind(&texture_here);
but what if my shader requires more than 1 texture?

8
SFML projects / Random game
« on: February 01, 2018, 09:52:49 pm »
Messing up with angles in SFML. Inspired in Arkanoid.

https://github.com/Powereleven/Bounce-game

9
General / When to use {} () in constructors
« on: January 29, 2018, 06:18:23 am »
I have in Game.h a class Game. In private: sf::RenderWindow app;
Then in Game.cpp I use:
Game::Game() : app({1000,800},"NAME")
{
}
The syntax
Game::Game() : app(sf::VideoMode(1000,800),"NAME")
{
}
also works.
My question is: why can you omit sf::VideoMode in the first case, and if you do so, why do you HAVE to use {} for the videomode parameters? Using () In the first case results in an error.

10
General / Should you call events by reference?
« on: January 28, 2018, 07:32:39 pm »
I was testing a button function that its implementations are not the subject of this post. It basically just calls the pollEvent and does something. the RenderWindow parameter must have the & to work, but the event parameter works with both (by reference and by value). Which one is preferable and why?

void button(sf::RenderWindow &app, sf::Event &e)
{
}

or

void button(sf::RenderWindow &app, sf::Event e)
{
}

11
Graphics / Views
« on: January 27, 2018, 03:26:47 am »
Quick question: on the view topic there is this line:
view.setViewport(sf::FloatRect(0.25f, 0.25, 0.5f, 0.5f));
why didn't the writer use the sufix f in the second parameter and used in the other 3?

12
SFML projects / Flappy-Bird Clone Attempt
« on: January 24, 2018, 09:13:55 pm »
Hello forums,
I created my first project using sfml but as an inexperienced programmer some constructive criticism, guidance and tips for my future projects would be good. If you like reading random code. Feel free to check it out :)

https://github.com/Powereleven/Flappy-Bird-Clone

Pages: [1]
anything