Skip to content

Instantly share code, notes, and snippets.

@pema99
Created May 9, 2025 18:48
Show Gist options
  • Save pema99/9a2cd933332106915a970b96ce05e286 to your computer and use it in GitHub Desktop.
Save pema99/9a2cd933332106915a970b96ce05e286 to your computer and use it in GitHub Desktop.
Mipmap level selection accounting for anisotropic filtering.
void EllipsoidTransformDerivatives(inout float2 dx, inout float2 dy)
{
bool anyZero = length(dx) == 0 || length(dy) == 0;
bool parallel = (dx.x * dy.y - dx.y * dy.x) == 0;
bool perpendicular = dot(dx, dy) == 0;
bool nonFinite = isinf(dx) || isinf(dy) || isnan(dx) || isnan(dy);
if (!anyZero && !parallel && !perpendicular && !nonFinite)
{
float A = dx.y*dx.y + dy.y*dy.y;
float B = -2.0 * (dx.x * dx.y + dy.x * dy.y);
float C = dx.x*dx.x + dy.x*dy.x;
float F = (dx.x * dy.y - dy.x * dx.y) * (dx.x * dy.y - dy.x * dx.y);
float p = A - C;
float q = A + C;
float t = sqrt(p*p + B*B);
float2 newDx, newDy;
newDx.x = sqrt(F * (t+p) / ( t * (q+t)));
newDx.y = sqrt(F * (t-p) / ( t * (q+t)))*sign(B);
newDy.x = sqrt(F * (t-p) / ( t * (q-t)))*-sign(B);
newDy.y = sqrt(F * (t+p) / ( t * (q-t)));
bool failed = any(isnan(newDx) || isinf(newDx) || isnan(newDy) || isinf(newDy));
if (!failed)
{
dx = newDx;
dy = newDy;
}
}
}
float CalculateLodLevel(float2 texSize, float2 dx, float2 dy, float anisoLevel)
{
dx *= texSize;
dy *= texSize;
// Ellipsoid transform
EllipsoidTransformDerivatives(dx, dy);
// Regular mip selection
if (anisoLevel == 0)
{
float lengthX = sqrt(dx.x*dx.x + dx.y*dx.y);
float lengthY = sqrt(dy.x*dy.x + dy.y*dy.y);
return log2(max(lengthX,lengthY));
}
// Anisotropic filtering
else
{
float squaredLengthX = dx.x*dx.x + dx.y*dx.y;
float squaredLengthY = dy.x*dy.x + dy.y*dy.y;
float determinant = abs(dx.x*dy.y - dx.y*dy.x);
bool isMajorX = squaredLengthX > squaredLengthY;
float squaredLengthMajor = isMajorX ? squaredLengthX : squaredLengthY;
float lengthMajor = sqrt(squaredLengthMajor);
float ratioOfAnisotropy = squaredLengthMajor/determinant;
float lengthMinor;
if (ratioOfAnisotropy > anisoLevel)
{
ratioOfAnisotropy = anisoLevel;
lengthMinor = lengthMajor/ratioOfAnisotropy;
}
else
{
lengthMinor = determinant/lengthMajor;
}
return log2(lengthMinor);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment