12
votes

Réglage des cadres Max par seconde dans OpenGL

Y a-t-il un moyen de calculer la quantité de mises à jour nécessaires pour atteindre la fréquence de trame souhaitée, non spécifique au système? J'ai trouvé que pour Windows, mais j'aimerais savoir si quelque chose comme ça existe à OpenGL elle-même. Ce devrait être une sorte de minuterie.

ou comment puis-je empêcher FPS de tomber ou de soulever considérablement? Pour cette période, je le teste sur le dessin important de sommets de sommets en ligne et que vous utilisez FRAPS, je peux voir la fréquence de trame d'aller de 400 à 200 fps avec un ralentissement évident du dessin.


0 commentaires

7 Réponses :


12
votes

Vous avez deux façons différentes de résoudre ce problème:

  1. supposons que vous ayez une variable appelée maximum_fps , qui contient pour le nombre maximal de cadres que vous souhaitez afficher.

    Ensuite, vous mesurez la quantité de temps passée sur la dernière image (une minuterie fera)

    Supposons maintenant que vous ayez dit que vous vouliez un maximum de 60fps sur votre demande. Ensuite, vous voulez que le temps mesuré soit inférieur à 1/60. Si le temps mesuré s inférieur, alors vous appelez veille () pour atteindre la quantité de temps laissée pour un cadre.

  2. ou vous pouvez avoir une variable appelée cocher , contenant le "temps de jeu" actuel de l'application. Avec la même minuterie, vous l'incrémenterez à chaque boucle principale de votre application. Ensuite, sur vos routines de dessin, vous calculez les positions basées sur la coche var, car elle contient l'heure actuelle de l'application.

    Le grand avantage de l'option 2 est que votre application sera beaucoup plus facile à déboguer, car vous pouvez jouer avec la variable cocher , allez en avant et en arrière quand tu veux. Ceci est un gros plus.


5 commentaires

Le premier n'est que pour ralentir le FPS en bas et il est dangereux de compter sur la précision de l'intervalle de sommeil.


Dans certains cas simples (et mon article actuel) est la 1ère solution suffisamment bonne, car j'ai juste besoin d'unir FPS lors de l'exécution de l'application, sachant que mon taux de trame n'a jamais diminué de 200 ans, il sera efficace. Donc peut-être un dangereux mais simple à entrer dans votre code sans beaucoup de changements, c'est aussi bon que seconde ..


"Ensuite, vous mesurez la quantité de temps consacrée à la dernière image" Comment savez-vous que la dernière image est terminée et son temps pour mesurer le délai?


@Allahjane comme l'habituel: la minuterie = temps (); rendu_frame (); Time_Spent = Time () - Minuterie;


En fait, je voulais dire l'appel OpenGL qui vous indique que le tirage au sort est terminé



5
votes

existe-t-il un moyen de calculer combien de mises à jour doivent être apportées pour atteindre la fréquence de trame souhaitée, non spécifique au système?

non.

Il n'y a aucun moyen de calculer avec précision combien de mises à jour doivent être appelées pour atteindre le framerate souhaité.

Cependant, vous pouvez mesurer combien de temps a passé de temps depuis la dernière image, calculez-le en fonction de l'encadrement en fonction de celui-ci, comparez-le avec le framerate souhaité, puis introduisez un peu de Dormez ing pour réduire le framerate actuel à la valeur souhaitée. Pas une solution précise, mais cela fonctionnera.

J'ai trouvé que pour Windows, mais j'aimerais savoir si quelque chose comme ça existe à OpenGL elle-même. Ce devrait être une sorte de minuterie.

OpenGL n'est concerné que sur le rendu de rendu et n'a rien à voir avec les minuteries. En outre, l'utilisation de la minuterie Windows n'est pas une bonne idée. Utilisez QueryPerformancecounter, gettickcount ou sdl_getticks pour mesurer le temps passé et dormir pour atteindre le framerate souhaité.

ou comment d'autriennement puis-je empêcher FPS de chuter ou de soulever considérablement?

Vous empêchez FPS de lever en sommeil.

comme pour empêcher FPS de tomber ...

