Last active
October 9, 2022 13:27
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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