PDA

Prikaži potpunu verziju : Ujednačen framerate u C++-u, WTF?!


Geomaster
13.12.2008, 13:53
Pravim igru u kojoj trenutno pokušavam da napravim ujednačen framerate (tj. da kada je FPS manji od normalnog za igru, da igra secka a ne da radi sporije). Radim u C++-u i pokušao sam neke stvari koje sam ja po mojoj logici zaključio ali i dalje isto :()
Moja ideja je bila da podelim normalni FPS sa trenutnim FPS-om i onda na toliki interval pozivam funkcije za sledeći frejm i za renderovanje ali on ne reaguje :confused: tj. i dalje sporije radi :confused:

Zna li neko kako ovo da uradim (ne znam šta da tražim na Google-u jer uvek prikazuje neke gaming rezultate :D)

Stevvan
13.12.2008, 17:39
treba ti f-ja koja ti govori trenutno vreme. Onda radis sledece:


dt = GetTime() - perv_time();
perv_time = GetTime();


Posle svako pomeranje objekata vrsis tako sto mnozis dt sa pomerajem i nekom konstantom koju sam odredis kako ne bi islo prebrzo ili presporo.

Geomaster
13.12.2008, 17:45
Haha, ja sam mislio da je stvar u frame skip-u :to_care:

A ček, ovo perv_time = GetTime() ide na kraj?
Znači, recimo, sensivity kamere bi bio normalan_sensivity * dt * mojakonstanta?
A ne znam šta da stavim za tu moju konstantu, neki broj > 1, < 1 ili kako?

Thanx... :)

Stevvan
13.12.2008, 18:03
te 2 linije moraju biti zajedno, jedna ispod druge, nema veze gde e u loop-u nalaze, ali je standardno da su na pocetku.
Upravo tako.
Konstanta moze biti od 0 do 65535 :D

EclipsE
13.12.2008, 18:26
moze da bude i -65535!! samo shto bi to dovelo do nekog invertovanja kamere :D

Geomaster
13.12.2008, 18:45
@Stevvan: Nisi morao da odgovaraš, rekao si mi preko MSNa :) Nema veze, neka bude za one kojima treba takva pomoc :)
OMG meni ovaj lik ide prebrzo i sa konstantom 1, a ko zna koliko će da bude sa -65535 :rolleyes: :D

sasha vukelic
15.12.2008, 10:11
Dva su najpopularnija nacina za to... Prvi je ovaj koji je Stevvan naveo, dakle mjeris koliko je vremena proslo za renderovanje frejma i nakon toga mnozis svo pomjeranje sa tim brojem. To je najbolji nacin, ali i najkomplikovaniji, tako da rijetko koja komercijalna igra to koristi.

Ono sto se najcesce koristi je puno jednostavnije: postavi se odredjena brzina refreshovanja svijeta, sto je u velikoj vecini slucajeva 60FPS. Crtanje frejmova i refreshovanje svijeta se vrsi odvojeno, gdje refresh, naravno, ima puno veci prioritet.

Uzmimo za primjer da vsync nije ukljucen. Slika se iscrtava po pikselima kao sto se npr. pise u svesku. Ukoliko je racunar jako spor, od iscrtavanja jedne slike, znaci dok imaginarna ruka crtaca dodje iz gornjeg lijevog ugla ekrana u donji desni moze da se desi da se svijet refreshuje vise puta i tako nastaje pojava zvana tearing.

Ako je vsync ukljucen, jedna slika ce se prikazati na ekranu tek kad bude u cijelosti nacrtana. U tom slucaju ocigledne nuspojave su input lag i, cesto, manji frame rate u poredjenju s tim kad je vsync iskljucen.

