21 #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
26 static XMVECTORF32 lScale = { 0.2125f, 0.7154f, 0.0721f, 1.f };
28 static_assert(
CNMAP_CHANNEL_RED == 0x1,
"CNMAP_CHANNEL_ flag values don't match mask" );
39 XMVECTOR v = XMVectorMultiply( val, lScale );
40 XMStoreFloat4A( &f, v );
41 return f.x + f.y + f.z;
52 _In_
size_t width, _In_ DWORD
flags )
54 assert( pSource && pDest );
57 for(
size_t x = 0; x < width; ++x )
77 _In_ DXGI_FORMAT
format, _In_
const Image& normalMap )
79 if ( !srcImage.pixels || !normalMap.pixels )
87 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
89 const size_t width = srcImage.width;
90 const size_t height = srcImage.height;
91 if ( width != normalMap.width || height != normalMap.height )
99 ScopedAlignedArrayFloat buffer( reinterpret_cast<float*>( _aligned_malloc( ( (
sizeof(
float) * ( width + 2 ) ) * 3 ), 16 ) ) );
101 return E_OUTOFMEMORY;
103 uint8_t* pDest = normalMap.pixels;
107 XMVECTOR* row0 = scanline.get();
108 XMVECTOR* row1 = row0 + width;
109 XMVECTOR* row2 = row1 + width;
110 XMVECTOR* target = row2 + width;
112 float* val0 = buffer.get();
113 float* val1 = val0 + width + 2;
114 float* val2 = val1 + width + 2;
116 const size_t rowPitch = srcImage.rowPitch;
117 const uint8_t* pSrc = srcImage.pixels;
120 if ( !
_LoadScanline( row1, width, pSrc, rowPitch, srcImage.format ) )
127 memcpy_s( row0, rowPitch, row1, rowPitch );
132 if ( !
_LoadScanline( row0, width, pSrc + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
142 for(
size_t y = 0;
y < height; ++
y )
145 if (
y < (height-1) )
147 if ( !
_LoadScanline( row2, width, pSrc, rowPitch, srcImage.format ) )
152 if ( flags & CNMAP_MIRROR_V )
155 if ( !
_LoadScanline( row2, width, srcImage.pixels + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
161 if ( !
_LoadScanline( row2, width, srcImage.pixels, rowPitch, srcImage.format ) )
170 XMVECTOR *dptr = target;
171 for(
size_t x = 0; x < width; ++x )
174 float totDelta = ( val0[x] - val0[x+2] ) + ( val1[x] - val1[x+2] ) + ( val2[x] - val2[x+2] );
175 float deltaZX = totDelta * amplitude / 6.f;
177 totDelta = ( val0[x] - val2[x] ) + ( val0[x+1] - val2[x+1] ) + ( val0[x+2] - val2[x+2] );
178 float deltaZY = totDelta * amplitude / 6.f;
180 XMVECTOR vx = XMVectorSetZ( g_XMNegIdentityR0, deltaZX );
181 XMVECTOR vy = XMVectorSetZ( g_XMNegIdentityR1, deltaZY );
183 XMVECTOR normal = XMVector3Normalize( XMVector3Cross( vx, vy ) );
193 float t = val0[x] - c;
if ( t > 0.f ) delta += t;
194 t = val0[x+1] - c;
if ( t > 0.f ) delta += t;
195 t = val0[x+2] - c;
if ( t > 0.f ) delta += t;
196 t = val1[x] - c;
if ( t > 0.f ) delta += t;
198 t = val1[x+2] - c;
if ( t > 0.f ) delta += t;
199 t = val2[x] - c;
if ( t > 0.f ) delta += t;
200 t = val2[x+1] - c;
if ( t > 0.f ) delta += t;
201 t = val2[x+2] - c;
if ( t > 0.f ) delta += t;
204 delta *= 0.125f * amplitude;
208 float r = sqrtf( 1.f + delta*delta );
209 alpha = (r - delta) / r;
217 XMVECTOR n1 = XMVectorMultiplyAdd( (flags &
CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf );
218 *dptr++ = XMVectorSetW( n1, alpha );
222 *dptr++ = XMVectorSetW( XMVectorNegate( normal ), alpha );
226 *dptr++ = XMVectorSetW( normal, alpha );
230 if ( !
_StoreScanline( pDest, normalMap.rowPitch, format, target, width ) )
240 pDest += normalMap.rowPitch;
254 _Use_decl_annotations_
261 static_assert(
CNMAP_CHANNEL_RED == 0x1,
"CNMAP_CHANNEL_ flag values don't match mask" );
262 switch( flags & 0xf )
280 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
296 hr =
_ComputeNMap( srcImage, flags, amplitude, format, *img );
306 _Use_decl_annotations_
310 if ( !srcImages || !nimages || !
IsValid(format) )
317 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
319 static_assert(
CNMAP_CHANNEL_RED == 0x1,
"CNMAP_CHANNEL_ flag values don't match mask" );
320 switch( flags & 0xf )
355 for(
size_t index=0; index < nimages; ++index )
357 assert( dest[ index ].format == format );
359 const Image& src = srcImages[ index ];
363 return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
372 hr =
_ComputeNMap( src, flags, amplitude, format, dest[ index ] );
std::unique_ptr< DirectX::XMVECTOR, aligned_deleter > ScopedAlignedArrayXMVECTOR
const Image * GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const
bool IsPlanar(_In_ DXGI_FORMAT fmt)
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
HRESULT Initialize(_In_ const TexMetadata &mdata, _In_ DWORD flags=CP_FLAGS_NONE)
HRESULT Initialize2D(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags=CP_FLAGS_NONE)
_Use_decl_annotations_ bool _LoadScanline(XMVECTOR *pDestination, size_t count, LPCVOID pSource, size_t size, DXGI_FORMAT format)
bool IsCompressed(_In_ DXGI_FORMAT fmt)
size_t GetImageCount() const
_In_ size_t _In_ const TexMetadata & metadata
_Use_decl_annotations_ DWORD _GetConvertFlags(DXGI_FORMAT format)
bool IsValid(_In_ DXGI_FORMAT fmt)
std::unique_ptr< float, aligned_deleter > ScopedAlignedArrayFloat
static float _EvaluateColor(_In_ FXMVECTOR val, _In_ DWORD flags)
_In_ size_t _In_ const TexMetadata _In_ DWORD _Out_writes_(nImages) Image *images
bool IsPalettized(_In_ DXGI_FORMAT fmt)
_In_ size_t _In_ DXGI_FORMAT _In_reads_(count) const XMVECTOR *pSource
bool IsTypeless(_In_ DXGI_FORMAT fmt, _In_ bool partialTypeless=true)
static HRESULT _ComputeNMap(_In_ const Image &srcImage, _In_ DWORD flags, _In_ float amplitude, _In_ DXGI_FORMAT format, _In_ const Image &normalMap)
HRESULT ComputeNormalMap(_In_ const Image &srcImage, _In_ DWORD flags, _In_ float amplitude, _In_ DXGI_FORMAT format, _Out_ ScratchImage &normalMap)
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
const Image * GetImages() const
static void _EvaluateRow(_In_reads_(width) const XMVECTOR *pSource, _Out_writes_(width+2) float *pDest, _In_ size_t width, _In_ DWORD flags)
_Use_decl_annotations_ bool _StoreScanline(LPVOID pDestination, size_t size, DXGI_FORMAT format, const XMVECTOR *pSource, size_t count, float threshold)