web-dev-qa-db-fra.com

Superposition sur une application 3D plein écran

Je souhaite afficher des graphiques personnalisés au-dessus d'une application Windows plein écran tierce.

Avez-vous joué à des jeux Steam? Il possède un exécutable, GameOverlayUI.exe, qui vous permet d'accéder aux fenêtres Steam à partir d'un jeu. (Les éléments de l'interface graphique semblent dessinés sur mesure, je ne sais pas si c'est une nécessité; mais ils ont exactement la même apparence dans un jeu que sur le bureau.) Cela va même jusqu'à `` atténuer '' les graphiques du jeu dans l'arrière-plan.

Je me demande comment on pourrait faire pour écrire une telle application.

Je me demande également quelle serait la portée des solutions. Pourriez-vous utiliser une méthode pour toutes les applications OpenGL? Pour toutes les applications Direct3D moins DirectDraw? Pour toutes les applications Windows plein écran?

Je recherche des solutions plus "modernes" et génériques - superposer une invite de commande ou une application couleur indexée 320x240 n'est pas un problème.

Edit: Quelques précisions: l'application plein écran n'est pas la mienne. Ça peut être n'importe quoi. Ce sera probablement un jeu en 3D. Je veux afficher, disons une horloge numérique dans le coin inférieur droit de l'écran, en haut des graphiques du jeu. J'aimerais éviter des astuces telles que l'injection de code ou le débogage du processus, si possible.

42
aib

Eh bien, voici un autre exemple. Xfire est un programme de chat qui superpose son interface dans des jeux afin que vous puissiez recevoir des messages tout en jouant. La façon dont ils le font est d'éditer le d3d/opengl DLL au niveau de la mémoire de processus, comme l'injection de sauts d'assemblage. Je le sais parce que leur méthode faisait planter mon mod, et j'ai vu en fait l'étrange code d'assemblage qu'ils injectaient dans le d3d9.dll.

Voici comment Xfire procède:

  1. cibler le processus du jeu
  2. rechercher dans sa mémoire de processus d3d.dll/opengl.dll
  3. injecter dans le processus un DLL contenant la logique d'interface personnalisée
  4. connecter les fonctions de l'interface au flux du programme en écrivant manuellement les sauts d'assemblage dans les fonctions d3d/opengl présentes dans la mémoire de processus

Il n'y a pas d'autre moyen concevable puisque vous devez détourner le périphérique graphique qui appartient à ce jeu. Je suis prêt à parier que Steam le fait de la même manière que Xfire. Donc, oui, pas de moyen facile de le faire à moins que quelqu'un n'ait créé une bibliothèque utile pour faire tout ce que vous devez faire au niveau bas.

Vous avez également demandé de réduire les graphismes du jeu sous votre superposition. Il s'agit simplement d'un simple appel DrawPrimitive pour dessiner un rectangle transparent rempli sur l'écran.

23
Shaun Lebron

Création d'un Gist avec le code complet ici

C'est un art assez ésotérique, et il existe plusieurs façons de le faire. Je préfère ce qu'on appelle un Direct3D Wrapper. Cela fait des années que je n'ai pas fait ça, mais je l'ai fait avec un jeu une fois. J'ai peut-être omis certains détails, mais j'espère simplement illustrer l'idée.

Tous les jeux Direct3D9 doivent appeler IDirect3DDevice9 :: EndScene une fois l'écran rendu et prêt à être dessiné. Donc en théorie, nous pouvons mettre du code personnalisé dans EndScene qui dessine ce que nous voulons sur le jeu. Nous faisons cela en créant une classe qui ressemble à IDirect3DDevice9 pour le jeu, mais c'est vraiment juste un wrapper qui transfère tous les appels de fonction à la classe réelle. Alors maintenant, dans notre classe personnalisée, notre fonction wrapper pour EndScene ressemble à ceci:

HRESULT IDirect3DDevice9::EndScene()
{
   // draw overlays here

   realDevice.EndScene();
}

Ensuite, nous le compilons dans un DLL appelé d3d9.dll, et le déposons dans le répertoire de l'exécutable du jeu. Le vrai d3d9.dll doit se trouver dans le dossier/system32, mais le jeu regarde d'abord dans le répertoire répertoire actuel, et charge à la place le nôtre. Une fois le jeu chargé, il utilise notre DLL pour créer une instance de notre classe wrapper. Et maintenant, chaque fois que EndScene est appelé, notre code est exécuté pour dessiner ce que nous voulons à l'écran.

Je pense que vous pouvez essayer le même principe avec OpenGL. Mais pour empêcher la falsification, je pense que certains jeux modernes essaient d'empêcher cela.

21
Shaun Lebron

therers un projet de logiciel libre son nom c'est taksi texte du lien . Je ne sais pas comment cette application remplace le processus car je suis en train d'examiner le code, mais vérifiez que je pense que c'est un bon projet

2
Car

J'y ai pensé. Pour OpenGL, j'accrocherais les SwapBuffers de WGL avec Detours, dessinerais mes trucs après le jeu et échangerais ensuite les tampons moi-même.

0
user212277