Računarska grafika

Rasterska grafika

Iscrtavanje scene (renderovanje)

Scena - Skup geometrijskih objekata i njihovih osobina koje želimo iscrtati.

Dva osnovna pristupa iscrtavanju scene:

  • Image-order
    • for-each pixel { ... } (Iterira po pikselima slike koju želimo proizvesti.)
    • Za svaki piksel pronalazi kom objektu pripada, izračunava kako ta tačka na objektu izgleda i to smešta u sliku.
    • Uglavnom se zasnivaju na simuliranju fizike (npr. ray tracing).
  • Object-order
    • for-each object { ... } (Iterira po objektima scene koje želimo prikazati.)
    • Za svaki objekat izračunava njegov položaj na slici i ispunjava piksele koji mu pripadaju - rasterizacija + shading

Rasterizacija i shading

w:366 w:366 w:366

Rasterizacija = Određivanje piksela koji pripadaju geometrijskom objektu.

Shading = Određivanje boje tih piksela.

Elementarni geometrijski objekat, primitiv, (╱, ⚫,⬛) → grupa piksela

Rasterizacija triangulacije

Ciljevi:

  • Nema rupa između trouglova.
  • Piksel pripada najviše jednom trouglu.

Gore-levo pravilo. Piksel je u trouglu akko:

  • njegov centar je u unutrašnjosti trougla, ili
  • njegov centar je na stranici trougla koja je (tj. koje su obe u slučaju temena)
    • horizontalna i gore, ili
    • sa leve stranice trougla.

Rasterizacija duži

  • Matematička linija nema debljinu i sastoji se od beskonačno mnogo tačaka.
  • Pikseli su mali kvadrati i ima ih konačno mnogo.
  • Koje piksele izabrati da prikažu liniju?

Brezenhamov algoritam (1965)

😊 Izuzetno brz! (Jednostavan, koristi celobrojnu aritmetiku.)
🙂 Određuje piksele koji optimalno aproksimiraju zadatu duž.

😡 Dozvoljene su samo celobrojne koordinate krajeva duži.
😡 Izgleda ružno - stepeničasto (pikseli samo "crni" ili "beli").

Brezenhamov algoritam

Za tačke A=(Ax,Ay)A = (A_x, A_y), B=(Bx,By)B = (B_x, B_y), definišemo grešku tačke C=(Cx,Cy)C = (C_x, C_y)

err(C):=AB×ACerr(C) := \overrightarrow{AB} \times \overrightarrow{AC}

err(C)=(BxAx)(CyAy)(CxAx)(ByAy)err(C) = (B_x-A_x)(C_y-A_y)-(C_x-A_x)(B_y-A_y)

err(C)=0    err(C) = 0 \quad \implies \quad CC je na ABAB
err(C)>0    err(C) > 0 \quad \implies \quad CC je sa leve strane ABAB
err(C)<0    err(C) < 0 \quad \implies \quad CC je sa desne strane ABAB

err(C)|err(C)| proporcionalno udaljenosti CC od ABAB.

Dx:=BxAxDy:=ByAyD_x := B_x - A_x \qquad D_y := B_y - A_y

err(C+(1,0))err(C)=(ByAy)=Dyerr(C+(1,0)) - err(C) = -(B_y - A_y) = -D_y

err(C+(0,1))err(C)=+(BxAx)=+Dxerr(C+(0,1)) - err(C) = +(B_x - A_x) = +D_x

Korak desno: errerr -= DyD_y.
Korak gore: errerr += DxD_x.

Na slici su prikazane errerr vrednosti piksela.

Dalje smatramo da je BB gore desno od AA.

Algoritam:

  • Krećemo od C=AC = A.
  • U svakom koraku CC prelazi na onaj od tri susedna piksela koji ima najmanju apsolutnu vrednost greške.
  • Zaustavljamo se kad bude C=BC = B.

Implementacija:

  • U toku izvršavanja u promenljivoj err pamtimo err(C+(1,1))err(C+(1,1)).
    Početna vrednost za err, kada je C=AC = A:
    err=err(A+(1,1))=DxDyerr = err(A+(1,1)) = D_x - D_y
  • Povećavamo y (idemo gore ili gore-desno) ako
    err(C+(1,1))<err(C+(1,0))|err(C+(1,1))| < |err(C+(1,0))|
    err<errDx\Leftrightarrow |err| < |err - D_x|
    2err<Dx\Leftrightarrow 2 err < D_x
  • Povećavamo x (idemo desno ili gore-desno) ako
    err(C+(1,1))<err(C+(0,1))|err(C+(1,1))| < |err(C+(0,1))|
    err<err+Dy\Leftrightarrow |err| < |err + D_y|
    2err>Dy\Leftrightarrow 2 err > -D_y

💻 LineDrawing.drawLineBresenham

    void drawLineBresenham(PixelWriter pw, int ax, int ay, int bx, int by) {
        int dx = Math.abs(bx - ax),   dy = Math.abs(by - ay);
        int sx = ax < bx ? 1 : -1 ,   sy = ay < by ? 1 : -1;
        int cx = ax               ,   cy = ay;
        int err = dx - dy;		
        while (cx != bx || cy != by) {
            pw.setColor(cx, cy, Color.WHITE);
            int err2 = 2 * err;
            if (err2 > -dy) {
                cx += sx;
                err -= dy;
            }			
            if (err2 < dx) {
                cy += sy;
                err += dx;
            }
        }
        pw.setColor(cx, cy, Color.WHITE);
    }

Rasterizacija duži

Xiaolin Wu algoritam

Pikseli mogu imati bilo koju nijansu (providnost). Nijansa zavisi od toga "koliko je linija blizu centra piksela".

🙂 Brz, ali sporiji od Brezenhamovog algoritma.
😊 Perceptualno prijatniji od Brezenhama.
🙂 Dozvoljava realne koordinate krajeva duži

Na slici gore: Brezenham
Na slici dole: Xiaolin Wu

--- # Anti-aliasing ![bg vertical right:20%](Aliased.png) ![bg](Antialiased.png) ![bg](Antialiased-lanczos.png) Postupak umanjenja stepeničastih efekata. - Vrste: - **Geometrijski pristup** - Računa koliki deo piksela je zauzet objektom koji se iscrtava. Samo za jednostavne objekte. - **Fast-aproximate** - Primenjuje zamućivanje ivica na već iscrtanoj slici. - **Multi-sampling** - Vrednost svakog piksela se postavlja na prosek izračunatih uzoraka unutar tog piksela. Postoje razni metodi za odabir uzoraka. <-- Ovo se izgleda zove super-sampling a multi-sampling je nesto drugo? -> - **Temporal** - Pikseli menjaju boju u svakom frejmu kako bi se u proseku dobila željena boja <-- Ovo nije temporal anti-aliasing, videti wikipedia članak. (Ovo je temporal dithering valjda.) -> 💻 `Antialiasing` --- ![supersampling](supersampling.png)