在软件渲染器中旋转精灵的各个像素时的“棋盘”效果

问题描述 投票:0回答:1

我正在编写一个 2D 软件渲染器,在实现旋转时我遇到了一个问题,我希望这个问题足够简单可以解决:

基本上,当以某些角度旋转时,我的精灵像素会得到一种“棋盘”效果。

为了尝试获得正确的旋转,我尝试对旋转的像素进行舍入/下限/上限操作,但这没有解决问题:

旋转问题

像素似乎设置到了错误的位置并且彼此重叠。不太清楚为什么会发生这种情况?我认为这可能是一个精度问题或其他问题,也许,真的不确定..

我的代码的相关部分:

uint width = image.width;
uint height = image.height;

uint originX = width / 2;
uint originY = height;

float radians = angleDegrees * PI / 180.0f;

float sine = sin(radians);
float cosine = cos(radians);
for (uint r = 0; r < height; r++)
{
    for (uint p = 0; p < width; p++)
    {
        int translatedR = r - originY;
        int translatedP = p - originX;

        int rotatedR = round(translatedP * sine + translatedR * cosine) + originY;
        int rotatedP = round(translatedP * cosine - translatedR * sine) + originX;

        size_t index = (x + rotatedP + (frameBufferWidth * y)) + (frameBufferWidth * rotatedR);
        size_t index2 = p + (image.width * r);

        if (!image.pixels[index2].a)
            continue;
        
        frameBuffer[index].r = image.pixels[index2].r;
        frameBuffer[index].g = image.pixels[index2].g;
        frameBuffer[index].b = image.pixels[index2].b;
    }
}

我希望我是可以理解的。任何帮助将不胜感激!

c++ 2d rendering framebuffer image-rotation
1个回答
0
投票

发生这种情况是因为您的旋转算法很幼稚。 它访问精灵上的每个像素,计算帧缓冲区上相应像素的坐标,并将像素复制到那里。这执行得很糟糕,并导致您观察到的棋盘效应,因为计算中没有任何内容可以保证您将访问帧缓冲区中的所有必要像素:计算自然不会产生所有所需的目标坐标,而它们两次产生一些目标坐标。结果是帧缓冲区上的一些像素没有被绘制,而帧缓冲区的一些像素被绘制,然后不必要地重新绘制。

所以,我担心我会让你对“我希望足够简单地解决”部分感到非常失望:解决起来一点也不简单。这将需要完全重写你的精灵旋转例程。

渲染旋转精灵的实际算法相当复杂,超出了堆栈溢出问答的解释范围。 不过我可以给你一个提示:

技巧是始终逐条光栅线访问帧缓冲区上的像素,并且在一条光栅线内,始终从左到右依次访问像素。帧缓冲区上每个像素的值必须来自沿斜线访问精灵上的像素。要沿着斜线访问像素图上的像素,您需要阅读布雷森纳姆直线算法。 (维基百科。)

这就是实际操作:https://www.youtube.com/watch?v=AApyC2a4KVw

© www.soinside.com 2019 - 2024. All rights reserved.