Прежде всего, позвольте мне сразу же извиниться, если на этот вопрос уже есть ответ, потому что я мог бы просто искать его в нестандартных поисковых терминах.
Я хочу рисовать 2D-графику в приложении, которое использует DirectX для рисования собственной графики (игра). Я буду делать это путем внедрения DLL в приложение (эта часть у меня не вызывает вопросов, я могу это сделать) и рисования моей графики. Но я не очень хорош в DirectX / OpenGL, у меня есть пара фундаментальных вопросов.
1) Чтобы нарисовать графику в этом окне, нужно ли мне получать уже существующий контекст из памяти процесса, своего рода дескриптор сцены рисования?
2) Если приложение использует DirectX, могу ли я использовать на нем графику OpenGL?
Пожалуйста, дайте мне знать, как я могу подойти к этому. Любые детали будут оценены 🙂
Заранее спасибо.
«1) Чтобы нарисовать графику в этом окне, нужно ли мне получать уже существующий контекст из памяти процесса, какой-то дескриптор сцены рисования?»
Да, вам нужно убедиться, что ваши хуки перехватывают важные функции создания контекста.
Например, вам интересны все варианты CreateDevice в d3d.
Вы не упомянули, какой DirectX вы используете, но между версиями есть некоторые различия.
Например, в DirectX 9 вас больше всего интересуют функции, которые:
1. Создание / возврат объектов IDirect3DSwapChain9
2. Создать / вернуть объекты IDirect3DDevice9, IDirect3DDevice9Ex
В более новых версиях DirectX их код был разделен на (в основном) Device, DeviceContext, & DXGI.
Если вы выполняете «определенную миссию», сообщите, к какой версии DirectX вы обращаетесь.
Помимо перехвата всех необходимых объектов, чтобы разрешить ваш собственный рендеринг, вы также хотите перехватить все события презентации («SwapBuffers» в GL, «Present» в DX),
Потому что пришло время добавить свой оверлей.
Поскольку кажется, что вы пытаетесь отобразить оверлей поверх приложений DX, позвольте мне предупредить вас, что создать действительно общее решение (которое работает во всех играх) нелегко.
в основном из-за необходимости поддерживать различные версии DX наряду с многочисленными способами создания
Если вы сосредоточены на конкретной игре / приложении, это, естественно, намного проще.
«2. Если приложение использует DirectX, могу ли я использовать на нем графику OpenGL?»
Ну, во-первых, да. Возможно.
Терминология, которую вы хотите найти, — совместимость OpenGL DirectX (или короткое взаимодействие).
Вот пример:
https://sites.google.com/site/snippetsanddriblits/OpenglDxInterop
Я не знаю, доступно ли расширение, которое они использовали, только на устройствах nVidia или нет — проверьте его.
Еще одна вещь, связанная с этим, заключается в том, что для этого вам нужна действительно хорошая мотивация, как правило, я бы просто использовал DX для подключения и рендеринга.
Я предполагаю, что внутреннее взаимодействие между различными версиями DX является лучшим вариантом.
Лично я бы, вероятно, пошел с DirectX9 для вашего собственного кода рендеринга.
Конечно, если вам нужна поддержка только одной версии DirectX, взаимодействие не требуется.
Бонус:
Если вам когда-нибудь понадобится сгенерировать полные обертки классов C ++, быстрый и грязный обертка dll или просто глобальный хук функций, можете использовать эту библиотеку, которую я создал:
http://code.google.com/p/hookit/
Это далеко не полностью протестированный инструмент, просто что-то, что я взломал за 2 дня, но я нашел его очень полезным.
Обратите внимание, что в вашем случае я рекомендую просто использовать перехват VTable, вам, вероятно, придется жестко закодировать смещение функции в таблице, но это вряд ли изменится.
Удачи 🙂
Ваш подход к внедрению DLL действительно правильный путь. Такие программы, как FRAPS использовать тот же подход. Я не могу рассказать вам о методе для Direct3D, но для OpenGL вы должны сделать следующее:
Сначала вы должны подключиться к функциям wglMakeCurrent
, glFinish
а также wglSwapBuffers
из opengl32.dll
так что ваша DLL замечает, когда для рисования выбран контекст OpenGL. Передайте их звонки в ОС. когда wglMakeCurrent
называется использовать функцию GetPixelFormat
чтобы узнать, является ли окно двойной буферизацией или нет. Также используйте glGet…
OpenGL звонит, чтобы узнать, с какой версией контекста OpenGL вы имеете дело. В случае, если у вас есть унаследованный контекст OpenGL, вы должны использовать другие методы для рисования оверлея, чем для современного базового контекста OpenGL-3 или новее.
В случае двойного буферизованного окна используйте ваш крючок на wglSwapBuffers
выполнить дальнейшие операции рисования OpenGL. OpenGL — это просто перья и кисти (в виде точек, линий и треугольников), рисующие на холсте. Затем пройдите через wglSawpBuffers
позвоните, чтобы сделать все видимым.
В случае одного буферизованного контекста вместо wglSwapBuffers
функция для подключения glFinish
,
Рисовать 2D с помощью OpenGL так же просто, как отключить буферизацию глубины и использовать матрицу ортографической проекции. Вы можете изменить состояние OpenGL, когда захотите. Просто убедитесь, что вы восстановили все в исходное состояние, прежде чем покинуть крючки.