|
12 | 12 | #include <d3dcompiler.h>
|
13 | 13 |
|
14 | 14 | #include <DirectXTex.h>
|
| 15 | +#include <FreeImage.h> |
15 | 16 |
|
16 | 17 | #include <iostream>
|
17 | 18 |
|
|
21 | 22 | #pragma comment(lib, "winmm.lib")
|
22 | 23 | #pragma comment(lib, "dxguid.lib")
|
23 | 24 |
|
| 25 | +#if defined(_DEBUG) |
| 26 | +#pragma comment(lib, "FreeImageLibd.lib") |
| 27 | +#else |
| 28 | +#pragma comment(lib, "FreeImageLib.lib") |
| 29 | +#endif |
| 30 | + |
24 | 31 | template <UINT TDebugNameLength>
|
25 | 32 | inline void SetDebugName(_In_ ID3D11DeviceChild* deviceResource, _In_z_ const char (&debugName)[TDebugNameLength])
|
26 | 33 | {
|
@@ -133,9 +140,161 @@ bool ImageLibraryApplication::Initialize()
|
133 | 140 |
|
134 | 141 | _pipelineFactory = std::make_unique<PipelineFactory>(_device);
|
135 | 142 |
|
| 143 | + FreeImage_Initialise(); |
136 | 144 | return true;
|
137 | 145 | }
|
138 | 146 |
|
| 147 | +WRL::ComPtr<ID3D11ShaderResourceView> CreateTextureViewFromDDS(ID3D11Device* device, const std::wstring& pathToDDS) |
| 148 | +{ |
| 149 | + DirectX::TexMetadata metaData = {}; |
| 150 | + DirectX::ScratchImage scratchImage; |
| 151 | + if (FAILED(DirectX::LoadFromDDSFile(pathToDDS.c_str(), DirectX::DDS_FLAGS_NONE, &metaData, scratchImage))) |
| 152 | + { |
| 153 | + std::cout << "DXTEX: Failed to load image\n"; |
| 154 | + return nullptr; |
| 155 | + } |
| 156 | + |
| 157 | + WRL::ComPtr<ID3D11Resource> texture = nullptr; |
| 158 | + if (FAILED(DirectX::CreateTexture( |
| 159 | + device, |
| 160 | + scratchImage.GetImages(), |
| 161 | + scratchImage.GetImageCount(), |
| 162 | + metaData, |
| 163 | + &texture))) |
| 164 | + { |
| 165 | + std::cout << "DXTEX: Failed to create texture out of image\n"; |
| 166 | + scratchImage.Release(); |
| 167 | + return nullptr; |
| 168 | + } |
| 169 | + |
| 170 | + ID3D11ShaderResourceView* srv = nullptr; |
| 171 | + |
| 172 | + if (FAILED(DirectX::CreateShaderResourceView( |
| 173 | + device, |
| 174 | + scratchImage.GetImages(), |
| 175 | + scratchImage.GetImageCount(), |
| 176 | + metaData, |
| 177 | + &srv))) |
| 178 | + { |
| 179 | + std::cout << "DXTEX: Failed to create shader resource view out of texture\n"; |
| 180 | + scratchImage.Release(); |
| 181 | + return nullptr; |
| 182 | + } |
| 183 | + |
| 184 | + return srv; |
| 185 | +} |
| 186 | + |
| 187 | + |
| 188 | +WRL::ComPtr<ID3D11ShaderResourceView> CreateTextureView(ID3D11Device* device, const std::wstring& pathToTexture) |
| 189 | +{ |
| 190 | + FIBITMAP* image = nullptr; |
| 191 | + //Open our file |
| 192 | + HANDLE file = CreateFileW(pathToTexture.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, 0); |
| 193 | + |
| 194 | + size_t fileSize = GetFileSize(file, nullptr); |
| 195 | + //Create our data buffer and read in the entire file |
| 196 | + { |
| 197 | + std::vector<BYTE> fileDataRaw(fileSize); |
| 198 | + if (!ReadFile(file, fileDataRaw.data(), fileDataRaw.size(), nullptr, nullptr)) |
| 199 | + { |
| 200 | + CloseHandle(file); |
| 201 | + return nullptr; |
| 202 | + } |
| 203 | + |
| 204 | + //Close our file handle as we don't need it anymore |
| 205 | + CloseHandle(file); |
| 206 | + |
| 207 | + FIMEMORY* memHandle = FreeImage_OpenMemory(fileDataRaw.data(), fileDataRaw.size()); |
| 208 | + FREE_IMAGE_FORMAT imageFormat = FreeImage_GetFileTypeFromMemory(memHandle); |
| 209 | + if (imageFormat == FIF_UNKNOWN) |
| 210 | + { |
| 211 | + FreeImage_CloseMemory(memHandle); |
| 212 | + std::cout << "CreateTextureView: Unsupported texture format from file: '" << pathToTexture.c_str() << "'\n"; |
| 213 | + return nullptr; |
| 214 | + } |
| 215 | + image = FreeImage_LoadFromMemory(imageFormat, memHandle); |
| 216 | + |
| 217 | + //We no longer need the original data |
| 218 | + FreeImage_CloseMemory(memHandle); |
| 219 | + |
| 220 | + } //local scope cleans up fileDataRaw |
| 221 | + |
| 222 | + //Flip the image vertically so this matches up with what DirectXTex loads |
| 223 | + FreeImage_FlipVertical(image); |
| 224 | + |
| 225 | + uint32_t textureWidth = FreeImage_GetWidth(image); |
| 226 | + uint32_t textureHeight = FreeImage_GetHeight(image); |
| 227 | + uint32_t textureBPP = FreeImage_GetBPP(image); |
| 228 | + |
| 229 | + D3D11_TEXTURE2D_DESC textureDesc{}; |
| 230 | + D3D11_SUBRESOURCE_DATA initialData{}; |
| 231 | + WRL::ComPtr<ID3D11Texture2D> texture = nullptr; |
| 232 | + |
| 233 | + DXGI_FORMAT textureFormat; |
| 234 | + switch (textureBPP) |
| 235 | + { |
| 236 | + case 8: |
| 237 | + textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8_UNORM; |
| 238 | + break; |
| 239 | + case 16: |
| 240 | + textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8G8_UNORM; |
| 241 | + break; |
| 242 | + case 24: |
| 243 | + //D3D11 does not support 24 bit formats for textures, we'll need to convert |
| 244 | + { |
| 245 | + textureBPP = 32; |
| 246 | + FIBITMAP* newImage = FreeImage_ConvertTo32Bits(image); |
| 247 | + FreeImage_Unload(image); |
| 248 | + image = newImage; |
| 249 | + textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM; |
| 250 | + } |
| 251 | + break; |
| 252 | + case 32: |
| 253 | + textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM; |
| 254 | + break; |
| 255 | + default: |
| 256 | + { |
| 257 | + //we could try to handle some weird bitcount, but these will probably be HDR or some antique format, just exit instead.. |
| 258 | + std::cout << "CreateTextureView: Texture has nontrivial bits per pixel ( " << textureBPP << " ), file: '" << pathToTexture.c_str() << "'\n"; |
| 259 | + return nullptr; |
| 260 | + } |
| 261 | + break; |
| 262 | + } |
| 263 | + textureDesc.Format = textureFormat; |
| 264 | + textureDesc.ArraySize = 1; |
| 265 | + textureDesc.MipLevels = 1; |
| 266 | + textureDesc.Height = textureHeight; |
| 267 | + textureDesc.Width = textureWidth; |
| 268 | + textureDesc.SampleDesc.Count = 1; |
| 269 | + textureDesc.Usage = D3D11_USAGE_IMMUTABLE; |
| 270 | + textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; |
| 271 | + |
| 272 | + //populate initial data |
| 273 | + initialData.pSysMem = FreeImage_GetBits(image); |
| 274 | + initialData.SysMemPitch = (textureBPP / 8) * textureWidth; |
| 275 | + |
| 276 | + if (FAILED(device->CreateTexture2D(&textureDesc, &initialData, texture.GetAddressOf()))) |
| 277 | + { |
| 278 | + FreeImage_Unload(image); |
| 279 | + return nullptr; |
| 280 | + } |
| 281 | + FreeImage_Unload(image); |
| 282 | + |
| 283 | + ID3D11ShaderResourceView* srv = nullptr; |
| 284 | + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{}; |
| 285 | + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; |
| 286 | + srvDesc.Format = textureDesc.Format; |
| 287 | + srvDesc.Texture2D.MipLevels = textureDesc.MipLevels; |
| 288 | + |
| 289 | + if (FAILED(device->CreateShaderResourceView(texture.Get(), &srvDesc, &srv))) |
| 290 | + { |
| 291 | + std::cout << "CreateTextureView: Failed to create SRV from texture: " << pathToTexture.c_str() << "\n"; |
| 292 | + return nullptr; |
| 293 | + } |
| 294 | + |
| 295 | + return srv; |
| 296 | +} |
| 297 | + |
139 | 298 | bool ImageLibraryApplication::Load()
|
140 | 299 | {
|
141 | 300 | PipelineDescriptor pipelineDescriptor = {};
|
@@ -176,37 +335,14 @@ bool ImageLibraryApplication::Load()
|
176 | 335 | return false;
|
177 | 336 | }
|
178 | 337 |
|
179 |
| - DirectX::TexMetadata metaData = {}; |
180 |
| - DirectX::ScratchImage scratchImage; |
181 |
| - if (FAILED(DirectX::LoadFromDDSFile(L"Assets/Textures/T_Froge.dds", DirectX::DDS_FLAGS_NONE, &metaData, scratchImage))) |
182 |
| - { |
183 |
| - std::cout << "DXTEX: Failed to load image\n"; |
184 |
| - return false; |
185 |
| - } |
| 338 | + _fallbackTextureSrv = CreateTextureView(_device.Get(), L"Assets/Textures/default.png"); |
| 339 | + assert(_fallbackTextureSrv != nullptr); //as a fallback resource, this "needs" to exist |
186 | 340 |
|
187 |
| - WRL::ComPtr<ID3D11Resource> texture = nullptr; |
188 |
| - if (FAILED(DirectX::CreateTexture( |
189 |
| - _device.Get(), |
190 |
| - scratchImage.GetImages(), |
191 |
| - scratchImage.GetImageCount(), |
192 |
| - metaData, |
193 |
| - &texture))) |
194 |
| - { |
195 |
| - std::cout << "DXTEX: Failed to create texture out of image\n"; |
196 |
| - scratchImage.Release(); |
197 |
| - return false; |
198 |
| - } |
199 |
| - |
200 |
| - if (FAILED(DirectX::CreateShaderResourceView( |
201 |
| - _device.Get(), |
202 |
| - scratchImage.GetImages(), |
203 |
| - scratchImage.GetImageCount(), |
204 |
| - metaData, |
205 |
| - &_textureSrv))) |
| 341 | + _textureSrv = CreateTextureViewFromDDS(_device.Get(), L"Assets/Textures/T_Froge.dds"); |
| 342 | + if (_textureSrv == nullptr) |
206 | 343 | {
|
207 |
| - std::cout << "DXTEX: Failed to create shader resource view out of texture\n"; |
208 |
| - scratchImage.Release(); |
209 |
| - return false; |
| 344 | + //this is "fine", we can use our fallback! |
| 345 | + _textureSrv = _fallbackTextureSrv; |
210 | 346 | }
|
211 | 347 |
|
212 | 348 | _pipeline->BindTexture(0, _textureSrv.Get());
|
|
0 commit comments