c++ - 在 OpenGL 中使用 Wu 算法的数字微分分析仪

标签 c++ algorithm opengl antialiasing dda

我正在尝试使用 DDA(数字微分分析仪)制作一种绘制线条的算法,该算法还使用 Wu 的算法作为抗锯齿。

问题是输出看起来不太好。 特别是:

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

如何选择我想要的线条颜色?考虑到它受算法的影响?

代码如下:

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);
}

最佳答案

  1. 您的代码仅适用于第一个八分圆

    所以我希望你只在那里测试

  2. 你忘了混合背景颜色和线条颜色

    因此添加透明度或直接读取背景像素并自行混合颜色。 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); 绘制一个像素x,y,颜色为col
col=pnt(x,y); 从屏幕/图像中读取像素到 col
col 是 32 位颜色 (0x00RRGGBB),union 的存在只是为了方便 r,g,b 访问

example output

关于c++ - 在 OpenGL 中使用 Wu 算法的数字微分分析仪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30006412/

相关文章:

c++ - 使用 opengl 2 从鼠标转换光线

c++ - OpenGL以像素为单位定义顶点位置

c++ - 使用 stbi_write_png 从 OpenGL 帧缓冲区保存的 PNG 向右移动

c++ - 将二进制编码的十进制 (BCD) 解码为无符号整数

java - 较大值的错误结果

algorithm - 索引句子的最佳算法

java - 无法绘制到FrameBufferObject,然后绘制到frameBuffer,在LWJGL中

c++ - 将 const vector<pointers> 传递给方法但更改指向的值

android - Android 版 Opencv SDK 中的 opencv "C"方法

algorithm - 测试 2 个字符串 75%+ 相似度的最快算法?