Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

glut lagged bij het tekenen

Pagina: 1
Acties:

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
hallo allemaal,

ik ben bezig met een projectje waarin een vogel object door een ruimte vliegt. ik ben momenteel bezig met het in 2d te renderen en wil dan later uitbreiden naar 3d. ik heb alleen nu een probleem dat de tekening erg gaat laggen. het object wordt steeds stukje kleiner en dan weer groter waardoor het lijkt te pulseren. Als ik naar 1 punt kijk zie ik duidelijk hoe hij lagt met bewegen.

Ik gebruik een timer die volgens een bepaalde tijd afvuurt. Daarna berekent deze functie de nieuwe positie aan de hand van de snelheid en richtingshoeken van het object. Op google staat vooral dat ik een dubbele buffer moet gebruiken, wat ik al doe.
Ik weet niet zo goed hoe ik dit probleem moet oplossen. Heeft iemand hier misschien een idee? Alvast bedankt!
ik gebruik freeglut en c++ met visual studio 2013 professional op windows 7 64-bit.

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
De mseconds parameter van glutTimerFunc beschrijft een lower-bound, je zult dus nog moeten compenseren voor het daadwerkelijk verstreken aantal milliseconden.

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
PrisonerOfPain schreef op woensdag 23 april 2014 @ 16:53:
De mseconds parameter van glutTimerFunc beschrijft een lower-bound, je zult dus nog moeten compenseren voor het daadwerkelijk verstreken aantal milliseconden.
daarom had ik het op 50 ms gezet, maar dat helpt niet. zou die tekenfunctie er echt zo lang over doen?

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
williewonka03 schreef op woensdag 23 april 2014 @ 16:55:
[...]

daarom had ik het op 50 ms gezet, maar dat helpt niet. zou die tekenfunctie er echt zo lang over doen?
Wat die 50 doet is zorgen dat er minimaal 50 milliseconden verstrijken voor dat de timer opnieuw word aangeroepen. Het kan dus ook makkelijk zijn dat er 100 milliseconden verstrijken, dat is niet aan jou of je render functie, maar ook aan externe factoren zoals de system-load of de thread-scheduler.

Wat je dus ook nog moet doen is meten hoeveel tijd er verstreken is ten opzichte van de vorige keer dat je timer afging, en daarmee compenseren.

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
PrisonerOfPain schreef op woensdag 23 april 2014 @ 16:57:
[...]


Wat die 50 doet is zorgen dat er minimaal 50 milliseconden verstrijken voor dat de timer opnieuw word aangeroepen. Het kan dus ook makkelijk zijn dat er 100 milliseconden verstrijken, dat is niet aan jou of je render functie, maar ook aan externe factoren zoals de system-load of de thread-scheduler.

Wat je dus ook nog moet doen is meten hoeveel tijd er verstreken is ten opzichte van de vorige keer dat je timer afging, en daarmee compenseren.
ja dat snap ik, maar dat zou alleen uitmaken als er daadwerkelijk meer dan die 50 is verstreken. en dat lijkt me zeer sterk voor die paar handelingen die ik doe om te tekenen. bovendien als ik de tijd groter maak met een vaste hoeveelheid dan blijft ie gewoon laggen helaas. dus zelfs als ik dat meten zou doe en als het meer dan 50 is dan blijft ie nog steeds laggen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

williewonka03 schreef op woensdag 23 april 2014 @ 17:00:
[...]

ja dat snap ik, maar dat zou alleen uitmaken als er daadwerkelijk meer dan die 50 is verstreken.
Dat is per definitie zo. Zoals je code nu is opgezet kan het nooit dat hij exact om de 50ms de functie uitvoert, want de timer wordt pas weer opnieuw ingesteld binnen de functie. Dus zelfs al wordt de functie zelf exact na 50ms opnieuw aangeroepen, tegen de tijd dat je glutTimerFunc() aanroept is er alweer wat tijd verstreken. In het beste geval zit je er dus steeds een fractie van een seconde naast, in de praktijk kan dat best een paar ms schelen.

