Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support sRGB color space in RenderTexture #1757

Merged
merged 2 commits into from May 11, 2021

Conversation

Sakarah
Copy link
Contributor

@Sakarah Sakarah commented Mar 10, 2021

  • Has this change been discussed on the forum or in an issue before?
  • Does the code follow the SFML Code Style Guide?
  • Have you provided some example/test code for your changes?
  • Does the fix fully solve the issue

Description

This PR tries to fix #1092.

When the sf::ContextSettings asks for an sRGB capable buffer, set the rendered image to sRGB mode and convert pixels when drawing.

This is the choice of simplicity compared to actually support textures with more than 8 bit color depth: see my post in forum (https://en.sfml-dev.org/forums/index.php?topic=20358.msg175496#msg175496).

It differs from #1093 because now we try to both convert to sRGB space when writing to the texture and when decoding from the texture. This repairs the rendering on multisampled textures, and on non-FBO implementations.
It also repairs rendering for sRGB RenderTexture used along a non-sRGB window (or no window at all).

Tasks

  • Tested on Linux
  • Tested on Windows
  • Tested on macOS
  • Tested on iOS
  • Tested on Android

How to test this PR?

To test the PR, you should run the following code and check that it matches the reference output for all parameter combination.
You will need to following image: Gradient.png

GitHub's image compression makes it slightly hard to see, but it is normal if configurations lS -> sT -> lW and sS -> lT -> sW show color banding, the other configurations must not.
Enabling or disabling antialiasing should not change the output at all.

The code is adapted from the issue by @Fewes in the forum thread https://en.sfml-dev.org/forums/index.php?topic=20358.msg146448#msg146448.

#include <SFML/Graphics.hpp>

void updateWindowTitle(sf::Window& window, bool bypass_texture, bool sRgbSprite, bool sRgbTexture, bool sRgbWindow, bool antialiasing)
{
    sf::String title;
    title += sRgbSprite ? "sS" : "lS";
    title += " -> ";
    if (!bypass_texture)
    {
        title += sRgbTexture ? "sT" : "lT";
        if (antialiasing)
            title += " (MSAA x2)";
        title += " -> ";
    }
    title += sRgbWindow ? "sW" : "lW";
    window.setTitle(title);
}

int main()
{
    bool bypass_texture = false;

    sf::RenderWindow window;
    sf::VideoMode videoMode;
    videoMode.width = 800;
    videoMode.height = 600;
    sf::ContextSettings windowContextSettings;
    windowContextSettings.sRgbCapable = true;

    window.create(videoMode, "sRGB testing", sf::Style::Default, windowContextSettings);

    sf::Texture spriteTexture;
    spriteTexture.setSrgb(true);
    spriteTexture.setSmooth(true);
    spriteTexture.loadFromFile("Gradient.png");

    sf::Sprite sprite;
    sprite.setTexture(spriteTexture);

    sf::RenderTexture renderTexture;
    renderTexture.setSmooth(true);
    sf::ContextSettings textureContextSettings;
    textureContextSettings.sRgbCapable = true;
    renderTexture.create(videoMode.width, videoMode.height, textureContextSettings);

    sf::Sprite renderTextureDrawable;
    renderTextureDrawable.setTexture(renderTexture.getTexture());

    updateWindowTitle(window, bypass_texture, spriteTexture.isSrgb(), textureContextSettings.sRgbCapable, windowContextSettings.sRgbCapable, textureContextSettings.antialiasingLevel);

    while (window.isOpen())
    {
        // Poll events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Window closed
            if (event.type == sf::Event::Closed || (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::Escape))
            {
                window.close();
            }
            else if (event.type == sf::Event::KeyPressed)
            {
                if (event.key.code == sf::Keyboard::Space)
                {
                    bypass_texture = !bypass_texture;
                }
                else if (event.key.code == sf::Keyboard::A)
                {
                    textureContextSettings.antialiasingLevel = textureContextSettings.antialiasingLevel ? 0 : 2;
                    renderTexture.create(videoMode.width, videoMode.height, textureContextSettings);
                }
                else if (event.key.code == sf::Keyboard::T)
                {
                    textureContextSettings.sRgbCapable = !textureContextSettings.sRgbCapable;
                    renderTexture.create(videoMode.width, videoMode.height, textureContextSettings);
                }
                else if (event.key.code == sf::Keyboard::S)
                {
                    spriteTexture.setSrgb(!spriteTexture.isSrgb());
                    spriteTexture.loadFromFile("Gradient.png");
                }
                else if (event.key.code == sf::Keyboard::W)
                {
                    windowContextSettings.sRgbCapable = !windowContextSettings.sRgbCapable;
                    window.create(videoMode, "sRGB testing", sf::Style::Default, windowContextSettings);
                }
                updateWindowTitle(window, bypass_texture, spriteTexture.isSrgb(), textureContextSettings.sRgbCapable, windowContextSettings.sRgbCapable, textureContextSettings.antialiasingLevel);
            }
        }

        // Clear render texture
        renderTexture.clear(sf::Color(0, 0, 0, 255));
        // Draw gradient sprite
        renderTexture.draw(sprite);
        // Finished drawing to render texture
        renderTexture.display();

        // Clear window
        window.clear(sf::Color(0, 0, 0, 255));
        if (bypass_texture)
        {
            window.draw(sprite);
        }
        else
        {
            // Draw render texture drawable
            window.draw(renderTextureDrawable);
        }

        // Finished drawing to the window
        window.display();
    }

    return 0;
}

