Open 0x4E69676874466F78 opened 1 year ago
Дядя Миша Нормалки перед сохранением в ATI2N - убедитесь что Z-компонента больше нуля, иначе будет ошибка кодирования. Второй момент - кодируйте не в стереографическую, а в параболическую проекцию - для нее восстановление в шейдере идентично стереографической, только корень не нужен, впрочем оно даже с корнем боле-мене корректно восстанавливается. При параболической проекции кол-во артефактов резко падает. Собственно, параноевский maketex этот вариант и реализует. Но вы его наверное не используете.
Я нашёл такое в архиве с maketex:
A pseudocode here:
typedef struct dds_s { uint dwIdent; // must matched with DDSHEADER uint dwSize; uint dwFlags; // determines what fields are valid uint dwHeight; uint dwWidth; uint dwLinearSize; // Formless late-allocated optimized surface size uint dwDepth; // depth if a volume texture uint dwMipMapCount; // number of mip-map levels requested uint dwAlphaBitDepth; // depth of alpha buffer requested uint dwReserved1[10]; // reserved for future expansions dds_pixf_t dsPixelFormat; dds_caps_t dsCaps; uint dwTextureStage; } dds_t;
encode type goes into dds_t->dwReserved1[0] average color goes into dds_t->dwReserved1[1]
if( dds_t->dwReserved1[1] != 0 ) { // store texture reflectivity byte avgRed = ((dds_t->dwReserved1[1] & 0x000000FF) >> 0 ); byte avgGreen = ((dds_t->dwReserved1[1] & 0x0000FF00) >> 8 ); byte avgBlue = ((dds_t->dwReserved1[1] & 0x00FF0000) >> 16); byte avgAlpha = ((dds_t->dwReserved1[1] & 0xFF000000) >> 24); }
GLSL, decode YCoCG:
vec4 decodeYCoCg( vec4 YCoCg ) { float Y = YCoCg.a 2.0; float scale = 1.0 / ((255.0 / 7.0) YCoCg.b + 1.0); float Co = (YCoCg.r - (128.0 / 255.0)) scale; float Cg = (YCoCg.g - (128.0 / 255.0)) scale;
float R = Y + Co - Cg;
float G = Y + Cg;
float B = Y - Co - Cg;
return vec4( R, G, B, 2.0 ) * 0.5;
}
> GLSL, decode normals:
```glsl
// get support for various normalmap encode
vec3 decodeNormal( vec4 normalmap )
{
vec3 N;
#if defined( DXT_ENCODE_NORMAL_AG_ORTHO )
// simple orthographic method
N.xy = 2.0 * ( normalmap.ag - 0.5 );
N.z = sqrt( 1.0 - saturate( dot( N.xy, N.xy )));
#elif defined( DXT_ENCODE_NORMAL_AG_STEREO )
// stereographic method
float pX = 2.0 * ( normalmap.a - 0.5 );
float pY = 2.0 * ( normalmap.g - 0.5 );
float denom = 2.0 / ( 1.0 + pX * pX + pY * pY );
N.x = pX * denom;
N.y = pY * denom;
N.z = denom - 1.0;
#elif defined( DXT_ENCODE_NORMAL_AG_PARABOLOID ) // like orthographic but without sqrt
N.x = 2.0 * ( normalmap.a - 0.5 );
N.y = 2.0 * ( normalmap.g - 0.5 );
N.z = 1.0 - saturate( dot( N.xy, N.xy ));
#elif defined( DXT_ENCODE_NORMAL_AG_QUARTIC )
N.x = 2.0 * ( normalmap.a - 0.5 );
N.y = 2.0 * ( normalmap.g - 0.5 );
N.z = saturate(( 1.0 - N.x * N.x ) * ( 1.0 - N.y * N.y ));
#elif defined( DXT_ENCODE_NORMAL_AG_AZIMUTHAL )
N.x = 4.0 * normalmap.a - 2.0;
N.y = 4.0 * normalmap.g - 2.0;
float f = dot( N.xy, N.xy );
float g = sqrt( 1.0 - f / 4.0 );
N.xy *= g;
N.z = 1.0 - f / 2.0;
#else
// pass untransformed normals
N = ( 2.0 * ( normalmap.xyz - 0.5 ));
#endif
N = normalize( N );
N.y = -N.y;
return N;
}