#pragma kernel RenderTextureToMat_sRGB
#pragma kernel RenderTextureToMat_Linear

Texture2D<unorm float4> Source;
RWStructuredBuffer<uint> Destination;
bool HFlip;
bool VFlip;

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

// Packed alpha conversion
uint PackRGBA(float4 a)
{
    uint4 i = (uint4) (round(a * 255.0));
    return i.x | (i.y << 8) | (i.z << 16) | (i.w << 24);
}

[numthreads(8,8,1)]
void RenderTextureToMat_sRGB(uint3 id : SV_DispatchThreadID)
{

    uint w, h;
    Source.GetDimensions(w, h);

    float4 v = Source[id.xy];

    uint x = HFlip ? w - id.x - 1 : id.x;
    uint y = VFlip ? h - id.y - 1 : id.y;
    
    v = saturate(v);

    Destination[x + y * w] = PackRGBA(v);

}

[numthreads(8, 8, 1)]
void RenderTextureToMat_Linear(uint3 id : SV_DispatchThreadID)
{

    uint w, h;
    Source.GetDimensions(w, h);

    float4 v = Source[id.xy];

    uint x = HFlip ? w - id.x - 1 : id.x;
    uint y = VFlip ? h - id.y - 1 : id.y;

    // saturate values to ensure they are in [0, 1] range
    v = saturate(v);
    
    Destination[x + y * w] = PackRGBA(saturate(LinearTosRGB(v)));
}
