Résolutions multiples

Le problème des résolutions multiples

Les développeurs ont souvent du mal à comprendre comment bien supporter plusieurs résolutions dans leurs jeux. Pour jeu sur consoles et pc cela est plus ou moins simple, car la plupart des formats d'écrans sont en 16:9 et les résolutions d'écrans standard (720p, 1080p, 1440p, 4K, ...).

Pour les jeux mobiles, au début, c'était facile. Pendant de nombreuses années, l'iPhone et l'iPad ont utilisé la même résolution. Lorsque Retina a été implémenté, ils ont juste doublé la densité de pixels ; la plupart des développeurs ont dû fournir des assets en résolution par défaut et double.

Aujourd'hui, cela n'est plus le cas, comme il y a pleins de différentes tailles d'écrans, densités et résolutions. Des tailles non-conventionnelles sont devenu plus populaire, tel que les écrans ultra-larges.

Pour les jeux 3D il n'y a pas vraiment besoin de supporter différentes résolutions (d'un point de vue esthétique). La geometry 3D va juste remplir l'écran grâce au champ de vision (FOV), peu importe la résolution. Dans notre cas la principale raison de vouloir cela est une question de performance (rendre en plus petite résolution pour améliorer les images par seconde).

Pour la 2D et les interfaces c'est différent, vu que les ressources graphiques doivent être créés en utilisant un nombre spécifique de pixel dans des logiciels comme Photoshop, GIMP ou Krita.

Comme les agencements, les ratios d'aspect, les résolutions, et la densité des pixels peuvent beaucoup changer, il n'est plus possible de concevoir des interfaces utilisateur pour chaque écran spécifique. Une autre méthode doit être utilisée.

Une taille qui convient pour tous

L'approche la plus courante est d'utiliser une seule résolution base et de l'adapter ensuite à tout le reste. Cette résolution correspond à la façon dont la plupart des joueurs sont censés jouer au jeu (compte tenu de leur matériel). Pour le mobile, Google a des stats utiles en ligne, et pour le bureau, Steam a aussi.

A titre d'exemple, Steam montre que la résolution d'affichage primaire la plus courante est 1920×1080, donc une approche sensée consiste à développer un jeu pour cette résolution, puis à gérer la mise à l'échelle pour différentes tailles et différents rapports d'aspect.

Godot fournit plusieurs outils utiles pour le faire facilement.

Taille de base

Une taille de base pour la fenêtre peut être spécifiée dans les Paramètres du projet sous Display → Window.

../../_images/screenres.png

Cependant, cela fait n'est pas complètement évident ; le moteur ne tentera pas de faire passer le moniteur à cette résolution. Considérez plutôt ce paramètre comme la "taille de la conception", c'est-à-dire la taille de la zone avec laquelle vous travaillez dans l'éditeur. Ce paramètre correspond directement à la taille du rectangle bleu dans l'éditeur 2D.

Il est souvent nécessaire de prendre en charge des appareils dont les tailles d'écran et de fenêtre sont différentes de cette taille de base. Godot offre plusieurs façons de contrôler comment le viewport sera redimensionnée et étirée à différentes tailles d'écran.

Note

Godot suit une approche moderne des résolutions multiples. Le moteur ne changera jamais la résolution du moniteur par lui-même. Bien que le changement de la résolution du moniteur soit l'approche la plus efficace, c'est aussi la moins fiable car elle peut laisser le moniteur bloqué sur une résolution basse si le jeu plante. C'est particulièrement fréquent sous MacOS ou Linux qui ne gèrent pas les changements de résolution aussi bien que Windows.

La modification de la résolution de l'écran supprime également tout contrôle du développeur de jeu sur le filtrage et le rapport d'étirement hauteur/largeur, qui peuvent être importants pour garantir un affichage correct pour les jeux en pixel art.

De plus, le changement de résolution du moniteur rend alt-tabbing dans et hors d’un jeu beaucoup plus lent, puisque le moniteur doit changer de résolution à chaque fois.

Redimensionner

Il existe plusieurs types d'appareils, avec plusieurs types d'écrans, qui à leur tour ont des densités de pixels et des résolutions différentes. Les manipuler tous peut être un travail considérable, alors Godot essaie de rendre la vie du développeur un peu plus facile. Le nœud Viewport a plusieurs fonctions pour gérer le redimensionnement, et le nœud racine de l'arbre de scènes est toujours un viewport (les scènes chargées sont instanciées comme un enfant de celui-ci, et on peut toujours y accéder en appelant get_tree().get_root() ou get_node("/root")).

Dans tous les cas, bien que la modification des paramètres du Viewport racine soit probablement la façon la plus souple de traiter le problème, cela peut représenter beaucoup de travail, de code et de devinettes, c'est pourquoi Godot fournit un ensemble simple de paramètres dans les paramètres du projet pour gérer plusieurs résolutions.