Stevvan
15.12.2008, 11:32
Uh daleko od toga da je najtezi, cak nisu najprimenljiviji ni jedan ni drugi. Oba su pocetnicka, i imaju svoje mane. Recimo za tvoj nacin gde programer fakticki ogranicava framerate sa vsync-om, dolazi do toga da je na razlicitim komjuterima vsynic drugaciji, sto odmah izaziva promenu u brzini. Ako bi se recimo ogranicio na 60, onda onima kojima je refresh rate 75 to izgleda kao da malo secka, dok kod ovoga gde se uzima dt toga nema.
E sad simulacije fizike zahtevaju da dt za njih uvek bude isti (1/60, doduse ne zahtevaju ali je preporucljivo da ne bi dolazilo do bugova) pa onda onaj nacin koji sam ja rekao gaomasteru moze biti problem. Svakako moze se koristi tvoj nacin ali onda ostaju oni problemi. Ja sam to resio kao sto je objasnjeno u ovom article-u http://gafferongames.wordpress.com/game-physics/fix-your-timestep/ Meni su zadnji delovi delovali konfuzno, pa sam se malo pomucio da ih skapiram (nije se podudarao source programa sa onim sto je autor hteo da kaze, odnosno nije ih dobro objasnio) tako da ako neko bude imao problema sa razumevanjem moze da me pita. Dakle najbolji nacin je ovaj sa interpolacijom izmedju frameova, koji nam pruzamogucnosti kao sto su da usporimo vreme i da nema seckanja, i pomeranje cini tecnim, ali svakako ovo moze ici na stetu procesora. Medjutim ko sto jedan pametan covek rece: "Prvo napravi pa onda optimizuj". Ja trenutno nemam problema sa tim nacinom, a masina mi je za danasnji standard ispodprosecna, tako da ako bude bilo potrebe za optimizacijama javicu vam :)

@Geomaster: Tvoja igra nije preterano zavisna od fizike, tako da nemoras da se mucis da implementiras ovaj sistem, tako da mislim da je najbolje da koristis ovaj sa delay time-om.

sasha vukelic
15.12.2008, 12:00
nema tu sta pocetnicki, to su dva glavna nacina koja postoje: fixed timestep i variable timestep.

npr. sve igre za xbox360 i ps3 su radjene tako (60FPS fixed timestep); primjer za pc recimo doom 3 engine, znaci sve igre radjene na njemu.

to da "sjecka" na monitoru od 75HZ je tacno jer svaku ~cetvrtu sliku ce dvaput prikazati. medjutim standardan prelaz sa 24FPS na 30FPS kada se filmovi prikazuju na normalnom tv programu je nemoguce primjetiti golim okom, tako da dodje da prelaz sa 60HZ na 75HZ je skoro tri puta teze od nemoguceg :D btw. oba nacina su ogranicena vsync-om monitora... ne mozes vidjeti vise slika nego sto monitor moze prikazati ;) a kako vecina ljudi danas imaju tft/lcd, koji rade na 60HZ, fiksni korak je opet logican izbor.

laksi je za programiranje zato sto ti je fizika, refresh, uvijek se desava u isto vrijeme - 60 puta u jednoj sekundi - i sa programerske strane, ocigledno da je i jednostavniji i precizniji - uvijek tacno znas (ili mozes da odredis) vremenske okvire akcija. varijabilni korak je tezi i rijetko ko se upusta u programiranje sa njim - svaki put kad iscrtas jednu sliku to ti je trajalo odredjen broj milisekundi i svaki put je to drugaciji broj. prakticno ako igra podrzava multiplayer, varijabilni timestep mozes da zaboravis, jer je tu sinhronizacija nocna mora.

Geomaster
15.12.2008, 14:03
@Stevvan, sasha vukelic: Hvala ljudi na pomoći! Baš kao što Stevvan kaže, nemam puno korišćenja fizike jer sve što ima veze sa fizikom se radi preko ODE-a i built-inovano je u engine pa nema problema (testirao sam gravitaciju i ne primećujem promenu) ;)

Stevvan
17.12.2008, 13:51
@sasha vukelic:
Fixed time step stoji za konzole posto kod njih ne dolazi do seckanja, ali sta recimo ako ti je time step 1/60, a komp je nesto slabiji, pa mu igra radi na 25 fps-a? Cini mi se da ce to dovesti do usporenja. Fixed time step je ok jedino u slucajevima da nema seckanja.

