【问题标题】:SFML - Why does a sprite drawn to a window scale with the window (resize)SFML - 为什么绘制到窗口的精灵会随窗口缩放(调整大小)
【发布时间】:2021-06-23 08:12:26
【问题描述】:

这是一个 MWE

#include <SFML/Graphics.hpp>


#include <string>
#include <iostream>


int main(int argc, char *argv)
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "Title");

    std::string image_filename;
    image_filename = "image.png";

    sf::Image image;
    if(!image.loadFromFile(image_filename))
    {
        std::cout << "Error: Could not load file " << image_filename << std::endl;
    }

    sf::Texture texture;
    texture.loadFromImage(image);

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

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

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

    return 0;
}

启动应用程序时,窗口如下所示:

调整窗口大小后,窗口如下所示:

精灵的全局和局部边界在重新调整大小之前和之后是相同的。

行为(如屏幕截图所示)不是我所期望的默认行为。

  • 窗口的像素数(宽度和高度)发生了变化。
  • 图像/纹理/精灵的相同区域被绘制到窗口。
  • 已应用某种插值算法将初始窗口宽度和高度缩放到调整后的窗口宽度和高度。

也许这已经很明显了。这种行为在设计诸如游戏**之类的东西时是有意义的,但对于我打算实现的应用程序却没有意义。

** (因为调整窗口大小时背景会“缩放”,而渲染分辨率会提前固定,可能是通过配置文件)

在尝试改变行为之前,我想了解为什么会出现这种行为。

大概打开一个具有一些初始默认分辨率(宽度 x 高度)的RenderWindow 会在 GPU 上以该宽度和高度启动某种渲染实例。另一方面,调整窗口大小可能会更改“窗口系统”(窗口管理器,无论它在哪个操作系统上运行)中窗口的宽度和高度,但 不会 更新或更改相应的GPU 渲染实例的宽度和高度。

或者至少这是我对会发生什么的最佳猜测。

有没有办法改变这种行为?也许使用 SFML RenderWindow 之类的东西从根本上说是错误的使用方法?

注意:我检查了精灵的“比例”在调整大小操作期间没有改变。所以我的假设是初始窗口大小固定要渲染的像素数组的分辨率,然后在使用某种插值将像素数据绘制到显示像素缓冲区时放大/缩小以适应实际窗口的大小算法。

【问题讨论】:

    标签: c++ sfml


    【解决方案1】:

    您可以将以下事件侦听器添加到事件循环中:

    if(event.type == sf::Event::Resized)
    {
        sf::FloatRect view(0, 0, event.size.width, event.size.height);
        window.setView(sf::View(view));
    }
    

    这将在每次调整窗口大小时将渲染区域更新为窗口的尺寸,而不是缩放渲染区域以适应窗口。

    【讨论】:

    • 感谢您的建议,这似乎是正确的。但是,目前仅添加此代码会导致一些视觉伪影,例如在调整窗口大小时图像(精灵)跳来跳去。我需要添加诸如帧速率限制或垂直同步之类的东西吗?
    • 您可能遇到了同步问题。如果是这样,在创建窗口后添加window.setVerticalSyncEnabled(true) 应该可以在大多数情况下解决它。但是,如果在显卡设置中禁用了垂直同步,则此功能将不起作用,在这种情况下,您需要在创建窗口后通过window.setFramerateLimit(60)限制帧速率。
    • 不幸的是,这并没有什么不同。我先尝试了setVerticalSyncEnabled,然后又尝试了setFramerateLimit(60),结果是一样的。
    猜你喜欢
    • 2018-02-05
    • 2012-02-15
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多