- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 538
- Реакции
- 14
External софт и «плавающие» боксы — классическая боль любого кодера. Часто при написании внешнего чита на ImGui (особенно на древнем D3D9) можно заметить, что ESP неприятно отстает от моделей игроков при резких движениях камеры. Обычно это списывают на плохую оптимизацию, но корень зла кроется в дефолтной вертикальной синхронизации и кривых таймингах.
Суть проблемы
По умолчанию DirectX может использовать D3DPRESENT_INTERVAL_ONE, что заставляет оверлей ждать обновления монитора. Вкупе со стандартным Sleep() в главном цикле это дает дикую задержку, из-за которой боксы буквально гуляют по экрану отдельно от игры.
Решение
Нужно принудительно отключить лимиты FPS на уровне инициализации девайса и реализовать прецизионный контроль кадров через std::chrono. Это уберет «желейность» отрисовки.
1. Настройка инициализации (D3D9)
Выставляем немедленный вывод кадра в параметрах презентации:
2. Оптимизация Main Loop
Вместо того чтобы грузить процессор бесконечным циклом или использовать неточный системный таймер, реализуем стабильный лимит (например, 300 FPS). Это даст плавную картинку без лишнего оверхеда.
Почему это тащит:
Метод универсален и легко адаптируется под D3D11/12 через флаги SwapChain, если вы до сих пор сидите на старых базах.
Интересно будет глянуть на тесты этого костыля в тяжелых проектах типа Таркова, где любая задержка кадра критична.
Суть проблемы
По умолчанию DirectX может использовать D3DPRESENT_INTERVAL_ONE, что заставляет оверлей ждать обновления монитора. Вкупе со стандартным Sleep() в главном цикле это дает дикую задержку, из-за которой боксы буквально гуляют по экрану отдельно от игры.
Решение
Нужно принудительно отключить лимиты FPS на уровне инициализации девайса и реализовать прецизионный контроль кадров через std::chrono. Это уберет «желейность» отрисовки.
1. Настройка инициализации (D3D9)
Выставляем немедленный вывод кадра в параметрах презентации:
Код:
D3DPRESENT_PARAMETERS Params = { 0 };
Params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Убираем V-Sync
Params.FullScreen_RefreshRateInHz = 0; // Сбрасываем рефрешрейт до дефолта
2. Оптимизация Main Loop
Вместо того чтобы грузить процессор бесконечным циклом или использовать неточный системный таймер, реализуем стабильный лимит (например, 300 FPS). Это даст плавную картинку без лишнего оверхеда.
Код:
const int TARGET_FPS = 300;
const auto FRAME_DURATION = std::chrono::microseconds(1000000 / TARGET_FPS); // Шаг в 3.33 мс
auto last_time = std::chrono::high_resolution_clock::now();
while (true)
{
auto current_time = std::chrono::high_resolution_clock::now();
if (current_time - last_time >= FRAME_DURATION) {
RenderFrame();
last_time += FRAME_DURATION;
}
// Здесь можно воткнуть минимальный Sleep(1) для разгрузки потока,
// но для максимального отклика лучше крутить чистый цикл.
}
Почему это тащит:
- Immediate Presentation Interval убирает инпут-лаг самого оверлея.
- Таргет в 300 FPS позволяет отрисовывать ESP чаще, чем обновляется типичный монитор (144/240Hz), что визуально «приклеивает» боксы к моделям.
- Использование high_resolution_clock дает микросекундную точность, которую не выжать из обычного WinAPI.
Метод универсален и легко адаптируется под D3D11/12 через флаги SwapChain, если вы до сих пор сидите на старых базах.
Интересно будет глянуть на тесты этого костыля в тяжелых проектах типа Таркова, где любая задержка кадра критична.