En denk nou niet dat de oplossing is door glutTimerFunc() naar het begin van de functie te verplaatsen, maar doe gewoon wat PrisonerOfPain zegt: meet de tijd die verstreken is en gebruik dat om relatieve updates te doen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Je kunt dit overigens vrij eenvoudig doen met glutGet(GLUT_ELAPSED_TIME) al is dat niet heel nauwkeurig.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

ms-precisie is over het algemeen wel voldoende (al heb ik geen ervaring met die functie, is dat ook werkelijk de granulariteit?). Het is vooral van belang dat die onnauwkeurigheid niet accumuleert.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Voor precies deze situatie is ms genoeg inderdaad :)

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
ok ik heb toegepast wat PrisonerOfPain zei en het maakt helaas niks uit. Heeft iemand verder nog ideeën?

  • Gleighton
  • Registratie: November 2008
  • Niet online
Volgen wat .oisyn zegt, want glutTimerFunc staat nog steeds niet op een logische plek.

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Gleighton schreef op woensdag 23 april 2014 @ 23:54:
Volgen wat .oisyn zegt, want glutTimerFunc staat nog steeds niet op een logische plek.
Als het advies van PoP goed is opgevolgd dan maakt het niet meer uit waar glutTimerFunc staat, de lokatie is dan enkel relevant voor de 1e en 2e run en alle volgende runs wordt het gecompenseerd doordat er simpelweg meer of minder tijd verstreken (naargelang het gezet is) is en die tijd moet je gewoon meeberekenen.

Dus als de het van het begin van de loop tot aan de aanroep van de tijd functie 1 msec duurt, dan duurt de 1e run 50 msec, de 2e run duurt dan ook nog 50 msec (want er was nog geen begintijd om mee te corrigeren) maar de 3e run die gaat na 49 msec (+1 msec voor je loop=50 msec) runnen.
Start je nu iets heel zwaars op waardoor je loopfunctie 45 msec gaat duren, als je dan goed gecompenseerd hebt heb je 1 frame lag en daarna wordt er maar 5 msec gewacht omdat je gewoon die 45 msec kan corrigeren.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Gleighton schreef op woensdag 23 april 2014 @ 23:54:
Volgen wat .oisyn zegt, want glutTimerFunc staat nog steeds niet op een logische plek.
Ik zeg juist dat dat géén goede oplossing is :).

Wat er nu iig mis gaat is dat je je timestep pas toepast de volgende frame ipv de huidige. Je moet de berekening voor de update zetten. Al begin ik me wel af te vragen of dat het door jou geschetste probleem verklaart... misschien is er meer aan de hand.

Wat voor waardes krijg je eigenlijk uit die timestep berekeningen?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 17-10 16:43
PrisonerOfPain schreef op woensdag 23 april 2014 @ 17:13:
Je kunt dit overigens vrij eenvoudig doen met glutGet(GLUT_ELAPSED_TIME) al is dat niet heel nauwkeurig.
Waarom niet gewoon de functies uit de nieuwe chrono namespace, die zijn wel 'precies'

~ Mijn prog blog!


  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02
Je kan wel gaan kloten met de wait times enz, maar wellicht is het ook wel verstandig om de delta time mee te nemen in de positieberekeningen. Dan krijg je ook geen microstuttering in de beweging van je objecten doordat de frametijden telkens veranderen. 1ms verschil lijkt niet veel, maar als de verplaatsing groot genoeg is ga je het toch merken.
De uiteindelijke oplossing in het artikel dat ik eerder heb geplaatst is wellicht wat overkill, maar de ideeën en oplossingen die er in worden beschreven zijn volgens mij wel de oplossing voor dit probleem. De simpelste oplossing is om deltatime mee te nemen in de berekeningen, maar dan kan je snel last krijgen van accumulatie van onnauwkeurigheid. De meest correcte oplossing (lijkt mij) is om de updates los te koppelen van de draws en met een vaste timestep te berekenen. Soms loopt je update vooruit op de draw en in dat geval teken je een interpolatie tussen de updates. Dat kan alleen wel behoorlijk wat meer werk zijn om in te bouwen.

