[ glorius @ 04.11.2007. 14:54 ] @
Simulacija 3D prostora od nule ( Softverski rendering ).

Mozemo zapoceti mali projekat softverskog renderinga pa ko zna neshto o ovome neka se ukljuci i da neke primere ili ideje:)
Lepo je znati kako 3D radi "ispod haube".

Evo objasnjenja na brzinu kako poceti sa softverskim renderingom.

Imamo tacku u prostoru sa koordinatama x, y i z.

Da bi je projektovali na ekran u koordinate sx i sy ( screen ), koristimo sledece obrasce...

1. Prvo, kao sto je poznato ljudima koji su iole podesavali kameru u DirectX i OpenGL, treba nam FOV ( Field-of-view ) koji se predstavlja kao ugao.

- alpha ( neka nam je alpha = 45 stepeni )

Moramo ga predstaviti u radijanima pomocu obrasca

- alphaRad = alpha*PI/180

2. Racunamo d, distancu do ravni projektovanja koja je:

- d = 1/tan(alphaDeg)

3. Racunamo projektovane tacke:

- sx = d*x/z;
- sy = d*y/z;

4. Jedan problemcic je sto tacka nije na sredini ekrana kao sto bi ocekivali... Resenje je da je pomerimo na sredinu ekrana

- sx = sirinaEkrana/2 + (d*x)/z;
- sy = visinaEkrana/2 + (d*y)/z;

/// I znaci

Code:

float tacka[3];   // u prostoru            ( ovde bi stajala neka Vertex ( ili Vector3 ) klasa )
int sTacka[2];  // projektovana       ( Vector2 )

int screenWidth = 640;
int screenHeight = 480;

float alphaRad = 45*3.14f/180; // ugao od 45 stepeni
float d = 1/tan(alphaRad);

// tacka sa koordinatama {10, 10, 10}
tacka[0] = 10;
tacka[1] = 10;
tacka[2] = 10;

sTacka[0] = screenWidth/2 + (int)(d*x)/z;
sTacka[1] = screenHeight/2 + (int)(d*y)/z;


Ovde ima dosta problema ( z ne sme da bude nula, float vs int ( grrrr ).... ).

Za pocetak, ovo je trivijalni primer kako simulirati 3D prostor i koji je dovoljan za 'igranje' sa z koordinatom...

Inace, ovaj primer se mogao odraditi i matricnim transformacijama kao sto se i pokazuje u referentnim knjigama o OpenGL i DirectX.
[ bkaradzic @ 04.11.2007. 16:50 ] @
Kod softverskog renderinga kada dođeš do rasterizera najbolje je koristiti fixed point brojeve. Floating point, iako precizniji, ponekad proizvodi grešku u koraku i zbog zaokruživanja rasterizer može da crta isti pixel dva puta, što je nepoželjno. Da bi izbegao probleme sa z koordinatom, potrebno je prvo da izvršiš clipping trougla. Za početak možeš da odradiš trivijalni culling koji bi preskočio rasterizaciju trougla koji izlazi iz vidljivog dela ekrana. Frustum je u world prostoru zarubljena piramida, dok je u screen prostoru kocka. Znači kada prebaciš trougao u homogene screen koordinate (screen prostor, bez projekcije), onda ćeš moći da izvršiš culling proveravajući da li je trougao između -1.0f i 1.0f po x, y, i z osi.

Ovde možeš da vidiš par mojih radova na temu softversko renderovanje (iz 1995):
http://www.youtube.com/watch?v=WXlNoEOoftw

;)

Evo ti i par referenci:
http://en.wikipedia.org/wiki/Fixed-point_arithmetic
http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
http://en.wikipedia.org/wiki/Sutherland_hodgman
http://en.wikipedia.org/wiki/Affine_transformations
[ vlaiv @ 05.11.2007. 14:32 ] @
Evo mali predlog za rasterizaciju trougla koji sam koristio pre jedno X godina kada sam se zezao sa 320x200 rezolucijom
i pisanjem mini 3d software engine-a ...

