sqrt[-1]

07-06-2010, 07:06 PM

I am writing a shader that does texture atlasing without edge filter issues - and I just though I would share. (emulating array textures on hardware that does not have array textures)

Cg code for mip level calculation:

(copied from http://linedef.com/personal/demos/?p=virtual-texturing)

#define SUB_TEXTURE_SIZE 512.0

#define SUB_TEXTURE_MIPCOUNT 10

float MipLevel( float2 uv )

{

float2 dx = ddx( uv * SUB_TEXTURE_SIZE );

float2 dy = ddy( uv * SUB_TEXTURE_SIZE );

float d = max( dot( dx, dx ), dot( dy, dy ) );

// Clamp the value to the max mip level counts

const float rangeClamp = pow(2, (SUB_TEXTURE_MIPCOUNT - 1) * 2);

d = clamp(d, 1.0, rangeClamp);

float mipLevel = 0.5 * log2(d);

mipLevel = floor(mipLevel);

return mipLevel;

}

Calculating half texel offset for selected mip level also

#define SUB_TEXTURE_SIZE 512.0

#define SUB_TEXTURE_MIPCOUNT 10

float MipLevel( float2 uv, out float a_halfOffset )

{

float2 dx = ddx( uv * SUB_TEXTURE_SIZE );

float2 dy = ddy( uv * SUB_TEXTURE_SIZE );

float d = max( dot( dx, dx ), dot( dy, dy ) );

// Clamp the value to the max mip level counts

const float rangeClamp = pow(2, SUB_TEXTURE_MIPCOUNT - 1);

d = clamp(sqrt(d), 1.0, rangeClamp);

float mipLevel = log2(d);

mipLevel = floor(mipLevel);

a_halfOffset = d * (1.0 / pow(2.0, SUB_TEXTURE_MIPCOUNT));

return mipLevel;

}

You can then use tex2Dlod to lookup the texture (with adjusted UV's to clamp the edge filtering - clamp to edge or mirror repeating only)

Edit:

Just realised that you can calculate the half pixel size by simply

a_halfOffset = pow(2.0, mipLevel - SUB_TEXTURE_MIPCOUNT);

Cg code for mip level calculation:

(copied from http://linedef.com/personal/demos/?p=virtual-texturing)

#define SUB_TEXTURE_SIZE 512.0

#define SUB_TEXTURE_MIPCOUNT 10

float MipLevel( float2 uv )

{

float2 dx = ddx( uv * SUB_TEXTURE_SIZE );

float2 dy = ddy( uv * SUB_TEXTURE_SIZE );

float d = max( dot( dx, dx ), dot( dy, dy ) );

// Clamp the value to the max mip level counts

const float rangeClamp = pow(2, (SUB_TEXTURE_MIPCOUNT - 1) * 2);

d = clamp(d, 1.0, rangeClamp);

float mipLevel = 0.5 * log2(d);

mipLevel = floor(mipLevel);

return mipLevel;

}

Calculating half texel offset for selected mip level also

#define SUB_TEXTURE_SIZE 512.0

#define SUB_TEXTURE_MIPCOUNT 10

float MipLevel( float2 uv, out float a_halfOffset )

{

float2 dx = ddx( uv * SUB_TEXTURE_SIZE );

float2 dy = ddy( uv * SUB_TEXTURE_SIZE );

float d = max( dot( dx, dx ), dot( dy, dy ) );

// Clamp the value to the max mip level counts

const float rangeClamp = pow(2, SUB_TEXTURE_MIPCOUNT - 1);

d = clamp(sqrt(d), 1.0, rangeClamp);

float mipLevel = log2(d);

mipLevel = floor(mipLevel);

a_halfOffset = d * (1.0 / pow(2.0, SUB_TEXTURE_MIPCOUNT));

return mipLevel;

}

You can then use tex2Dlod to lookup the texture (with adjusted UV's to clamp the edge filtering - clamp to edge or mirror repeating only)

Edit:

Just realised that you can calculate the half pixel size by simply

a_halfOffset = pow(2.0, mipLevel - SUB_TEXTURE_MIPCOUNT);