Плохой рендер CEF

nonelike

Известный
Автор темы
54
2
plugin.hpp:
#ifndef PLUGIN_HPP
#define PLUGIN_HPP

#include <windows.h>

#include <kthook/kthook.hpp>
#include <RakHook/rakhook.hpp>

#include "overlay.hpp"

using namespace std::placeholders;


class c_plugin {

public:
    c_plugin() = default;
    ~c_plugin() { rakhook::destroy(); render::destroy(); overlay::destroy(); };

    kthook::kthook_simple<void(__cdecl*)()> update_hook { reinterpret_cast<void*>(0x561B10), std::bind(&c_plugin::update_hooked, this, _1) };
    void update_hooked(const decltype(update_hook)& hook);

    kthook::kthook_simple<HRESULT(__stdcall*)(HWND, UINT, WPARAM, LPARAM)> wnd_proc_hook{ reinterpret_cast<void*>(0x747EB0), std::bind(&c_plugin::wnd_proc_hooked, this, _1, _2, _3, _4, _5) };
    HRESULT wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
};


#endif // PLUGIN_HPP
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>

#include "include/cef_app.h"
#include "render.hpp"


class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {

public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override { this->browser = browser; }
 
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 840, 660); };
 
    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;

    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};


namespace overlay {
    inline static c_overlay* cef;

    inline LPDIRECT3DTEXTURE9 texture;

    void initialize();
 
    void create_browser(std::string url = "https://url.com");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);

    void destroy();
}


#endif // !OVERLAY_HPP
plugin.cpp:
#include "plugin.hpp"


void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
     
        overlay::initialize();
        render::initialize();
     
        render::on_present += []() {
            if (!overlay::texture || !render::device)
                return;

            render::device->SetTexture(0, overlay::texture);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                FLOAT u, v;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));
        };
    }
    return hook.call_trampoline();
}


HRESULT c_plugin::wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    overlay::wnd_proc(hwnd, umsg, wp, lp);

    return hook.call_trampoline(hwnd, umsg, wp, lp);
}

overlay.cpp:
#include "overlay.hpp"


void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    if (!overlay::texture)
        D3DXCreateTexture(render::device, width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &overlay::texture);

    D3DLOCKED_RECT locked_rect;
 
    overlay::texture->LockRect(0, &locked_rect, nullptr, 0);
    memcpy(locked_rect.pBits, buffer, width * height * 4);

    overlay::texture->UnlockRect(0);
}


void overlay::create_browser(std::string url) {
    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;

    window_info.SetAsWindowless(nullptr);
 
    CefBrowserHost::CreateBrowser(window_info, cef, url.c_str(), browser_settings, nullptr, nullptr);
}


void overlay::initialize() {
    cef = new c_overlay();
 
    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cache");

    CefSettings settings;
 
    CefString(&settings.browser_subprocess_path).FromASCII(std::string(work_path + "\\cef-sub-process.exe").c_str());
    CefString(&settings.log_file) = work_path + "\\cef-log.log";
    CefString(&settings.cache_path).FromASCII(std::string(work_path + "\\cache").c_str());
    CefString(&settings.locales_dir_path).FromASCII(std::string(work_path + "\\locales").c_str());
    CefString(&settings.resources_dir_path) = work_path;
    CefString(&settings.locale).FromASCII("ru");
    CefString(&settings.accept_language_list).FromASCII("en-US,en,ru-RU,ru");

    settings.no_sandbox = 1;
    settings.multi_threaded_message_loop = 1;
    settings.windowless_rendering_enabled = 1;

    settings.background_color = 0;
    settings.log_severity = LOGSEVERITY_DEBUG;
    settings.command_line_args_disabled = 1;

    CefMainArgs main_args;

    CefInitialize(main_args, settings, nullptr, nullptr);
 
    create_browser();
}


bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (cef && cef->GetBrowser()) {
        CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

        if (umsg >= WM_MOUSEMOVE && umsg <= WM_MBUTTONUP || umsg == WM_MOUSEWHEEL) {
            POINT point = { LOWORD(lp), HIWORD(lp) };
            ScreenToClient(hwnd, &point);

            CefMouseEvent mouse_event;
         
            mouse_event.x = point.x;
            mouse_event.y = point.y;
            mouse_event.modifiers = 0;

            switch (umsg) {
                case WM_LBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); break;
                case WM_LBUTTONUP:   host->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1); break;
                case WM_RBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1); break;
                case WM_RBUTTONUP:   host->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1); break;
                case WM_MBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_MIDDLE, false, 1); break;
                case WM_MBUTTONUP:   host->SendMouseClickEvent(mouse_event, MBT_MIDDLE, true, 1); break;
                case WM_MOUSEWHEEL: {
                    int delta = GET_WHEEL_DELTA_WPARAM(wp);
                    host->SendMouseWheelEvent(mouse_event, 0, delta);
                    break;
                }
                default: {
                    host->SendMouseMoveEvent(mouse_event, false);
                    break;
                }
            }
            return true;
        }

        if (umsg >= WM_KEYDOWN && umsg <= WM_CHAR) {
            int keycode = static_cast<int>(wp);
            int modifiers = 0;

            if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= EVENTFLAG_SHIFT_DOWN;
            if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= EVENTFLAG_CONTROL_DOWN;
            if (GetKeyState(VK_MENU) & 0x8000) modifiers |= EVENTFLAG_ALT_DOWN;

            CefKeyEvent event;
         
            event.windows_key_code = keycode;
            event.native_key_code = static_cast<int>(lp);
            event.modifiers = modifiers;

            if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) { event.type = KEYEVENT_RAWKEYDOWN; }
            else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) { event.type = KEYEVENT_KEYUP; }
            else if (umsg == WM_CHAR) { event.type = KEYEVENT_CHAR; }

            host->SendKeyEvent(event);

            return true;
        }
    }
    return false;
}


void overlay::destroy() {
    CefShutdown();
 
    if (texture)
        texture->Release();
 
    delete cef;
}

main.cpp:
#include "plugin.hpp"

c_plugin* plugin;


int __stdcall DllMain(HMODULE instance, DWORD call_reason, LPVOID reserved) {

    if (call_reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(instance);

        plugin = new c_plugin();
    }
    else if (call_reason == DLL_PROCESS_DETACH)
        delete plugin;

    return TRUE;
}

render.hpp:
#ifndef RENDER_HPP
#define RENDER_HPP

#include <imgui_impl_dx9.h>
#include <imgui_impl_win32.h>
#include <imgui_internal.h>

#include <d3d9.h>
#include <d3dx9.h>

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

#include "kthook/kthook.hpp"

#include "samp.hpp"


namespace render {
    template <typename T>
    struct on_event : public std::vector<std::function<T>> {
        on_event& operator+=(std::function<T> func) {
            this->push_back(func);
            return *this;
        }
    };
    inline on_event<void()> on_present;

    inline bool initialized = false;

    inline IDirect3DDevice9* device;

    void initialize();
    void destroy();
}

#endif // !RENDER_HPP

render.cpp:
#include "render.hpp"
#include "overlay.hpp"

kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, const RECT*, const RECT*, HWND, const RGNDATA*)> present_hook;
kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*)> reset_hook;


std::optional<HRESULT> d3d9_present_hooked(const decltype(present_hook)& hook, IDirect3DDevice9* device, CONST RECT* src_rect, CONST RECT* dest_rect, HWND dest_window, CONST RGNDATA* dirty_region) {
    if (!render::initialized) {
        render::device = device;
        render::initialized = true;
    }
    else {
        for (auto& f : render::on_present) {
            if (f) f();
        }
    }
    return std::nullopt;
}


std::optional<HRESULT> d3d9_lost_hooked(const decltype(reset_hook)& hook, LPDIRECT3DDEVICE9 device, D3DPRESENT_PARAMETERS* present_params) {
    return std::nullopt;
}


uintptr_t find_device(uint32_t length) {
    static uintptr_t base = [](size_t length) {
        std::string path(MAX_PATH, '\0');

        if (auto size = GetSystemDirectoryA(path.data(), MAX_PATH)) {
            path.resize(size);
            path += "\\d3d9.dll";

            uintptr_t object_base = reinterpret_cast<uintptr_t>(LoadLibraryA(path.c_str()));

            while (object_base++ < object_base + length) {
                if (*reinterpret_cast<uint16_t*>(object_base + 0x00) == 0x06C7 && *reinterpret_cast<uint16_t*>(object_base + 0x06) == 0x8689 && *reinterpret_cast<uint16_t*>(object_base + 0x0C) == 0x8689) {
                    object_base += 2;

                    break;
                }
            }
            return object_base;
        }
        return uintptr_t(0);
    }(length);

    return base;
}