C'est un sujet incroyablement large. Voyons. Cela fait quelque chose comme ça: utilisez des objets de tampon de sommet ou des listes d'affichage, , ne pas Utilisez des textures incroyablement grosses, n'utilisez pas trop de mélange alpha-mélange, évitez «RAW» OpenGL (GLVERTEX3F), ne rendez pas d'objets invisibles (même si aucun polygones ne sont tirés, les traiter prennent du temps), envisagez d'apprendre à propos des BSP ou des Octrees pour Rendu des scènes complexes, dans des surfaces paramétriques et des courbes, n'utilisez pas de trop de primitives (si vous rendantez un cercle en utilisant un million de polygones, personne ne remarquera la différence), désactivez VSYNC. En bref - Réduire le nombre minimal possible absolu d'appels de rendu, nombre de polygones rendus, nombre de pixels rendus, nombre de texels lisez, lisez chaque documentation de performance disponible de NVIDIA, et vous devez obtenir un coup de pouce de performance.


3 commentaires

J'ai constaté que même OGL ait sa propre minuterie comme ceci: GluttiMerfunc (40, Minuterie, 0); Quoi qu'il en soit, lorsque je parlais de Windows One, je pensais que QueryPerformEcanceCounter et QueryPerformanceFréquence ne sont disponibles que sur Windows.


@Raven: "Gluttimerfunc" Ce n'est pas une fonction OpenGL - Glut ne fait pas partie de OpenGL. "Sont disponibles uniquement sur Windows" Oui, ils sont uniquement des fenêtres. Si vous souhaitez une solution multiplate-forme, utilisez sdl_getticks.


Mais si vous utilisez une galet (Freeglut dans mon cas), vous avez encore une solution multiplate-forme. Bien sûr, il y a un besoin de bibliothèque Freeglut alors, mais Glut fournit des fonctions précieuses (comme cette minuterie) dans cette pièce de fichier ...



1
votes

Vous posez la mauvaise question. Votre moniteur ne s'affichera jamais uniquement à 60 fps (50 FPS en Europe, ou éventuellement 75 FPS si vous êtes un pro-joueur).

Au lieu de cela, vous devriez chercher à verrouiller votre FPS à 60 ou 30. Il existe des extensions OpenGL qui vous permettent de le faire. Cependant, les extensions ne sont pas une plate-forme transversale (heureusement, elles ne sont pas spécifiques à la carte vidéo ou que cela deviendrait vraiment effrayant).

  • Windows : wglswapIntervalext
  • x11 (Linux) : GlxSwapIntervLalsgi
  • max os x :?

    Ces extensions sont étroitement liées à votre moniteur V-Sync . Une fois que les appels activés pour échanger, le tampon arrière OpenGL sera bloqué jusqu'à ce que le moniteur soit prêt pour cela. C'est comme mettre un sommeil dans votre code pour appliquer 60 FPS (ou 30, ou un autre numéro ou un autre numéro si vous n'utilisez pas un moniteur qui s'affiche à 60 Hz). La différence que le "sommeil" est toujours parfaitement chronométré au lieu d'une supposition éduquée basée sur la durée de prise de la dernière image.


12 commentaires

"Vous posez la mauvaise question." C'est une question de développement de jeux tout à fait raisonnable. "Votre moniteur ne sera jamais jamais affiché" YEP, mais une application peut facilement produire 600 images par seconde. En outre, un très haut framerate est utile pour capturer la vidéo et la ralentissement de la suite.


"Au lieu de cela, vous devriez chercher à verrouiller votre FPS à 60 ou 30.". Vous ne devriez certainement pas faire cela - si vous faites ce jeu ne fonctionnera pas si le matériel n'est pas assez puissant. Le jeu correctement effectué doit pouvoir fonctionner sur n'importe quel framerate (de 5 à 1000). "wglwapintervalextext" Il a très peu de choses à voir avec le framerate.


J'étais un peu vague. Bien sûr, vous devriez dégrader gracieusement si le système ne peut pas pousser 30 FPS. Cependant, pour une meilleure expérience utilisateur, il est préférable de "verrouiller" votre taux de trame à quelque chose de cohérent plutôt que de sauter partout de 20 à 2 heures.


De plus, je pense que nous parlons un peu les uns des autres. J'approche cela du point de vue du jeu vidéo. Avec un jeu vidéo, il s'agit d'une erreur de débutant courante de pousser le SPP aussi haut que possible car plus grand est évidemment mieux. Avec des jeux vidéo Il est toujours préférable d'avoir un FPS cohérent, à une exception une exception lorsque vous testez des performances graphiques. Je n'avais jamais considéré qu'il y aurait une raison valable de pousser un énorme FPS autre que de montrer un moteur de jeu.


@Caspin: "J'approche cela du point de vue du jeu vidéo." Je parle aussi du point de vue du jeu vidéo. Verrouillage FPS n'est pas fiable (vous n'obtiendrez jamais une valeur exacte) et doit être évitée à moins de limiter une limitation (disons, dans le moteur de physique), tout en soutenant un framerer variable, n'est pas difficile. De mon avis, la manière appropriée est de faire de la variable framérée - mesurer le temps passé, mettez à jour la scène en conséquence.


@CASPIN: "Raison valide de pousser un énorme FPS" J'ai déjà vu suffisamment de discussions chauffées sur ce sujet, il existe deux arguments principaux - avec un FPS plus élevé, vous obtiendrez un contrôle plus fluide. Même si FPS est au-dessus du tarif de rafraîchissement du moniteur. Un autre argument consiste à faire des vidéos de jeu vidéo (disons, avec FRAPS) - lorsque le framerate est supérieur à 200, vous pouvez facilement faire une bonne vidéo à mouvement lent.


@CASPIN: parlant de Slow-motion, il sera plus difficile de faire des mouvements de ralentis dans le jeu qui ne prend pas en charge que le moteur à framerate fixe, le moteur à framerate variable ne s'en soucierait pas - de changer la vitesse du flux de temps, vous devez multiplier Deltat et C'est tout ce dont vous avez besoin. Avec un framérat fixe, vous devrez modifier le nombre de mises à jour, vous obtiendrez ainsi un mouvement jerky ou une charge supplémentaire de la CPU (si vous voulez que tout se déplace plus rapidement). De plus, si vous le souhaitez, il est très facile de convertir un moteur à framerate variable vers un framerate fixe - il vous suffira de modifier une classe qui calcule Deltat et ajoutez un peu de sommeil.


@Caspin: "Notre moniteur ne sera jamais jamais affiché à 60 FPS" en supposant que le moniteur ne soutiendra jamais que si le framerate est incorrect. Il n'y a pas si longtemps, il y avait beaucoup de moniteurs CRT qui pourraient soutenir le taux de rafraîchissement de 120Hz. Si un nouvel appareil apparaît sur le marché et que votre jeu sera verrouillé au taux de rafraîchissement sous le taux de rafraîchissement des moniteurs, le client ne sera pas heureux. Le moteur doit pouvoir supporter autant de cadres par seconde que possible, mais un utilisateur doit avoir une option pour activer VSYNC. Je crois que c'est la fin de la discussion.


Très bien, laissez-moi clarifier, je ne suis que pas d'accord avec vous sur le problème de la FPS. Tout le reste est la meilleure pratique pour un développement de jeux. Nous sommes d'accord: les mises à jour du jeu (moteur / physique / etc.) devraient être indépendantes du taux de trame. Pour exécuter un jeu au ralenti, je voudrais réduire l'échelle, le temps passé les mises à jour. Nous sommes d'accord: l'entrée d'échantillonnage plus rapide que 60Hz est une bonne chose. Personnellement, je pense que cela vous nourrit de la dernière fois que le Deltat actuel est une mauvaise idée (je ne pense pas que vous préconisiez cela, clarifiez simplement). Au lieu de cela, le Deltat devrait être lissé d'une manière ou d'une autre au cas où il y a eu une pic FPS.


Nous sommes d'accord: un taux de trame ne peut pas vraiment être verrouillé. Nous désagrément : le taux de trame devrait préférer la cohérence sur la vitesse brute. Je pense que nous convenons que la situation parfaite (qui ne se produirait jamais) est que le moteur se fait avec la mise à jour du dernier écran, tout comme le moniteur est prêt pour un nouveau. Lorsque vous utilisez un double tampon, la coordination des mises à jour de rendu avec V-Sync est la manière préférée. Lorsque vous utilisez des techniques triple-tampon, les deux techniques fonctionnent bien. Par défaut DirectX Sychronise avec V-Sync, même lorsque la touche tamponnée triple.


