Vorgehensweise: Initialisieren einer Textur aus einer Datei
Sie können die Api für windows-Bildverarbeitungskomponenten verwenden, um eine Textur aus einer Datei zu initialisieren. Zum Laden einer Textur müssen Sie eine Textur und eine Texturansicht erstellen. In diesem Thema wird gezeigt, wie Sie die Windows-Bildverarbeitungskomponente (WiC) verwenden, um die Textur und die Ansicht separat zu erstellen.
Hinweis
Dieses Thema ist nützlich für Bilder, die Sie als einfache 2D-Texturen erstellen. Für komplexere Ressourcen verwenden Sie DDS. Eine vollständige DDS-Dateileser-, Writer- und Texturverarbeitungspipeline finden Sie unter DirectXTex und DirectXTK.
Am Ende dieses Themas finden Sie den vollständigen Beispielcode. Das Thema beschreibt die Teile des Beispielcodes, die die Textur und die Ansicht erstellen.
So initialisieren Sie eine Textur und eine Ansicht separat.
Rufen Sie CoCreateInstance auf, um die Imaging Factory-Schnittstelle (IWICImagingFactory) zu erstellen.
Rufen Sie die IWICImagingFactory::CreateDecoderFromFilename-Methode auf, um ein IWICBitmapDecoder-Objekt aus einem Imagedateinamen zu erstellen.
Rufen Sie die IWICBitmapDecoder::GetFrame-Methode auf, um die IWICBitmapFrameDecode-Schnittstelle für den Bildrahmen abzurufen.
Rufen Sie die IWICBitmapSource::GetPixelFormat-Methode (IWICBitmapFrameDecode-Schnittstelle erbt von IWICBitmapSource) auf, um das Pixelformat des Bilds abzurufen.
Konvertieren Sie das Pixelformat gemäß dieser Tabelle in einen DXGI_FORMAT-Typ :
WIC-Pixelformat Gleichwertige DXGI_FORMAT GUID_WICPixelFormat128bppRGBAFloat DXGI_FORMAT_R32G32B32A32_FLOAT GUID_WICPixelFormat64bppRGBAHalf DXGI_FORMAT_R16G16B16A16_FLOAT GUID_WICPixelFormat64bppRGBA DXGI_FORMAT_R16G16B16A16_UNORM GUID_WICPixelFormat32bppRGBA DXGI_FORMAT_R8G8B8A8_UNORM GUID_WICPixelFormat32bppBGRA DXGI_FORMAT_B8G8R8A8_UNORM (DXGI 1.1) GUID_WICPixelFormat32bppBGR DXGI_FORMAT_B8G8R8X8_UNORM (DXGI 1.1) GUID_WICPixelFormat32bppRGBA1010102XR DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM (DXGI 1.1) GUID_WICPixelFormat32bppRGBA1010102 DXGI_FORMAT_R10G10B10A2_UNORM GUID_WICPixelFormat32bppRGBE DXGI_FORMAT_R9G9B9E5_SHAREDEXP GUID_WICPixelFormat16bppBGRA5551 DXGI_FORMAT_B5G5R5A1_UNORM (DXGI 1.2) GUID_WICPixelFormat16bppBGR565 DXGI_FORMAT_B5G6R5_UNORM (DXGI 1.2) GUID_WICPixelFormat32bppGrayFloat DXGI_FORMAT_R32_FLOAT* GUID_WICPixelFormat16bppGrayHalf DXGI_FORMAT_R16_FLOAT* GUID_WICPixelFormat16bppGray DXGI_FORMAT_R16_UNORM* GUID_WICPixelFormat8bppGray DXGI_FORMAT_R8_UNORM* GUID_WICPixelFormat8bppAlpha DXGI_FORMAT_A8_UNORM GUID_WICPixelFormat96bppRGBFloat (Windows 8 WIC) DXGI_FORMAT_R32G32B32_FLOAT * Die DXGI-Formate mit einem Kanal sind alle roten Kanäle. Daher benötigen Sie HLSL-Shader-Swizzles wie .rrr, um diese als Graustufen zu rendern.
Rufen Sie die IWICBitmapSource::CopyPixels-Methode auf, um die Bildpixel in einen Puffer zu kopieren. Verwenden Sie den DXGI_FORMAT Typ und den Puffer, um die 2D-Texturressource und das Shader-resource-view-Objekt zu initialisieren.
Rufen Sie die ID3D11Device::CreateTexture2D-Methode auf, um die 2D-Texturressource zu initialisieren. Übergeben Sie in diesem Aufruf die Adresse eines ID3D11Texture2D-Schnittstellenzeigers .
// Create texture D3D11_TEXTURE2D_DESC desc; desc.Width = width; desc.Height = height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = temp.get(); initData.SysMemPitch = static_cast<UINT>( rowPitch ); initData.SysMemSlicePitch = static_cast<UINT>( imageSize ); ID3D11Texture2D* tex = nullptr; hr = d3dDevice->CreateTexture2D( &desc, &initData, &tex );
Rufen Sie die ID3D11Device::CreateShaderResourceView-Methode auf, um ein Shader-resource-view-Objekt zu initialisieren. Übergeben Sie entweder eine NULL-Shader-Resource-View-Beschreibung (zum Abrufen einer Ansicht mit Standardparametern) oder eine Shader-Resource-View-Beschreibung ohne NULL (um eine Ansicht mit nicht standardmäßigen Parametern abzurufen). Ermitteln Sie ggf. den Texturtyp, indem Sie ID3D11Resource::GetType und das Texturformat aufrufen, indem Sie ID3D11ShaderResourceView::GetDesc aufrufen.
if ( SUCCEEDED(hr) && tex != 0 ) { if (textureView != 0) { D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; memset( &SRVDesc, 0, sizeof( SRVDesc ) ); SRVDesc.Format = format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = 1; hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView ); if ( FAILED(hr) ) { tex->Release(); return hr; } } }
Im vorherigen Beispielcode wird davon ausgegangen, dass es sich bei der Variablen d3dDevice um ein ID3D11Device-Objekt handelt, das zuvor initialisiert wurde.
Hier ist der Header, den Sie in Ihre App einschließen können. Der Header deklariert die Funktionen CreateWICTextureFromFile und CreateWICTextureFromMemory , die Sie in Ihrer App aufrufen können, um eine Textur aus einer Datei und aus dem Arbeitsspeicher zu erstellen.
//--------------------------------------------------------------------------------------
// File: WICTextureLoader.h
//
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
// (auto-generating mipmaps if possible)
//
// Note: Assumes application has already called CoInitializeEx
//
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
// auto-gen mipmap support.
//
// 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.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// https://go.microsoft.com/fwlink/?LinkId=248926
// https://go.microsoft.com/fwlink/?LinkId=248929
//--------------------------------------------------------------------------------------
#ifdef _MSC_VER
#pragma once
#endif
#include <d3d11.h>
#pragma warning(push)
#pragma warning(disable : 4005)
#include <stdint.h>
#pragma warning(pop)
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_bytecount_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
Hier ist die vollständige Quelle, die Sie in Ihrer App verwenden können. Die Quelle implementiert die Funktionen CreateWICTextureFromFile und CreateWICTextureFromMemory .
//--------------------------------------------------------------------------------------
// File: WICTextureLoader.cpp
//
// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it
// (auto-generating mipmaps if possible)
//
// Note: Assumes application has already called CoInitializeEx
//
// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for
// auto-gen mipmap support.
//
// 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.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// https://go.microsoft.com/fwlink/?LinkId=248926
// https://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 <dxgiformat.h>
#include <assert.h>
#pragma warning(push)
#pragma warning(disable : 4005)
#include <wincodec.h>
#pragma warning(pop)
#include <memory>
#include "WICTextureLoader.h"
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS)
#define DXGI_1_2_FORMATS
#endif
//---------------------------------------------------------------------------------
template<class T> class ScopedObject
{
public:
explicit ScopedObject( T *p = 0 ) : _pointer(p) {}
~ScopedObject()
{
if ( _pointer )
{
_pointer->Release();
_pointer = nullptr;
}
}
bool IsNull() const { return (!_pointer); }
T& operator*() { return *_pointer; }
T* operator->() { return _pointer; }
T** operator&() { return &_pointer; }
void Reset(T *p = 0) { if ( _pointer ) { _pointer->Release(); } _pointer = p; }
T* Get() const { return _pointer; }
private:
ScopedObject(const ScopedObject&);
ScopedObject& operator=(const ScopedObject&);
T* _pointer;
};
//-------------------------------------------------------------------------------------
// WIC Pixel Format Translation Data
//-------------------------------------------------------------------------------------
struct WICTranslate
{
GUID wic;
DXGI_FORMAT format;
};
static WICTranslate g_WICFormats[] =
{
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT },
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT },
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM },
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM },
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM },
{ GUID_WICPixelFormat32bppRGBE, DXGI_FORMAT_R9G9B9E5_SHAREDEXP },
#ifdef DXGI_1_2_FORMATS
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM },
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM },
#endif // DXGI_1_2_FORMATS
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT },
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT },
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM },
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM },
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM },
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
{ GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT },
#endif
};
//-------------------------------------------------------------------------------------
// WIC Pixel Format nearest conversion table
//-------------------------------------------------------------------------------------
struct WICConvert
{
GUID source;
GUID target;
};
static WICConvert g_WICConvert[] =
{
// Note target GUID in this conversion table must be one of those directly supported formats (above).
{ GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
{ GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
{ GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM
{ GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT
{ GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT
#ifdef DXGI_1_2_FORMATS
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM
#else
{ GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat16bppBGRA5551, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat16bppBGR565, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
#endif // DXGI_1_2_FORMATS
{ GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM
{ GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
{ GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
{ GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
{ GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
{ GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
{ GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
{ GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
{ GUID_WICPixelFormat96bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT
{ GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
{ GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
{ GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
{ GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT
#endif
// We don't support n-channel formats
};
//--------------------------------------------------------------------------------------
static IWICImagingFactory* _GetWIC()
{
static IWICImagingFactory* s_Factory = nullptr;
if ( s_Factory )
return s_Factory;
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
(LPVOID*)&s_Factory
);
if ( FAILED(hr) )
{
s_Factory = nullptr;
return nullptr;
}
return s_Factory;
}
//---------------------------------------------------------------------------------
static DXGI_FORMAT _WICToDXGI( const GUID& guid )
{
for( size_t i=0; i < _countof(g_WICFormats); ++i )
{
if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 )
return g_WICFormats[i].format;
}
return DXGI_FORMAT_UNKNOWN;
}
//---------------------------------------------------------------------------------
static size_t _WICBitsPerPixel( REFGUID targetGuid )
{
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return 0;
ScopedObject<IWICComponentInfo> cinfo;
if ( FAILED( pWIC->CreateComponentInfo( targetGuid, &cinfo ) ) )
return 0;
WICComponentType type;
if ( FAILED( cinfo->GetComponentType( &type ) ) )
return 0;
if ( type != WICPixelFormat )
return 0;
ScopedObject<IWICPixelFormatInfo> pfinfo;
if ( FAILED( cinfo->QueryInterface( __uuidof(IWICPixelFormatInfo), reinterpret_cast<void**>( &pfinfo ) ) ) )
return 0;
UINT bpp;
if ( FAILED( pfinfo->GetBitsPerPixel( &bpp ) ) )
return 0;
return bpp;
}
//---------------------------------------------------------------------------------
static HRESULT CreateTextureFromWIC( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_ IWICBitmapFrameDecode *frame,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize )
{
UINT width, height;
HRESULT hr = frame->GetSize( &width, &height );
if ( FAILED(hr) )
return hr;
assert( width > 0 && height > 0 );
if ( !maxsize )
{
// This is a bit conservative because the hardware could support larger textures than
// the Feature Level defined minimums, but doing it this way is much easier and more
// performant for WIC than the 'fail and retry' model used by DDSTextureLoader
switch( d3dDevice->GetFeatureLevel() )
{
case D3D_FEATURE_LEVEL_9_1:
case D3D_FEATURE_LEVEL_9_2:
maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
break;
case D3D_FEATURE_LEVEL_9_3:
maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
break;
case D3D_FEATURE_LEVEL_10_0:
case D3D_FEATURE_LEVEL_10_1:
maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/;
break;
default:
maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
break;
}
}
assert( maxsize > 0 );
UINT twidth, theight;
if ( width > maxsize || height > maxsize )
{
float ar = static_cast<float>(height) / static_cast<float>(width);
if ( width > height )
{
twidth = static_cast<UINT>( maxsize );
theight = static_cast<UINT>( static_cast<float>(maxsize) * ar );
}
else
{
theight = static_cast<UINT>( maxsize );
twidth = static_cast<UINT>( static_cast<float>(maxsize) / ar );
}
assert( twidth <= maxsize && theight <= maxsize );
}
else
{
twidth = width;
theight = height;
}
// Determine format
WICPixelFormatGUID pixelFormat;
hr = frame->GetPixelFormat( &pixelFormat );
if ( FAILED(hr) )
return hr;
WICPixelFormatGUID convertGUID;
memcpy( &convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID) );
size_t bpp = 0;
DXGI_FORMAT format = _WICToDXGI( pixelFormat );
if ( format == DXGI_FORMAT_UNKNOWN )
{
for( size_t i=0; i < _countof(g_WICConvert); ++i )
{
if ( memcmp( &g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID) ) == 0 )
{
memcpy( &convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID) );
format = _WICToDXGI( g_WICConvert[i].target );
assert( format != DXGI_FORMAT_UNKNOWN );
bpp = _WICBitsPerPixel( convertGUID );
break;
}
}
if ( format == DXGI_FORMAT_UNKNOWN )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
else
{
bpp = _WICBitsPerPixel( pixelFormat );
}
if ( !bpp )
return E_FAIL;
// Verify our target format is supported by the current device
// (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support)
UINT support = 0;
hr = d3dDevice->CheckFormatSupport( format, &support );
if ( FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) )
{
// Fallback to RGBA 32-bit format which is supported by all devices
memcpy( &convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID) );
format = DXGI_FORMAT_R8G8B8A8_UNORM;
bpp = 32;
}
// Allocate temporary memory for image
size_t rowPitch = ( twidth * bpp + 7 ) / 8;
size_t imageSize = rowPitch * theight;
std::unique_ptr<uint8_t[]> temp( new uint8_t[ imageSize ] );
// Load image data
if ( memcmp( &convertGUID, &pixelFormat, sizeof(GUID) ) == 0
&& twidth == width
&& theight == height )
{
// No format conversion or resize needed
hr = frame->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
if ( FAILED(hr) )
return hr;
}
else if ( twidth != width || theight != height )
{
// Resize
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return E_NOINTERFACE;
ScopedObject<IWICBitmapScaler> scaler;
hr = pWIC->CreateBitmapScaler( &scaler );
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 = scaler->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
if ( FAILED(hr) )
return hr;
}
else
{
ScopedObject<IWICFormatConverter> FC;
hr = pWIC->CreateFormatConverter( &FC );
if ( FAILED(hr) )
return hr;
hr = FC->Initialize( scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
if ( FAILED(hr) )
return hr;
}
}
else
{
// Format conversion but no resize
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return E_NOINTERFACE;
ScopedObject<IWICFormatConverter> FC;
hr = pWIC->CreateFormatConverter( &FC );
if ( FAILED(hr) )
return hr;
hr = FC->Initialize( frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom );
if ( FAILED(hr) )
return hr;
hr = FC->CopyPixels( 0, static_cast<UINT>( rowPitch ), static_cast<UINT>( imageSize ), temp.get() );
if ( FAILED(hr) )
return hr;
}
// See if format is supported for auto-gen mipmaps (varies by feature level)
bool autogen = false;
if ( d3dContext != 0 && textureView != 0 ) // Must have context and shader-view to auto generate mipmaps
{
UINT fmtSupport = 0;
hr = d3dDevice->CheckFormatSupport( format, &fmtSupport );
if ( SUCCEEDED(hr) && ( fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN ) )
{
autogen = true;
}
}
// Create texture
D3D11_TEXTURE2D_DESC desc;
desc.Width = twidth;
desc.Height = theight;
desc.MipLevels = (autogen) ? 0 : 1;
desc.ArraySize = 1;
desc.Format = format;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE);
desc.CPUAccessFlags = 0;
desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = temp.get();
initData.SysMemPitch = static_cast<UINT>( rowPitch );
initData.SysMemSlicePitch = static_cast<UINT>( imageSize );
ID3D11Texture2D* tex = nullptr;
hr = d3dDevice->CreateTexture2D( &desc, (autogen) ? nullptr : &initData, &tex );
if ( SUCCEEDED(hr) && tex != 0 )
{
if (textureView != 0)
{
D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
memset( &SRVDesc, 0, sizeof( SRVDesc ) );
SRVDesc.Format = format;
SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1;
hr = d3dDevice->CreateShaderResourceView( tex, &SRVDesc, textureView );
if ( FAILED(hr) )
{
tex->Release();
return hr;
}
if ( autogen )
{
assert( d3dContext != 0 );
d3dContext->UpdateSubresource( tex, 0, nullptr, temp.get(), static_cast<UINT>(rowPitch), static_cast<UINT>(imageSize) );
d3dContext->GenerateMips( *textureView );
}
}
if (texture != 0)
{
*texture = tex;
}
else
{
#if defined(_DEBUG) || defined(PROFILE)
tex->SetPrivateData( WKPDID_D3DDebugObjectName,
sizeof("WICTextureLoader")-1,
"WICTextureLoader"
);
#endif
tex->Release();
}
}
return hr;
}
//--------------------------------------------------------------------------------------
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_bytecount_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize
)
{
if (!d3dDevice || !wicData || (!texture && !textureView))
{
return E_INVALIDARG;
}
if ( !wicDataSize )
{
return E_FAIL;
}
#ifdef _M_AMD64
if ( wicDataSize > 0xFFFFFFFF )
return HRESULT_FROM_WIN32( ERROR_FILE_TOO_LARGE );
#endif
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return E_NOINTERFACE;
// Create input stream for memory
ScopedObject<IWICStream> stream;
HRESULT hr = pWIC->CreateStream( &stream );
if ( FAILED(hr) )
return hr;
hr = stream->InitializeFromMemory( const_cast<uint8_t*>( wicData ), static_cast<DWORD>( wicDataSize ) );
if ( FAILED(hr) )
return hr;
// Initialize WIC
ScopedObject<IWICBitmapDecoder> decoder;
hr = pWIC->CreateDecoderFromStream( stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder );
if ( FAILED(hr) )
return hr;
ScopedObject<IWICBitmapFrameDecode> frame;
hr = decoder->GetFrame( 0, &frame );
if ( FAILED(hr) )
return hr;
hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize );
if ( FAILED(hr))
return hr;
#if defined(_DEBUG) || defined(PROFILE)
if (texture != 0 && *texture != 0)
{
(*texture)->SetPrivateData( WKPDID_D3DDebugObjectName,
sizeof("WICTextureLoader")-1,
"WICTextureLoader"
);
}
if (textureView != 0 && *textureView != 0)
{
(*textureView)->SetPrivateData( WKPDID_D3DDebugObjectName,
sizeof("WICTextureLoader")-1,
"WICTextureLoader"
);
}
#endif
return hr;
}
//--------------------------------------------------------------------------------------
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* fileName,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize )
{
if (!d3dDevice || !fileName || (!texture && !textureView))
{
return E_INVALIDARG;
}
IWICImagingFactory* pWIC = _GetWIC();
if ( !pWIC )
return E_NOINTERFACE;
// Initialize WIC
ScopedObject<IWICBitmapDecoder> decoder;
HRESULT hr = pWIC->CreateDecoderFromFilename( fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder );
if ( FAILED(hr) )
return hr;
ScopedObject<IWICBitmapFrameDecode> frame;
hr = decoder->GetFrame( 0, &frame );
if ( FAILED(hr) )
return hr;
hr = CreateTextureFromWIC( d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize );
if ( FAILED(hr))
return hr;
#if defined(_DEBUG) || defined(PROFILE)
if (texture != 0 || textureView != 0)
{
CHAR strFileA[MAX_PATH];
WideCharToMultiByte( CP_ACP,
WC_NO_BEST_FIT_CHARS,
fileName,
-1,
strFileA,
MAX_PATH,
nullptr,
FALSE
);
const CHAR* pstrName = strrchr( strFileA, '\\' );
if (!pstrName)
{
pstrName = strFileA;
}
else
{
pstrName++;
}
if (texture != 0 && *texture != 0)
{
(*texture)->SetPrivateData( WKPDID_D3DDebugObjectName,
static_cast<UINT>( strnlen_s(pstrName, MAX_PATH) ),
pstrName
);
}
if (textureView != 0 && *textureView != 0 )
{
(*textureView)->SetPrivateData( WKPDID_D3DDebugObjectName,
static_cast<UINT>( strnlen_s(pstrName, MAX_PATH) ),
pstrName
);
}
}
#endif
return hr;
}
Zugehörige Themen