ulaz:

tri tacke trougla u 2d ekranskom prostoru

privremena promenljiva:

niz parova integera (x koordinata) 0..Vertikalna rezolucija ekrana-1 (npr scr_buf[768][2] za 1024x768)
koji se inicializuje na [+MAX][-MIN] za svaki od 768 parova (gde su MAX i MIN proizvoljne vrednosti van ekrana (moze 1024 i -1)

Za svaku ivicu trougla, nekim algoritmom za rasterizaciju linije dobijamo X,Y koordinate tacaka koje leze na toj liniji
(bresenham ili koji god vec) ... i upisujemo u scr_buf[Y][0 ili 1] = X koordinatu, u 0 ako je X manje od scr_buf[Y][0] odnosno scr_buf[Y][1] ako
je X vece od scr_buf[Y][1]

Kada se prodju sve tri linije u scr_buf sadrzi parove X1, X2 za svaki Y na ekranu izmedju kojih treba popuniti pixele ...

ukoliko je scr_buf[Y][0] manje od scr_buf[Y][1] onda se iscrtavaju pixeli

for Y = 0 to 1023
if (scr_buf[Y][0]<scr_buf[Y][1]) {
for X = scr_buf[Y][0] to scr_buf[Y][1]
DrawPixel(X,Y)
}

To je neka osnova, treba povesti racuna prilikom upisa X1 i X2 da budu takvi da je scr_buf[Y][0]<scr_buf[Y][1] ako sadrze X1 i X2 ...

Ako se zeli implementirati i Z buffer onda je potrebno zapisivati i Z koordinatu pored X1 i X2, odnosno za svaki Y upisivati parove X1,Z1 i X2,Z2 i
interpolirati Z prilikom X for petlje...

Razlicitim IF uslovima prilikom rasterizacije moguce je dobiti ubrzanja u slucaju postavljanja CLIP ravni ...
[ glorius @ 06.11.2007. 14:46 ] @
Evo jedne super knjizice za Softverski Rendering...

Sams - Tricks of the 3D Game Programming Gurus - Advanced 3D Graphics and Rasterization

[Ovu poruku je menjao tosa dana 07.11.2007. u 03:45 GMT+1]
[ Nothingman @ 07.11.2007. 16:55 ] @
Citat:
glorius: Evo jedne super knjizice za Softverski Rendering...

Sams - Tricks of the 3D Game Programming Gurus - Advanced 3D Graphics and Rasterization

[Ovu poruku je menjao tosa dana 07.11.2007. u 03:45 GMT+1]


Ta knjiga je verovatno najbolja za one koji se nikad nisu sretali sa softverskim renderingom. Veoma opsirna i detaljna, do te mere da ponekad vredja ljudsku inteligenciju ;)
Ako vec imas neka iskustva sa softverskim renderingom (ili ako si vec procitao glavne delove iz gore navedene knjige) onda je "Computer Graphics: Principles and Practice" verovatno najbolje sto mozes da procitas, jer je teoretski jako dobro potkovana knjiga. Jedina mana ove knjige je sto nije bash za ljude koji se prvi put srecu sa renderingom, jer ipak trazi neko predznanje.

Posle toga, sto se softverskog renderinga tiche, ostaje jos da pogledas neke stvari u vezi ray tracinga. Preporucujem dve knjige:

-An Introduction to Ray tracing, ISBN: 978-0-12-286160-4
-Realistic Ray Tracing, ISBN 1-56881-110-1 (hvala bkaradzicu jos jednom sto mi je preporucio ovu knjigu pre par godina :) )
[ vlaiv @ 08.11.2007. 13:29 ] @
Kuda zapravo vodi ovaj thread? Hoce li biti kakvog projekta?

OS?

Gde ce biti hostovan?

Da li smo sada u fazi sakupljanja zainteresovanih?
[ glorius @ 08.11.2007. 14:24 ] @
OS? Hmm, mozda bi bilo dobro da bude neki Rendering sistem... Potpuno softverski... Sa ciljem da ljudi razumeju kako sve to radi, gde idu svi ti podaci.... Ja sam tek pre neki dan poceo da se bavim 3D-om od nule... Dobro poznajem OpenGL i DirectX ali, to nije dovoljno dobro... Pa sam odlucio da vidim kako sve to radi...

