#include "TextureAssetLoader.h" #include #include #include #include #include bool LoadTextureAsset(const ShaderTextureAsset& textureAsset, GLuint& textureId, std::string& error) { textureId = 0; HRESULT comInitResult = CoInitializeEx(NULL, COINIT_MULTITHREADED); const bool shouldUninitializeCom = (comInitResult == S_OK || comInitResult == S_FALSE); if (FAILED(comInitResult) && comInitResult != RPC_E_CHANGED_MODE) { error = "Could not initialize COM to load shader texture assets."; return false; } CComPtr imagingFactory; HRESULT result = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&imagingFactory)); if (FAILED(result) || !imagingFactory) { if (shouldUninitializeCom) CoUninitialize(); error = "Could not create a WIC imaging factory to load shader texture assets."; return false; } CComPtr bitmapDecoder; result = imagingFactory->CreateDecoderFromFilename(textureAsset.path.wstring().c_str(), NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &bitmapDecoder); if (FAILED(result) || !bitmapDecoder) { if (shouldUninitializeCom) CoUninitialize(); error = "Could not open shader texture asset: " + textureAsset.path.string(); return false; } CComPtr bitmapFrame; result = bitmapDecoder->GetFrame(0, &bitmapFrame); if (FAILED(result) || !bitmapFrame) { if (shouldUninitializeCom) CoUninitialize(); error = "Could not decode the first frame of shader texture asset: " + textureAsset.path.string(); return false; } CComPtr formatConverter; result = imagingFactory->CreateFormatConverter(&formatConverter); if (FAILED(result) || !formatConverter) { if (shouldUninitializeCom) CoUninitialize(); error = "Could not create a WIC format converter for shader texture asset: " + textureAsset.path.string(); return false; } result = formatConverter->Initialize(bitmapFrame, GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom); if (FAILED(result)) { if (shouldUninitializeCom) CoUninitialize(); error = "Could not convert shader texture asset to BGRA: " + textureAsset.path.string(); return false; } UINT width = 0; UINT height = 0; result = formatConverter->GetSize(&width, &height); if (FAILED(result) || width == 0 || height == 0) { if (shouldUninitializeCom) CoUninitialize(); error = "Shader texture asset has an invalid size: " + textureAsset.path.string(); return false; } const UINT stride = width * 4; std::vector pixels(static_cast(stride) * static_cast(height)); result = formatConverter->CopyPixels(NULL, stride, static_cast(pixels.size()), pixels.data()); if (FAILED(result)) { if (shouldUninitializeCom) CoUninitialize(); error = "Could not read shader texture pixels: " + textureAsset.path.string(); return false; } std::vector flippedPixels(pixels.size()); for (UINT row = 0; row < height; ++row) { const std::size_t srcOffset = static_cast(row) * stride; const std::size_t dstOffset = static_cast(height - 1 - row) * stride; std::memcpy(flippedPixels.data() + dstOffset, pixels.data() + srcOffset, stride); } glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, static_cast(width), static_cast(height), 0, GL_BGRA, GL_UNSIGNED_BYTE, flippedPixels.data()); glBindTexture(GL_TEXTURE_2D, 0); if (shouldUninitializeCom) CoUninitialize(); return true; }