Цифровой дифференциальный анализатор с алгоритмом Ву в OpenGL

Я пытаюсь создать алгоритм, который рисует линии, используя 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);
}

3

Решение

  1. ваш код работает только для первого октанта

    так что я надеюсь, что вы тестируете только там

  2. Вы забыли смешать цвет фона и цвет линий

    поэтому добавьте прозрачность или прочитайте фоновый пиксель напрямую и смешайте цвета самостоятельно. a,a0 Коэффициенты будут альфа для прозрачности смешения цветов. В этом случае вы не должны менять r,g,b значения, но альфа только вместо этого. Также, если вы знаете цвет фона, вы можете игнорировать считывание пикселей, но результат будет немного при пересечении чего-то уже визуализированного.

Я изменяю ваш код, чтобы он был совместим с моим кодированием в 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), что объединение есть просто r,g,b доступ

пример вывода

4

Другие решения