1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3
4 #pragma once
5
6 /*! \brief utility library containing sampling functions */
7
8 // convention is to return the sample (Vec3fa) generated from given Vec2f 's'ample as last parameter
9 // sampling functions often come in pairs: sample and pdf (needed later for MIS)
10 // good reference is "Total Compendium" by Philip Dutre http://people.cs.kuleuven.be/~philip.dutre/GI/
11
12 #include "../math/vec.h"
13 #include "../math/linearspace.h"
14
15 namespace embree {
16
17 struct Sample3f
18 {
19 Vec3fa v;
20 float pdf;
21 };
22
make_Sample3f(const Vec3fa & v,const float pdf)23 inline Sample3f make_Sample3f(const Vec3fa& v, const float pdf) {
24 Sample3f s; s.v = v; s.pdf = pdf; return s;
25 }
26
27 #if defined(ISPC)
make_Sample3f(const Vec3fa & v,const float pdf)28 inline Sample3f make_Sample3f(const Vec3fa& v, const float pdf) {
29 Sample3f s; s.v = v; s.pdf = pdf; return s;
30 }
31 #endif
32
cartesian(const float phi,const float sinTheta,const float cosTheta)33 inline Vec3fa cartesian(const float phi, const float sinTheta, const float cosTheta)
34 {
35 const float sinPhi = sinf(phi);
36 const float cosPhi = cosf(phi);
37 //sincosf(phi, &sinPhi, &cosPhi);
38 return Vec3fa(cosPhi * sinTheta,
39 sinPhi * sinTheta,
40 cosTheta);
41 }
42
cartesian(const float phi,const float cosTheta)43 inline Vec3fa cartesian(const float phi, const float cosTheta)
44 {
45 return cartesian(phi, cos2sin(cosTheta), cosTheta);
46 }
47
48
49 /// cosine-weighted sampling of hemisphere oriented along the +z-axis
50 ////////////////////////////////////////////////////////////////////////////////
51
cosineSampleHemisphere(const Vec2f s)52 inline Vec3fa cosineSampleHemisphere(const Vec2f s)
53 {
54 const float phi =float(two_pi) * s.x;
55 const float cosTheta = sqrt(s.y);
56 const float sinTheta = sqrt(1.0f - s.y);
57 return cartesian(phi, sinTheta, cosTheta);
58 }
59
cosineSampleHemispherePDF(const Vec3fa & dir)60 inline float cosineSampleHemispherePDF(const Vec3fa &dir)
61 {
62 return dir.z / float(M_PI);
63 }
64
cosineSampleHemispherePDF(float cosTheta)65 inline float cosineSampleHemispherePDF(float cosTheta)
66 {
67 return cosTheta / float(M_PI);
68 }
69
70 /*! Cosine weighted hemisphere sampling. Up direction is provided as argument. */
cosineSampleHemisphere(const float u,const float v,const Vec3fa & N)71 inline Sample3f cosineSampleHemisphere(const float u, const float v, const Vec3fa& N)
72 {
73 Vec3fa localDir = cosineSampleHemisphere(Vec2f(u,v));
74 Sample3f s;
75 s.v = frame(N) * localDir;
76 s.pdf = cosineSampleHemispherePDF(localDir);
77 return s;
78 }
79
80 /// power cosine-weighted sampling of hemisphere oriented along the +z-axis
81 ////////////////////////////////////////////////////////////////////////////////
82
powerCosineSampleHemisphere(const float n,const Vec2f & s)83 inline Vec3fa powerCosineSampleHemisphere(const float n, const Vec2f &s)
84 {
85 const float phi =float(two_pi) * s.x;
86 const float cosTheta = pow(s.y, 1.0f / (n + 1.0f));
87 return cartesian(phi, cosTheta);
88 }
89
powerCosineSampleHemispherePDF(const float cosTheta,const float n)90 inline float powerCosineSampleHemispherePDF(const float cosTheta, const float n) // TODO: order of arguments
91 {
92 return (n + 1.0f) * (0.5f / float(M_PI)) * pow(cosTheta, n);
93 }
94
powerCosineSampleHemispherePDF(const Vec3fa & dir,const float n)95 inline float powerCosineSampleHemispherePDF(const Vec3fa& dir, const float n) // TODO: order of arguments
96 {
97 return (n + 1.0f) * (0.5f / float(M_PI)) * pow(dir.z, n);
98 }
99
100 /// sampling of cone of directions oriented along the +z-axis
101 ////////////////////////////////////////////////////////////////////////////////
102
uniformSampleCone(const float cosAngle,const Vec2f & s)103 inline Vec3fa uniformSampleCone(const float cosAngle, const Vec2f &s)
104 {
105 const float phi =float(two_pi) * s.x;
106 const float cosTheta = 1.0f - s.y * (1.0f - cosAngle);
107 return cartesian(phi, cosTheta);
108 }
109
uniformSampleConePDF(const float cosAngle)110 inline float uniformSampleConePDF(const float cosAngle)
111 {
112 return rcp(float(two_pi)*(1.0f - cosAngle));
113 }
114
_uniformSampleConePDF(const float cosAngle)115 inline float _uniformSampleConePDF(const float cosAngle)
116 {
117 return rcp(float(two_pi)*(1.0f - cosAngle));
118 }
119
120
121 /// sampling of disk
122 ////////////////////////////////////////////////////////////////////////////////
123
uniformSampleDisk(const float radius,const Vec2f & s)124 inline Vec3fa uniformSampleDisk(const float radius, const Vec2f &s)
125 {
126 const float r = sqrtf(s.x) * radius;
127 const float phi =float(two_pi) * s.y;
128 const float sinPhi = sinf(phi);
129 const float cosPhi = cosf(phi);
130 //sincosf(phi, &sinPhi, &cosPhi);
131 return Vec3fa(r * cosPhi, r * sinPhi, 0.f);
132 }
133
uniformSampleDiskPDF(const float radius)134 inline float uniformSampleDiskPDF(const float radius)
135 {
136 return rcp(float(M_PI) * sqr(radius));
137 }
138
_uniformSampleDiskPDF(const float radius)139 inline float _uniformSampleDiskPDF(const float radius)
140 {
141 return rcp(float(M_PI) * sqr(radius));
142 }
143
144
145 /// sampling of triangle abc
146 ////////////////////////////////////////////////////////////////////////////////
147
uniformSampleTriangle(const Vec3fa & a,const Vec3fa & b,const Vec3fa & c,const Vec2f & s)148 inline Vec3fa uniformSampleTriangle(const Vec3fa &a, const Vec3fa &b, const Vec3fa &c, const Vec2f &s)
149 {
150 const float su = sqrtf(s.x);
151 return c + (1.0f - su) * (a-c) + (s.y*su) * (b-c);
152 }
153
uniformSampleTrianglePDF(const Vec3fa & a,const Vec3fa & b,const Vec3fa & c)154 inline float uniformSampleTrianglePDF(const Vec3fa &a, const Vec3fa &b, const Vec3fa &c)
155 {
156 return 2.0f * rcp(abs(length(cross(a-c, b-c))));
157 }
158
159 } // namespace embree
160