@Sakarah Sakarah marked this pull request as ready for review April 14, 2021 11:12
@Sakarah Sakarah changed the title WIP: Support sRGB color space in RenderTexture Support sRGB color space in RenderTexture Apr 14, 2021
@Sakarah
Copy link
Contributor Author

Sakarah commented Apr 16, 2021

Independently on how we plan to solve the issue, I updated the code to test the PR in a more reproducible way.

When the sf::ContextSettings asks for an sRGB capable buffer, set the
rendered image to sRGB mode and convert pixels when drawing.

This is the choice of simplicity compared to actually support textures
with more color depth.
This fixes wrong rendering for RenderTexture that need sRGB encoding along a
non-sRGB window.
We cannot simply always enable GL_FRAMEBUFFER_SRGB because some drivers
enable sRGB encoding on non-sRGB window surfaces.
Also add a isSrgb() method to tell if a RenderTarget is encoding into
sRGB color space.
@Sakarah
Copy link
Contributor Author

Sakarah commented May 5, 2021

@binary1248 Any remarks on the current state of this PR ?

@binary1248
Copy link
Member

Looks good to me now. Test works on my system.

@eXpl0it3r eXpl0it3r added this to Discussion in SFML 2.6.0 via automation May 11, 2021
@eXpl0it3r eXpl0it3r added this to the 2.6 milestone May 11, 2021
@eXpl0it3r eXpl0it3r moved this from Discussion to Ready in SFML 2.6.0 May 11, 2021
@eXpl0it3r eXpl0it3r merged commit 1f21e54 into SFML:master May 11, 2021
SFML 2.6.0 automation moved this from Ready to Done May 11, 2021
ChrisThrasher added a commit to SFML/CSFML that referenced this pull request Jul 4, 2023
ChrisThrasher added a commit to SFML/CSFML that referenced this pull request Jul 6, 2023
ChrisThrasher added a commit to SFML/CSFML that referenced this pull request Jul 6, 2023
ChrisThrasher added a commit to SFML/CSFML that referenced this pull request Jul 6, 2023
ChrisThrasher added a commit to SFML/CSFML that referenced this pull request Jul 6, 2023
ChrisThrasher added a commit to SFML/CSFML that referenced this pull request Jul 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
SFML 2.6.0
  
Done
Development

Successfully merging this pull request may close these issues.

Drawing to RenderTexture with sRGB conversion enabled results in banded colors
3 participants