OpenGL中基于吴算法的数字微分分析仪

rqcrx0a6  于 2022-12-12  发布在  其他
关注(0)|答案(2)|浏览(181)

我正在尝试使用DDA(数字微分分析仪)绘制线条的算法,该算法还使用吴的算法作为抗锯齿。
问题是输出看起来不太好,特别是:

  • 我选择的颜色,它会改变(我知道为什么,但我想知道是否必须这样)
  • 像素的颜色越亮越亮

如何选择线条的颜色?考虑到它会受到算法的影响?
代码如下:

void dda(int x0, int y0, int x1, int y1, int z, float red, float green, float blue) {
    float dy = y1-y0;
    float dx = x1-x0;
    float m = dy/dx;

    if (m<=1) {
        int x;
        float y;
        y = y0;
        for (x=x0; x<x1; x++) {
            pixel(x, round(y), z, frame, rfpart(red), rfpart(green), rfpart(blue));
            pixel(x, round(y)+1, z, frame, fpart(red), fpart(green), fpart(blue));
            y = y+m;
        }
    }
}

int round(float d) {
  return floor(d + 0.5);
}

float fpart(float x) {
    if (x < 0)
        return 1 - (x - floor(x));
    return x - floor(x);
}

float rfpart(float x) {
    return 1 - fpart(x);
}
iibxawm4

iibxawm41#

1.您的代码仅适用于第一个八分圆
所以我希望您只在那里进行测试
1.您忘记混合背景颜色和线条颜色
因此,直接添加透明度或读取背景像素并自行混合颜色。a,a0系数将是透明度颜色混合的alpha。在这种情况下,您不应更改r,g,b值,而只应更改alpha。此外,如果您知道背景颜色,您可以忽略像素的阅读,但结果将是与已渲染的内容交叉时的位。

我将您的代码更改为与我的C++代码兼容:

void DDA_line_antialiasing(int x0,int y0,int x1,int y1,int col) // DDA antialiasing
    {
    int   x,y,dx,dy,kx,ky,f,df;
    DWORD a,a0;
    union
        {
        DWORD dd;
        BYTE db[4];
        } c,c0;
    dx=x1-x0; kx=0; if (dx>0) kx=+1; else if (dx<0) { kx=-1; dx=-dx; }
    dy=y1-y0; ky=0; if (dy>0) ky=+1; else if (dy<0) { ky=-1; dy=-dy; }
    if (dx+dy==0)
        {
        pnt(x0,y0,col);
        pnt(x1,y1,col);
        return;
        }
    if (dx>=dy)
     for (df=(dy<<8)/dx,x=x0,y=y0,f=0;;f+=df,x+=kx)
        {
        // fixed point y step
        if (f>=256) { f-=256; y+=ky; }
        // line color + background color mixing
        c.dd=col; c0.dd=pnt(x,y); a=256-f; a0=f;
        c.db[0]=DWORD(((DWORD(c.db[0])*a)+(DWORD(c0.db[0])*a0))>>8);
        c.db[1]=DWORD(((DWORD(c.db[1])*a)+(DWORD(c0.db[1])*a0))>>8);
        c.db[2]=DWORD(((DWORD(c.db[2])*a)+(DWORD(c0.db[2])*a0))>>8);
        pnt(x,y   ,c.dd);
        // line color + background color mixing
        c.dd=col; c0.dd=pnt(x,y+ky); a=f; a0=256-f;
        c.db[0]=DWORD(((DWORD(c.db[0])*a)+(DWORD(c0.db[0])*a0))>>8);
        c.db[1]=DWORD(((DWORD(c.db[1])*a)+(DWORD(c0.db[1])*a0))>>8);
        c.db[2]=DWORD(((DWORD(c.db[2])*a)+(DWORD(c0.db[2])*a0))>>8);
        pnt(x,y+ky,c.dd);
        if (x==x1) break;
        }
    else
     for (df=(dx<<8)/dy,x=x0,y=y0,f=0;;f+=df,y+=ky)
        {
        // fixed point x step
        if (f>=256) { f-=256; x+=kx; }
        // line color + background color mixing
        c.dd=col; c0.dd=pnt(x,y); a=256-f; a0=f;
        c.db[0]=DWORD(((DWORD(c.db[0])*a)+(DWORD(c0.db[0])*a0))>>8);
        c.db[1]=DWORD(((DWORD(c.db[1])*a)+(DWORD(c0.db[1])*a0))>>8);
        c.db[2]=DWORD(((DWORD(c.db[2])*a)+(DWORD(c0.db[2])*a0))>>8);
        pnt(x,y   ,c.dd);
        // line color + background color mixing
        c.dd=col; c0.dd=pnt(x+kx,y); a=f; a0=256-f;
        c.db[0]=DWORD(((DWORD(c.db[0])*a)+(DWORD(c0.db[0])*a0))>>8);
        c.db[1]=DWORD(((DWORD(c.db[1])*a)+(DWORD(c0.db[1])*a0))>>8);
        c.db[2]=DWORD(((DWORD(c.db[2])*a)+(DWORD(c0.db[2])*a0))>>8);
        pnt(x+kx,y,c.dd);
        if (y==y1) break;
        }
    }

