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 - thomas9459

Pages: [1]
1
Feature requests / Full Support for High-DPI Displays and DPI Awareness
« on: December 25, 2014, 04:26:41 am »
While SFML currently has partial support for high-DPI displays, their are some issues that cannot be resolved without making SFML's API DPI aware. I've done some research and compiled a list of links to how this is handled on various systems / libraries:
  • OS X - Comprehensive documentation for OS X
  • Windows - Introduction tutorial for Windows
  • Windows - Comprehensive documentation for Windows
  • iOS - Section from the iOS documentation
  • Android - Description for Android devices
  • GLFW- Small section describing DPI handling in GLFW
I was unable to find any good resources for Linux, but it seems like it is a limitation in X that prevents correct DPI awareness (although supposedly Wayland has support for it).

For those who are new to DPI awareness, I would highly recommend the introduction in the OS X documentation: it's not too long and explains the basic concept very well (and has pictures!).

For the most part, it seems like all the systems use the same basic design: window management, mouse coordinates, etc. use a more abstract system for screen coordinates, with various names being used for the measuring unit ("points", "density-independent pixels", "screen coordinates", etc.), whereas lower-level drawing commands ,including most interactions with OpenGL, using the actual pixel coordinates. Then a scaling factor is exposed in the API to convert between these two systems. Since SFML encompasses of these domains, it should make a distinction between these two systems in its own API.

I took the liberty of going through the SFML API and identifying the changes that would have to be made in order to make SFML fully DPI aware. First, the following would have to be changed to use screen coordinates rather than physical pixels (this includes making these values floats):

  • sf::Event::MouseButtonEvent: x, y
  • sf::Event::MouseMoveEvent: x, y
  • sf::Event::MouseWheelEvent: x, y
  • sf::Event::SizeEvent: width, height
  • sf::Event::TouchEvent: x, y
  • sf::Mouse: getPosition(), setPosition()
  • sf::VideoMode: width, height
  • sf::Window: getPosition(), setPosition(), getSize(), setSize()

The following should continue to use physical pixels:

  • sf::RenderTarget: getSize()
  • sf::RenderTexture
  • sf::Texture
  • sf::Image

Other classes in SFML (such as views, shapes, etc.) already use coordinate systems that are not tied to pixels/screen coordinates, and are thus not affected.

In addition to the above changes, the following should be added to the API:

  • Add the function sf::Window/RenderWindow::getScaleFactor() that would retrieve the current scaling factor for the window.
  • Change the default view generation for sf::RenderWindow so that it is based on screen coordinates rather than pixels. This way, the default view is independent of the DPI of the screen it was created on.
  • A scaling field should be added to sf::Event::SizeEvent for cases like when a window is moved between displays with different scaling factors. Alternatively, we could do similar to GLFW and create a new event type that deals exclusively with scaling events (sf::Event::ScaleEvent?).

There is one more modification that needs to be made that concerns sf::RenderWindow::getSize(). Since sf::Window::getSize() should use screen coordinates, as it is part of window management, and sf::RenderTarget::getSize() should use pixels, as it works with OpenGL, which way should sf::RenderWindow::getSize() go?  Here is a short list of ideas:

  • Rename the getSize() methods so that the one inherited form sf::Window is kept distinct from the one inherited from sf::RenderTexture.
  • Add a bool argument to getSize() to signal which version we want.
  • Exclude sf::RnderWindow::getSize() from the public API so the user has to explicitly specify render_window.Window::getSize() or render_window.RenderTarget::getSize().
  • Use composition rather than inheritance between sf::RenderTarget and sf::RenderWindow.

None of these options are very clean, however. I'm also not sure of all the other changes planned for SFML 3 though, so maybe they affect this issue somehow, hopefully for the better?

Two final notes: First, dynamic changes to the scaling, such as the user moving the window between two monitors with different scaling factors, does not require full multiple monitor support, as it is possible to query the current scaling factor for a given window directly (at least on OS X and Windows 8.1), so this does not depend on complete multiple monitor support in SFML.

Second, although above I called them physical pixels, it turns out that even what OpenGL works with does not always correspond to physical pixels on the screen. For example, on my Retina display MacBook, the virtual screen is 1440x900 and the physical screen is 2560x1600, but the scaling factor is 2.0x. This is because OS X renders everything to a framebuffer of 2880x1800, then scales it in hardware back to 2560x1600 for output. This happens well after SFML, or even OpenGL, is involved, and we aren't really supposed to be concerned with it, but it is interesting nonetheless.

Anyways, is full DPI awareness support something we should target for SFML 3? And, if so, is it too soon to start work on implementing it, especially considering that it does change quite a lot of types in the API?

2
Window / Issue with Retina Display and gl_FragCoord on OS X
« on: December 21, 2014, 06:10:22 am »
So I was playing around with shaders and I encountered this bug. Basically, when a window is switched between a Retina display and a non-high DPI display, gl_FragCoord (in a fragment shader) begins reporting incorrect values. In this gist there is some example code that can be used to reproduce this issue. Here are some pictures that demonstrate this issue in action.

This first one is what the program looks like when launched on the non-DPI screen:


And this is what it looks like on the Retina display:


My guess as to what is occurring here is that when the application switches into "high-DPI" mode, the screen size doubles, but SFML attempts to hid this in its own API (see here, here, here, etc.), but OpenGL is still aware of the change and changes gl_FragCoord accordingly, so that they now differ from what SFML would report. This explains why above the range of values reported by gl_FragCoord double, as evident by the original gradient being shrunk down to a quarter of the size in the second image. Note that the problem is the opposite if the window is originally launched on the Retina display: then the image displays normally on the Retina display, but if the image is moved to the low-DPI display, then it appears "zoomed in" by a factor of 2.

I have narrowed down the bug to this commit (which makes sense, as it's the one that added support for high-DPI displays). I don't really know how to fix this issue, or if it is even possible. Any ideas?

3
Feature requests / An Implementation for Generic Blend Modes
« on: January 15, 2014, 12:13:50 am »
The topic of adding more blend modes has come up several times before, and there is even an open issue in the tracker for it (https://github.com/SFML/SFML/issues/298). Unfortunately, there does not seem to be any progress for over a year on the topic. I recently could have used such a feature myself for creating special effects and believe that this feature would benefit many others as well. I would be more than willing to implement the code if Laurent approves a design.

Here is my design proposal:
  • Change sf::BlendMode to a class with the following public members: sourceFactor, destFactor, and equation.
  • Change the current enumerators of sf::BlendMode to static members of sf::BlendMode of type sf::BlendMode (similar to sf::Transform::Identitiy).
  • Overload the == operator in sf::BlendMode to test if the modes are the same (useful for the cache when drawing).
  • Rewrite RenderTarget::applyBlendMode(BlendMode mode) to simply set the OpenGL blend functions to sourceFactor and destFactor.

Issues:
  • Because this proposal changes the type of sf::BlendMode, should it wait until SFML 3.0 to be implemented?
  • Should the OpenGL constants (GL_ZERO, GL_ONE, GL_SRC_ALPHA, etc.) be used, or should similar constants be defined in the sf namespace?
  • How, if at all, should the separate blending function for alpha be handled?

These changes should (if I understand correctly) keep the following code valid,
void Laser::draw(sf::RenderTarget &target, sf::RenderStates states) const {
    states.blendMode = sf::BlendMode::BlendAdd;
    target.draw(m_sprite, states);
}
while allowing the following as well.
void Laser::draw(sf::RenderTarget &target, sf::RenderStates states) const {
    states.blendMode = sf::BlendMode::BlendAdd;
    // The texture uses premultiplied alpha
    states.blendMode.srcFactor = GL_ONE; // or sf::BlendFactor::One
    target.draw(m_sprite, states);
}

What do you guys think? Any suggestions and/or improvements?

4
I do not know if this is a bug with SFML or not, but the sf::Window::setSize function does not resize the window if the sf::Style::Resize flag is not passed to sf::Window::Create, as shown below.

#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

int main()
{
        // Create the window
        sf::RenderWindow window(sf::VideoMode(640, 480), "SFML works!", sf::Style::Titlebar | sf::Style::Close /*| sf::Style::Resize*/);
        window.setSize(sf::Vector2u(320,240));

        // Create a simple shape
        sf::CircleShape shape(100.f);
        shape.setFillColor(sf::Color::Green);
        shape.setPosition(400, 240);

        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();
        }

        return 0;
}

If sf::Style::Resize is uncommented, the window will resize just fine. Is this expected behaviour? If it is, how would you allow the window to be resizeable, but not allow the user to resize it directly (by dragging the corner of the window)?

Pages: [1]