From 450a6606cedbf45aa888637058af4742d5491b01 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sun, 28 Apr 2019 14:32:59 -0700 Subject: Implemented loading textures from KTX --- TextureLoader/src/TextureLoader.cpp | 360 ++++++++++++++++++------------------ 1 file changed, 181 insertions(+), 179 deletions(-) (limited to 'TextureLoader/src/TextureLoader.cpp') diff --git a/TextureLoader/src/TextureLoader.cpp b/TextureLoader/src/TextureLoader.cpp index 1f63aae..50ba00a 100644 --- a/TextureLoader/src/TextureLoader.cpp +++ b/TextureLoader/src/TextureLoader.cpp @@ -34,209 +34,211 @@ namespace Diligent { - template - ChannelType SRGBAverage(ChannelType c0, ChannelType c1, ChannelType c2, ChannelType c3) - { - constexpr float NormVal = static_cast(std::numeric_limits::max()); - float fc0 = static_cast(c0) / NormVal; - float fc1 = static_cast(c1) / NormVal; - float fc2 = static_cast(c2) / NormVal; - float fc3 = static_cast(c3) / NormVal; - - float fLinearAverage = (SRGBToLinear( fc0 ) + SRGBToLinear( fc1 ) + SRGBToLinear( fc2 ) + SRGBToLinear( fc3 )) / 4.f; - float fSRGBAverage = LinearToSRGB(fLinearAverage); - Int32 SRGBAverage = static_cast(fSRGBAverage * NormVal); - SRGBAverage = std::min(SRGBAverage, static_cast( std::numeric_limits::max()) ); - SRGBAverage = std::max(SRGBAverage, static_cast( std::numeric_limits::min()) ); - return static_cast(SRGBAverage); - } - template < typename ChannelType > - void ComputeCoarseMip(Uint32 NumChannels, bool IsSRGB, - const void* pFineMip, - Uint32 FineMipStride, - void* pCoarseMip, - Uint32 CoarseMipStride, - Uint32 CoarseMipWidth, - Uint32 CoarseMipHeight) - { - for( size_t row = 0; row < size_t{CoarseMipHeight}; ++row ) - for( size_t col = 0; col < size_t{CoarseMipWidth}; ++col ) - { - auto FineRow0 = reinterpret_cast( reinterpret_cast(pFineMip) + row * 2 * size_t{FineMipStride} ); - auto FineRow1 = reinterpret_cast( reinterpret_cast(pFineMip) + (row * 2 + 1 ) * size_t{FineMipStride} ); +template +ChannelType SRGBAverage(ChannelType c0, ChannelType c1, ChannelType c2, ChannelType c3) +{ + constexpr float NormVal = static_cast(std::numeric_limits::max()); + float fc0 = static_cast(c0) / NormVal; + float fc1 = static_cast(c1) / NormVal; + float fc2 = static_cast(c2) / NormVal; + float fc3 = static_cast(c3) / NormVal; + + float fLinearAverage = (SRGBToLinear( fc0 ) + SRGBToLinear( fc1 ) + SRGBToLinear( fc2 ) + SRGBToLinear( fc3 )) / 4.f; + float fSRGBAverage = LinearToSRGB(fLinearAverage); + Int32 SRGBAverage = static_cast(fSRGBAverage * NormVal); + SRGBAverage = std::min(SRGBAverage, static_cast( std::numeric_limits::max()) ); + SRGBAverage = std::max(SRGBAverage, static_cast( std::numeric_limits::min()) ); + return static_cast(SRGBAverage); +} + +template < typename ChannelType > +void ComputeCoarseMip(Uint32 NumChannels, bool IsSRGB, + const void* pFineMip, + Uint32 FineMipStride, + void* pCoarseMip, + Uint32 CoarseMipStride, + Uint32 CoarseMipWidth, + Uint32 CoarseMipHeight) +{ + for( size_t row = 0; row < size_t{CoarseMipHeight}; ++row ) + for( size_t col = 0; col < size_t{CoarseMipWidth}; ++col ) + { + auto FineRow0 = reinterpret_cast( reinterpret_cast(pFineMip) + row * 2 * size_t{FineMipStride} ); + auto FineRow1 = reinterpret_cast( reinterpret_cast(pFineMip) + (row * 2 + 1 ) * size_t{FineMipStride} ); - for( Uint32 c = 0; c < NumChannels; ++c ) - { - auto Col00 = FineRow0[ col*2 * NumChannels + c ]; - auto Col01 = FineRow0[ (col*2+1) * NumChannels + c ]; - auto Col10 = FineRow1[ col*2 * NumChannels + c ]; - auto Col11 = FineRow1[ (col*2+1) * NumChannels + c ]; - auto &DstCol = reinterpret_cast(reinterpret_cast(pCoarseMip) + row * size_t{CoarseMipStride})[col * NumChannels + c]; - if( IsSRGB ) - DstCol = SRGBAverage( Col00, Col01, Col10, Col11 ); - else - DstCol = (Col00 + Col01 + Col10 + Col11)/4; - } + for( Uint32 c = 0; c < NumChannels; ++c ) + { + auto Col00 = FineRow0[ col*2 * NumChannels + c ]; + auto Col01 = FineRow0[ (col*2+1) * NumChannels + c ]; + auto Col10 = FineRow1[ col*2 * NumChannels + c ]; + auto Col11 = FineRow1[ (col*2+1) * NumChannels + c ]; + auto &DstCol = reinterpret_cast(reinterpret_cast(pCoarseMip) + row * size_t{CoarseMipStride})[col * NumChannels + c]; + if( IsSRGB ) + DstCol = SRGBAverage( Col00, Col01, Col10, Col11 ); + else + DstCol = (Col00 + Col01 + Col10 + Col11)/4; } - } + } +} - template < typename ChannelType > - void RGBToRGBA(const void* pRGBData, - Uint32 RGBStride, - void* pRGBAData, - Uint32 RGBAStride, - Uint32 Width, - Uint32 Height) - { - for( size_t row = 0; row < size_t{Height}; ++row ) - for( size_t col = 0; col < size_t{Width}; ++col ) +template < typename ChannelType > +void RGBToRGBA(const void* pRGBData, + Uint32 RGBStride, + void* pRGBAData, + Uint32 RGBAStride, + Uint32 Width, + Uint32 Height) +{ + for( size_t row = 0; row < size_t{Height}; ++row ) + for( size_t col = 0; col < size_t{Width}; ++col ) + { + for( int c = 0; c < 3; ++c ) { - for( int c = 0; c < 3; ++c ) - { - reinterpret_cast( (reinterpret_cast(pRGBAData) + size_t{RGBAStride} * row) ) [col *4 + c] = - reinterpret_cast( (reinterpret_cast(pRGBData) + size_t{RGBStride} * row))[col*3 + c]; - } - reinterpret_cast( (reinterpret_cast(pRGBAData) + size_t{RGBAStride} * row) ) [col *4 + 3] = std::numeric_limits::max(); + reinterpret_cast( (reinterpret_cast(pRGBAData) + size_t{RGBAStride} * row) ) [col *4 + c] = + reinterpret_cast( (reinterpret_cast(pRGBData) + size_t{RGBStride} * row))[col*3 + c]; } - } + reinterpret_cast( (reinterpret_cast(pRGBAData) + size_t{RGBAStride} * row) ) [col *4 + 3] = std::numeric_limits::max(); + } +} - void CreateTextureFromImage( Image* pSrcImage, - const TextureLoadInfo& TexLoadInfo, - IRenderDevice* pDevice, - ITexture** ppTexture ) +void CreateTextureFromImage( Image* pSrcImage, + const TextureLoadInfo& TexLoadInfo, + IRenderDevice* pDevice, + ITexture** ppTexture ) +{ + const auto& ImgDesc = pSrcImage->GetDesc(); + TextureDesc TexDesc; + TexDesc.Name = TexLoadInfo.Name; + TexDesc.Type = RESOURCE_DIM_TEX_2D; + TexDesc.Width = ImgDesc.Width; + TexDesc.Height = ImgDesc.Height; + TexDesc.MipLevels = ComputeMipLevelsCount( TexDesc.Width, TexDesc.Height ); + if( TexLoadInfo.MipLevels > 0 ) + TexDesc.MipLevels = std::min(TexDesc.MipLevels, TexLoadInfo.MipLevels); + TexDesc.Usage = TexLoadInfo.Usage; + TexDesc.BindFlags = TexLoadInfo.BindFlags; + TexDesc.Format = TexLoadInfo.Format; + TexDesc.CPUAccessFlags = TexLoadInfo.CPUAccessFlags; + auto ChannelDepth = ImgDesc.BitsPerPixel / ImgDesc.NumComponents; + + Uint32 NumComponents = ImgDesc.NumComponents == 3 ? 4 : ImgDesc.NumComponents; + bool IsSRGB = (ImgDesc.NumComponents >= 3 && ChannelDepth == 8) ? TexLoadInfo.IsSRGB : false; + if( TexDesc.Format == TEX_FORMAT_UNKNOWN ) { - const auto& ImgDesc = pSrcImage->GetDesc(); - TextureDesc TexDesc; - TexDesc.Name = TexLoadInfo.Name; - TexDesc.Type = RESOURCE_DIM_TEX_2D; - TexDesc.Width = ImgDesc.Width; - TexDesc.Height = ImgDesc.Height; - TexDesc.MipLevels = ComputeMipLevelsCount( TexDesc.Width, TexDesc.Height ); - if( TexLoadInfo.MipLevels > 0 ) - TexDesc.MipLevels = std::min(TexDesc.MipLevels, TexLoadInfo.MipLevels); - TexDesc.Usage = TexLoadInfo.Usage; - TexDesc.BindFlags = TexLoadInfo.BindFlags; - TexDesc.Format = TexLoadInfo.Format; - TexDesc.CPUAccessFlags = TexLoadInfo.CPUAccessFlags; - auto ChannelDepth = ImgDesc.BitsPerPixel / ImgDesc.NumComponents; - - Uint32 NumComponents = ImgDesc.NumComponents == 3 ? 4 : ImgDesc.NumComponents; - bool IsSRGB = (ImgDesc.NumComponents >= 3 && ChannelDepth == 8) ? TexLoadInfo.IsSRGB : false; - if( TexDesc.Format == TEX_FORMAT_UNKNOWN ) + if( ChannelDepth == 8 ) { - if( ChannelDepth == 8 ) + switch( NumComponents ) { - switch( NumComponents ) - { - case 1: TexDesc.Format = TEX_FORMAT_R8_UNORM; break; - case 2: TexDesc.Format = TEX_FORMAT_RG8_UNORM; break; - case 4: TexDesc.Format = IsSRGB ? TEX_FORMAT_RGBA8_UNORM_SRGB : TEX_FORMAT_RGBA8_UNORM; break; - default: LOG_ERROR_AND_THROW( "Unexpected number of color channels (", ImgDesc.NumComponents, ")" ); - } + case 1: TexDesc.Format = TEX_FORMAT_R8_UNORM; break; + case 2: TexDesc.Format = TEX_FORMAT_RG8_UNORM; break; + case 4: TexDesc.Format = IsSRGB ? TEX_FORMAT_RGBA8_UNORM_SRGB : TEX_FORMAT_RGBA8_UNORM; break; + default: LOG_ERROR_AND_THROW( "Unexpected number of color channels (", ImgDesc.NumComponents, ")" ); } - else if( ChannelDepth == 16 ) + } + else if( ChannelDepth == 16 ) + { + switch( NumComponents ) { - switch( NumComponents ) - { - case 1: TexDesc.Format = TEX_FORMAT_R16_UNORM; break; - case 2: TexDesc.Format = TEX_FORMAT_RG16_UNORM; break; - case 4: TexDesc.Format = TEX_FORMAT_RGBA16_UNORM; break; - default: LOG_ERROR_AND_THROW( "Unexpected number of color channels (", ImgDesc.NumComponents, ")" ); - } + case 1: TexDesc.Format = TEX_FORMAT_R16_UNORM; break; + case 2: TexDesc.Format = TEX_FORMAT_RG16_UNORM; break; + case 4: TexDesc.Format = TEX_FORMAT_RGBA16_UNORM; break; + default: LOG_ERROR_AND_THROW( "Unexpected number of color channels (", ImgDesc.NumComponents, ")" ); } - else - LOG_ERROR_AND_THROW( "Unsupported color channel depth (", ChannelDepth, ")" ); } else - { - const auto& TexFmtDesc = GetTextureFormatAttribs( TexDesc.Format ); - if( TexFmtDesc.NumComponents != NumComponents ) - LOG_ERROR_AND_THROW( "Incorrect number of components ", ImgDesc.NumComponents, ") for texture format ", TexFmtDesc.Name ); - if( TexFmtDesc.ComponentSize != ChannelDepth / 8 ) - LOG_ERROR_AND_THROW( "Incorrect channel size ", ChannelDepth, ") for texture format ", TexFmtDesc.Name ); - } + LOG_ERROR_AND_THROW( "Unsupported color channel depth (", ChannelDepth, ")" ); + } + else + { + const auto& TexFmtDesc = GetTextureFormatAttribs( TexDesc.Format ); + if( TexFmtDesc.NumComponents != NumComponents ) + LOG_ERROR_AND_THROW( "Incorrect number of components ", ImgDesc.NumComponents, ") for texture format ", TexFmtDesc.Name ); + if( TexFmtDesc.ComponentSize != ChannelDepth / 8 ) + LOG_ERROR_AND_THROW( "Incorrect channel size ", ChannelDepth, ") for texture format ", TexFmtDesc.Name ); + } - std::vector pSubResources(TexDesc.MipLevels); - std::vector< std::vector > Mips(TexDesc.MipLevels); + std::vector pSubResources(TexDesc.MipLevels); + std::vector< std::vector > Mips(TexDesc.MipLevels); - if( ImgDesc.NumComponents == 3 ) - { - VERIFY_EXPR( NumComponents == 4 ); - auto RGBAStride = ImgDesc.Width * NumComponents * ChannelDepth / 8; - RGBAStride = (RGBAStride + 3) & (-4); - Mips[0].resize(size_t{RGBAStride} * size_t{ImgDesc.Height}); - pSubResources[0].pData = Mips[0].data(); - pSubResources[0].Stride = RGBAStride; - if( ChannelDepth == 8 ) - RGBToRGBA( pSrcImage->GetData()->GetDataPtr(), ImgDesc.RowStride, - Mips[0].data(), RGBAStride, - ImgDesc.Width, ImgDesc.Height); - else if( ChannelDepth == 16 ) - RGBToRGBA( pSrcImage->GetData()->GetDataPtr(), ImgDesc.RowStride, - Mips[0].data(), RGBAStride, - ImgDesc.Width, ImgDesc.Height); - } - else - { - pSubResources[0].pData = pSrcImage->GetData()->GetDataPtr(); - pSubResources[0].Stride = ImgDesc.RowStride; - } + if( ImgDesc.NumComponents == 3 ) + { + VERIFY_EXPR( NumComponents == 4 ); + auto RGBAStride = ImgDesc.Width * NumComponents * ChannelDepth / 8; + RGBAStride = (RGBAStride + 3) & (-4); + Mips[0].resize(size_t{RGBAStride} * size_t{ImgDesc.Height}); + pSubResources[0].pData = Mips[0].data(); + pSubResources[0].Stride = RGBAStride; + if( ChannelDepth == 8 ) + RGBToRGBA( pSrcImage->GetData()->GetDataPtr(), ImgDesc.RowStride, + Mips[0].data(), RGBAStride, + ImgDesc.Width, ImgDesc.Height); + else if( ChannelDepth == 16 ) + RGBToRGBA( pSrcImage->GetData()->GetDataPtr(), ImgDesc.RowStride, + Mips[0].data(), RGBAStride, + ImgDesc.Width, ImgDesc.Height); + } + else + { + pSubResources[0].pData = pSrcImage->GetData()->GetDataPtr(); + pSubResources[0].Stride = ImgDesc.RowStride; + } - auto MipWidth = TexDesc.Width; - auto MipHeight = TexDesc.Height; - for( Uint32 m = 1; m < TexDesc.MipLevels; ++m ) + auto MipWidth = TexDesc.Width; + auto MipHeight = TexDesc.Height; + for( Uint32 m = 1; m < TexDesc.MipLevels; ++m ) + { + auto CoarseMipWidth = std::max(MipWidth/2u, 1u); + auto CoarseMipHeight = std::max(MipHeight/2u, 1u); + auto CoarseMipStride = CoarseMipWidth * NumComponents * ChannelDepth / 8; + CoarseMipStride = (CoarseMipStride + 3) & (-4); + Mips[m].resize(size_t{CoarseMipStride} * size_t{CoarseMipHeight}); + + if (TexLoadInfo.GenerateMips) { - auto CoarseMipWidth = std::max(MipWidth/2u, 1u); - auto CoarseMipHeight = std::max(MipHeight/2u, 1u); - auto CoarseMipStride = CoarseMipWidth * NumComponents * ChannelDepth / 8; - CoarseMipStride = (CoarseMipStride + 3) & (-4); - Mips[m].resize(size_t{CoarseMipStride} * size_t{CoarseMipHeight}); + if (ChannelDepth == 8) + ComputeCoarseMip(NumComponents, IsSRGB, + pSubResources[m - 1].pData, pSubResources[m - 1].Stride, + Mips[m].data(), CoarseMipStride, + CoarseMipWidth, CoarseMipHeight); + else if (ChannelDepth == 16) + ComputeCoarseMip(NumComponents, IsSRGB, + pSubResources[m - 1].pData, pSubResources[m - 1].Stride, + Mips[m].data(), CoarseMipStride, + CoarseMipWidth, CoarseMipHeight); + } - if (TexLoadInfo.GenerateMips) - { - if (ChannelDepth == 8) - ComputeCoarseMip(NumComponents, IsSRGB, - pSubResources[m - 1].pData, pSubResources[m - 1].Stride, - Mips[m].data(), CoarseMipStride, - CoarseMipWidth, CoarseMipHeight); - else if (ChannelDepth == 16) - ComputeCoarseMip(NumComponents, IsSRGB, - pSubResources[m - 1].pData, pSubResources[m - 1].Stride, - Mips[m].data(), CoarseMipStride, - CoarseMipWidth, CoarseMipHeight); - } + pSubResources[m].pData = Mips[m].data(); + pSubResources[m].Stride = CoarseMipStride; - pSubResources[m].pData = Mips[m].data(); - pSubResources[m].Stride = CoarseMipStride; + MipWidth = CoarseMipWidth; + MipHeight = CoarseMipHeight; + } - MipWidth = CoarseMipWidth; - MipHeight = CoarseMipHeight; - } + TextureData TexData; + TexData.pSubResources = pSubResources.data(); + TexData.NumSubresources = TexDesc.MipLevels; - TextureData TexData; - TexData.pSubResources = pSubResources.data(); - TexData.NumSubresources = TexDesc.MipLevels; + pDevice->CreateTexture( TexDesc, &TexData, ppTexture ); +} - pDevice->CreateTexture( TexDesc, &TexData, ppTexture ); - } +void CreateTextureFromDDS( IDataBlob* pDDSData, + const TextureLoadInfo& TexLoadInfo, + IRenderDevice* pDevice, + ITexture** ppTexture ) +{ + CreateDDSTextureFromMemoryEx(pDevice, + reinterpret_cast(pDDSData->GetDataPtr()), + static_cast(pDDSData->GetSize()), + 0, // maxSize + TexLoadInfo.Usage, + TexLoadInfo.Name, + TexLoadInfo.BindFlags, + TexLoadInfo.CPUAccessFlags, + MISC_TEXTURE_FLAG_NONE, // miscFlags + TexLoadInfo.IsSRGB, // forceSRGB + ppTexture ); +} - void CreateTextureFromDDS( IDataBlob *pDDSData, - const TextureLoadInfo& TexLoadInfo, - IRenderDevice *pDevice, - ITexture **ppTexture ) - { - CreateDDSTextureFromMemoryEx(pDevice, - reinterpret_cast(pDDSData->GetDataPtr()), - static_cast(pDDSData->GetSize()), - 0, // maxSize - TexLoadInfo.Usage, - TexLoadInfo.Name, - TexLoadInfo.BindFlags, - TexLoadInfo.CPUAccessFlags, - MISC_TEXTURE_FLAG_NONE, // miscFlags - TexLoadInfo.IsSRGB, // forceSRGB - ppTexture ); - } } -- cgit v1.2.3