Skip to content

Instantly share code, notes, and snippets.

@oskarbraten
Last active October 9, 2022 13:27
Show Gist options
  • Save oskarbraten/79d29fffb8f82a1d471da69375db4404 to your computer and use it in GitHub Desktop.
Save oskarbraten/79d29fffb8f82a1d471da69375db4404 to your computer and use it in GitHub Desktop.
Shader code for sampling 1D data that has been packed in a 2D texture (with mipmaps)
/*
Fetches the texel at x by mapping it to the texel-coords of the relevant mipmap level.
*/
float textureUnpack1D_texelFetch(sampler2D map, int x, int level) {
if (level > 0) {
/*
Adjusts x to the appropriate mipmap level:
For example, a sample at position 6 in level 0, will be at positions:
- level 1: 6/4¹ = 1.5 = 1
- level 2: 6/4² = 0.375 = 0
- etc ...
*/
x = int(float(x) / pow(4.0, float(level)));
}
ivec2 size = textureSize(map, level);
ivec2 uv = ivec2(x % size.x, x / size.x); // Convert from 1D to 2D coordinates.
return texelFetch(map, uv, level).r;
}
/*
Fetches the two closest texels and linearly interpolates between them.
*/
float textureUnpack1D_filterLinear(sampler2D map, float x, int level) {
float a = textureUnpack1D_texelFetch(map, int(floor(x)), level);
float b = textureUnpack1D_texelFetch(map, int(ceil(x)), level);
return mix(a, b, fract(x));
}
/*
Fetches and filters adjacent texels from a packed 1D texture using linear interpolation and mipmaps.
map = packed 1D texture with mipmaps
x = 1D texture coordinate
d = partial derivative of x, used to calculate mipmap-level
*/
float textureUnpack1D_filterMipmap(sampler2D map, float x, float d) {
if (d <= 1.0) {
// Magnification (linear interpolation, 2 texel fetches):
return textureUnpack1D_filterLinear(map, x, 0);
} else {
return 0.0;
// Minification (mipmap with linear interpolation, 4 texel fetches):
float level = log2(d) / log2(4.0); // log₄(d)
float a = textureUnpack1D_filterLinear(map, x, int(floor(level)));
float b = textureUnpack1D_filterLinear(map, x, int(ceil(level)));
return mix(a, b, fract(level));
}
}
float textureUnpack1D(sampler2D map, float x) {
float d = fwidth(x);
return textureUnpack1D_filterMipmap(map, x, d);
}
float textureUnpack1D(sampler2D map, float x, float d) {
return textureUnpack1D_filterMipmap(map, x, d);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment