ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
60.95k stars 10.29k forks source link

Dx9 and Dx11 load and render same image #6346

Closed Huan912 closed 1 year ago

Huan912 commented 1 year ago

Version: 1.89.3 Branch: master

Back-end/Renderer/Compiler/OS

Back-ends: (imgui_impl_dx11.cpp and imgui_impl_dx9.cpp) + imgui_impl_win32.cpp Compiler: Visual Studio C++ 2022 Operating System: Windows 10 x64 21H2

My Issue/Question: As in the title, I am rendering the same image in both engines, and following the example on the imgui documentation. My problem is that I don't know why and the images rendered by DirectX9 are very unclear (low quality and blur) and the resolution of the read-in image file is always 1024x1024, The correct size of the image should be 1000x563, Even if I force the image to be rendered as 1000x563, the image will be unclear.

Screenshots/Video DirectX9: image

DirectX11: image

DirectX9 (Force resize image size): image

Code - DirectX9

LoadTextureFromFile("TestRender.png", &my_texture, &my_image_width, &my_image_height);

ImGui::Begin("DirectX9 Texture Test");
ImGui::Text("pointer = %p", my_texture);
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
ImGui::Image((void*)my_texture, ImVec2(my_image_width, my_image_height));
ImGui::End();

Code - DirectX11

LoadTextureFromFile("TestRender.png", &my_texture, &my_image_width, &my_image_height);

ImGui::Begin("DirectX11 Texture Test");
ImGui::Text("pointer = %p", my_texture);
ImGui::Text("size = %d x %d", my_image_width, my_image_height);
ImGui::Image((void*)my_texture, ImVec2(my_image_width, my_image_height));
ImGui::End();
Huan912 commented 1 year ago

I tried imgui-1.89.5 and the problem still exists image

ocornut commented 1 year ago

It is likely that DX9 textures needs to be power of two in your hw/sw setup, or the and our wiki sample loading functions doesn't accommodate for it. None of this is really related to dear imgui but if you find a fix we can contemplate adding note in our example.

Also see e.g. https://gamedev.net/forums/topic/446610-how-do-you-get-the-width-and-height-from-a-lpdirect3dtexture9/446610/ https://gamedev.net/forums/topic/650787-how-to-get-texture-width-and-size/5114247/ https://www.gamedev.net/forums/topic/294380-direct3d-dx9-and-texture-dimensionspower-of-two/ https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxcreatetexturefromfileex

Try to get the texture size and fill *out_width / *out_height with it instead. This is already what we are doing with the GetLevelDesc() call.

Huan912 commented 1 year ago

@ocornut Thank you very much for your answer, I tried to use photoshop to change the image size to 1024x1024 (2's square), but the result is still the same

On Photoshop image

ocornut commented 1 year ago

I'll have to close this because we can't debug your usage of D3DXCreateTextureFromFileA() here, it's not really a Dear ImGui problem. Please investigate links above and post your DX9 caps. If you have suggestion how to further improve the Wiki entry we're happy to read them, but that wiki is mainly a help to get people started with graphics programming and we are not providing a complete engine here, for obvious reasons.

Huan912 commented 1 year ago

Thanks Problem has benn resolve, just change D3DXCreateTextureFromFile to D3DXCreateTextureFromFileExA and fill in "D3DX_DEFAULT_NONPOW2" for Width and Height. I hope this can help people who have the same trouble as me!!!

bool LoadTextureFromFile(const char* filename, PDIRECT3DTEXTURE9* out_texture, int* out_width, int* out_height)
{
    // Load texture from disk
    PDIRECT3DTEXTURE9 texture;
    D3DXIMAGE_INFO info;
    HRESULT hr = D3DXCreateTextureFromFileExA(
        g_pd3dDevice,
        filename,
        D3DX_DEFAULT_NONPOW2,
        D3DX_DEFAULT_NONPOW2,
        D3DX_DEFAULT,
        0,
        D3DFMT_UNKNOWN,
        D3DPOOL_MANAGED,
        D3DX_DEFAULT,
        D3DX_DEFAULT,
        0,
        &info,
        NULL,
        &texture
    );

    if (hr != S_OK)
        return false;

    // Retrieve description of the texture surface so we can access its size
    *out_texture = texture;
    *out_width = (int)info.Width;
    *out_height = (int)info.Height;
    return true;
}