diff --git a/GDP/D3D9/D3D9.vcxproj b/GDP/D3D9/D3D9.vcxproj index c6a49c3..a6e002a 100644 --- a/GDP/D3D9/D3D9.vcxproj +++ b/GDP/D3D9/D3D9.vcxproj @@ -184,6 +184,7 @@ + @@ -195,6 +196,7 @@ + diff --git a/GDP/D3D9/D3D9.vcxproj.filters b/GDP/D3D9/D3D9.vcxproj.filters index a081ecc..d3ddd1e 100644 --- a/GDP/D3D9/D3D9.vcxproj.filters +++ b/GDP/D3D9/D3D9.vcxproj.filters @@ -42,6 +42,9 @@ Source Files + + Source Files + @@ -71,5 +74,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/GDP/D3D9/Material.cpp b/GDP/D3D9/Material.cpp index 5b0be34..7c5614e 100644 --- a/GDP/D3D9/Material.cpp +++ b/GDP/D3D9/Material.cpp @@ -1,15 +1,23 @@ #include "Material.h" #include "Utilities.h" +#include "WICTextureLoader9.h" -UINT Material::init(IDirect3DDevice9* pD3DDevice, LPCTSTR textureFileName) +UINT Material::init(IDirect3DDevice9* pD3DDevice, LPCWSTR textureFileName) { + // load texture + // https://github.com/microsoft/DirectXTex/tree/main/WICTextureLoader + HRESULT hr = DirectX::CreateWICTextureFromFile(pD3DDevice, textureFileName, &_pTexture); + CheckFailed(hr, 600); + return 0; } void Material::render(IDirect3DDevice9* pD3DDevice) { + pD3DDevice->SetTexture(0, _pTexture); } void Material::deInit() { + safeRelease(_pTexture); } diff --git a/GDP/D3D9/Material.h b/GDP/D3D9/Material.h index 508c4c0..ba6769d 100644 --- a/GDP/D3D9/Material.h +++ b/GDP/D3D9/Material.h @@ -4,11 +4,11 @@ class Material { public: - UINT init(IDirect3DDevice9* pD3DDevice, LPCTSTR textureFileName); + UINT init(IDirect3DDevice9* pD3DDevice, LPCWSTR textureFileName); void render(IDirect3DDevice9* pD3DDevice); void deInit(); private: - IDirect3DTexture9* _texture = {}; + IDirect3DTexture9* _pTexture = {}; }; diff --git a/GDP/D3D9/Mesh.cpp b/GDP/D3D9/Mesh.cpp index 518bb3e..ff220f4 100644 --- a/GDP/D3D9/Mesh.cpp +++ b/GDP/D3D9/Mesh.cpp @@ -131,18 +131,31 @@ UINT Mesh::createVertexBuffer(IDirect3DDevice9* pD3DDevice) //pVertices[2] = Vertex(0.5f, -0.5f, 0.0f); //pVertices[3] = Vertex(-0.5f, -0.5f, 0.0f); - // cube + //// cube with color + //// front + //pVertices[0] = Vertex(-0.5f, 0.5f, -0.5f, 255, 0, 0); + //pVertices[1] = Vertex(0.5f, 0.5f, -0.5f, 0, 255, 0); + //pVertices[2] = Vertex(0.5f, -0.5f, -0.5f, 0, 0, 255); + //pVertices[3] = Vertex(-0.5f, -0.5f, -0.5f, 255, 0, 255); + + //// back + //pVertices[4] = Vertex(0.5f, 0.5f, 0.5f, 255, 255, 0); + //pVertices[5] = Vertex(-0.5f, 0.5f, 0.5f, 0, 255, 255); + //pVertices[6] = Vertex(-0.5f, -0.5f, 0.5f, 0, 0, 0); + //pVertices[7] = Vertex(0.5f, -0.5f, 0.5f, 200, 200, 200); + + // cube with uv // front - pVertices[0] = Vertex(-0.5f, 0.5f, -0.5f, 255, 0, 0); - pVertices[1] = Vertex(0.5f, 0.5f, -0.5f, 0, 255, 0); - pVertices[2] = Vertex(0.5f, -0.5f, -0.5f, 0, 0, 255); - pVertices[3] = Vertex(-0.5f, -0.5f, -0.5f, 255, 0, 255); + pVertices[0] = Vertex(-0.5f, 0.5f, -0.5f, 0.0f, 0.0f); + pVertices[1] = Vertex(0.5f, 0.5f, -0.5f, 1.0f, 0.0f); + pVertices[2] = Vertex(0.5f, -0.5f, -0.5f, 1.0f, 1.0f); + pVertices[3] = Vertex(-0.5f, -0.5f, -0.5f, 0.0f, 1.0f); // back - pVertices[4] = Vertex(0.5f, 0.5f, 0.5f, 255, 255, 0); - pVertices[5] = Vertex(-0.5f, 0.5f, 0.5f, 0, 255, 255); - pVertices[6] = Vertex(-0.5f, -0.5f, 0.5f, 0, 0, 0); - pVertices[7] = Vertex(0.5f, -0.5f, 0.5f, 200, 200, 200); + pVertices[4] = Vertex(0.5f, 0.5f, 0.5f, 0.0f, 0.0f); + pVertices[5] = Vertex(-0.5f, 0.5f, 0.5f, 1.0f, 0.0f); + pVertices[6] = Vertex(-0.5f, -0.5f, 0.5f, 1.0f, 1.0f); + pVertices[7] = Vertex(0.5f, -0.5f, 0.5f, 0.0f, 1.0f); hr = _pVertexBuffer->Unlock(); // transfer vertex buffer back from cpu memory to video memory CheckFailed(hr, 320); diff --git a/GDP/D3D9/Vertex.h b/GDP/D3D9/Vertex.h index 04f4bf6..b7dce7b 100644 --- a/GDP/D3D9/Vertex.h +++ b/GDP/D3D9/Vertex.h @@ -1,7 +1,7 @@ #pragma once #include -#define FVF D3DFVF_XYZ | D3DFVF_DIFFUSE +#define FVF D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 struct Vertex { @@ -11,7 +11,11 @@ struct Vertex D3DCOLOR color; - Vertex() : x(0.0f), y(0.0f), z(0.0f), color(0xFFFFFFFF) {} - Vertex(FLOAT _x, FLOAT _y, FLOAT _z) : x(_x), y(_y), z(_z), color(0xFFFFFFFF) {} - Vertex(FLOAT _x, FLOAT _y, FLOAT _z, UINT r, UINT g, UINT b) : x(_x), y(_y), z(_z), color(D3DCOLOR_XRGB(r, g, b)) {} + FLOAT u; + FLOAT v; + + Vertex() : x(0.0f), y(0.0f), z(0.0f), color(0xFFFFFFFF), u(0.0f), v(0.0f) {} + Vertex(FLOAT _x, FLOAT _y, FLOAT _z) : x(_x), y(_y), z(_z), color(0xFFFFFFFF), u(0.0f), v(0.0f) {} + Vertex(FLOAT _x, FLOAT _y, FLOAT _z, UINT r, UINT g, UINT b) : x(_x), y(_y), z(_z), color(D3DCOLOR_XRGB(r, g, b)), u(0.0f), v(0.0f) {} + Vertex(FLOAT _x, FLOAT _y, FLOAT _z, FLOAT _u, FLOAT _v) : x(_x), y(_y), z(_z), color(0xFFFFFFFF), u(_u), v(_v) {} }; \ No newline at end of file diff --git a/GDP/D3D9/WICTextureLoader9.cpp b/GDP/D3D9/WICTextureLoader9.cpp new file mode 100644 index 0000000..ae35f0d --- /dev/null +++ b/GDP/D3D9/WICTextureLoader9.cpp @@ -0,0 +1,650 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader9.cpp +// +// Function for loading a WIC image and creating a Direct3D runtime texture for it +// +// Note: Assumes application has already called CoInitializeEx +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +// We could load multi-frame images (TIFF/GIF) into a texture array. +// For now, we just load the first frame (note: DirectXTex supports multi-frame images) + +#include "WICTextureLoader9.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef _MSC_VER +// Off by default warnings +#pragma warning(disable : 4619 4616 4061 4623 4626 5027) +// C4619/4616 #pragma warning warnings +// C4061 enumerator 'x' in switch of enum 'y' is not explicitly handled by a case label +// C4623 default constructor was implicitly defined as deleted +// C4626 assignment operator was implicitly defined as deleted +// C5027 move assignment operator was implicitly defined as deleted +#endif + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wswitch-enum" +#endif + +using namespace DirectX; +using Microsoft::WRL::ComPtr; + +namespace +{ + //------------------------------------------------------------------------------------- + // WIC Pixel Format Translation Data + //------------------------------------------------------------------------------------- + struct WICTranslate + { + const GUID& wic; + D3DFORMAT format; + + constexpr WICTranslate(const GUID& wg, D3DFORMAT fmt) noexcept : + wic(wg), + format(fmt) + { + } + }; + + constexpr WICTranslate g_WICFormats[] = + { + { GUID_WICPixelFormat128bppRGBAFloat, D3DFMT_A32B32G32R32F }, + + { GUID_WICPixelFormat64bppRGBAHalf, D3DFMT_A16B16G16R16F }, + { GUID_WICPixelFormat64bppRGBA, D3DFMT_A16B16G16R16 }, + + { GUID_WICPixelFormat32bppBGRA, D3DFMT_A8R8G8B8 }, + + { GUID_WICPixelFormat32bppRGBA1010102, D3DFMT_A2B10G10R10 }, + + { GUID_WICPixelFormat16bppBGRA5551, D3DFMT_A1R5G5B5 }, + { GUID_WICPixelFormat16bppBGR555, D3DFMT_X1R5G5B5 }, + { GUID_WICPixelFormat16bppBGR565, D3DFMT_R5G6B5 }, + + { GUID_WICPixelFormat32bppGrayFloat, D3DFMT_R32F }, + { GUID_WICPixelFormat16bppGrayHalf, D3DFMT_R16F }, + { GUID_WICPixelFormat16bppGray, D3DFMT_L16 }, + { GUID_WICPixelFormat8bppGray, D3DFMT_L8 }, + + { GUID_WICPixelFormat8bppAlpha, D3DFMT_A8 }, + }; + + //------------------------------------------------------------------------------------- + // WIC Pixel Format nearest conversion table + //------------------------------------------------------------------------------------- + struct WICConvert + { + const GUID& source; + const GUID& target; + + constexpr WICConvert(const GUID& src, const GUID& tgt) noexcept : + source(src), + target(tgt) + { + } + }; + + constexpr WICConvert g_WICConvert[] = + { + // Note target GUID in this conversion table must be one of those directly supported formats (above). + + { GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // D3DFMT_L8 + + { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + + { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // D3DFMT_L8 + { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // D3DFMT_L8 + + { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // D3DFMT_R16F + { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // D3DFMT_R32F + + { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // D3DFMT_A2B10G10R10 + + { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat32bppBGR, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat32bppRGBA, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + + { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + + { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + + { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F + { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F + { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F + { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F + { GUID_WICPixelFormat32bppRGBE, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F + + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + + { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppBGRA }, // D3DFMT_A8R8G8B8 + { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // D3DFMT_A16B16G16R16 + { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // D3DFMT_A16B16G16R16F + { GUID_WICPixelFormat96bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // D3DFMT_A32B32G32R32F + + // We don't support n-channel formats + }; + + //-------------------------------------------------------------------------------------- + BOOL WINAPI InitializeWICFactory(PINIT_ONCE, PVOID, PVOID* ifactory) noexcept + { + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory2, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory2), + ifactory + ); + + if (SUCCEEDED(hr)) + { + // WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed + return TRUE; + } + else + { + hr = CoCreateInstance( + CLSID_WICImagingFactory1, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory), + ifactory + ); + return SUCCEEDED(hr) ? TRUE : FALSE; + } + } + + IWICImagingFactory* GetWIC() noexcept + { + static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT; + + IWICImagingFactory* factory = nullptr; + if (!InitOnceExecuteOnce( + &s_initOnce, + InitializeWICFactory, + nullptr, + reinterpret_cast(&factory))) + { + return nullptr; + } + + return factory; + } + + //--------------------------------------------------------------------------------- + D3DFORMAT WICToD3D9(const GUID& guid) noexcept + { + for (size_t i = 0; i < std::size(g_WICFormats); ++i) + { + if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0) + return g_WICFormats[i].format; + } + + return D3DFMT_UNKNOWN; + } + + //--------------------------------------------------------------------------------- + void FitPowerOf2(UINT origx, UINT origy, UINT& targetx, UINT& targety, size_t maxsize) + { + const float origAR = float(origx) / float(origy); + + if (origx > origy) + { + size_t x; + for (x = maxsize; x > 1; x >>= 1) { if (x <= targetx) break; } + targetx = UINT(x); + + float bestScore = FLT_MAX; + for (size_t y = maxsize; y > 0; y >>= 1) + { + const float score = fabsf((float(x) / float(y)) - origAR); + if (score < bestScore) + { + bestScore = score; + targety = UINT(y); + } + } + } + else + { + size_t y; + for (y = maxsize; y > 1; y >>= 1) { if (y <= targety) break; } + targety = UINT(y); + + float bestScore = FLT_MAX; + for (size_t x = maxsize; x > 0; x >>= 1) + { + const float score = fabsf((float(x) / float(y)) - origAR); + if (score < bestScore) + { + bestScore = score; + targetx = UINT(x); + } + } + } + } + + //--------------------------------------------------------------------------------- + HRESULT CreateTextureFromWIC( + _In_ LPDIRECT3DDEVICE9 device, + _In_ IWICBitmapFrameDecode* frame, + _In_ size_t maxsize, + _In_ DWORD usage, + _In_ D3DPOOL pool, + _In_ WIC_LOADER_FLAGS loadFlags, + _Outptr_ LPDIRECT3DTEXTURE9* texture) noexcept + { + UINT width, height; + HRESULT hr = frame->GetSize(&width, &height); + if (FAILED(hr)) + return hr; + + if (maxsize > UINT32_MAX) + return E_INVALIDARG; + + assert(width > 0 && height > 0); + + if (!maxsize) + { + maxsize = 4096u /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; + } + + assert(maxsize > 0); + + UINT twidth = width; + UINT theight = height; + if (loadFlags & WIC_LOADER_FIT_POW2) + { + FitPowerOf2(width, height, twidth, theight, maxsize); + } + else if (width > maxsize || height > maxsize) + { + const float ar = static_cast(height) / static_cast(width); + if (width > height) + { + twidth = static_cast(maxsize); + theight = std::max(1, static_cast(static_cast(maxsize) * ar)); + } + else + { + theight = static_cast(maxsize); + twidth = std::max(1, static_cast(static_cast(maxsize) / ar)); + } + assert(twidth <= maxsize && theight <= maxsize); + } + + if (loadFlags & WIC_LOADER_MAKE_SQUARE) + { + twidth = std::max(twidth, theight); + theight = twidth; + } + + // Determine format + WICPixelFormatGUID pixelFormat; + hr = frame->GetPixelFormat(&pixelFormat); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID convertGUID; + memcpy_s(&convertGUID, sizeof(WICPixelFormatGUID), &pixelFormat, sizeof(GUID)); + + D3DFORMAT format = WICToD3D9(pixelFormat); + if (format == D3DFMT_UNKNOWN) + { + for (size_t i = 0; i < std::size(g_WICConvert); ++i) + { + if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0) + { + memcpy_s(&convertGUID, sizeof(WICPixelFormatGUID), &g_WICConvert[i].target, sizeof(GUID)); + + format = WICToD3D9(g_WICConvert[i].target); + assert(format != D3DFMT_UNKNOWN); + break; + } + } + + if (format == D3DFMT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + if (loadFlags & WIC_LOADER_FORCE_RGBA32) + { + memcpy_s(&convertGUID, sizeof(WICPixelFormatGUID), &GUID_WICPixelFormat32bppBGRA, sizeof(GUID)); + format = D3DFMT_A8R8G8B8; + } + + // Create texture + if (loadFlags & WIC_LOADER_MIP_AUTOGEN) + usage |= D3DUSAGE_AUTOGENMIPMAP; + + ComPtr pTexture; + hr = device->CreateTexture(twidth, theight, 1u, + usage, format, pool, + pTexture.GetAddressOf(), nullptr); + if (FAILED(hr)) + return hr; + + // Create staging texture memory + ComPtr pStagingTexture; + if (pool == D3DPOOL_DEFAULT) + { + hr = device->CreateTexture(twidth, theight, 1u, + 0u, format, D3DPOOL_SYSTEMMEM, + pStagingTexture.GetAddressOf(), nullptr); + if (FAILED(hr)) + return hr; + } + else + { + pStagingTexture = pTexture; + } + + D3DLOCKED_RECT LockedRect = {}; + hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0); + if (FAILED(hr)) + return hr; + + const uint64_t numBytes = uint64_t(LockedRect.Pitch) * uint64_t(theight); + + pStagingTexture->UnlockRect(0); + + if (numBytes > UINT32_MAX) + { + return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW); + } + + // Load image data + if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0 + && twidth == width + && theight == height) + { + // No format conversion or resize needed + hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0); + if (FAILED(hr)) + return hr; + + hr = frame->CopyPixels(nullptr, static_cast(LockedRect.Pitch), static_cast(numBytes), + static_cast(LockedRect.pBits)); + + pStagingTexture->UnlockRect(0); + + if (FAILED(hr)) + return hr; + } + else if (twidth != width || theight != height) + { + // Resize + auto pWIC = GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr scaler; + hr = pWIC->CreateBitmapScaler(scaler.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat(&pfScaler); + if (FAILED(hr)) + return hr; + + if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0) + { + // No format conversion needed + hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0); + if (FAILED(hr)) + return hr; + + hr = scaler->CopyPixels(nullptr, static_cast(LockedRect.Pitch), static_cast(numBytes), + static_cast(LockedRect.pBits)); + + pStagingTexture->UnlockRect(0); + + if (FAILED(hr)) + return hr; + } + else + { + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pfScaler, convertGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(nullptr, static_cast(LockedRect.Pitch), static_cast(numBytes), + static_cast(LockedRect.pBits)); + + pStagingTexture->UnlockRect(0); + + if (FAILED(hr)) + return hr; + } + } + else + { + // Format conversion but no resize + auto pWIC = GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ComPtr FC; + hr = pWIC->CreateFormatConverter(FC.GetAddressOf()); + if (FAILED(hr)) + return hr; + + BOOL canConvert = FALSE; + hr = FC->CanConvert(pixelFormat, convertGUID, &canConvert); + if (FAILED(hr) || !canConvert) + { + return E_UNEXPECTED; + } + + hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, nullptr, 0, WICBitmapPaletteTypeMedianCut); + if (FAILED(hr)) + return hr; + + hr = pStagingTexture->LockRect(0, &LockedRect, nullptr, 0); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(nullptr, static_cast(LockedRect.Pitch), static_cast(numBytes), + static_cast(LockedRect.pBits)); + + pStagingTexture->UnlockRect(0); + + if (FAILED(hr)) + return hr; + } + + if (pool == D3DPOOL_DEFAULT) + { + hr = device->UpdateTexture(pStagingTexture.Get(), pTexture.Get()); + if (FAILED(hr)) + return hr; + } + + *texture = pTexture.Detach(); + + return S_OK; + } +} // anonymous namespace + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromMemory( + LPDIRECT3DDEVICE9 d3dDevice, + const uint8_t* wicData, + size_t wicDataSize, + LPDIRECT3DTEXTURE9* texture, + size_t maxsize, + WIC_LOADER_FLAGS loadFlags) noexcept +{ + return CreateWICTextureFromMemoryEx(d3dDevice, wicData, wicDataSize, maxsize, 0u, D3DPOOL_DEFAULT, loadFlags, texture); +} + + +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromMemoryEx( + LPDIRECT3DDEVICE9 d3dDevice, + const uint8_t* wicData, + size_t wicDataSize, + _In_ size_t maxsize, + _In_ DWORD usage, + _In_ D3DPOOL pool, + _In_ WIC_LOADER_FLAGS loadFlags, + LPDIRECT3DTEXTURE9* texture) noexcept +{ + if (texture) + { + *texture = nullptr; + } + + if (!d3dDevice || !wicData || !wicDataSize || !texture) + return E_INVALIDARG; + + if (!wicDataSize) + return E_FAIL; + + if (wicDataSize > UINT32_MAX) + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + + auto pWIC = GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + // Create input stream for memory + ComPtr stream; + HRESULT hr = pWIC->CreateStream(stream.GetAddressOf()); + if (FAILED(hr)) + return hr; + + hr = stream->InitializeFromMemory(const_cast(wicData), static_cast(wicDataSize)); + if (FAILED(hr)) + return hr; + + // Initialize WIC + ComPtr decoder; + hr = pWIC->CreateDecoderFromStream(stream.Get(), nullptr, WICDecodeMetadataCacheOnDemand, decoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr frame; + hr = decoder->GetFrame(0, frame.GetAddressOf()); + if (FAILED(hr)) + return hr; + + return CreateTextureFromWIC(d3dDevice, frame.Get(), maxsize, usage, pool, loadFlags, texture); +} + +//-------------------------------------------------------------------------------------- +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromFile( + LPDIRECT3DDEVICE9 d3dDevice, + const wchar_t* fileName, + LPDIRECT3DTEXTURE9* texture, + size_t maxsize, + WIC_LOADER_FLAGS loadFlags) noexcept +{ + return CreateWICTextureFromFileEx(d3dDevice, fileName, maxsize, 0u, D3DPOOL_DEFAULT, loadFlags, texture); +} + +_Use_decl_annotations_ +HRESULT DirectX::CreateWICTextureFromFileEx( + LPDIRECT3DDEVICE9 d3dDevice, + const wchar_t* fileName, + size_t maxsize, + DWORD usage, + D3DPOOL pool, + WIC_LOADER_FLAGS loadFlags, + LPDIRECT3DTEXTURE9* texture) noexcept +{ + if (texture) + { + *texture = nullptr; + } + + if (!d3dDevice || !fileName || !texture) + return E_INVALIDARG; + + auto pWIC = GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + // Initialize WIC + ComPtr decoder; + HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, + nullptr, + GENERIC_READ, + WICDecodeMetadataCacheOnDemand, + decoder.GetAddressOf()); + if (FAILED(hr)) + return hr; + + ComPtr frame; + hr = decoder->GetFrame(0, frame.GetAddressOf()); + if (FAILED(hr)) + return hr; + + return CreateTextureFromWIC(d3dDevice, frame.Get(), maxsize, usage, pool, loadFlags, texture); +} \ No newline at end of file diff --git a/GDP/D3D9/WICTextureLoader9.h b/GDP/D3D9/WICTextureLoader9.h new file mode 100644 index 0000000..81735fd --- /dev/null +++ b/GDP/D3D9/WICTextureLoader9.h @@ -0,0 +1,93 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader9.h +// +// Function for loading a WIC image and creating a Direct3D runtime texture for it +// (auto-generating mipmaps if possible) +// +// Note: Assumes application has already called CoInitializeEx +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//-------------------------------------------------------------------------------------- + +#pragma once + +#ifndef DIRECT3D_VERSION +#define DIRECT3D_VERSION 0x900 +#endif +#include + +#pragma comment(lib,"windowscodecs.lib") + +#include +#include + +namespace DirectX +{ +#ifndef WIC_LOADER_FLAGS_DEFINED +#define WIC_LOADER_FLAGS_DEFINED + enum WIC_LOADER_FLAGS : uint32_t + { + WIC_LOADER_DEFAULT = 0, + WIC_LOADER_MIP_AUTOGEN = 0x8, + WIC_LOADER_FIT_POW2 = 0x20, + WIC_LOADER_MAKE_SQUARE = 0x40, + WIC_LOADER_FORCE_RGBA32 = 0x80, + }; + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec" +#pragma clang diagnostic ignored "-Wextra-semi-stmt" +#endif + + DEFINE_ENUM_FLAG_OPERATORS(WIC_LOADER_FLAGS); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#endif + + // Standard version + HRESULT CreateWICTextureFromMemory( + _In_ LPDIRECT3DDEVICE9 d3dDevice, + _In_reads_bytes_(wicDataSize) const uint8_t* wicData, + _In_ size_t wicDataSize, + _Outptr_ LPDIRECT3DTEXTURE9* texture, + _In_ size_t maxsize = 0, + _In_ WIC_LOADER_FLAGS loadFlags = WIC_LOADER_DEFAULT) noexcept; + + HRESULT CreateWICTextureFromFile( + _In_ LPDIRECT3DDEVICE9 d3dDevice, + _In_z_ const wchar_t* fileName, + _Outptr_ LPDIRECT3DTEXTURE9* texture, + _In_ size_t maxsize = 0, + _In_ WIC_LOADER_FLAGS loadFlags = WIC_LOADER_DEFAULT) noexcept; + + // Extended version + HRESULT CreateWICTextureFromMemoryEx( + _In_ LPDIRECT3DDEVICE9 d3dDevice, + _In_reads_bytes_(wicDataSize) const uint8_t* wicData, + _In_ size_t wicDataSize, + _In_ size_t maxsize, + _In_ DWORD usage, + _In_ D3DPOOL pool, + _In_ WIC_LOADER_FLAGS loadFlags, + _Outptr_ LPDIRECT3DTEXTURE9* texture) noexcept; + + HRESULT CreateWICTextureFromFileEx( + _In_ LPDIRECT3DDEVICE9 d3dDevice, + _In_z_ const wchar_t* fileName, + _In_ size_t maxsize, + _In_ DWORD usage, + _In_ D3DPOOL pool, + _In_ WIC_LOADER_FLAGS loadFlags, + _Outptr_ LPDIRECT3DTEXTURE9* texture) noexcept; +} \ No newline at end of file diff --git a/GDP/D3D9/main.cpp b/GDP/D3D9/main.cpp index 4075ab3..0086aed 100644 --- a/GDP/D3D9/main.cpp +++ b/GDP/D3D9/main.cpp @@ -57,7 +57,7 @@ int WINAPI WinMain( // 6. create a material Material material = {}; - error = material.init(d3d.getDevice(), TEXT("wall.jpg")); + error = material.init(d3d.getDevice(), L"wall.jpg"); CheckError(error); // 7. create light source diff --git a/GDP/D3D9/wall.jpg b/GDP/D3D9/wall.jpg new file mode 100644 index 0000000..088fa60 Binary files /dev/null and b/GDP/D3D9/wall.jpg differ