Parametre d'étirement

Les paramètres d'étirement sont situés dans les paramètres du projet et fournissent plusieurs options :

../../_images/stretchsettings.png

Mode Étirement

Le paramètre Mode d'étirement définit comment la taille de base est étirée pour s'adapter à la résolution de la fenêtre ou de l'écran.

../../_images/stretch.png

Les animations ci-dessous utilisent une "taille de base" de seulement 16×9 pixels pour démontrer l'effet des différents modes d'étirement. Un seul sprite, également de taille 16×9 pixels, couvre la totalité du viewport, et une diagonale Line2D est ajoutée par-dessus :

../../_images/stretch_demo_scene.png
  • Stretch Mode = Disabled (par défaut) : Il n'y a pas d'étirement. Une unité dans la scène correspond à un pixel sur l'écran. Dans ce mode, le réglage Stretch Aspect n'a aucun effet.

    C'est une bonne option si vous voulez un contrôle total sur chaque pixel de l'écran, et c'est probablement la meilleure option pour les jeux 3D.

    ../../_images/stretch_disabled_expand.gif
  • Stretch Mode = 2D : Dans ce mode, la taille spécifiée dans les paramètres d'affichage/largeur et d'affichage/hauteur du projet est étirée pour couvrir tout l'écran (en tenant compte du paramètre Stretch Aspect). Cela signifie que tout est rendu directement à la résolution cible. La 3D n'est pratiquement pas touchée, alors qu'en 2D, il n'y a plus de correspondance 1:1 entre les pixels des sprites et les pixels de l'écran, ce qui peut entraîner des artefacts de mise à l'échelle.

    C'est une bonne option si votre art 2D a une résolution suffisamment élevée et ne nécessite pas un rendu parfait au pixel près. Pensez à activer le filtrage des textures et le mipmapping sur vos textures et polices 2D.

    ../../_images/stretch_2d_expand.gif
  • Stretch Mode = Viewport : La mise à l'échelle du Viewport signifie que la taille de la racine Viewport est définie précisément à la taille de base spécifiée dans la section Display des paramètres du projet. La scène est d'abord rendue dans ce viewport. Enfin, ce viewport est mise à l'échelle pour s'adapter à l'écran (en tenant compte du paramètre Stretch Aspect).

    Ce mode est utile pour travailler sur des jeux précis au pixel près, ou pour obtenir un rendu à une résolution plus faible afin d'améliorer les performances.

    ../../_images/stretch_viewport_expand.gif

Stretch Aspect

Le deuxième réglage est le stretch aspect. Notez que cela ne prend effet que si Stretch Mode est réglé sur autre chose que Désactivé.

