Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Astc normal maps #493

Merged
merged 36 commits into from
Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
cbddc69
Add first implementation of normal map support
wasimabbas-arm Oct 14, 2021
8e9e39f
Fix astc normal mode and add tests
wasimabbas-arm Oct 19, 2021
96364e0
Update docs
abbaswasim Nov 9, 2021
c989580
Update reference images
abbaswasim Nov 15, 2021
bcebc17
Update reference generator script
abbaswasim Nov 15, 2021
e381b43
Add error message when normal mode is used with non-linear textures
abbaswasim Nov 15, 2021
17799dd
Update docs
abbaswasim Nov 15, 2021
2b63d44
Fix astc normal map tests
abbaswasim Nov 26, 2021
1618ca4
Fix some typos
abbaswasim Nov 29, 2021
a90bb69
Add blank line
abbaswasim Nov 30, 2021
22d0dd1
Add Iron_Bars_001_normal and move normal mode swizzle selection to to…
abbaswasim Dec 17, 2021
ca2d9a2
Rename Iron_Bars_001_normal to be more explicit that its not normalized
abbaswasim Dec 21, 2021
dadacb2
Add normalize option
abbaswasim Dec 21, 2021
f054401
Add normalize support
abbaswasim Dec 21, 2021
9636d90
Add normal map .png versions
abbaswasim Dec 21, 2021
4c00a18
Normal map support for different types (uint8, uint16, float32 etc, f…
abbaswasim Dec 23, 2021
1376f77
Change basisu::clamp to cclamp
abbaswasim Dec 29, 2021
d92aa03
Minor documentation changes, remove separateRGToRGBA_A from basis opt…
abbaswasim Feb 4, 2022
0140218
Add normalisation tests
abbaswasim Feb 7, 2022
4ec4dac
Add normal_mode tests for uastc and etc1s
abbaswasim Feb 7, 2022
07b9a46
Corrects documentation
abbaswasim Feb 7, 2022
4c52f30
Corrects documentation
abbaswasim Feb 7, 2022
b43c1df
Remove useless messages from astc-encode
abbaswasim Feb 7, 2022
812bd2b
Change unittests.cpp to image_unittests.cc
abbaswasim Feb 8, 2022
a3f67c4
Add --normalize to normal tests
abbaswasim Feb 8, 2022
edc6b73
Fix writerScParams issues, now correctly encodes encoder params
abbaswasim Feb 8, 2022
dc29f3d
Change golden images after writerScParams bug fix
abbaswasim Feb 8, 2022
7e1384b
Merge branch 'KhronosGroup:master' into astc_normal_maps
wasimabbas-arm Feb 8, 2022
c44f03f
Add space after @b
abbaswasim Feb 8, 2022
a883d71
Fix normalize and normal_mode documentation
abbaswasim Feb 9, 2022
e6d7458
Allow inputSwizzle to be set for normal maps.
abbaswasim Feb 9, 2022
b85772a
Move normal mode swizzle selection to astc_encode and basis_encode
abbaswasim Feb 9, 2022
04f9cb5
Update reference images
abbaswasim Feb 9, 2022
d10c7ce
Fix inputSwizzle and normalSwizzle
abbaswasim Feb 15, 2022
3939a12
Refactor and formating fixes
abbaswasim Feb 15, 2022
2bba286
Limit etc1s test to apple
abbaswasim Feb 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions include/ktx.h
Original file line number Diff line number Diff line change
Expand Up @@ -1291,22 +1291,19 @@ typedef struct ktxBasisParams {
This will override the value chosen by @c qualityLevel.
*/
char inputSwizzle[4];
/*!< A swizzle to apply before encoding. It must match the regular
/*!< A swizzle to apply before encoding. It must match the regular
expression /^[rgba01]{4}$/. If both this and preSwizzle
are specified ktxTexture_CompressBasisEx will raise
KTX_INVALID_OPERATION. */

KTX_INVALID_OPERATION.
*/
ktx_bool_t normalMap;
/*!< Tunes codec parameters for better quality on normal maps (no
selector RDO, no endpoint RDO). Only valid for linear textures.
selector RDO, no endpoint RDO) and sets the texture's DFD appropriately.
Only valid for linear textures.
*/
ktx_bool_t separateRGToRGB_A;
/*!< Separates the input R and G channels to RGB and A (for tangent
space XY normal maps). Equivalent to @c inputSwizzle "rrrg".
Separation is the default for 2 component textures. If both this
and inputSwizzle are set, the latter wins therefore set
@c inputSwizzle to change the default for 2 component
textures.
/*!< @deprecated. This was and is a no-op. 2-component inputs have always been
automatically separated using an "rrrg" inputSwizzle. @sa inputSwizzle and normalMode.
*/
ktx_bool_t preSwizzle;
/*!< If the texture has @c KTXswizzle metadata, apply it before
Expand Down
18 changes: 4 additions & 14 deletions lib/astc_encode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ static ktxAstcParams
astcDefaultOptions() {
ktxAstcParams params{};
params.structSize = sizeof(params);
params.verbose = false;
params.threadCount = 1;
params.blockDimension = KTX_PACK_ASTC_BLOCK_DIMENSION_6x6;
params.mode = KTX_PACK_ASTC_ENCODER_MODE_LDR;
Expand Down Expand Up @@ -599,6 +598,7 @@ ktxTexture2_CompressAstcEx(ktxTexture2* This, ktxAstcParams* params) {
astcenc_profile profile{ASTCENC_PRF_LDR_SRGB};

astcenc_swizzle swizzle{ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A};
const astcenc_swizzle normal_swizzle{ASTCENC_SWZ_R, ASTCENC_SWZ_R, ASTCENC_SWZ_R, ASTCENC_SWZ_G};

uint32_t block_size_x{6};
uint32_t block_size_y{6};
Expand All @@ -610,7 +610,7 @@ ktxTexture2_CompressAstcEx(ktxTexture2* This, ktxAstcParams* params) {
block_size_x, block_size_y, block_size_z);
quality = astcQuality(params->qualityLevel);
profile = astcEncoderAction(*params, BDB);
swizzle = astcSwizzle(*params);
swizzle = params->normalMap ? normal_swizzle : astcSwizzle(*params);
MarkCallow marked this conversation as resolved.
Show resolved Hide resolved

astcenc_config astc_config;
astcenc_context *astc_context;
Expand All @@ -619,18 +619,14 @@ ktxTexture2_CompressAstcEx(ktxTexture2* This, ktxAstcParams* params) {
quality, flags,
&astc_config);

if (astc_error != ASTCENC_SUCCESS) {
std::cout << "ASTC config init failed with error " << astcenc_get_error_string(astc_error) << std::endl;
if (astc_error != ASTCENC_SUCCESS)
return KTX_INVALID_OPERATION;
}

astc_error = astcenc_context_alloc(&astc_config, threadCount,
&astc_context);

if (astc_error != ASTCENC_SUCCESS) {
std::cout << "ASTC context alloc failed with error " << astcenc_get_error_string(astc_error) << std::endl;
if (astc_error != ASTCENC_SUCCESS)
return KTX_INVALID_OPERATION;
}

// Walk in reverse on levels so we don't have to do this later
assert(prototype->dataSize && "Prototype texture size not initialized.\n");
Expand All @@ -657,12 +653,6 @@ ktxTexture2_CompressAstcEx(ktxTexture2* This, ktxAstcParams* params) {
ktx_size_t offset = ktxTexture2_levelDataOffset(This, level);

for (uint32_t image = 0; image < levelImages; image++) {
if (params->verbose)
std::cout << "ASTC compressor: compressing image " <<
(This->numLevels - level - 1) * levelImages + image + 1
<< " of " << This->numLevels * levelImages
<< std::endl;

astcenc_image *input_image = nullptr;
if (num_components == 1)
input_image = unorm8x1ArrayToImage(This->pData + offset,
Expand Down
96 changes: 59 additions & 37 deletions lib/basis_encode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ swizzle_rg_to_rgb_a(uint8_t* rgbadst, uint8_t* rgsrc, ktx_size_t image_size,
static KTX_error_code
ktxTexture2_rewriteDfd4BasisLzETC1S(ktxTexture2* This,
alpha_content_e alphaContent,
bool isLuminance)
bool isLuminance,
swizzle_e swizzle[4])
{
uint32_t* cdfd = This->pDfd;
uint32_t* cbdb = cdfd + 1;
Expand Down Expand Up @@ -270,7 +271,9 @@ ktxTexture2_rewriteDfd4BasisLzETC1S(ktxTexture2* This,
uint16_t channelId, bitOffset;
if (sample == 0) {
bitOffset = 0;
if (getDFDNumComponents(cdfd) < 3 && !isLuminance)

if (!isLuminance && swizzle
&& swizzle[0] == swizzle[1] && swizzle[1] == swizzle[2])
channelId = KHR_DF_CHANNEL_ETC1S_RRR;
else
channelId = KHR_DF_CHANNEL_ETC1S_RGB;
Expand Down Expand Up @@ -300,7 +303,9 @@ ktxTexture2_rewriteDfd4BasisLzETC1S(ktxTexture2* This,

static KTX_error_code
ktxTexture2_rewriteDfd4Uastc(ktxTexture2* This,
alpha_content_e alphaContent)
alpha_content_e alphaContent,
bool isLuminance,
swizzle_e swizzle[4])
{
uint32_t* cdfd = This->pDfd;
uint32_t* cbdb = cdfd + 1;
Expand Down Expand Up @@ -335,8 +340,11 @@ ktxTexture2_rewriteDfd4Uastc(ktxTexture2* This,
if (alphaContent == eAlpha) {
channelId = KHR_DF_CHANNEL_UASTC_RGBA;
} else if (alphaContent == eGreen) {
channelId = KHR_DF_CHANNEL_UASTC_RRRG;
} else if (swizzle && swizzle[2] == 0 && swizzle[3] == 1) {
channelId = KHR_DF_CHANNEL_UASTC_RG;
} else if (getDFDNumComponents(cdfd) == 1) {
} else if (!isLuminance && swizzle
&& swizzle[0] == swizzle[1] && swizzle[1] == swizzle[2]) {
channelId = KHR_DF_CHANNEL_UASTC_RRR;
} else {
channelId = KHR_DF_CHANNEL_UASTC_RGB;
Expand Down Expand Up @@ -389,8 +397,8 @@ static bool basisuEncoderInitialized = false;
* @exception KTX_INVALID_OPERATION
* The texture image format's component size is not 8-bits.
* @exception KTX_INVALID_OPERATION
* @c separateRGToRGB_A is specified but the texture
* has only 1 component.
* @c normalMode is specified but the texture has only
* one component.
* @exception KTX_INVALID_OPERATION
* Both preSwizzle and and inputSwizzle are specified
* in @a params.
Expand Down Expand Up @@ -426,8 +434,8 @@ ktxTexture2_CompressBasisEx(ktxTexture2* This, ktxBasisParams* params)
if (component_size != 1)
return KTX_INVALID_OPERATION; // Basis must have 8-bit components.

if (params->separateRGToRGB_A && num_components == 1)
return KTX_INVALID_OPERATION;
if (num_components == 1 && params->normalMap)
return KTX_INVALID_OPERATION; // Not enough components.

if (This->pData == NULL) {
result = ktxTexture2_LoadImageData(This, NULL, 0);
Expand Down Expand Up @@ -465,29 +473,21 @@ ktxTexture2_CompressBasisEx(ktxTexture2* This, ktxBasisParams* params)
cparams.m_source_images.resize(num_images);
basisu::vector<image>::iterator iit = cparams.m_source_images.begin();

swizzle_e meta_mapping[4] = {};
// Since we have to copy the data into the vector image anyway do the
// separation here to avoid another loop over the image inside
// basis_compressor.
swizzle_e rg_to_rgba_mapping_etc1s[4] = { R, R, R, G };
swizzle_e rg_to_rgba_mapping_uastc[4] = { R, G, ZERO, ONE };
swizzle_e normal_map_mapping[4] = { R, R, R, G };
swizzle_e r_to_rgba_mapping[4] = { R, R, R, ONE };
swizzle_e meta_mapping[4] = {};
// All the above declarations need to stay here so they remain in scope
// until after the pixel copy loop as comp_mapping will ultimately point
// to one of them.
swizzle_e* comp_mapping = 0;

alpha_content_e alphaContent = eNone;
bool isLuminance = false;
if (num_components == 1) {
comp_mapping = r_to_rgba_mapping;
} else if (num_components == 2) {
if (params->uastc)
comp_mapping = rg_to_rgba_mapping_uastc;
else {
comp_mapping = rg_to_rgba_mapping_etc1s;
alphaContent = eGreen;
}
} else if (num_components == 4) {
alphaContent = eAlpha;
}

std::string swizzleString = params->inputSwizzle;
if (params->preSwizzle) {
Expand All @@ -512,7 +512,24 @@ ktxTexture2_CompressBasisEx(ktxTexture2* This, ktxBasisParams* params)
}
}

if (swizzleString.size() > 0) {
if (swizzleString.size() == 0) {
// Set appropriate default swizzle
if (params->normalMap) {
comp_mapping = normal_map_mapping;
alphaContent = eGreen;
} else if (num_components == 1) {
comp_mapping = r_to_rgba_mapping;
} else if (num_components == 2) {
if (params->uastc)
comp_mapping = rg_to_rgba_mapping_uastc;
else {
comp_mapping = rg_to_rgba_mapping_etc1s;
alphaContent = eGreen;
}
} else if (num_components == 4) {
alphaContent = eAlpha;
}
} else {
// Only set comp_mapping for cases we can't shortcut.
// If num_components < 3 we always swizzle so no shortcut there.
if (num_components < 3
Expand All @@ -531,19 +548,21 @@ ktxTexture2_CompressBasisEx(ktxTexture2* This, ktxBasisParams* params)
comp_mapping = meta_mapping;
}

// An incoming swizzle of RRR1 or RRRG is assumed to be for a
// luminance texture. Set isLuminance to distinguish from
// an identical swizzle generated internally for R & RG cases.
int i;
for (i = 0; i < 3; i++) {
if (meta_mapping[i] != r_to_rgba_mapping[i])
break;
}
if (i == 3) {
isLuminance = true;
}
if (meta_mapping[3] != ONE) {
alphaContent = eAlpha;
if (!params->normalMap) {
// An incoming swizzle of RRR1 or RRRG is assumed to be for a
// luminance texture. Set isLuminance so we can later distinguish
// this from the identical swizzle used for normal maps.
// cases for ETC1S.
if (meta_mapping[0] == meta_mapping[1]
&& meta_mapping[1] == meta_mapping[2]) {
// Same component in r, g & b
isLuminance = true;
}
if (meta_mapping[3] != ONE) {
alphaContent = eAlpha;
}
} else {
alphaContent = eGreen;
}
}

Expand Down Expand Up @@ -972,7 +991,9 @@ ktxTexture2_CompressBasisEx(ktxTexture2* This, ktxBasisParams* params)
// Delayed modifying texture until here so it's after points of
// possible failure.
if (params->uastc) {
result = ktxTexture2_rewriteDfd4Uastc(This, alphaContent);
result = ktxTexture2_rewriteDfd4Uastc(This, alphaContent,
isLuminance,
comp_mapping);
if (result != KTX_SUCCESS) goto cleanup;

// Reflect this in the formatSize
Expand All @@ -981,7 +1002,8 @@ ktxTexture2_CompressBasisEx(ktxTexture2* This, ktxBasisParams* params)
priv._requiredLevelAlignment = 4 * 4;
} else {
result = ktxTexture2_rewriteDfd4BasisLzETC1S(This, alphaContent,
isLuminance);
isLuminance,
comp_mapping);
if (result != KTX_SUCCESS) goto cleanup;

This->supercompressionScheme = KTX_SS_BASIS_LZ;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_10x5_FlightHelmet_baseColor.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_12x10_FlightHelmet_baseColor.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_12x12_FlightHelmet_baseColor.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_4x4_FlightHelmet_baseColor.ktx2
Git LFS file not shown
3 changes: 3 additions & 0 deletions tests/testimages/astc_ldr_5x4_Iron_Bars_001_normal.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_6x5_FlightHelmet_baseColor.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_6x6_3dtex_7.ktx2
Git LFS file not shown
3 changes: 3 additions & 0 deletions tests/testimages/astc_ldr_6x6_Iron_Bars_001_normal.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_6x6_arraytex_7.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_6x6_arraytex_7_mipmap.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_6x6_posx.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_8x6_FlightHelmet_baseColor.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_8x8_FlightHelmet_baseColor.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_ldr_cubemap_6x6.ktx2
Git LFS file not shown
2 changes: 1 addition & 1 deletion tests/testimages/astc_mipmap_ldr_10x5_posx.ktx2
Git LFS file not shown
2 changes: 1 addition & 1 deletion tests/testimages/astc_mipmap_ldr_12x10_posx.ktx2
Git LFS file not shown
2 changes: 1 addition & 1 deletion tests/testimages/astc_mipmap_ldr_12x12_posx.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_mipmap_ldr_4x4_posx.ktx2
Git LFS file not shown
4 changes: 2 additions & 2 deletions tests/testimages/astc_mipmap_ldr_6x5_posx.ktx2
Git LFS file not shown
2 changes: 1 addition & 1 deletion tests/testimages/astc_mipmap_ldr_6x6_kodim17_fast.ktx2
Git LFS file not shown
2 changes: 1 addition & 1 deletion tests/testimages/astc_mipmap_ldr_6x6_kodim17_fastest.ktx2
Git LFS file not shown
2 changes: 1 addition & 1 deletion tests/testimages/astc_mipmap_ldr_6x6_kodim17_medium.ktx2
Git LFS file not shown
Loading