Skip to content

Instantly share code, notes, and snippets.

@BeRo1985
Last active December 3, 2023 05:01
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BeRo1985/a099d46c376b636771bbe580d72fd6d6 to your computer and use it in GitHub Desktop.
Save BeRo1985/a099d46c376b636771bbe580d72fd6d6 to your computer and use it in GitHub Desktop.
GLSL Octahedral Texture Mapping with Edge Mirroring and Bilinear Interpolation
// GLSL Octahedral Texture Mapping with Edge Mirroring and Bilinear Interpolation (by Benjamin 'BeRo' Rosseaux)
ivec2 wrapOctahedralTexelCoordinates(const in ivec2 texel, const in ivec2 texSize) {
ivec2 wrapped = ((texel % texSize) + texSize) % texSize;
return ((((abs(texel.x / texSize.x) + int(texel.x < 0)) ^ (abs(texel.y / texSize.y) + int(texel.y < 0))) & 1) != 0) ? (texSize - (wrapped + ivec2(1))) : wrapped;
}
vec4 textureOctahedralMap(const in sampler2D tex, vec3 direction) {
direction = normalize(direction); // just for to make sure that it is normalized
vec2 uv = direction.xy / (abs(direction.x) + abs(direction.y) + abs(direction.z));
uv = fma((direction.z < 0.0) ? ((1.0 - abs(uv.yx)) * vec2((uv.x >= 0.0) ? 1.0 : -1.0, (uv.y >= 0.0) ? 1.0 : -1.0)) : uv, vec2(0.5), vec2(0.5));
ivec2 texSize = textureSize(tex, 0).xy;
vec2 invTexSize = vec2(1.0) / vec2(texSize);
if(any(lessThanEqual(uv, invTexSize)) || any(greaterThanEqual(uv, vec2(1.0) - invTexSize))){
// Handle edges with manual bilinear interpolation using texelFetch for correct octahedral texel edge mirroring
uv = fma(uv, texSize, vec2(-0.5));
ivec2 baseCoord = ivec2(floor(uv));
vec2 fractionalPart = uv - vec2(baseCoord);
return mix(mix(texelFetch(tex, wrapOctahedralTexelCoordinates(baseCoord + ivec2(0, 0), texSize), 0),
texelFetch(tex, wrapOctahedralTexelCoordinates(baseCoord + ivec2(1, 0), texSize), 0), fractionalPart.x),
mix(texelFetch(tex, wrapOctahedralTexelCoordinates(baseCoord + ivec2(0, 1), texSize), 0),
texelFetch(tex, wrapOctahedralTexelCoordinates(baseCoord + ivec2(1, 1), texSize), 0), fractionalPart.x), fractionalPart.y);
}else{
// Non-edge texels can be sampled directly with textureLod
return textureLod(tex, uv, 0.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment