SDL屏幕沿窗口顶部渲染位置错误

时间:2014-03-04 05:34:19

标签: c++ rendering sdl render culling

我正在使用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

我还整合了摄像机平移,如下所示(由于我的摄像机平移逻辑跨越多个文件而包含一些代码片段,因为我的游戏采用面向对象的设计):

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

        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
}

2 个答案:

答案 0 :(得分:0)

当您将头寸转换为整数时,可能会出现舍入错误。也许你应该四舍五入到最接近的整数,而不是只是采取发言权(这是你正在做的事情)。位置(0.8,0.8)处的图块将在像素(0,0)处呈现,此时它应该在位置(1,1)处呈现。

或者你可以确保你的图块的大小总是一个整数,然后不应该累积错误。

答案 1 :(得分:0)

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

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

长答案:

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

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

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

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

typedef unsigned int Uint32;
typedef signed int Sint32;

所以我只使用DSMathematics::Vector2<float>而不是DSMathematics::Vector2<int>的正确实现。

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

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