- Status
- Offline
- Joined
- Mar 3, 2026
- Messages
- 805
- Reaction score
- 457
Stop loading images from disk and bloating your internal with file dependencies.
If you are tired of your menu looking like a generic ImGui paste, adding some custom textures or a logo is the easiest way to give it a unique look. The problem most people face is the DX9 "moment" where colors come out inverted because of the BGRA format requirements. Found this logic while messing around with menu assets, and it is a solid way to bake your data directly into the binary.
The Workflow:
Technical Implementation Notes:
Don't be a clown and recreate this texture every frame. Use std::call_once or a simple null check inside your hkPresent / EndScene hook. If you don't management your objects properly, you'll be staring at a memory leak that will crash the game client faster than a manual ban.
This is a basic but effective way to handle assets without needing an external loader or complex library dependencies in your project settings.
How are you guys handling animated GIFs or multi-frame textures in your internal menus lately?
If you are tired of your menu looking like a generic ImGui paste, adding some custom textures or a logo is the easiest way to give it a unique look. The problem most people face is the DX9 "moment" where colors come out inverted because of the BGRA format requirements. Found this logic while messing around with menu assets, and it is a solid way to bake your data directly into the binary.
The Workflow:
- Grab your PNG and convert it to raw RGBA data (plenty of online converters like convertio for this).
- Open the raw file in HxD and use "Export as C" to get your unsigned char array.
- Implement the swap logic because DX9 is picky about its format.
Code:
void draw_custom_texture(IDirect3DDevice9* device, int width = 124, int height = 130)
{
static IDirect3DTexture9* tex = nullptr;
if (!tex)
{
device->CreateTexture(
img_width,
img_height,
1,
D3DUSAGE_DYNAMIC,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&tex,
NULL
);
D3DLOCKED_RECT rect;
tex->LockRect(0, &rect, NULL, 0);
unsigned char* dst = (unsigned char*)rect.pBits;
unsigned char* src = raw_data_buffer; // Your HxD exported array
// RGBA to BGRA loop for DX9 compatibility
for (int y = 0; y < img_height; y++)
{
unsigned char* drow = dst + y * rect.Pitch;
unsigned char* srow = src + y * img_width * 4;
for (int x = 0; x < img_width; x++)
{
drow[x*4 + 0] = srow[x*4 + 2]; // Blue
drow[x*4 + 1] = srow[x*4 + 1]; // Green
drow[x*4 + 2] = srow[x*4 + 0]; // Red
drow[x*4 + 3] = srow[x*4 + 3]; // Alpha
}
}
tex->UnlockRect(0);
}
ImGui::Image((ImTextureID)tex, ImVec2((float)width, (float)height));
}
Technical Implementation Notes:
Don't be a clown and recreate this texture every frame. Use std::call_once or a simple null check inside your hkPresent / EndScene hook. If you don't management your objects properly, you'll be staring at a memory leak that will crash the game client faster than a manual ban.
— If colors look blue/red shifted: Check your channel swap loop. DX9 expects BGRA in memory for D3DFMT_A8R8G8B8.
— If the image is skewed: Ensure your image width/height matches exactly with the raw buffer size.
— Performance: Creating textures on the fly is heavy. Always initialize once and just call ImGui::Image in your render loop.
— If the image is skewed: Ensure your image width/height matches exactly with the raw buffer size.
— Performance: Creating textures on the fly is heavy. Always initialize once and just call ImGui::Image in your render loop.
This is a basic but effective way to handle assets without needing an external loader or complex library dependencies in your project settings.
How are you guys handling animated GIFs or multi-frame textures in your internal menus lately?