Mislim da bi, kao zajednicki, projekat bio ogroman, sto znaci, potpuna organizacija ali, posto je ovo ipak entuzijasticki projekat, mogle da se daju neke ideje o razlicitim tehnikama u procesu rasterizacije i ostalih aspekata enginea ... i vremenom, to se sve moze sklopiti u jedan engine...

Za pocetak, to ne moraju biti optimizovani algoritmi ( da vidite samo moj algoritam za rasterizaciju poligona, hahaha ) ali, vremenom se sve moze optimizovati...

[ Ivan Dimkovic @ 08.11.2007. 14:35 ] @
Citat:

Dobro poznajem OpenGL i DirectX ali, to nije dovoljno dobro... Pa sam odlucio da vidim kako sve to radi...


Sta tacno nije dobro kod OpenGL ili DirectX APIja? To je glavno pitanje - ako ti ne odgovara realizam koji dobijas OpenGL/DirectX renderom to je zbog toga sto su oba tzv. rasterski sistemi sencenja koji nisu namenjeni realizmu vec performansma.

Ako te zanima realizam, moraces da se upoznas sa Ray Tracing algoritmom i dodatnim stvarima koje su neophodne za postizanje realisticnosti (globalna iluminacija - photon mapping, radiosity i sl...)

Vodi racuna da su rasterski algoritmi fundamentalno drugaciji od Ray Tracing algoritama - i zahtevaju potpuno drugaciji pristup.
[ glorius @ 08.11.2007. 14:40 ] @
Pogresno sa rekao ono sto sam mislio... Mislio sam da nedovoljno dobro poznajem DirectX i OpenGL... Znam ja da koristim funkcije, renderujem, .... Ali, zelim da saznam sta je "ispod haube"... Sorry za nepreciznost...

I Raytracing me zanima, naravno, danas se moze koristiti za realisticnost ali u smislu generisanja staticne slike sto je, opet, zanimljivo...
[ Nothingman @ 08.11.2007. 16:39 ] @
Citat:
glorius: OS? Hmm, mozda bi bilo dobro da bude neki Rendering sistem... Potpuno softverski... Sa ciljem da ljudi razumeju kako sve to radi, gde idu svi ti podaci.... Ja sam tek pre neki dan poceo da se bavim 3D-om od nule... Dobro poznajem OpenGL i DirectX ali, to nije dovoljno dobro... Pa sam odlucio da vidim kako sve to radi...

Mislim da bi, kao zajednicki, projekat bio ogroman, sto znaci, potpuna organizacija ali, posto je ovo ipak entuzijasticki projekat, mogle da se daju neke ideje o razlicitim tehnikama u procesu rasterizacije i ostalih aspekata enginea ... i vremenom, to se sve moze sklopiti u jedan engine...

Za pocetak, to ne moraju biti optimizovani algoritmi ( da vidite samo moj algoritam za rasterizaciju poligona, hahaha ) ali, vremenom se sve moze optimizovati...


Velike projekte je najbolje odmah precrtati, jer je to najcesca greska koja se u startu pravi. Mislim da je najbolje da krenes prvo da citas gore pomenute tekstove i knjige, i da polako pocnes da gradis svoj engine. Kako ubacujes neke nove feature, tako postujes ovde code sa objasnjenjem na cemu si radio i sta ti je zadavalo probleme. Ostali bi mogli da ti daju savete kako da nesto poboljsas ili drugacije uradish. Ranije je bila jedna tema "Ajde da pravimo igru" (ili nesto slicno) gde je jedan covek upravo radio na ovaj nacin, i bila je prilicno produktivna tema. Zato mislim da je to lep nacin da ljudi nesto nauche.
Sto se tiche OS-a, ja bih na tvom mestu koristio SDL za osnovne funkcije (poput setovanja rezolucije, upis pixela...). Na taj nacin bi dobio prilicno portabilan softverski engine, tj. ne bi morao mnogo da razmisljas o OS-u. Takodje (to si i sam zakljucio), nemoj mnogo se opterecujes brzinom engine-a, mislim da je bolje da se skoncentrises na "korektne" algoritme, nego na razne "varke". Ionako je cilj svega ovoga da se nesto nauchi ;)
[ glorius @ 08.11.2007. 18:53 ] @
Da. Izabrao sam SDL zato sto je laksi od DirectDraw-a u pogledu upisivanja pixela na ekran, lockovanja i uopste, nepotrebnih uslozavanja i dovodjenja do "full-of-bugs" koda...

Inace, pre 3 dana sam poceo da citam ovu knjigu i, sa podosta rada, vec sam stigao da nacrtam shade-ovan poligon u 3D okruzenju sa manipulacijama world, view matrice, podesavanjem FOV-a, wireframe i constant rezimom shadinga... Tj, najzad je osenceni trougao na monitoru :)

Sledece je interpolacija boja na poligonu ( vertex colors ) i dodavanje svetala... ( Pisao sam razne shadere tako da ce ovaj deo biti lak kada, naravno, napravim algoritam za interpolaciju :) )

Naravno, optimizacija, backface - removing i ostale 'zanimljive' stvarcice cu kasnije ubaciti...

Postavicu link ka source-u kada budem odradio Flat shading :)

Ah, da.. cilj postavljanja topica je razmena znanja i iskustava i, naravno, ako su ljudi raspolozeni, pomaganja pri resavanju problema ( kojih ce, verovatno, biti )...

Hvala na podrsci....
[ vlaiv @ 08.11.2007. 19:54 ] @
Citat:
glorius: OS? Hmm, mozda bi bilo dobro da bude neki Rendering sistem...


Ovaj, da OS as in Open Source, ne Operating System ako ti je to palo na pamet ...

Pa ako hoces da pokrenes neki projekat, onda se baci na odredjivanje smernica

- velicina projekta
- sta projekat Aims to achieve
- kako se u projektu ucestvuje
- kako ce ljudi da razmenjuju ideje, kod i tako to ...

Ili zelis licno da pravis projekat za svoje potrebe ucenja, onda ovaj thread moze biti mesto za razmenu ideja i
da se pohvalis dokle si stigao ...

na to sam mislio ...
[ tosa @ 09.11.2007. 02:54 ] @
Ja bih savetovao svakome zainteresovanom da sedne i sam napiše softverski rasterajzer.
Zajednički projekat i nema preteranog smisla jer je obim posla prilično mali.
[ glorius @ 09.11.2007. 03:25 ] @
Toso, uz sve postovanje, izbrisi ovaj svoj thread...

Ljudi su zainteresovani..

Neki ljudi znaju, neki zele da saznaju..

[ tosa @ 09.11.2007. 03:40 ] @
Ne vidim zbog čega bi te pogađao moj komentar u toj meri da tražiš brisanje (koje se neće desiti)?
Tutorijala za sofverski rasterajzing ima na hiljade, dovoljno je par sekundi u bilo kom pretraživaču
da i sam to vidiš. U vreme kada sam ja to radio internet u Srbiji nije ni postojao a nabaviti knjigu
koja o tome priča je bio prilično težak posao, neretko nemoguć. Sve me to nije sprečilo da napišem
dosta rasterajzera od kojih je svaki sledeći bio bolji.

Smatram da je pisanje ovako nečega prilično osnovna stvar za svakoga ko želi da se bavi 3D grafikom.
Tu su sadržani svi elementi koji su neophodni za rad tako da deljenje tog posla po meni nema preteranog
smisla jer preskakanjem nekih delova ostaješ uskraćen za elementarna znanja.
[ bkaradzic @ 09.11.2007. 07:12 ] @
Udruživanje na ovako elementarnom nivou je kao kada bi se četiri sedmogodišnjaka udružila da zajednički završe prva četri razreda od jednom. Do kraja jedan sedmogodišnjak bi završio prvi razred, a ostala tri bi bili zbunjeni sa gradivom viših razreda jer su preskočili niže razrede. ;) Tako i kod rasterizera delovi posla teško mogu da se razdvoje, a i da mogu onda je i nepoželjno. Da ne spominjem koliko ima neuspešnog udruživanja po forumima (obrati pažnju na teme sa naslovima "okupljam tim", "počinjemo", itd). Ako hoćeš da učiš u forumu, najbolje je da kao što je Nothingman predložio, u ovoj temi postuješ korak po korak kako napreduješ pa ćemo ti mi skrenuti pažnju ako radiš nešto pogrešno. Na kraju kada napraviš taj rasterizer ova tema bi bila veoma kvalitetan izvor informacija na Srpskom jeziku nekome ko bi u budućnosti radio istu stvar kao i ti. I takođe dobro je učiti na greškama. Čak i bez čitanja knjiga, sam provali kako bi ti uradio rasterizer. Pa kada ga uradiš pročitaj knjigu pa uporedi. Npr. moj prvi texture mapping je bio bukvalno brute force bresenham rasterizer linije koji je interpolirao koordinate u x, y prostoru i u u, v, ali u oba prostra se radilo o bresenham linijama, a ne scan linija u x, y prostoru (ukratko masivno precrtavanja piksela). Znači nemoj da se trudiš da napraviš perfektan rasterizer odmah, nego se trudi da ga što pre završiš, da bi mogao da pređeš na verziju 2.0 koja će biti 10x bolja od verzije 1.0. ;)
[ vlaiv @ 09.11.2007. 12:02 ] @
To sto drugi nisu izgurali projekat do kraja je posledica lose organizacije ...

Slazem se da na ovako malom projektu vise vremena odlazi na samo uskladjivanje nego na rad, ali
mislim da moze biti interesantno ...

@glorius

Ja sam za, koliko mi vreme bude dozvoljavalo ...
Obzirom da si ti pokretac ideje, ti odluci ...

Mogu se postaviti i drugi ciljevi projekta (portabilnost koda, istrazivanje novih metoda rasterizacije, sencenja,
svega i svacega, moze tu svasta interesantno da se desi i ne mora, zavisi od ucesnika)
[ glorius @ 09.11.2007. 16:07 ] @
Ne razumem bas potpuno koncept fixed point brojeva...
Znam da se jedan deo koristi za 'celi' deo broja a drugi za brojeve iza zareza...

Kako se to koristi u praksi?
[ glorius @ 09.11.2007. 17:04 ] @
Evo necega i da se vidi:

Kod za transformisanje iz local u screen:

Code:


// ovo racunam pre poziva funkcije Project
mat4x4 trans = m_matCurrWorldTransform*m_pCamera->GetViewMatrix();

float angle = m_pCamera->m_fFOV*3.14f/180;
m_fD = 0.5*(m_nScreenWidth - 1)*tan(angle/2);


void DEngine::Project(DPoly * pPoly)
{

    for(int i=0;i<3;i++)
    {
        float z = pPoly->m_Vertices[i].GetLocalPos().z;
                         
                          // ovo bi culling mehanizam odbacio PRE ovog koda ali za sada je ovako
        if(z < 1)
              z = 1;

        vec2 & projected = pPoly->m_Vertices[i].GetScreenPos();

        projected.x = m_fD*pPoly->m_Vertices[i].GetTransformedPos().x/z;
        projected.y = m_fD*pPoly->m_Vertices[i].GetTransformedPos().y/z;

        projected.x = projected.x + (0.5*m_nScreenWidth - 0.5);
        projected.y = -projected.y + (0.5*m_nScreenHeight - 0.5);
    }
}



kod "rasterajzera"

Code:


#include "DRasterizer.h"
#include "DEngine.h"

DRasterizer::DRasterizer(void)
{
}

DRasterizer::~DRasterizer(void)
{
}

