#ifndef _ENVIRONMENT_IMPORTANCE_SAMPLING_HLSL_
#define _ENVIRONMENT_IMPORTANCE_SAMPLING_HLSL_
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Sampling/Sampling.hlsl"
// Equiareal mapping
float2 MapSkyDirectionToUV(float3 dir)
{
float cosTheta = dir.y;
float phi = atan2(-dir.z, -dir.x);
return float2(0.5 - phi * INV_TWO_PI, (cosTheta + 1.0) * 0.5);
}
// Equiareal mapping
float3 MapUVToSkyDirection(float2 uv)
{
float phi = TWO_PI * (1.0 - uv.x);
float cosTheta = 2.0 * uv.y - 1.0;
return TransformGLtoDX(SphericalToCartesian(phi, cosTheta));
}
// Dichotomic search
float SampleSkyCDF(StructuredBuffer<float> cdf, uint size, uint bufferOffset, float smp)
{
uint i = 0;
for (uint halfsize = size >> 1, offset = halfsize; offset > 0; offset >>= 1)
{
if (smp < cdf[bufferOffset + halfsize])
{
// i is already in the right half (lower one)
halfsize -= offset >> 1;
}
else
{
// i has to move to the other half (upper one)
i += offset;
halfsize += offset >> 1;
}
}
// MarginalTexture[0] stores the PDF normalization factor, so we need a test on i == 0
float cdfInf = i == 0 ? 0.0 : cdf[bufferOffset + i];
float cdfSup = i + 1 == size ? 1.0f : cdf[bufferOffset + i + 1];
return (i + (smp - cdfInf) / (cdfSup - cdfInf)) / size;
}
float GetSkyPDFNormalizationFactor(StructuredBuffer<float> marginalBuffer)
{
return marginalBuffer[0];
}
// This PDF approximation is valid only if PDF/CDF tables are computed with equiareal mapping
float GetSkyPDFFromValue(float3 value, float pdfNormalization)
{
return Luminance(value) * pdfNormalization;
}
float GetSkyPDFFromValue(float3 value, StructuredBuffer<float> marginalBuffer)
{
return GetSkyPDFFromValue(value, GetSkyPDFNormalizationFactor(marginalBuffer));
}
float2 SampleSky(float2 rand, uint marginalResolution, StructuredBuffer<float> marginalBuffer, uint conditionalResolution, StructuredBuffer<float> conditionalBuffer)
{
float v = SampleSkyCDF(marginalBuffer, marginalResolution, 0, rand.x);
float u = SampleSkyCDF(conditionalBuffer, conditionalResolution, conditionalResolution * uint(v * marginalResolution), rand.y);
return float2(u, v);
}
#endif