Ik had zelf overigens iets meer dan een half jaar geleden hetzelfde probleem (zover ik het goed begrijp hier) met freeglut en het afstappen van die timerfunctie heeft toen geholpen. Gewoon zelf een loop maken en daar fatsoenlijk met de detlatime rekenen voorkomt dit soort microstuttering. Je zit dan dus alleen met die onnauwkeurigheid die op kan stapelen bij grote schommelingen in delta time (of hele kleine delta time).

[ Voor 16% gewijzigd door Caelorum op 24-04-2014 10:08 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Caelorum schreef op donderdag 24 april 2014 @ 10:03:
Je kan wel gaan kloten met de wait times enz, maar wellicht is het ook wel verstandig om de delta time mee te nemen in de positieberekeningen.
Dat doet ie dus ook, alleen gebruikt hij de timestep van de vorige frame ipv die van de huidige frame.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
.oisyn schreef op donderdag 24 april 2014 @ 10:34:
[...]

Dat doet ie dus ook, alleen gebruikt hij de timestep van de vorige frame ipv die van de huidige frame.
Dat heb ik zojuist gefixed, het ziet er een stukje beter uit maar nog stuttert nog steeds vrij merkbaar. Ik ga even kijken om de timefunc te dumpen zoals Caelorum voorstelde. Is het mogelijk om een functie per frame aan te roepen en dan de frametijd te krijgen? dan zet ik mijn update daar gewoon in.

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Een paar dingen verder nog,

Je RotateVector functie roept sin/cos aan met een waarde die jij opgeeft in degrees terwijl deze functies radians verwachtten. Dit zorgde voor het pulserende effect.

Je reset je timer met tijd van je vorige frame, wat je beter kunt doen is:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void init()
{ 
    prevtime = glutGet(GLUT_ELAPSED_TIME);
}

void TimeStep(int id)
{
    int current = glutGet(GLUT_ELAPSED_TIME);
    int elapsed = current - prevtime;
    prevtime = current;
    TimeStepSize = (double)elapsed / 1000.0;

    glutTimerFunc(someOtherTime, TimeStep, 0);
}

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
PrisonerOfPain schreef op donderdag 24 april 2014 @ 11:34:
Een paar dingen verder nog,

Je RotateVector functie roept sin/cos aan met een waarde die jij opgeeft in degrees terwijl deze functies radians verwachtten. Dit zorgde voor het pulserende effect.

Je reset je timer met tijd van je vorige frame, wat je beter kunt doen is:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void init()
{ 
    prevtime = glutGet(GLUT_ELAPSED_TIME);
}

void TimeStep(int id)
{
    int current = glutGet(GLUT_ELAPSED_TIME);
    int elapsed = current - prevtime;
    prevtime = current;
    TimeStepSize = (double)elapsed / 1000.0;

    glutTimerFunc(someOtherTime, TimeStep, 0);
}
Het eerste wat je zegt klopt half, ik converteer het in de constructor van Bird voor de init hoek, maar converteerde het nog niet bij het veranderen van waypoint, dat heb ik zojuist gefixed.

het tweede snap ik niet goed wat je bedoelt, ik doe namelijk al update nadat ik de stepsize heb berekend.

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Het twee gaat over deze regel: glutTimerFunc(lapsedtime, TimeStep, 0);

Je moet 'lapsedtime' (whatever that means) niet gebruiken, maar een constante.

[ Voor 19% gewijzigd door PrisonerOfPain op 24-04-2014 14:01 ]


  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02
.oisyn schreef op donderdag 24 april 2014 @ 10:34:
[...]

Dat doet ie dus ook, alleen gebruikt hij de timestep van de vorige frame ipv die van de huidige frame.
Ik zie het hem nergens doen in de code. Op regel 58 zie ik:
C:
1
(*it)->UpdatePosition();

Ik zie hem daar nergens een deltaT meegeven om de positie te kunnen berekenen. Als die timestep functie ook maar 1 ms later wordt aangeroepen dan de frame daarvoor *kan* je al verschil gaan merken bij de verplaatsing.

Overigens weet ik ook niet hoelang deze call duurt, maar wellicht is het handig om die maar 1 keer aan te roepen zodat je niet een verschil kan krijgen:
C:
1
2
    int lapsedtime = glutGet(GLUT_ELAPSED_TIME) - prevtime;
    prevtime = glutGet(GLUT_ELAPSED_TIME);

Je kan er zo makkelijk een 1ms naast zitten. Zou niet zo'n groot probleem moeten zijn, maar ja..

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Caelorum schreef op donderdag 24 april 2014 @ 14:01:
[...]

Ik zie het hem nergens doen in de code. Op regel 58 zie ik:
C:
1
(*it)->UpdatePosition();

Ik zie hem daar nergens een deltaT meegeven om de positie te kunnen berekenen. Als die timestep functie ook maar 1 ms later wordt aangeroepen dan de frame daarvoor *kan* je al verschil gaan merken bij de verplaatsing.
Dat gaat via de global TimeStepSize

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02
Ah, ok :)
PrisonerOfPain schreef op donderdag 24 april 2014 @ 14:01:
[...] Je moet 'lapsedtime' (whatever that means) niet gebruiken, maar een constante.
Of aan het eind de tijd berekenen tot de volgende gewenste update.

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
huh ik doe toch echt eerst de global TimeStepScale update en dan pas de nieuwe punten uitrekenen hoor.
ik heb nu dit:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void TimeStep(int id)
{
    int currenttime = glutGet(GLUT_ELAPSED_TIME);
    int lapsedtime = currenttime - prevtime;
    prevtime = currenttime;

    TimeStepSize = (double)lapsedtime / 1000;
    glutTimerFunc(Time, TimeStep, 0);

    for (list<Bird*>::iterator it = birds.begin(), end = birds.end(); it != end; ++it)
    {
        (*it)->UpdatePosition();
    }
    glutPostRedisplay();
}

