AntyAliasing - nie działa poprawnie (multisampling)

0

Napisałem sobie alg. wg. przepisu (graficznego) mojego prowadzącego AntyAliasingu. Coś robi poprawnie, ale nie do końca. W zależności od gałęzi |x| >= |y| lub na odwrót albo góra albo dół linii jest nieatyaliasowany, natomiast drugi brzeg jest antyaliasowany. Ktoś mógłby podać linka do poprawnego multisamplingu lub pomóc w rozgryzieniu tej zagadki?

Kod (w paczce z resztą też jest)

        private void AntyAliasedLineDraw(Point from, Point to, int grubosc)
        {

            double offsetX = to.X - from.X;
            double offsetY = to.Y - from.Y;
            var fromX = from.X;
            var fromY = from.Y;
            var toX = to.X;
            var toY = to.Y;

            if (Math.Abs(offsetX) >= Math.Abs(offsetY))
            {
                // robimy po x
                if (from.X > to.X)
                {
                    fromX = to.X;
                    fromY = to.Y;
                    toX = from.X;
                    toY = from.Y;
                    offsetX = -offsetX;
                    offsetY = -offsetY;
                }

                var yPerPixel = offsetY/offsetX;
                double actualHeight = _Sampling*fromY;

                for (var j = _Sampling * fromX; j <= _Sampling * toX; j++) // robimy po X-ach
                {
                    var bottom = (int)Math.Floor((double)actualHeight + grubosc*_Sampling);
                    var top = (int)Math.Ceiling((double) actualHeight);

                    for (var i = top; i <= bottom; i++)
                        _Pkts[j,i] = true;

                    actualHeight += yPerPixel;
                }

                actualHeight = fromY;

                for (var j = fromX; j <= toX; j++)
                {
                    var bottom = (int)Math.Floor((double)actualHeight + grubosc);
                    var top = (int)Math.Ceiling((double)actualHeight);

                    for (var i = top; i <= bottom; i++ )
                    {
                        var ile = 0;
                        for (var k = 0; k < _Sampling; k++)   // x
                            for (var l = 0 ; l < _Sampling; l++) // y
                            {
                                if (_Pkts[_Sampling * j + k, _Sampling * i + l] == true)
                                {
                                    _Pkts[_Sampling*j + k, _Sampling*i + l] = false;
                                    ++ile;
                                }
                            }
                      
                        var stos = (double) ile/(double) (_Sampling*_Sampling);
                        stos = 1 - stos;
                        //var stos = 0;
                        var war = (int)Math.Floor(255.00*stos);
                        _Bmp.SetPixel(j, i, Color.FromArgb(war, war, war));
                    }
                        actualHeight += yPerPixel;
                }


            }
            else
            {
                // robimy po y
                if (from.Y > to.Y)
                {
                    fromX = to.X;
                    fromY = to.Y;
                    toX = from.X;
                    toY = from.Y;
                    offsetX = -offsetX;
                    offsetY = -offsetY;
                }

                var xPerPixel = offsetX / offsetY;
                double actualWidth = _Sampling * fromX;

                for (var i = _Sampling * fromY; i <= _Sampling * toY; i++) // robimy po X-ach
                {
                    var right = (int)Math.Floor((double)actualWidth + grubosc * _Sampling);
                    var left = (int)Math.Ceiling((double)actualWidth);

                    for (var j = left; j <= right; j++)
                        _Pkts[j, i] = true;

                    actualWidth += xPerPixel;
                }

                actualWidth = fromX;

                for (var i = fromY; i <= toY; i++)
                {
                    var right = (int)Math.Floor((double)actualWidth + grubosc);
                    var left = (int)Math.Ceiling((double)actualWidth);

                    for (var j = left; j <= right; j++)
                    {
                        var ile = 0;
                        for (var l = 0; l < _Sampling; l++)   // y
                            for (var k = 0; k < _Sampling; k++) // x
                            {
                                if (_Pkts[_Sampling * j + k, _Sampling * i + l] == true)
                                {
                                    _Pkts[_Sampling*j + k, _Sampling*i + l] = false;
                                    ++ile;
                                }
                            }

                        var stos = (double)ile / (double)(_Sampling * _Sampling);
                        stos = 1 - stos;
                        //var stos = 0;
                        var war = (int)Math.Floor(255.00 * stos);
                        _Bmp.SetPixel(j, i, Color.FromArgb(war, war, war));
                    }
                    actualWidth += xPerPixel;
                }

            }

        }
0

Po co multisampling przy rysowaniu linii? Nie lepiej (prościej i efektywniej) policzyć stopień wypełnienia piksela?
Coś w stylu:

Jeśli abs(dx)>abs(dy) to idź po kolejnych `x`-ach
policz `y` dla danego `x` 
policz `y1 = y + grubość/2`; `y2 = y - grubość/2`
pomaluj pełnym kolorem piksele o współrzędnych y od ceil(y1) do floor(y2)
pomaluj piksel z nieprzezroczystością `alfa1 = ceil(y1) - y1` współrzędną `ceil(y1)-1`
pomaluj piksel z nieprzezroczystością `alfa2 = y2 - floor(y2`) współrzędną `floor(y2)+1`
Jeśli abs(dx)<=abs(dy) to idź po kolejnych `y`-kach
....
0
MarekR22 napisał(a):

Po co multisampling przy rysowaniu linii? Nie lepiej (prościej i efektywniej) policzyć stopień wypełnienia piksela?

Zgodzę się z tobą, to jest coś ala algorytm Xialoin Wu's (antyaliasing), ale niestety, miałem takie zadanie (albo takie sobie zadałem, dla przećwiczenia (algorytm do implementacji z zajęć

1 użytkowników online, w tym zalogowanych: 0, gości: 1