

//vertex shader

//(t[n], space0): Sampled textures, followed by storage textures, followed by storage buffers
//(s[n], space0): Samplers with indices corresponding to the sampled textures
//(b[n], space1): Uniform buffers

//fragment shader

//(t[n], space2): Sampled textures, followed by storage textures, followed by storage buffers
//(s[n], space2): Samplers with indices corresponding to the sampled textures
//(b[n], space3): Uniform buffers

//compute shader

//(t[n], space0): Sampled textures, followed by read-only storage textures, followed by read-only storage buffers
//(u[n], space1): Read-write storage textures, followed by read-write storage buffers
//(b[n], space2): Uniform buffers


struct SphereRay
{
    float4 Position;
    float4 Heading;
};

struct SphereHit
{
    float RayDistance;
    int SphereId;
    int HitCount;
};

struct Sphere
{
    float4 PositionAndRadius;
};


struct PixelIdData
{
    float4 id;
};

// Converts a normalized direction vector to UV coordinates for an octahedron.
float2 OctahedronUV(float3 direction) {
    direction.z *= -1;
    // Get the octant signs
    float3 octant = sign(direction);

    // Scale the vector so that |x| + |y| + |z| = 1
    float sum = dot(direction, octant);
    float3 octahedron = direction / sum;

    // Reflect corners when z < 0
    if (octahedron.z < 0) {
        float3 absolute = abs(octahedron);
        octahedron.xy = octant.xy * float2(1.0f - absolute.y, 1.0f - absolute.x);
    }

    // Map to UV space in [0, 1] range
    return octahedron.xy * 0.5f + 0.5f;
}

// Converts UV coordinates back to a normalized 3D vector on the octahedron.
float3 UVtoOctahedron(float2 uv) {
    // Unpack UV [0, 1] to [-1, 1] space
    float3 position = float3(2.0f * (uv - 0.5f), 0.0f);

    // Compute z-coordinate using the Manhattan metric
    float2 absolute = abs(position.xy);
    position.z = 1.0f - absolute.x - absolute.y;

    // Reflect corners when z < 0
    if (position.z < 0) {
        position.xy = sign(position.xy) * float2(1.0f - absolute.y, 1.0f - absolute.x);
    }
    position.z *= -1;
    // Return the normalized direction vector
    return normalize(position);
}


float3 srgb2linear(float3 color)
{
    return float3(
        (color.r <= 0.04045) ? (color.r / 12.92) : pow((color.r + 0.055) / 1.055, 2.4),
        (color.g <= 0.04045) ? (color.g / 12.92) : pow((color.g + 0.055) / 1.055, 2.4),
        (color.b <= 0.04045) ? (color.b / 12.92) : pow((color.b + 0.055) / 1.055, 2.4)
    );
}

float3 linear2srgb(float3 color)
{
    return float3(
        (color.r <= 0.0031308) ? (color.r * 12.92) : (1.055 * pow(color.r, 1.0 / 2.4) - 0.055),
        (color.g <= 0.0031308) ? (color.g * 12.92) : (1.055 * pow(color.g, 1.0 / 2.4) - 0.055),
        (color.b <= 0.0031308) ? (color.b * 12.92) : (1.055 * pow(color.b, 1.0 / 2.4) - 0.055)
    );
}
/*

float3 fakehdr(float3 col)
{
    float3 hdrcol;
    hdrcol.rgb = pow(col.rgb, float3(2.2, 2.2, 2.2)); 
    float lum = dot(hdrcol.rgb, float3(0.2126, 0.7152, 0.0722));
    hdrcol.rgb = (lum * lum) * hdrcol.rgb; 
    return hdrcol;
}

#define whitesatval 1.0

float3 invfakehdr(float3 hdrcol)
{
    float3 ihdrcol;
    float lum = dot(hdrcol.rgb, float3(0.2126, 0.7152, 0.0722));
    float tonescale = ((lum / (whitesatval * whitesatval)) + 1.0) * lum / (lum + 1.0);
    ihdrcol.rgb = pow((tonescale / lum) * hdrcol.rgb, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2));
    return ihdrcol;
}

*/

#define fakehdr srgb2linear
#define invfakehdr linear2srgb