heb de suggesties van constante tijd van hierboven erin verwerkt. helaas helpt dit niet. Ik ga denk ik even proberen om een glutidle callback te doen en dan redraw aanvragen en dan in de display functie de positie berekening (aka de hierboven genoemde functie) aanroepen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Caelorum schreef op donderdag 24 april 2014 @ 14:01:
[...]

Ik zie het hem nergens doen in de code. Op regel 58 zie ik:
C:
1
(*it)->UpdatePosition();

Ik zie hem daar nergens een deltaT meegeven om de positie te kunnen berekenen.
Misschien moet je naar de implemenatie van die functie kijken in plaats van hoe die wordt aangeroepen ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02
.oisyn schreef op donderdag 24 april 2014 @ 14:34:
[...]
Misschien moet je naar de implemenatie van die functie kijken in plaats van hoe die wordt aangeroepen ;)
Ja, ik was er al op gewezen ;( Ik hou me wel weer even buiten de discussie...

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
.oisyn schreef op donderdag 24 april 2014 @ 14:34:
[...]

Misschien moet je naar de implemenatie van die functie kijken in plaats van hoe die wordt aangeroepen ;)
ja en naar shardeglobals.h ik gebruik een global voor de timestep. niet helemaal netjes, dus mss verander ik dat nog wel keer.

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
ok dus ik heb het veranderd naar dit, waarbij ik de hele timer eruit gooi:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
glutIdleFunc(Idle);
void Idle()
{
    TimeStep();
    glutPostRedisplay();
}

void TimeStep()
{
    int currenttime = glutGet(GLUT_ELAPSED_TIME);
    int lapsedtime = currenttime - prevtime;
    prevtime = currenttime;

    TimeStepSize = (double)lapsedtime / 1000;
    //glutTimerFunc(Time, TimeStep, 0);
    cout << TimeStepSize << endl;
    for (list<Bird*>::iterator it = birds.begin(), end = birds.end(); it != end; ++it)
    {
        (*it)->UpdatePosition();
    }
    //glutPostRedisplay();
}