Dans les animations ci-dessous, vous remarquerez des zones grises et noires. Les zones noires sont ajoutées par le moteur et ne peuvent pas être dessinées. Les zones grises font partie de votre scène, et peuvent être dessinées. Les zones grises correspondent à la région en dehors du cadre bleu que vous voyez dans l'éditeur 2D.

  • Stretch Aspect = Ignore : Ignore le ratio d'aspect lorsque vous étirez l'écran. Cela signifie que la résolution d'origine sera étirée pour remplir exactement l'écran, même s'il est plus large ou plus étroit. Cela peut entraîner un étirement non uniforme : les objets semblent plus larges ou plus hauts que prévu.

    ../../_images/stretch_viewport_ignore.gif
  • Stretch Aspect = Keep : Conservez le ratio d'aspect lorsque vous étirez l'écran. Cela signifie que le viewport conserve sa taille d'origine quelle que soit la résolution de l'écran, et des barres noires seront ajoutées en haut/en bas de l'écran ("letterboxing") ou sur les côtés ("pillarboxing").

    C'est une bonne option si vous connaissez à l'avance le ratio d'aspect de vos appareils cibles ou si vous ne voulez pas gérer des rapports d'aspect différents.

    ../../_images/stretch_viewport_keep.gif
  • Stretch Aspect = Keep Width : Conserve le ratio d'aspect lorsque vous étirez l'écran. Si l'écran est plus large que la taille de base, des barres noires sont ajoutées à gauche et à droite (pillarboxing). Mais si l'écran est plus grand que la résolution de base, la fenêtre sera agrandie dans le sens vertical (et plus de contenu sera visible vers le bas). Vous pouvez aussi considérer cela comme une "Expansion Verticale".

    C'est généralement la meilleure option pour créer des interfaces graphiques ou des HUDs à l'échelle, comme cela certaines commandes peuvent être ancrées au bas (Taille et ancrages).

    ../../_images/stretch_viewport_keep_width.gif
  • Stretch Aspect = Keep Height : Conserve le ratio d'aspect lorsque vous étirez l'écran. Si l'écran est plus grand que la taille de base, des barres noires sont ajoutées en haut et en bas (letterboxing). Mais si l'écran est plus large que la résolution de base, le viewport sera agrandi dans le sens horizontal (et plus de contenu sera visible à droite). Vous pouvez aussi considérer cela comme une "Expansion Horizontale".

    C'est généralement la meilleure option pour les jeux 2D qui défilent horizontalement (comme les runners ou les platformers).

    ../../_images/stretch_viewport_keep_height.gif
  • Stretch Aspect = Expand : Conserve le ratio d'aspect lorsque vous étirez l'écran, mais ne conserve ni la largeur ni la hauteur de base. En fonction du ratio d'aspect de l'écran, le viewport sera plus grand dans le sens horizontal (si l'écran est plus large que la taille de base) ou dans le sens vertical (si l'écran est plus haut que la taille d'origine).

    ../../_images/stretch_viewport_expand.gif

Stretch Shrink

Le paramètre Shrink vous permet d'ajouter un facteur d'échelle supplémentaire en plus de ce que les options Stretch ci-dessus fournissent déjà. La valeur par défaut de 1 signifie qu'il n'y a pas de mise à l'échelle.

Si, par exemple, vous réglez Shrink sur 4 et que vous laissez Stretch Mode sur Disabled, chaque unité de votre scène correspondra à 4×4 pixels à l'écran.

Si Stretch Mode est réglé sur autre chose que Disabled, la taille du viewport racine est réduit par le facteur Shrink et les pixels de la sortie sont augmentés de la même quantité. Ceci est rarement utile pour les jeux 2D, mais peut être utilisé pour augmenter les performances des jeux 3D en les rendant à une résolution plus faible.

Depuis les scripts

Pour configurer l'étirement à l'exécution d'un script, utilisez la méthode get_tree().set_screen_stretch()` (voir SceneTree.set_screen_stretch()).

Réduction de l'aliasing lors du sous-échantillonnage

Si le jeu a une très haute résolution de base (par exemple 3840×2160), un aliasing peut apparaître lors du downsampling à quelque chose de considérablement plus bas comme 1280×720. L'aliasing peut être rendu moins visible en réduisant toutes les images d'un facteur 2 lors du chargement. Ceci peut être fait en appelant la méthode ci-dessous avant que les données du jeu ne soient chargées :

VisualServer.texture_set_shrink_all_x2_on_set_data(true)

Vous pouvez également activer les mipmaps sur toutes vos textures 2D. Cependant, l'activation des mipmaps augmentera l'utilisation de la mémoire, ce qui peut être problématique sur les appareils mobiles bas de gamme.

Manipulation des rapports d'aspect

Une fois que vous avez pris en compte la mise à l'échelle pour les différentes résolutions, assurez-vous que votre interface utilisateur est également mise à l'échelle pour les différents ratio d'aspect. Cela peut être fait en utilisant anchors et/ou containers.

Mise à l'échelle du champ de vision

La propriété Keep Aspect du nœud Caméra 3D est par défaut le mode de mise à l'échelle Keep Height (également appelé Hor+). C'est généralement la meilleur valeur pour les jeux de bureau et les jeux mobiles en mode paysage, car les écrans larges utilisent automatiquement un champ de vision plus large.

Cependant, si votre jeu 3D est destiné à être joué en mode portrait, il peut être plus judicieux d'utiliser Keep Width à la place (aussi appelé Vert-). Ainsi, les smartphones dont le rapport hauteur/largeur est supérieur à 16:9 (par exemple 19:9) utiliseront un champ de vision plus grand, ce qui est plus logique ici.

Mettre à l'échelle différemment des éléments 2D et 3D à l'aide de Viewports

En utilisant plusieurs nœuds Viewport, vous pouvez avoir différentes échelles pour divers éléments. Par exemple, vous pouvez utiliser cela pour rendre le monde en 3D à une faible résolution tout en gardant les éléments en 2D à la résolution native. Cela peut améliorer considérablement les performances tout en conservant la netteté du HUD et des autres éléments 2D.

Pour ce faire, on utilise le nœud Viewport racine uniquement pour les éléments 2D, puis on crée un nœud Viewport pour afficher le monde 3D et on l'affiche à l'aide d'un nœud ViewportContainer ou TextureRect. Le projet final comprendra en fait deux viewports. L'un des avantages de l'utilisation de TextureRect par rapport à ViewportContainer est qu'elle permet d'activer le filtrage linéaire. Dans de nombreux cas, cela permet d'améliorer l'aspect des viewports 3D mis à l'échelle.

Voir la démo de mise à l'échelle du viewport 3D pour des exemples.