ImGui基于DX11加载/显示图片教程

2024-08-15 00:38:42 浏览数 (2)

前言

关于Imgui显示图片,在网上搜到的教程都不符合我的DX11下显示图片的要求故写此文

这是一个关于ImGui基于DX11下加载图片的教程

因为我现在也找不到DX11 Lib 和Include的下载路径,所以这里会提供一个github地址里面有我的DX11相关文件,和以下代码演示例的源代码。(如果有人能提供相应的下载路径万分感谢)

https://github.com/QWQcool/ImGuiDx11LoadImgExample

理论上来说能找到系统的DX11 lib 和include 也是可行的

不过现在一般都是DX12,应该需要选用DX12版本的Imgui。

另外其它的图形 API 和渲染平台后端之类的可能也需要自己的官方lib和include 我所提供的方式不一定适用,仅供参考~

DX11版本的Imgui导入示例可以参考这个

Windows下ImGui的快速使用介绍至项目建立(VS,DX11)原创


1.首先通过github地址下载这个DX11文件

位于github提供地址里的

ImGuiDx11LoadImgExample/src/位置

下载后如图所示

接着笔者是将DX11放在项目里了,如图所示

给项目添加附加包含目录

给项目添加附加库目录

导入必要的头文件

代码语言:cpp复制
#include <d3d11.h>

#pragma comment(lib,"d3d11.lib")

#include <D3DX11.h>
#ifdef _DEBUG
#pragma comment(lib,"d3dx11d.lib")
#else
#pragma comment(lib,"d3dx11.lib")
#endif // DEBUG

图形处理的相关cpp文件

代码语言:cpp复制
//DX11加载图片  具体实现放在Main里了
ID3D11ShaderResourceView* DX11LoadTextureImageFromFile(ID3D11Device* pD3dDevice, const char* lpszFilePath);

void* LoadImageEx(const char* path);

ID3D11ShaderResourceView* DX11LoadTextureImageFromFile(ID3D11Device* pD3dDevice, const char* lpszFilePath)
{

	ID3D11Texture2D* pTexture2D = NULL;
	D3D11_TEXTURE2D_DESC dec;


	HRESULT result;
	D3DX11_IMAGE_LOAD_INFO loadInfo;
	ZeroMemory(&loadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO));
	loadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE;
	loadInfo.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	loadInfo.MipLevels = 0; //这时会产生最大的mipmaps层。 
	loadInfo.MipFilter = D3DX11_FILTER_LINEAR;
	result = D3DX11CreateTextureFromFileA(pD3dDevice, lpszFilePath
		, &loadInfo, NULL, (ID3D11Resource**)(&pTexture2D), NULL);
	pTexture2D->GetDesc(&dec);
	if (result != S_OK)
	{
		return NULL;
	}

	ID3D11ShaderResourceView* pFontTextureView = NULL;

	// Create texture view
	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
	ZeroMemory(&srvDesc, sizeof(srvDesc));
	srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	srvDesc.Texture2D.MipLevels = dec.MipLevels;
	srvDesc.Texture2D.MostDetailedMip = 0;
	pD3dDevice->CreateShaderResourceView(pTexture2D, &srvDesc, &pFontTextureView);


	return pFontTextureView;
}

//加载图片路径用
void* LoadImageEx(const char* path)
{
	return DX11LoadTextureImageFromFile(g_pd3dDevice, path);
}

这两个函数的具体实现建议放在官方的main函数示例里,不然缺少什么都要自己引入。

DX11LoadTextureImageFromFile是用来跟Imgui交互渲染的函数,需要跟Imgui的相关函数放一起。

LoadImageEx是用来跟存储图片路径交互的函数,将图片所在路径传入即可,会返回一个指向该图片的void*指针。

这个Void* 指针用来跟 Imgui官方的ImGui::Image()进行交互

演示例

ImageLoadExample.cpp

代码语言:cpp复制
#include "ImguiAll.h" 
#include <iostream>   
#include <string>    
#define ImageIndex 7 // 定义图片索引常量,表示要加载的图片数量

static int sg_imageIndex = 0; // 定义全局变量,用于存储当前显示的图片索引

static void* sg_imageS[ImageIndex] = { nullptr }; // 定义全局数组,用于存储加载的图片指针

// 初始化图片函数,加载所有图片并存储在sg_imageS数组中
void ImageInit()
{
	static bool imageLoaded = false; // 定义静态变量,用于判断图片是否已加载
	if (imageLoaded) // 如果图片已加载,直接返回
	{
		return;
	}
	imageLoaded = true; // 设置图片已加载标志为true

	std::string imgPath = "./src/Image/"; // 定义图片路径前缀

	// 遍历所有图片索引,加载对应的图片
	for (int i = 0; i < ImageIndex; i  )
	{
		std::string imgIndex = imgPath   std::to_string(i   1)   ".jpg"; // 构建图片完整路径
		sg_imageS[i] = LoadImageEx(imgIndex.c_str()); // 加载图片并存储在数组中
	}
}

// 显示图片的示例函数
void ExampleImageLoad()
{
	ImVec2 center = ImGui::GetMainViewport()->GetCenter(); // 获取主视口中心点坐标

	// 设置窗口位置和大小
	ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
	ImGui::SetNextWindowSize(ImVec2(960, 720));

	// 开始创建一个新的窗口
	ImGui::Begin("ImageLoad", nullptr);

	// 调用ImageInit函数,初始化图片
	ImageInit();

	// 获取窗口大小
	ImVec2 windowSize = ImGui::GetWindowSize();

	// 设置光标位置,并创建两个按钮,用于上下切换图片
	ImGui::SetCursorPos(ImVec2(windowSize.x * 0.4f, windowSize.y * 0.04f));
	if (ImGui::Button("Up")) 
	{
		sg_imageIndex--; // 图片索引减1
		if (sg_imageIndex < 0) // 如果图片索引小于0
		{
			sg_imageIndex = ImageIndex - 1; // 将图片索引设置为最后一个图片的索引
		}
	}
	ImGui::SameLine(); // 同行显示下一个按钮
	if (ImGui::Button("Down")) 
	{
		sg_imageIndex  ; // 图片索引加1
		sg_imageIndex %= ImageIndex; // 对图片索引取模,确保索引在有效范围内
	}

	// 设置图片位置并显示图片
	ImGui::SetCursorPos(ImVec2(0, windowSize.y * 0.08f));
	ImGui::Image(sg_imageS[sg_imageIndex], ImVec2(windowSize.x * 1.0f, windowSize.y * 1.0f));

	// 设置光标位置,并添加分隔线和文本
	ImGui::SetCursorPos(ImVec2(0, windowSize.y * 0.1f));
	ImGui::SeparatorText(u8"ImageShow");

	// 结束窗口创建
	ImGui::End();
}

因为图片只需要加载一次,且图片的加载很耗费时间,所以我们构造一个只加载图片一次的函数

其次是图片显示后,并且如果不给Imgui的相关UI元素设置位置,则会被图片覆盖掉,因为图片的层数是最高的。所有UI元素都会被挤在图片脚下。

运行截图

总结

下载相关文件,并导入项目链接,项目引入相关的头文件后,在Imgui渲染,并通过LoadImageEx找到图片路径并存储其返回的图片指针,然后通过Imgui官方的ImGui::Image()进行交互即可显示图片

全部代码

main.cpp

代码语言:cpp复制
// Dear ImGui: standalone example application for DirectX 11

// Learn about Dear ImGui:
// - FAQ                  https://dearimgui.com/faq
// - Getting Started      https://dearimgui.com/getting-started
// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp

#include"ImGuiAll.h"
#include <tchar.h>

// Data
static ID3D11Device* g_pd3dDevice = nullptr;
static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr;
static IDXGISwapChain* g_pSwapChain = nullptr;
static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;

// Forward declarations of helper functions
bool CreateDeviceD3D(HWND hWnd);
void CleanupDeviceD3D();
void CreateRenderTarget();
void CleanupRenderTarget();
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

ID3D11ShaderResourceView* DX11LoadTextureImageFromFile(ID3D11Device* pD3dDevice, const char* lpszFilePath)
{

	ID3D11Texture2D* pTexture2D = NULL;
	D3D11_TEXTURE2D_DESC dec;


	HRESULT result;
	D3DX11_IMAGE_LOAD_INFO loadInfo;
	ZeroMemory(&loadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO));
	loadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE;
	loadInfo.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	loadInfo.MipLevels = 0; //这时会产生最大的mipmaps层。 
	loadInfo.MipFilter = D3DX11_FILTER_LINEAR;
	result = D3DX11CreateTextureFromFileA(pD3dDevice, lpszFilePath
		, &loadInfo, NULL, (ID3D11Resource**)(&pTexture2D), NULL);
	pTexture2D->GetDesc(&dec);
	if (result != S_OK)
	{
		return NULL;
	}

	ID3D11ShaderResourceView* pFontTextureView = NULL;

	// Create texture view
	D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
	ZeroMemory(&srvDesc, sizeof(srvDesc));
	srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	srvDesc.Texture2D.MipLevels = dec.MipLevels;
	srvDesc.Texture2D.MostDetailedMip = 0;
	pD3dDevice->CreateShaderResourceView(pTexture2D, &srvDesc, &pFontTextureView);


	return pFontTextureView;
}

void* LoadImageEx(const char* path)
{
	return DX11LoadTextureImageFromFile(g_pd3dDevice, path);
}

void ExampleImageLoad();

// Main code
int main(int, char**)
{
	//WSADATA wsaData = {};
	//WSAStartup(MAKEWORD(2, 2), &wsaData);

	// Create application window
	//ImGui_ImplWin32_EnableDpiAwareness();
	WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
	::RegisterClassExW(&wc);
	HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"ImGUIDX11", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);

	// Initialize Direct3D
	if (!CreateDeviceD3D(hwnd))
	{
		CleanupDeviceD3D();
		::UnregisterClassW(wc.lpszClassName, wc.hInstance);
		return 1;
	}

	// Show the window
	::ShowWindow(hwnd, SW_SHOWDEFAULT);
	::UpdateWindow(hwnd);

	// Setup Dear ImGui context
	IMGUI_CHECKVERSION();
	ImGui::CreateContext();
	ImGuiIO& io = ImGui::GetIO(); (void)io;
	io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
	io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls

	// Setup Dear ImGui style
	//ImGui::StyleColorsDark();
	ImGui::StyleColorsLight();

	// Setup Platform/Renderer back ends
	ImGui_ImplWin32_Init(hwnd);
	ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);

	// Load Fonts
	// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
	// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
	// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
	// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
	// - Use '#define IMGUI_ENABLE_FREETYPE' in your config file to use Free Type for higher quality font rendering.
	// - Read 'docs/FONTS.md' for more instructions and details.
	// - Remember that in C/C   if you want to include a backslash  in a string literal you need to write a double backslash \ !
	//io.Fonts->AddFontDefault();
	//io.Fonts->AddFontFromFileTTF("c:\Windows\Fonts\segoeui.ttf", 18.0f);
	//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
	//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
	//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
	ImFont* font = io.Fonts->AddFontFromFileTTF("c:\Windows\Fonts\msyh.ttc", 18.0f, nullptr, io.Fonts->GetGlyphRangesChineseFull());
	IM_ASSERT(font != nullptr);

	// Our state
	bool show_demo_window = true;
	ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

	// Main loop
	bool done = false;
	while (!done)
	{
		// Poll and handle messages (inputs, window resize, etc.)
		// See the WndProc() function below for our to dispatch events to the Win32 backend.
		MSG msg;
		while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
			if (msg.message == WM_QUIT)
				done = true;
		}
		if (done)
			break;

		// Handle window resize (we don't resize directly in the WM_SIZE handler)
		if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
		{
			CleanupRenderTarget();
			g_pSwapChain->ResizeBuffers(0, g_ResizeWidth, g_ResizeHeight, DXGI_FORMAT_UNKNOWN, 0);
			g_ResizeWidth = g_ResizeHeight = 0;
			CreateRenderTarget();
		}

		// Start the Dear ImGui frame
		ImGui_ImplDX11_NewFrame();
		ImGui_ImplWin32_NewFrame();
		ImGui::NewFrame();

		// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
		if (show_demo_window)
			ImGui::ShowDemoWindow(&show_demo_window);

		ExampleImageLoad();


		// Rendering
		ImGui::Render();
		const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
		g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
		g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
		ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

		g_pSwapChain->Present(1, 0); // Present with vsync
		//g_pSwapChain->Present(0, 0); // Present without vsync
	}

	// Cleanup
	ImGui_ImplDX11_Shutdown();
	ImGui_ImplWin32_Shutdown();
	ImGui::DestroyContext();

	CleanupDeviceD3D();
	::DestroyWindow(hwnd);
	::UnregisterClassW(wc.lpszClassName, wc.hInstance);

	return 0;
}

// Helper functions

bool CreateDeviceD3D(HWND hWnd)
{
	// Setup swap chain
	DXGI_SWAP_CHAIN_DESC sd;
	ZeroMemory(&sd, sizeof(sd));
	sd.BufferCount = 2;
	sd.BufferDesc.Width = 0;
	sd.BufferDesc.Height = 0;
	sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	sd.BufferDesc.RefreshRate.Numerator = 60;
	sd.BufferDesc.RefreshRate.Denominator = 1;
	sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
	sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	sd.OutputWindow = hWnd;
	sd.SampleDesc.Count = 1;
	sd.SampleDesc.Quality = 0;
	sd.Windowed = TRUE;
	sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

	UINT createDeviceFlags = 0;
	//createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
	D3D_FEATURE_LEVEL featureLevel;
	const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
	HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
	if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available.
		res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
	if (res != S_OK)
		return false;

	CreateRenderTarget();
	return true;
}

void CleanupDeviceD3D()
{
	CleanupRenderTarget();
	if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; }
	if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; }
	if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
}

void CreateRenderTarget()
{
	ID3D11Texture2D* pBackBuffer;
	g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
	g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
	pBackBuffer->Release();
}

void CleanupRenderTarget()
{
	if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; }
}

// Forward declare message handler from imgui_impl_win32.cpp
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Win32 message handler
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
		return true;

	switch (msg)
	{
	case WM_SIZE:
		if (wParam == SIZE_MINIMIZED)
			return 0;
		g_ResizeWidth = (UINT)LOWORD(lParam); // Queue resize
		g_ResizeHeight = (UINT)HIWORD(lParam);
		return 0;
	case WM_SYSCOMMAND:
		if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
			return 0;
		break;
	case WM_DESTROY:
		::PostQuitMessage(0);
		return 0;
	}
	return ::DefWindowProcW(hWnd, msg, wParam, lParam);
}

ImageLoadExample.cpp

代码语言:cpp复制
#include "ImguiAll.h" 
#include <iostream>   
#include <string>    
#define ImageIndex 12 // 定义图片索引常量,表示要加载的图片数量

static int sg_imageIndex = 0; // 定义全局变量,用于存储当前显示的图片索引

static void* sg_imageS[ImageIndex] = { nullptr }; // 定义全局数组,用于存储加载的图片指针

// 初始化图片函数,加载所有图片并存储在sg_imageS数组中
void ImageInit()
{
	static bool imageLoaded = false; // 定义静态变量,用于判断图片是否已加载
	if (imageLoaded) // 如果图片已加载,直接返回
	{
		return;
	}
	imageLoaded = true; // 设置图片已加载标志为true

	std::string imgPath = "./src/Image/"; // 定义图片路径前缀

	// 遍历所有图片索引,加载对应的图片
	for (int i = 0; i < ImageIndex; i  )
	{
		std::string imgIndex = imgPath   std::to_string(i   1)   ".jpg"; // 构建图片完整路径
		sg_imageS[i] = LoadImageEx(imgIndex.c_str()); // 加载图片并存储在数组中
	}
}

// 显示图片的示例函数
void ExampleImageLoad()
{
	ImVec2 center = ImGui::GetMainViewport()->GetCenter(); // 获取主视口中心点坐标

	// 设置窗口位置和大小
	ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
	ImGui::SetNextWindowSize(ImVec2(960, 720));

	// 开始创建一个新的窗口
	ImGui::Begin("ImageLoad", nullptr);

	// 调用ImageInit函数,初始化图片
	ImageInit();

	// 获取窗口大小
	ImVec2 windowSize = ImGui::GetWindowSize();

	// 设置光标位置,并创建两个按钮,用于上下切换图片
	ImGui::SetCursorPos(ImVec2(windowSize.x * 0.4f, windowSize.y * 0.04f));
	if (ImGui::Button("Up")) 
	{
		sg_imageIndex--; // 图片索引减1
		if (sg_imageIndex < 0) // 如果图片索引小于0
		{
			sg_imageIndex = ImageIndex - 1; // 将图片索引设置为最后一个图片的索引
		}
	}
	ImGui::SameLine(); // 同行显示下一个按钮
	if (ImGui::Button("Down")) 
	{
		sg_imageIndex  ; // 图片索引加1
		sg_imageIndex %= ImageIndex; // 对图片索引取模,确保索引在有效范围内
	}

	// 设置图片位置并显示图片
	ImGui::SetCursorPos(ImVec2(0, windowSize.y * 0.08f));
	ImGui::Image(sg_imageS[sg_imageIndex], ImVec2(windowSize.x * 1.0f, windowSize.y * 1.0f));

	// 设置光标位置,并添加分隔线和文本
	ImGui::SetCursorPos(ImVec2(0, windowSize.y * 0.1f));
	ImGui::SeparatorText(u8"ImageShow");

	// 结束窗口创建
	ImGui::End();
}

ImguiAll.h

代码语言:cpp复制
#pragma once
#include "Imgui/imconfig.h"
#include "Imgui/imgui.h"
#include "Imgui/imgui_impl_dx11.h"
#include "Imgui/imgui_impl_win32.h"
#include "Imgui/imgui_internal.h"
#include "Imgui/imstb_rectpack.h"
#include "Imgui/imstb_textedit.h"
#include "Imgui/imstb_truetype.h"

#include <d3d11.h>

#pragma comment(lib,"d3d11.lib")

#include <D3DX11.h>
#ifdef _DEBUG
#pragma comment(lib,"d3dx11d.lib")
#else
#pragma comment(lib,"d3dx11.lib")
#endif // DEBUG

//DX11加载图片  具体实现放在Main里了
ID3D11ShaderResourceView* DX11LoadTextureImageFromFile(ID3D11Device* pD3dDevice, const char* lpszFilePath);

void* LoadImageEx(const char* path);

0 人点赞