probleem is alleen nu dat de tijd te onnauwkeurig is
hij stuttert nu wel een stuk minder. git doet het niet meer opeens dus kan het even niet op github zetten.

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02
Wat bedoel je met "de tijd te onnauwkeurig is"?

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
Caelorum schreef op donderdag 24 april 2014 @ 16:17:
Wat bedoel je met "de tijd te onnauwkeurig is"?
nou als ik nu de stepsize print dan komt er soms nul uit. dit lijkt te wijzen op het feit dat de tijd nul lijkt. de tijd is niet precies genoeg dus
maar ben ff mijn git aan het repareren

[ Voor 6% gewijzigd door williewonka03 op 24-04-2014 16:18 ]


  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02
Wellicht dat de idle functie gewoon zo snel achter elkaar wordt aangeroepen dat je delta T <1ms is? Of iig. zodanig klein dat een deling door 1000 nul oplevert?
Dat zou mijn gok zijn, maar wellicht dat .oisyn of PoP het wat sneller zien :) Mijn c++ is nog niet zo super (plus mijn geheugen is enorm lek, dus die standaard regels duren altijd even voordat het opkomt ^^)

[ Voor 41% gewijzigd door Caelorum op 24-04-2014 16:24 ]


  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
Caelorum schreef op donderdag 24 april 2014 @ 16:23:
Wellicht dat de idle functie gewoon zo snel achter elkaar wordt aangeroepen dat je delta T <1ms is? Of iig. zodanig klein dat een deling door 1000 nul oplevert?
Dat zou mijn gok zijn, maar wellicht dat .oisyn of PoP het wat sneller zien :) Mijn c++ is nog niet zo super (plus mijn geheugen is enorm lek, dus die standaard regels duren altijd even voordat het opkomt ^^)
ja dat bedoel ik dus. dus dan moet de tijd in kleiner dan ms getelt worden. hopelijk verhelpt dat de laatste lag. het is al een heel stuk beter nu maar nog niet optimaal. het pulseren is wel weg in ieder geval. dat was echt super lelijk

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Je functie word binnen 1ms uitgevoerd, meer precisie kun je waarschijnlijk krijgen met std::chrono :)

C++:
1
2
3
4
std::chrono::system_clock::time_point prevtime;

// in init:
prevtime = std::chrono::system_clock::now();


C++:
1
2
3
4
5
// onidle
auto current = std::chrono::system_clock::now();
typedef std::chrono::duration<float> float_seconds;

float elapsed = std::chrono::duration_cast<float_seconds>(current - prevtime).count();


Dan heb je die lelijke / 1000 ook niet meer nodig.

[ Voor 5% gewijzigd door PrisonerOfPain op 24-04-2014 16:27 ]


  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
PrisonerOfPain schreef op donderdag 24 april 2014 @ 16:26:
Je functie word binnen 1ms uitgevoerd, meer precisie kun je waarschijnlijk krijgen met std::chrono :)

C++:
1
2
3
4
std::chrono::system_clock::time_point prevtime;

// in init:
prevtime = std::chrono::system_clock::now();


C++:
1
2
3
4
5
// onidle
auto current = std::chrono::system_clock::now();
typedef std::chrono::duration<float> float_seconds;

float elapsed = std::chrono::duration_cast<float_seconds>(current - prevtime).count();


Dan heb je die lelijke / 1000 ook niet meer nodig.
aha die kende ik nog niet! bedankt voor de tip, als mijn git is gerepareerd ga ik die even proberen.

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
ok done de lag is nu bijna weg, maar is er nog steeds een beetje als het object schuin omhoog gaat ipv recht.

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 14:02
Ben je al achter wat het resterende probleem is? Ben wel benieuwd eigenlijk :)

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
Caelorum schreef op donderdag 24 april 2014 @ 20:53:
Ben je al achter wat het resterende probleem is? Ben wel benieuwd eigenlijk :)
uhm nee niet echt. deze idle variant werkt al een heel stuk beter, maar nog steeds niet perfect.
Pagina: 1