【问题标题】:SDL Screen Render Position Error Along Top of Window沿窗口顶部的 SDL 屏幕渲染位置错误
【发布时间】:2014-04-05 12:04:21
【问题描述】:

我正在使用 SDL 2.0 和 C++ 制作一个自上而下的等距游戏,但遇到了一个小故障。

当使用SDL_RenderCopy函数将纹理渲染到屏幕上时,纹理顶部碰到屏幕顶部的那一刻,它会被向下推一个像素,从而导致下图中的边框缺失:

Pre-edit with no annotations

Post-edit with with annotations

以下是我特定于世界本身的渲染函数,因为世界的渲染与游戏中的其他一切都不同,因为我只是复制“源”纹理而不是为游戏中的每个图块加载纹理,这将是荒谬的低效。

//-----------------------------------------------------------------------------
// Rendering

DSDataTypes::Sint32 World::Render()
{
    //TODO: Change from indexing to using an interator (pointer) for efficiency
    for(int index = 0; index < static_cast<int>(mWorldSize.mX * mWorldSize.mY); ++index)
    {
        const int kTileType = static_cast<int>(mpTilesList[index].GetType());

        //Translate the world so that when camera panning occurs the objects in the world will all be in the accurate position

我还按如下方式合并了相机平移(由于我的游戏的面向对象设计,我的相机平移逻辑跨越多个文件,因此包含一些 sn-ps 代码来解释):

(上面的代码立即在下面继续)

        mpTilesList[index].SetRenderOffset(Window::GetPanOffset());

        //position (dstRect)
        SDL_Rect position;
        position.x = static_cast<int>(mpTilesList[index].GetPositionCurrent().mX + Window::GetPanOffset().mX);
        position.y = static_cast<int>(mpTilesList[index].GetPositionCurrent().mY + Window::GetPanOffset().mY);
        position.w = static_cast<int>(mpTilesList[index].GetSize().mX);
        position.h = static_cast<int>(mpTilesList[index].GetSize().mY);

        //clip (frame)
        SDL_Rect clip;
        clip.x = static_cast<int>(mpSourceList[kTileType].GetFramePos().mX);
        clip.y = static_cast<int>(mpSourceList[kTileType].GetFramePos().mY);
        clip.w = static_cast<int>(mpSourceList[kTileType].GetFrameSize().mX);
        clip.h = static_cast<int>(mpSourceList[kTileType].GetFrameSize().mY);

我对为什么会发生这种情况感到困惑,因为无论我是否包含我的简单剔除算法(如下所示),都会出现相同的结果。

(上面的代码立即在下面继续)

        //Check to ensure tile is being drawn within the screen size. If so, rendercopy it, else simply skip over and do not render it.
        //If the tile's position.x is greather than the left border of the screen
        if(position.x > (-mpSourceList[kTileType].GetRenderSize().mX))
        {
            //If the tile's position.y is greather than the top border of the screen
            if(position.y > (-mpSourceList[kTileType].GetRenderSize().mY))
            {
                //If the tile's position.x is less than the right border of the screen
                if(position.x < Window::msWindowSize.w)
                {
                    //If the tile's position.y is less than the bottom border of the screen
                    if(position.y < Window::msWindowSize.h)
                    {
                        SDL_RenderCopy(Window::mspRenderer.get(), mpSourceList[kTileType].GetTexture(), &clip, &position);
                    }
                }
            }
        }
    }

    return 0;//TODO
}

【问题讨论】:

    标签: c++ rendering sdl render culling


    【解决方案1】:

    将位置转换为整数时可能会出现舍入错误。也许你应该四舍五入到最接近的整数,而不是只占地板(这就是你正在做的事情)。位置 (0.8, 0.8) 的图块将在像素 (0, 0) 处呈现,而它可能应该在位置 (1, 1) 处呈现。

    或者您可以确保图块的大小始终为整数,这样就不会累积错误。

    【讨论】:

    • 我向上、向下和最近四舍五入,但这些都不起作用。我对为什么舍入不起作用的想法是因为如果舍入是问题所在,那么将不仅仅是屏幕上顶行中的瓷砖被向下推一个像素。更确切地说,世界上每一个朝错误方向四舍五入的图块都会被向下推一个像素。
    • 您能否在 3x3 平铺设置中重现此内容并打印出位置和平铺尺寸?
    • 对于延迟回复,我深表歉意。解决问题后,我打算在回复之前准确发现问题所在,但无法,因此完全忘记了回复这篇文章。我现在就回答。 =)
    • 在重新阅读了您建议的答案 ysalmi 之后,您似乎发现问题与路由有关。对于不同意您的回答,我再次道歉,因为它确实几乎完全是问题所在,只留下了一些小细节,如果没有完全访问代码库,您是无法知道的。谢谢!
    • 没问题,很高兴您找到了解决方案。
    【解决方案2】:

    答案的简短版本,在底部重述:

    • 通过修复我的数据类型问题,这使我能够修复我的数学库,从而消除了像素部分舍入的问题,因为没有像这样的东西渲染时屏幕上小于 1 但大于 0 像素。

    长答案:

    我认为该问题是由将 2D 网格旋转到对角等距透视图时使用的偏移逻辑的舍入误差引起的,舍入误差仅在处理 -1 和 +1 之间的屏幕坐标时发生。

    由于我基于将正交网格更改为 y 轴(行)上的对角网格的转换,这可以解释为什么单个像素偏移仅发生在屏幕的顶部边框而不是底部边框。

    即使每一行都在没有任何安全检查的情况下进行隐式舍入,但只有从世界坐标到屏幕坐标的转换处理了正数和负数之间的舍入。

    这一切背后的原因是因为我的模板化数学库有一个问题,我的很多代码都是基于类型定义的用户类型,例如:

    typedef unsigned int Uint32;
    typedef signed int Sint32;
    

    所以我只是使用了DSMathematics::Vector2&lt;float&gt;,而不是正确实现DSMathematics::Vector2&lt;int&gt;

    这是一个问题的原因是因为屏幕上不能有“半个像素”,因此必须使用整数而不是浮点值。

    通过修复我的数据类型问题,这让我能够修复我的数学库,这消除了像素部分舍入的问题,因为没有像这样的东西渲染时屏幕上小于1但大于0的像素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      相关资源
      最近更新 更多