更改为定点(8位小数部分)f,df
round更改为floor(我的像素已经移动了一半)
添加了与背景颜色的颜色混合
pnt(x,y,col);使用颜色col绘制像素x,y
col=pnt(x,y);将像素从屏幕/图像读入col
col是32位颜色(0x 00 RRGGBB),联合只是为了方便r,g,b访问

i2loujxw

i2loujxw2#

这里是一个完整的源代码,似乎为我工作,与VCL(Embarcadero)。我把下面的修改,以解决一个问题,在长线,使位置错误的x1,y1图纸(pb发现与一个标准的Bresenham线,MoveTo()和LineTo比较):

  • 将变量类型从“int”更改为“float,”
  • 在循环中将'dy'值转换为int。

还添加了一些Lambda,并使用了32位和8位的C++类型。尚未进行速度测试(double有时比float快)。
速度对我来说还可以,因为我在位图缓冲区中工作;这是必须要做的,因为直接在组件上绘图太慢了,与内存绘图相反(下面的pC是一个指向位图画布的指针)。2然后,所有的位图都被转移到颜料盒中。3感谢贡献者,@giogix和@Spektre。

void aaLine(int x0, int y0, int x1, int y1, int col)
{
    auto pnt = [&](int x, int y, uint32_t c){
        pC->Pixels[x][y] = static_cast<TColor>(c);
    };//-----------------------------

    auto pix_color = [&](uint32_t x, uint32_t y){
        return pC->Pixels[x][y];
    };//-----------------------------

    float   x, y, dx, dy, kx, ky, f, df;//Changed 'int' into 'float' to avoid error on x1,y1 drawing
    uint32_t a,a0;
    union {
        uint32_t dd;
        BYTE db[4];
       } c,c0;

    auto mix_colors = [&](){
        c.db[0]= uint32_t(( uint32_t(c.db[0])*a + uint32_t(c0.db[0])*a0)>>8);
        c.db[1]= uint32_t(( uint32_t(c.db[1])*a + uint32_t(c0.db[1])*a0)>>8);
        c.db[2]= uint32_t(( uint32_t(c.db[2])*a + uint32_t(c0.db[2])*a0)>>8);
    };

    dx=x1-x0; kx=0; if (dx>0) kx=+1; else if (dx<0) { kx=-1; dx=-dx; }
    dy=y1-y0; ky=0; if (dy>0) ky=+1; else if (dy<0) { ky=-1; dy=-dy; }

    if (dx+dy==0) {
        pnt(x0,y0,col);
        pnt(x1,y1,col);
        return;
    }
    if (dx>=dy)
     for (df=(int(dy)<<8)/dx, x=x0, y=y0, f=0;  ; f+=df, x+=kx) //Put int(dy)
     {
        // fixed point y step
        if (f>=256) { f-=256; y+=ky; }
        // line color + background color mixing
        c.dd=col; c0.dd=pix_color(x,y); a=256-f; a0=f;
        mix_colors();
        pnt(x,y   ,c.dd);
        // line color + background color mixing
        c.dd=col; c0.dd=pix_color(x,y+ky); a=f; a0=256-f;
        mix_colors();
        pnt(x,y+ky,c.dd);
        if (x==x1) break;
     }
    else
     for (df=(int(dx)<<8)/dy, x=x0, y=y0, f=0;  ; f+=df, y+=ky) //Put int(dx)
     {
        // fixed point x step
        if (f>=256) { f-=256; x+=kx; }
        // line color + background color mixing
        c.dd=col; c0.dd=pix_color(x,y); a=256-f; a0=f;
        mix_colors();
        pnt(x,y   ,c.dd);
        // line color + background color mixing
        c.dd=col; c0.dd=pix_color(x+kx,y); a=f; a0=256-f;
        mix_colors();
        pnt(x+kx,y,c.dd);
        if (y==y1) break;
     }
}

相关问题