windows - tag - Superposición en una aplicación 3D a pantalla completa
tag folders (5)
Bueno, aquí hay otro ejemplo. Xfire es un programa de chat que superpone su interfaz en juegos para que puedas recibir mensajes mientras juegas. La forma en que lo hacen es editando la DLL d3d / opengl en el nivel de memoria de proceso, como inyectar saltos de ensamblaje. Lo sé porque su método estaba causando que mi mod se bloquee, y realmente vi el extraño código de ensamblado que estaban inyectando en el d3d9.dll.
Así que aquí es cómo Xfire hace esto:
- apuntar al proceso del juego
- busca en su memoria de proceso para d3d.dll / opengl.dll
- inyectar en el proceso una DLL que contiene la lógica de la interfaz personalizada
- conecte las funciones de la interfaz al flujo del programa escribiendo manualmente saltos de ensamblaje en las funciones d3d / opengl encontradas en la memoria de proceso
No hay otra forma concebible ya que es necesario secuestrar el dispositivo gráfico que pertenece a ese juego. Estoy dispuesto a apostar que Steam lo hace de la misma manera que Xfire. Así que sí, no es una forma fácil de hacerlo a menos que alguien haya creado una biblioteca útil para hacer todo lo que necesita hacer en el nivel bajo.
También preguntaste sobre atenuar los gráficos del juego debajo de tu superposición. Esta es solo una simple llamada DrawPrimitive
para dibujar un rectángulo transparente lleno sobre la pantalla.
Quiero mostrar algunos gráficos personalizados sobre una aplicación de Windows de tercera parte de pantalla completa.
¿Has jugado algún juego de Steam? Tiene un ejecutable, GameOverlayUI.exe que te permite acceder a las ventanas de Steam desde dentro de un juego. (Los elementos de la GUI parecen dibujados a medida, no sé si eso es necesario, pero se ven exactamente igual dentro de un juego que en el escritorio). Incluso llega a oscurecer los gráficos del juego en el fondo.
Me pregunto cómo se podría escribir una aplicación así.
También me pregunto qué tan amplio sería el alcance de las soluciones. ¿Podría usar un método para todas las aplicaciones OpenGL? Para todas las aplicaciones Direct3D menos DirectDraw? Para todas las aplicaciones de Windows a pantalla completa?
Estoy buscando soluciones más ''modernas'' y genéricas: superponer un símbolo del sistema o una aplicación de color indexada de 320x240 no es una preocupación.
Editar: Algunas aclaraciones: la aplicación de pantalla completa no es mía. Puede ser cualquier cosa. Lo más probable es que sea un juego en 3D. Quiero mostrar, digamos un reloj digital en la esquina inferior derecha de la pantalla, en la parte superior de los gráficos del juego. Me gustaría evitar trucos como inyectar código o depurar el proceso, si es posible.
He estado pensando en esto. Para OpenGL, conectaría SwapBuffers de WGL con Detours, dibujaría mis cosas después del juego y luego intercambiaría búferes yo mismo.
He hecho superposiciones tanto con viewports de DirectX como de WPF (lo mismo, realmente), usando la superposición para pintar algunas cosas bonitas de 2D GDI + además de visualizaciones 3D.
Lo logré usando un panel en la parte superior de la visualización "real", estableciendo el color en transparente a excepción de los bits que quería superpuestos. Funcionó bastante bien, pero fue un poco doloroso pasar clic, arrastre y otros eventos a través de la capa de "dibujo" al control 3D.
existe un proyecto de software libre, su nombre es texto de enlace taksi. No estoy seguro de cómo esta aplicación anula el proceso porque todavía estoy examinando el código, pero compruebe que este es un buen proyecto
Creado un Gist con código completo here
Este es un arte bastante esotérico, y hay varias formas de hacerlo. Prefiero lo que se llama una envoltura Direct3D . Han pasado años desde que hice esto, pero lo hice con un juego una vez. Puede que haya omitido algunos detalles, pero solo espero ilustrar la idea.
Todos los juegos de Direct3D9 deben llamar a IDirect3DDevice9::EndScene después de que la pantalla se represente y esté lista para dibujarse. Entonces, en teoría, podemos poner código personalizado dentro de EndScene
que dibuje lo que queremos sobre el juego. Hacemos esto creando una clase que se parece a IDirect3DDevice9 para el juego, pero en realidad es solo un contenedor que reenvía todas las llamadas a la clase real. Así que ahora, en nuestra clase personalizada, nuestra función de envoltura para EndScene
ve así:
HRESULT IDirect3DDevice9::EndScene()
{
// draw overlays here
realDevice.EndScene();
}
Luego lo compilamos en un archivo DLL llamado d3d9.dll y lo colocamos en el directorio del ejecutable del juego. El archivo d3d9.dll real debe estar en la carpeta / system32, pero el juego primero se ve en el directorio actual y, en su lugar, carga el nuestro. Una vez que se carga el juego, utiliza nuestra DLL para crear una instancia de nuestra clase contenedora. Y ahora cada vez que se llama EndScene
, nuestro código se ejecuta para dibujar lo que queremos para la pantalla.
Creo que puedes probar el mismo principio con OpenGL. Pero para evitar manipulaciones, creo que algunos juegos modernos intentan evitar esto.