float3 DecodeFromSRGB(float3 color) { return select(color <= 0.04045, color / 12.92, pow(abs(color + 0.055) / 1.055, 2.4)); } float3 SphericalDirection(float sineTheta, float cosineTheta, float phi) { float clampedSine = clamp(sineTheta, -1.0, 1.0); return float3(clampedSine * cos(phi), clampedSine * sin(phi), clamp(cosineTheta, -1.0, 1.0)); } float SampleExponential(float randomSample, float extinction) { return -log(max(randomSample, EPSILON)) / max(extinction, EPSILON); } //"Building an Orthonormal Basis, Revisited" //https://jcgt.org/published/0006/01/01/ void CreateOrthonormalBasis(float3 normal, out float3 u, out float3 v) { float sign = (normal.z >= 0.0) ? 1.0 : -1.0; float a = -1.0 / (sign + normal.z); float b = normal.x * normal.y * a; u = float3(1.0 + sign * normal.x * normal.x * a, sign * b, -sign * normal.x); v = float3(b, sign + normal.y * normal.y * a, -normal.y); }