void* get_function_address(int virtual_table_index) {
    return (*reinterpret_cast<void***>(find_device(0x128000)))[virtual_table_index];
}


void render::initialize() {
    present_hook.set_dest(get_function_address(17));
    present_hook.install();
 
    reset_hook.set_dest(get_function_address(16));
    reset_hook.install();

    present_hook.before.connect(&d3d9_present_hooked);
    reset_hook.before.connect(&d3d9_lost_hooked);
}


void render::destroy() {
}

Увидел как-то на форуме CEF который отрисовывается на imgui, решил переделать в отрисовку через directx9, но плохо рендерится(текст, мыло и все пикселится, появляется черная обводка которой нет) и ломает ESC.
 

Вложения

  • sa-mp-010.png
    sa-mp-010.png
    71.6 KB · Просмотры: 126
  • sa-mp-009.png
    sa-mp-009.png
    1.2 MB · Просмотры: 123

vmprotect

Известный
388
251
насчет фикса рендеринга

в overlay.hpp ты указываешь размер

Код:
void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 1920, 1080); }; /* на месте 1920, 1080 указывать свое разрешение

ваще можно через imgui получать твое текущее разрешение, и туда вписывать
 

nonelike

Известный
Автор темы
54
2
насчет фикса рендеринга

в overlay.hpp ты указываешь размер

Код:
void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 1920, 1080); }; /* на месте 1920, 1080 указывать свое разрешение

ваще можно через imgui получать твое текущее разрешение, и туда вписывать
ну я ща в GetViewRect поменял на свое разрешение монитора, и в вершинах тоже, но чето рендеру все равно плохо
 

Вложения

  • sa-mp-012.png
    sa-mp-012.png
    1.7 MB · Просмотры: 107
Последнее редактирование:

dmitry.karle

Известный
359
100
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>
#include <include/cef_app.h>
#include "render.hpp"

class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override { this->browser = browser; }
 
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type,
                const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override {
        rect = CefRect(0, 0, 840, 660);
    };
 
    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;

    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};

namespace overlay {
    inline static c_overlay* cef;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;

    void initialize();
    void create_browser(std::string url = "https://url.com");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
    void destroy();
}

#endif // !OVERLAY_HPP

overlay.cpp:
#include "overlay.hpp"

void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    if (!overlay::texture || width != overlay::texture_width || height != overlay::texture_height) {
        if (overlay::texture) {
            overlay::texture->Release();
            overlay::texture = nullptr;
        }
      
        if (D3DXCreateTexture(render::device, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &overlay::texture) == D3D_OK) {
            overlay::texture_width = width;
            overlay::texture_height = height;
        } else {
            return;
        }
    }

    D3DLOCKED_RECT locked_rect;
    if (overlay::texture->LockRect(0, &locked_rect, nullptr, D3DLOCK_DISCARD) == D3D_OK) {
        for (int y = 0; y < height; ++y) {
            const uint8_t* src = static_cast<const uint8_t*>(buffer) + y * width * 4;
            uint8_t* dst = static_cast<uint8_t*>(locked_rect.pBits) + y * locked_rect.Pitch;
            memcpy(dst, src, width * 4);
        }
        overlay::texture->UnlockRect(0);
    }
}

void overlay::create_browser(std::string url) {
    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;
  
    browser_settings.windowless_frame_rate = 60;
    window_info.SetAsWindowless(nullptr);
 
    CefBrowserHost::CreateBrowser(window_info, cef, url.c_str(), browser_settings, nullptr, nullptr);
}

void overlay::initialize() {
    cef = new c_overlay();
 
    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cache");

    CefSettings settings;
    settings.windowless_rendering_enabled = true;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = true;
    settings.background_color = 0x00000000; // Fully transparent
  
    CefString(&settings.browser_subprocess_path).FromASCII((work_path + "\\cef-sub-process.exe").c_str());
    CefString(&settings.cache_path).FromASCII((work_path + "\\cache").c_str());
    CefString(&settings.locales_dir_path).FromASCII((work_path + "\\locales").c_str());
    CefString(&settings.resources_dir_path) = work_path;
    CefString(&settings.locale).FromASCII("ru");
    CefString(&settings.accept_language_list).FromASCII("en-US,en,ru-RU,ru");

    CefMainArgs main_args;
    CefInitialize(main_args, settings, nullptr, nullptr);
 
    create_browser();
}

bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (!cef || !cef->GetBrowser())
        return false;

    CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

    if (umsg >= WM_MOUSEFIRST && umsg <= WM_MOUSELAST) {
        POINT point = { LOWORD(lp), HIWORD(lp) };
        ScreenToClient(hwnd, &point);

        CefMouseEvent mouse_event;
        mouse_event.x = point.x;
        mouse_event.y = point.y;
      
        if (umsg == WM_MOUSEWHEEL) {
            int delta = GET_WHEEL_DELTA_WPARAM(wp);
            host->SendMouseWheelEvent(mouse_event, 0, delta);
            return true;
        }
      
        if (umsg >= WM_LBUTTONDOWN && umsg <= WM_MBUTTONUP) {
            cef_mouse_button_type_t button = MBT_LEFT;
            if (umsg == WM_RBUTTONDOWN || umsg == WM_RBUTTONUP) button = MBT_RIGHT;
            else if (umsg == WM_MBUTTONDOWN || umsg == WM_MBUTTONUP) button = MBT_MIDDLE;
          
            bool is_up = (umsg == WM_LBUTTONUP || umsg == WM_RBUTTONUP || umsg == WM_MBUTTONUP);
            host->SendMouseClickEvent(mouse_event, button, is_up, 1);
            return true;
        }
      
        host->SendMouseMoveEvent(mouse_event, false);
        return true;
    }

    if (umsg >= WM_KEYFIRST && umsg <= WM_KEYLAST) {
        CefKeyEvent event;
        event.windows_key_code = static_cast<int>(wp);
        event.native_key_code = static_cast<int>(lp);
      
        event.modifiers = 0;
        if (GetKeyState(VK_SHIFT) & 0x8000) event.modifiers |= EVENTFLAG_SHIFT_DOWN;
        if (GetKeyState(VK_CONTROL) & 0x8000) event.modifiers |= EVENTFLAG_CONTROL_DOWN;
        if (GetKeyState(VK_MENU) & 0x8000) event.modifiers |= EVENTFLAG_ALT_DOWN;
      
        if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) {
            event.type = KEYEVENT_RAWKEYDOWN;
        } else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) {
            event.type = KEYEVENT_KEYUP;
        } else if (umsg == WM_CHAR) {
            event.type = KEYEVENT_CHAR;
        }
      
        if (event.windows_key_code == VK_ESCAPE && event.type == KEYEVENT_RAWKEYDOWN) {
            return false; // Let the game process ESC
        }
      
        host->SendKeyEvent(event);
        return true;
    }
  
    return false;
}

void overlay::destroy() {
    if (texture) {
        texture->Release();
        texture = nullptr;
    }
  
    CefShutdown();
    delete cef;
    cef = nullptr;
}

plugin.cpp:
void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
        overlay::initialize();
        render::initialize();
  
        render::on_present += []() {
            if (!overlay::texture || !render::device)
                return;

            DWORD old_z_enable, old_alpha_blend, old_src_blend, old_dest_blend, old_lighting;
            render::device->GetRenderState(D3DRS_ZENABLE, &old_z_enable);
            render::device->GetRenderState(D3DRS_ALPHABLENDENABLE, &old_alpha_blend);
            render::device->GetRenderState(D3DRS_SRCBLEND, &old_src_blend);
            render::device->GetRenderState(D3DRS_DESTBLEND, &old_dest_blend);
            render::device->GetRenderState(D3DRS_LIGHTING, &old_lighting);

            render::device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);

            render::device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                DWORD color;
                FLOAT u, v;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
            render::device->SetTexture(0, overlay::texture);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));

            render::device->SetRenderState(D3DRS_ZENABLE, old_z_enable);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, old_alpha_blend);
            render::device->SetRenderState(D3DRS_SRCBLEND, old_src_blend);
            render::device->SetRenderState(D3DRS_DESTBLEND, old_dest_blend);
            render::device->SetRenderState(D3DRS_LIGHTING, old_lighting);
        };
    }
    return hook.call_trampoline();
}
проверь и исправь под себя😐
 
Последнее редактирование: