// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #ifndef __OCTAHEDRAL__ #define __OCTAHEDRAL__ // Implementation based on: // "A Survey of Efficient Representations for Independent Unit Vectors", Journal of Computer Graphics Tools (JCGT), vol. 3, no. 2, 1-30, 2014 // Zina H. Cigolle, Sam Donow, Daniel Evangelakos, Michael Mara, Morgan McGuire, and Quirin Meyer // http://jcgt.org/published/0003/02/01/ float GetSignNotZero(float v) { return v >= 0.0f ? 1.0f : -1.0f; } float2 GetSignNotZero(float2 v) { return float2(GetSignNotZero(v.x), GetSignNotZero(v.y)); } // Calculates octahedral coordinates (in range [-1; 1]) for direction vector float2 GetOctahedralCoords(float3 direction) { float2 uv = direction.xy * (1.0f / (abs(direction.x) + abs(direction.y) + abs(direction.z))); if (direction.z < 0.0f) uv = (1.0f - abs(uv.yx)) * GetSignNotZero(uv.xy); return uv; } // Calculates octahedral coordinates (in range [-1; 1]) for 2D texture (assuming 1 pixel border around) float2 GetOctahedralCoords(uint2 texCoords, uint resolution) { float2 uv = float2(texCoords.x % resolution, texCoords.y % resolution) + 0.5f; uv.xy /= float(resolution); return uv * 2.0f - 1.0f; } // Gets the direction vector from octahedral coordinates float3 GetOctahedralDirection(float2 coords) { float3 direction = float3(coords.x, coords.y, 1.0f - abs(coords.x) - abs(coords.y)); if (direction.z < 0.0f) direction.xy = (1.0f - abs(direction.yx)) * GetSignNotZero(direction.xy); return normalize(direction); } #endif