/*
Funkcija koja crta jednobojni trougao u wire mode. Boja je odredjena bojom poligona
*/

void DRasterizer::DrawWireTriangle(DSurface * pSurface, DPoly * pPoly)
{
    vec2 v0 = pPoly->m_Vertices[0].GetScreenPos();
    vec2 v1 = pPoly->m_Vertices[1].GetScreenPos();
    vec2 v2 = pPoly->m_Vertices[2].GetScreenPos();

    DrawLine(pSurface, v0.x, v0.y, v1.x, v1.y, pPoly->GetColor().x*255, 
        pPoly->GetColor().y*255, pPoly->GetColor().z*255);

    DrawLine(pSurface, v1.x, v1.y, v2.x, v2.y, pPoly->GetColor().x*255, 
        pPoly->GetColor().y*255, pPoly->GetColor().z*255);

    DrawLine(pSurface, v0.x, v0.y, v2.x, v2.y, pPoly->GetColor().x*255, 
        pPoly->GetColor().y*255, pPoly->GetColor().z*255);
}

/* Funkcija za crtanje linije */
void DRasterizer::DrawLine(DSurface * pSurface, int x0, int y0, int x1, int y1, Uint8 R, Uint8 G, UINT8 B)
{
    int dx = x1 - x0;
    int dy = y1 - y0;

    int stepx, stepy;

    if(dy < 0)
    {
        dy = -dy;
        stepy = -1;
    }
    else
        stepy = 1;

    if(dx < 0)
    {
        dx = -dx;
        stepx = -1;
    }
    else
        stepx = 1;

    dy <<= 1;
    dx <<= 1;

    pSurface->PutPixel(x0, y0, R, G, B);

    if(dx > dy)
    {
        int fraction = dy - ( dx >> 1 );
        while(x0 != x1)
        {
            if(fraction >= 0)
            {
                y0 += stepy;
                fraction -= dx;
            }
            x0 += stepx;
            fraction += dy;

            pSurface->PutPixel(x0, y0, R, G, B);
        }
    }
    else
    {
        int fraction = dx - ( dy >> 1 );
        while(y0 != y1)
        {
            if(fraction >= 0)
            {
                x0 += stepx;
                fraction -= dy;
            }
            y0 += stepy;
            fraction += dx;

            pSurface->PutPixel(x0, y0, R, G, B);
        }
    }

}

/* Funkcija koja crta jednobojni trougao*/

void DRasterizer::DrawTriangle(DSurface * pSurface, DPoly * pPoly)
{
    float minY, maxY;
    int   minIndex, midIndex, maxIndex;
    int   type = -1;

    vec2 vers[3];
    vers[0] = pPoly->m_Vertices[0].GetScreenPos();
    vers[1] = pPoly->m_Vertices[1].GetScreenPos();
    vers[2] = pPoly->m_Vertices[2].GetScreenPos();

    minY = vers[0].y;
    maxY = vers[0].y;

    minIndex = maxIndex = 0;

    for(int i=1;i<3;i++)
    {
        if(vers[i].y < minY)
        {
            minY = vers[i].y;
            minIndex = i;
        }

        if(vers[i].y > maxY)
        {
            maxY = vers[i].y;
            maxIndex = i;
        }
    }

    // klasifikujemo
    for(int i=0;i<3;i++)
    {
        if(i == minIndex)
            continue;

        if( (int)minY == (int)vers[i].y )
        {
            type = TRI_TOP_FLAT;
            break;
        }
    }

    for(int i=0;i<3;i++)
    {
        if(i == maxIndex)
            continue;

        if( (int)maxY == (int)vers[i].y )
        {
            type = TRI_BOTTOM_FLAT;
            break;
        }
    }

    if(type == -1)
        type = TRI_COMPLEX;

    /*    
    if(type == TRI_TOP_FLAT)
        cout << "Top flat" << endl;

    if(type == TRI_BOTTOM_FLAT)
        cout << "Bottom flat" << endl;

    if(type == TRI_COMPLEX)
        cout << "Complex" << endl;
        */
        

    if(type == TRI_BOTTOM_FLAT)
    {
        DrawPartOfTriangle(pSurface, TRUE, pPoly, minY, maxY, minIndex);
    }

    if(type == TRI_TOP_FLAT)
    {
        DrawPartOfTriangle(pSurface, FALSE, pPoly, minY, maxY, maxIndex);
    }

    if(type == TRI_COMPLEX)
    {
        int midIndex = 0;

        for(int i=0;i<3;i++)
        {
            if( i == maxIndex || i == minIndex )
                continue;

            midIndex = i;
        }

        DrawPartOfTriangle(pSurface, TRUE, pPoly, minY, vers[midIndex].y, minIndex);
        DrawPartOfTriangle(pSurface, FALSE, pPoly, vers[midIndex].y, maxY, maxIndex);
    }
}

// crta gornji ili donji deo trougla...
// sharpAngleIndex - index verteksa koji je predstavlja "vrh" trougla
void DRasterizer::DrawPartOfTriangle(DSurface * pSurface, bool upper, DPoly * pPoly, float minY, float maxY, int sharpAngleIndex)
{
    vec2 vers[3];

    // transformisani vertexi local->world->view->projection->screen
    vers[0] = pPoly->m_Vertices[0].GetScreenPos();
    vers[1] = pPoly->m_Vertices[1].GetScreenPos();
    vers[2] = pPoly->m_Vertices[2].GetScreenPos();

    if(upper) // draw upper triangle
    {
        int index = 0;
        vec2 bottomPoints[2];

        // izdvajamo donje dve tacke
        for(int i=0;i<3;i++)
        {
            if(i == sharpAngleIndex)
                continue;

            bottomPoints[index] = pPoly->m_Vertices[i].GetScreenPos();

            index++;
        }

        for(float i=minY;i<maxY;i++)
        {
            // k - 
            float k1 = (vers[sharpAngleIndex].x - bottomPoints[0].x)/(vers[sharpAngleIndex].y - bottomPoints[0].y);
            float k2 = (vers[sharpAngleIndex].x - bottomPoints[1].x)/(vers[sharpAngleIndex].y - bottomPoints[1].y);

            int x1 = (int)((i - minY)*k1 + vers[sharpAngleIndex].x + 0.5f);
            int x2 = (int)((i - minY)*k2 + vers[sharpAngleIndex].x + 0.5f);

            DRasterizer::DrawHorLine(pSurface, x1, x2, i, pPoly->GetColor().x*255, 
                pPoly->GetColor().y*255, pPoly->GetColor().z*255);
        }
    }
    else
    {   // draw bottom triangle
        vec2 topPoints[2];
        int index = 0;

        // izdvajamo donje dve tacke
        for(int i=0;i<3;i++)
        {
            if(i == sharpAngleIndex)
                continue;

            topPoints[index] = pPoly->m_Vertices[i].GetScreenPos();

            index++;
        }

        for(float i=minY;i<maxY;i++)
        {
            float k1 = (vers[sharpAngleIndex].x - topPoints[0].x)/(vers[sharpAngleIndex].y - topPoints[0].y);
            float k2 = (vers[sharpAngleIndex].x - topPoints[1].x)/(vers[sharpAngleIndex].y - topPoints[1].y);

            int x1 = (int)((i - maxY)*k1 + vers[sharpAngleIndex].x + 0.5f);
            int x2 = (int)((i - maxY)*k2 + vers[sharpAngleIndex].x + 0.5f);

            DRasterizer::DrawHorLine(pSurface, x1, x2, i, pPoly->GetColor().x*255, 
                pPoly->GetColor().y*255, pPoly->GetColor().z*255);
        }
    }
}

void DRasterizer::DrawHorLine(DSurface * pSurface, int x1, int x2, int y, Uint8 R, Uint8 G, Uint8 B)
{
    int screenWidth = ENGINE->GetSWidth();
    if( (x1 < 0 && x2 < 0) || (x1 > screenWidth && x2 > screenWidth) ) return;

    if( x2 < x1 )
    {
        int temp = x1;
        x1 = x2;
        x2 = temp;
    }

    for(int i=x1;i<x2;i++)
    {
        if(i <= 0 || i >= 640)
            continue;
    
        pSurface->PutPixel(i, y, R, G, B);
    }
}

[ glorius @ 09.11.2007. 19:36 ] @
Sto se tice zajednickog rada, svako moze da radi nezavisno neki deo, da napise po neku funkciju ili klasu, sa koriscenjem template-a ili tako neshto...

Bilo bi dobro, npr, da se napravi sajt gde sve to moze da se smesti... I tu da stavimo i linkove ka nekim tutorialima...

Imam neki svoj sajt koji sam radio kao vezbanje HTML, PHP i mySQL... koji je, nazalost, ogranicen na oko 100 mb ( koliko se secam )...

Ili, jednostavno, svako moze da okaci svoj neki deo rada na svoj sajt ili na neki uploader...

I ja mislim da je ovo deo nauke koji zahteva da se potpuno prouci... A ne da neko nauci samo Lighting a da nema pojma oko rasterizacije i sta ti ja znam ( za to su smisljeni OpenGL i DirectX :) )

Kuda bi sve ovo moglo da ide...

NPR... neki 3D modeler sistem bi bio cool... ( mislim na renderovanje krajnje slike, a sto se tice pogleda u viewportovima, OpenGL... npr. )

Mozda preterujem sa nekim vizijama ali...

Eto, neka cilj bude neki modeling sistem... Koji se na kraju moze i "baciti u promet"...


[ bkaradzic @ 10.11.2007. 07:23 ] @
Fixed point je zapravo veoma jednostavan. Pomnožiš float point broj sa vrednošću koja u fixed point predstavlja 1 i zaokružiš rezultat. U praksi to izgleda ovako:
Code:

typedef int fix16;

fix16 float2fix(float x)
{
    return int(x * 65536.0f);
}

float fix2float(fix16 x)
{
    return float(x) / 65536.0f;
}

fix16 int2fix(int x)
{
    return fix16(x) << 16;
}

int fix2int(fix16 x)
{
    return int(x) >> 16;
}

Obrati pažnju da što više bitova ostavljaš za ceo deo, to je preciznost manja, ili što više bitova ostavljaš za ostatak to je manji opseg celog dela broja. Pošto fixed point koristiš u maksimalnom opsegu koji je kao i rezolucija ekrana ceo deo broja ne mora da bude u širokog opsega.
[ glorius @ 10.11.2007. 12:26 ] @
Hcala na objasnjenju :)
[ glorius @ 14.11.2007. 18:22 ] @
Ubacio sam Goraud lighting i sve radi super...

Jedini problemcic...

U nekim trenucima mi je potrebno da dobijem normalu trougla u WORLDkoordinatama...

Ali, cini mi se da se normala ( koja je 'za sada' u LOCAL koordinatama ) ne moze transformisati pomocu WORLD matrice???

Sve radi kada uzmem vertexe koje transformisem WORLD matricom i onda nadjem vektorski proizvod... Normala je ok transformisana.

Ali, kada normalu, koju sam na pocetku prekalkulisao ( znaci u LOCAL koordinatama ) transformisem world matricom, dobijam nezeljene rezultate...

Da li je normala kao vektor drugacije prirode od pozicija vertexa? Postoji li nacin da prekalkulisane normale ( u LOCAL sistemu ) transformisem 'nekom' matricom jer je to znatno brze od Vektorskog proizvoda, etc... ?
[ tosa @ 14.11.2007. 18:46 ] @
Možeš uvek da transformišeš svetlo u lokalni prostor objekta, time menjaš
transformacije svih normala sa samo jednom transformacijom svetla - po objektu.
[ glorius @ 14.11.2007. 19:31 ] @
Aham! Da da! Hvala!
To, verovatno, pali i za Backface removing gde mi opet trebaju normale ( u WORLD ) i pozicija kamera koju cu, znaci, inverzno da transformisem world koordinatama...