36#define JPL_RAND_SEED std::random_device{}()
40 static constexpr float JPL_SPEED_OF_SOUND = 343.0f;
41 static constexpr float JPL_INV_SPEAD_OF_SOUND = 1.0f / JPL_SPEED_OF_SOUND;
46 namespace InternalUtils
48 template<std::
floating_po
int FloatType>
49 static constexpr auto four_pi = FloatType(4.0) * std::numbers::pi_v<FloatType>;
50 template<std::
floating_po
int FloatType>
51 static constexpr FloatType two_pi = FloatType(2.0) * std::numbers::pi_v<FloatType>;
53 template<std::
floating_po
int FloatType>
54 static inline FloatType RandFloat()
56 static constexpr auto bits = std::same_as<FloatType, double> ? 53u : 24u;
58 return std::generate_canonical<FloatType, bits>(mt);
62 static inline Vec3 RandDirection()
64 return Normalized(Vec3{
65 RandFloat<Internal::FloatOf<Vec3>>() * 2.0f - 1.0f,
67 RandFloat<Internal::FloatOf<Vec3>>() * 2.0f - 1.0f
73 static inline Vec3 GetImageSource(
const Vec3& point,
const Vec3& planeNormal,
float planeConstant)
75 const float signedDistance = DotProduct(point, planeNormal) + planeConstant;
76 return point - (planeNormal * (2.0f * signedDistance));
80 static inline Vec3 GetImageSource(
const Vec3& point,
const Vec3& planeNormal,
const Vec3& pointOnPlane)
82 const float planeConstant = DotProduct(-planeNormal, pointOnPlane);
83 return GetImageSource(point, planeNormal, planeConstant);
89 static auto GeometryTerm(
const Vec3& x,
const Vec3& xNorm,
const Vec3& y,
const Vec3& yNorm) ->
Internal::FloatOf<Vec3>
94 const FloatType dist2 = LengthSquared(dir);
95 if (dist2 < FloatType(1e-6))
96 return FloatType(0.0);
98 dir /= std::sqrt(dist2);
99 const FloatType cosThetaX = std::abs(DotProduct(xNorm, dir));
100 const FloatType cosThetaY = std::abs(DotProduct(yNorm, -dir));
103 return (cosThetaX * cosThetaY) / dist2;
113 const FloatType dist2 = LengthSquared(y - x);
114 if (dist2 < FloatType(1e-6))
115 return FloatType(0.0);
124 return GeometryTerm(x, y);
134 static Vec3 SpecularReflection(
const Vec3& incident,
const Vec3& normal)
141 static Vec3 SampleHemisphereCosine(
const Vec3& normal)
146 const FloatType u1 = InternalUtils::RandFloat<FloatType>();
147 const FloatType u2 = InternalUtils::RandFloat<FloatType>();
148 const FloatType r = std::sqrt(u1);
149 const FloatType phi = InternalUtils::two_pi<FloatType> *u2;
151 const FloatType x = r * std::cos(phi);
152 const FloatType z = r * std::sin(phi);
153 const FloatType y = std::sqrt(std::max(FloatType(0.0), FloatType(1.0) - u1));
156 Vec3 tangent, bitangent;
160 return Normalized(Vec3(
171 static Vec3 VectorBasedScatter2(
const Vec3& specular,
const Vec3& normal,
float diffusion)
174 const Vec3 randomDirection = SampleHemisphereCosine(normal);
175 return Normalized(diffusion * randomDirection + (FloatType(1.0) - diffusion) * specular);
182 static Vec3 VectorBasedScatter(
const Vec3& incident,
const Vec3& normal,
float diffusion)
184 const Vec3 specular = SpecularReflection(incident, normal);
185 return VectorBasedScatter2(specular, normal, diffusion);
213 if (InternalUtils::RandFloat<FloatType>() < diffusion)
216 const Vec3 outDirection = SampleHemisphereCosine(normal);
218 .OutDirection = outDirection,
220 std::max(FloatType(0.0), DotProduct(normal, outDirection)) *
221 std::numbers::inv_pi_v<FloatType>,
229 .OutDirection = SpecularReflection(incident, normal),
230 .PDF = FloatType(1.0) - diffusion,
237 JPL_INLINE
float ComputePDF(
const Vec3& normal,
const Vec3& outDirection,
float diffusion,
bool bIsSpecular)
241 : diffusion * std::max(0.0f,
static_cast<float>(DotProduct(normal, outDirection))) * JPL_INV_PI;
249 template<std::
floating_po
int FloatType>
250 static auto ABRDF(FloatType cosineAngle,
float diffusion) -> FloatType
253 const FloatType gamma = cosineAngle;
255 static constexpr auto epsilon =
256 std::numeric_limits<FloatType>::epsilon() * FloatType(8.0);
258 if (diffusion <= epsilon)
262 return FloatType(std::fabs(gamma - FloatType(1.0)) <= epsilon);
266 const FloatType d = diffusion;
267 const FloatType oneMinusD = FloatType(1.0) - d;
270 const FloatType a2 = oneMinusD * oneMinusD;
271 const FloatType gamma2 = gamma * gamma;
274 const FloatType rootArg = a2 * gamma2 + FloatType(2.0) * d - FloatType(1.0);
278 if (rootArg <= epsilon)
283 if (d < FloatType(0.5))
285 const FloatType gammaMin = std::sqrt((FloatType(1.0) - FloatType(2.0) * d) / a2);
286 if (gamma < gammaMin)
287 return FloatType(0.0);
290 const FloatType sqrtTerm = std::sqrt(rootArg);
291 const FloatType numer = FloatType(2.0) * rootArg;
293 if (d >= FloatType(0.5))
295 const FloatType denom1 = InternalUtils::four_pi<FloatType> * d * sqrtTerm;
296 const FloatType term1 = numer / denom1;
298 const FloatType term2 = (oneMinusD * gamma) / (InternalUtils::two_pi<FloatType> * d);
300 return term1 + term2;
304 const FloatType denom = InternalUtils::two_pi<FloatType> * d * sqrtTerm;
305 return numer / denom;
316 static JPL_INLINE
auto ABRDF(
const Vec3& specular,
const Vec3& outgoing,
float diffusion) ->
Internal::FloatOf<Vec3>
321 const FloatType gamma = DotProduct(specular, outgoing);
322 return ABRDF(gamma, diffusion);
333 static JPL_INLINE
auto ABRDF(
const Vec3& incident,
const Vec3& normal,
const Vec3& outgoing,
float diffusion) ->
Internal::FloatOf<Vec3>
336 const Vec3 specular = SpecularReflection(incident, normal);
337 return ABRDF(specular, outgoing, diffusion);
#define JPL_RAND_SEED
Definition Math.h:36
std::remove_cvref_t< decltype(GetX(std::declval< Vec3 >()))> FloatOf
Definition Vec3Math.h:36
void CreateOrthonormalBasis(const Vec3 &normal, Vec3 &tangent, Vec3 &bitangent) noexcept
Definition Vec3Math.h:84
JPL_INLINE float ComputePDF(const Vec3 &normal, const Vec3 &outDirection, float diffusion, bool bIsSpecular)
Definition Math.h:237
Definition AcousticMaterial.h:36
Vec3 OutDirection
Definition Math.h:191
float PDF
Definition Math.h:192
bool bIsSpecular
Definition Math.h:193