Also use doxy style function reference `#` prefix chars when referencing identifiers.
124 lines
3.2 KiB
GLSL
124 lines
3.2 KiB
GLSL
|
|
/**
|
|
* Sampling distribution routines for Monte-carlo integration.
|
|
*/
|
|
|
|
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
|
|
#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Microfacet GGX distribution
|
|
* \{ */
|
|
|
|
#define USE_VISIBLE_NORMAL 1
|
|
|
|
float pdf_ggx_reflect(float NH, float NV, float VH, float alpha)
|
|
{
|
|
float a2 = sqr(alpha);
|
|
#if USE_VISIBLE_NORMAL
|
|
float D = a2 / D_ggx_opti(NH, a2);
|
|
float G1 = NV * 2.0 / G1_Smith_GGX_opti(NV, a2);
|
|
return G1 * VH * D / NV;
|
|
#else
|
|
return NH * a2 / D_ggx_opti(NH, a2);
|
|
#endif
|
|
}
|
|
|
|
vec3 sample_ggx(vec3 rand, float alpha, vec3 Vt)
|
|
{
|
|
#if USE_VISIBLE_NORMAL
|
|
/* From:
|
|
* "A Simpler and Exact Sampling Routine for the GGXDistribution of Visible Normals"
|
|
* by Eric Heitz.
|
|
* http://jcgt.org/published/0007/04/01/slides.pdf
|
|
* View vector is expected to be in tangent space. */
|
|
|
|
/* Stretch view. */
|
|
vec3 Th, Bh, Vh = normalize(vec3(alpha * Vt.xy, Vt.z));
|
|
make_orthonormal_basis(Vh, Th, Bh);
|
|
/* Sample point with polar coordinates (r, phi). */
|
|
float r = sqrt(rand.x);
|
|
float x = r * rand.y;
|
|
float y = r * rand.z;
|
|
float s = 0.5 * (1.0 + Vh.z);
|
|
y = (1.0 - s) * sqrt(1.0 - x * x) + s * y;
|
|
float z = sqrt(saturate(1.0 - x * x - y * y));
|
|
/* Compute normal. */
|
|
vec3 Hh = x * Th + y * Bh + z * Vh;
|
|
/* Unstretch. */
|
|
vec3 Ht = normalize(vec3(alpha * Hh.xy, saturate(Hh.z)));
|
|
/* Microfacet Normal. */
|
|
return Ht;
|
|
#else
|
|
/* Theta is the cone angle. */
|
|
float z = sqrt((1.0 - rand.x) / (1.0 + sqr(alpha) * rand.x - rand.x)); /* cos theta */
|
|
float r = sqrt(max(0.0, 1.0 - z * z)); /* sin theta */
|
|
float x = r * rand.y;
|
|
float y = r * rand.z;
|
|
/* Microfacet Normal */
|
|
return vec3(x, y, z);
|
|
#endif
|
|
}
|
|
|
|
vec3 sample_ggx(vec3 rand, float alpha, vec3 V, vec3 N, vec3 T, vec3 B, out float pdf)
|
|
{
|
|
vec3 Vt = world_to_tangent(V, N, T, B);
|
|
vec3 Ht = sample_ggx(rand, alpha, Vt);
|
|
float NH = saturate(Ht.z);
|
|
float NV = saturate(Vt.z);
|
|
float VH = saturate(dot(Vt, Ht));
|
|
pdf = pdf_ggx_reflect(NH, NV, VH, alpha);
|
|
return tangent_to_world(Ht, N, T, B);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Uniform Hemisphere
|
|
* \{ */
|
|
|
|
float pdf_uniform_hemisphere()
|
|
{
|
|
return 0.5 * M_1_PI;
|
|
}
|
|
|
|
vec3 sample_uniform_hemisphere(vec3 rand)
|
|
{
|
|
float z = rand.x; /* cos theta */
|
|
float r = sqrt(max(0.0, 1.0 - z * z)); /* sin theta */
|
|
float x = r * rand.y;
|
|
float y = r * rand.z;
|
|
return vec3(x, y, z);
|
|
}
|
|
|
|
vec3 sample_uniform_hemisphere(vec3 rand, vec3 N, vec3 T, vec3 B, out float pdf)
|
|
{
|
|
vec3 Ht = sample_uniform_hemisphere(rand);
|
|
pdf = pdf_uniform_hemisphere();
|
|
return tangent_to_world(Ht, N, T, B);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Uniform Cone sampling
|
|
* \{ */
|
|
|
|
vec3 sample_uniform_cone(vec3 rand, float angle)
|
|
{
|
|
float z = cos(angle * rand.x); /* cos theta */
|
|
float r = sqrt(max(0.0, 1.0 - z * z)); /* sin theta */
|
|
float x = r * rand.y;
|
|
float y = r * rand.z;
|
|
return vec3(x, y, z);
|
|
}
|
|
|
|
vec3 sample_uniform_cone(vec3 rand, float angle, vec3 N, vec3 T, vec3 B)
|
|
{
|
|
vec3 Ht = sample_uniform_cone(rand, angle);
|
|
/* TODO: pdf? */
|
|
return tangent_to_world(Ht, N, T, B);
|
|
}
|
|
|
|
/** \} */
|