La vitesse brute est nécessaire pour une animation lente de qualité sur un jeu de réseau, car les mises à jour du réseau ne peuvent pas être ralentissées. Les mises à jour de chronométrage avec V-Sync ont l'avantage de perdre moins de temps de processeur (écrans RAW Speed ​​Rend les écrans qui ne seront jamais affichés sur le moniteur). Je dirons que les mises à jour de moniteur cohérentes sont importantes, par ex. Un 30 FPS cohérent est supérieur à un FPS allant de 55 à 65 sur un moniteur de 60Hz. Cela ne s'applique toutefois à la question à la main (ma réponse est fausse). Lorsque les tarifs sont toujours plus grands que le taux de rafraîchissement des moniteurs, le moniteur mettra toujours à jour à une vitesse cohérente.


-1 parce que les moniteurs européens sont identiques aux moniteurs dans le reste du monde. Le framerate 50/60 est quelque chose qui était vrai dans le mauvais vieux temps de moniteurs analogiques; Ce n'est pas vrai pour les affichages numériques.



10
votes

règle n ° 1. Ne faites pas de mises à jour () ou de boucle () Les fonctions comptent sur la fréquence à laquelle elle est appelée.

Vous ne pouvez pas vraiment obtenir votre FPS souhaité. Vous pouvez essayer de le stimuler en sautant quelques opérations coûteuses ou ralentissez-la en appelant le type de fonction (). Cependant, même avec ces techniques, FPS sera presque toujours différent du FPS exact que vous souhaitez. P>

Le moyen courant de faire face à ce problème consiste à utiliser le temps écoulé de la mise à jour précédente. Par exemple, P>

// Bad
void enemy::update()
{
  position.x += 10; // this enemy moving speed is totally up to FPS and you can't control it.
}

// Good
void enemy::update(elapsedTime)
{
  position.x += speedX * elapsedTime; // Now, you can control its speedX and it doesn't matter how often it gets called.
}


2 commentaires

Bassiquement, vous dites la même chose que Edison, mais cette démonstration de code donne clairement clair pour tout le monde maintenant je pense. Merci


Vous êtes la bienvenue ~ :) et Yeap, le mien est le même que le 2ème dans la réponse d'Edison. Je voulais juste souligner la faiblesse du 1er 1.



1
votes

Vous ne faites absolument pas pour étrangler votre cadence tout cela dépend de ce que vous avez En cours dans cette boucle de rendu et quelle est votre application. Surtout avec c'est Physique / Réseau associé. Ou si vous faites tout type de traitement graphique avec une boîte à outils latérale de sortie (Caire, QPainter, Skia, AGG, ...) Sauf si vous souhaitez des résultats de synchronisation ou une utilisation à 100% de la CPU.


0 commentaires

0
votes

Voici un question similaire, avec ma réponse et exemple de travail

J'aime aussi la réponse de Deft_Code et je cherche à ajouter ce qu'il suggère à ma solution.

La partie cruciale de ma réponse est la suivante:

Si vous envisagez de ralentir et d'accélérer les cadres, vous devez réfléchir avec soin de savoir si vous voulez dire des cadres de rendu ou d'animation dans chaque cas. Dans cet exemple, il est associé à une accélération simple pour des animations d'animation, pour tout cas lorsque des cadres peuvent être supprimés dans une animation potentiellement lente.

L'exemple concerne le code d'animation qui rend à la même vitesse, que le mode d'analyse comparative, ou le mode FPS fixe, est actif. Une animation déclenchée avant que le changement ne conserve même pas une vitesse constante après le changement.


0 commentaires

0
votes

Ce code peut faire le travail, à peu près.

static int redisplay_interval;

void timer(int) {
    glutPostRedisplay();
    glutTimerFunc(redisplay_interval, timer, 0);
}

void setFPS(int fps)
{
    redisplay_interval = 1000 / fps;
    glutTimerFunc(redisplay_interval, timer, 0);
}


0 commentaires