sasha vukelic
18.12.2008, 10:57
zasto bi doslo do usporenja? iscrtavanje slike uvijek ide nezavisno od refresh-a svijeta, tako da ce u slucaju da igra radi (tacno) 20FPS na ekranu biti 2 tearing-a -- ako uzmemo slucaj da je scena koju gledamo jednako kompleksna na citavoj povrsini ekrana, sto nije slucaj, jer su uglavnom najkompleksniji dijelovi na horizontu, u daljini. znaci u tom idealnom slucaju kompleksnosti (i, opet, vsync iskljucen): slika se crta, tako da nakon 1/60 sekunde na ekranu imamo 1/3 slike (gornji dio monitora). tada se svijet mijenja (ako je fixed timestep 60FPS). nastavljajuci piksel po piksel, iscrtava se dalje koliko moze, ali sada sa novim podacima o tome gdje se kamera nalazi, u kojem pravcu gleda itd. ocigledno da, ako se kamera krece, nastaje tearing izmedju gornje trecine i srednje trecine (a i srednje trecine i donje trecine) slike.

ima tu jedan fazon koji usporava, ali je on vezan samo za vsync i refresh rate monitora -- npr. ako ti je vsync ukljucen, monitor radi na 50HZ, a brzina igre koju igras varira izmedju 25HZ i 50HZ -- u tom slucaju ce se desiti da ce igra ugl. raditi na 25HZ.

kad bih imao kompjuter koji moze da tjera igre po 500FPS, i monitor sa refreshom od bar 200HZ, naravno da bih i ja vise volio da su sve igre napravljene sa varijabilnim step-om, jer jedino bi one mogle iskoristiti taj potencijal. tako, i varijabilni i fiksni timestep imaju i prednosti i mane. npr. input lag na fiksnom timestep-u je fiksan - uvjek ces imati ujednacen odziv izmedju tastature (misa) i igre. kad je timestep varijabilan i ako frame rate dosta varira (sto je cesta pojava u novim igrama) tada i input lag varira isto toliko.

Stevvan
18.12.2008, 13:22
Ako imamo objekat koji ima recimo brzinu 3. Ako je 60 fps onda ce se na poziciju tog objekta 60 puta u sekundi dodati 3. Ako je fps 20 onda ce se 20 puta u 1 sekundi na taj poziciju objekta dodati 3. Ako koristis variable time step toga nema, jer 1/60*3 u 60 frameova je isto sto i 1/20*3 u 20.

Evo sad vidim kazes refres sveta ide odvojeno. Jel mozes da pojasnis kako to radi?

sasha vukelic
18.12.2008, 14:36
program se odvaja u dva thread-a. u jednom threadu se 60 puta u sekundi radi refresh svijeta. taj thread ima veci prioritet i kad on nema sta da radi, tek tada se daje prioritet drugom thread-u, koji crta scenu.

lako je zamisliti sta se desava u drugom thread-u. crtanje ide onako kao sto sam vec opisao -- od gornjeg lijevog piksela do donjeg desnog. i tako crta se odredjeni dio ekrana dok ne prodje 1/60 sekunde, tada se taj thread zaledi, prvi thread koji je cekao odradjuje update svijeta, i kad on zavrsi, drugi nastavlja crtanje tamo gdje je stao (sto, ocigledno, moze biti bilo koja tacka na ekranu), dok ne prodje novih 1/60 sekunde :)

ovo sve mozes da programiras sam, ali to je ogroman posao. uvijek je bolje za pocetak uzeti neki gotov engine. u njemu ces uglavnom naci mjesto gdje trpas kod za refresh svijeta i mjesto na kom ga crtas. ostalo engine odradi sam -- sve sto treba uraditi jeste iskoristiti timestep koji engine nudi (ili podesiti onaj koji tebi odgovara, u slucaju da su ponudjena oba nacina)