Skip to content

Commit 31da541

Browse files
committed
light importance sampling 70%
1 parent cac5b3e commit 31da541

File tree

7 files changed

+293
-163
lines changed

7 files changed

+293
-163
lines changed

src/main.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,6 @@ int main(int argc, char** argv) {
104104

105105
const char* sceneFile = argv[1];
106106

107-
testDiscreteSampler();
108-
exit(0);
109-
110107
// Load scene file
111108
scene = new Scene(sceneFile);
112109

src/material.h

Lines changed: 143 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,7 @@
88

99
#define MATERIAL_DIELETRIC_USE_SCHLICK_APPROX false
1010

11-
struct Material {
12-
enum Type {
13-
Lambertian,
14-
MetallicWorkflow,
15-
Dielectric,
16-
Disney,
17-
Light
18-
};
19-
20-
std::string toString() const {
21-
std::stringstream ss;
22-
ss << "[Type = " << type << ", BaseColor = " << vec3ToString(baseColor) << "]";
23-
return ss.str();
24-
}
25-
26-
int type;
27-
glm::vec3 baseColor;
28-
float metallic;
29-
float roughness;
30-
float ior;
31-
float emittance;
32-
33-
int textureId;
34-
};
11+
#define InvalidPdf -1.f
3512

3613
enum BSDFSampleType {
3714
Diffuse = 1 << 0,
@@ -79,55 +56,6 @@ __device__ static float fresnel(float cosIn, float ior) {
7956
#endif
8057
}
8158

82-
__device__ static glm::vec3 lambertianBSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material &m) {
83-
return m.baseColor * Math::satDot(n, wi) * PiInv;
84-
}
85-
86-
__device__ static float lambertianPdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material& m) {
87-
return glm::dot(n, wi) * PiInv;
88-
}
89-
90-
__device__ static void lambertianSample(glm::vec3 n, glm::vec3 wo, const Material& m, glm::vec3 r, BSDFSample& sample) {
91-
sample.dir = Math::sampleHemisphereCosine(n, r.x, r.y);
92-
sample.bsdf = m.baseColor * PiInv;
93-
sample.pdf = glm::dot(n, sample.dir) * PiInv;
94-
sample.type = Diffuse | Reflection;
95-
}
96-
97-
__device__ static glm::vec3 dielectricBSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material& m) {
98-
return glm::vec3(0.f);
99-
}
100-
101-
__device__ static float dielectricPdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material& m) {
102-
return 0.f;
103-
}
104-
105-
__device__ static void dielectricSample(glm::vec3 n, glm::vec3 wo, const Material& m, glm::vec3 r, BSDFSample& sample) {
106-
float ior = m.ior;
107-
float pdfRefl = fresnel(glm::dot(n, wo), ior);
108-
109-
sample.bsdf = m.baseColor;
110-
111-
if (r.z < pdfRefl) {
112-
sample.dir = glm::reflect(-wo, n);
113-
sample.type = Specular | Reflection;
114-
sample.pdf = 1.f;
115-
}
116-
else {
117-
bool result = Math::refract(n, wo, ior, sample.dir);
118-
if (!result) {
119-
sample.type = Invalid;
120-
return;
121-
}
122-
if (glm::dot(n, wo) < 0) {
123-
ior = 1.f / ior;
124-
}
125-
sample.bsdf /= ior * ior;
126-
sample.type = Specular | Transmission;
127-
sample.pdf = 1.f;
128-
}
129-
}
130-
13159
__device__ static float schlickG(float cosTheta, float alpha) {
13260
float a = alpha * .5f;
13361
return cosTheta / (cosTheta * (1.f - a) + a);
@@ -149,7 +77,7 @@ __device__ static float ggxDistrib(float cosTheta, float alpha) {
14977
}
15078

15179
__device__ static float ggxPdf(glm::vec3 n, glm::vec3 m, glm::vec3 wo, float alpha) {
152-
return ggxDistrib(glm::dot(n, m), alpha) * schlickG(glm::dot(n, wo), alpha) *
80+
return ggxDistrib(glm::dot(n, m), alpha) * schlickG(glm::dot(n, wo), alpha) *
15381
Math::absDot(m, wo) / Math::absDot(n, wo);
15482
}
15583

@@ -178,89 +106,162 @@ __device__ static glm::vec3 ggxSample(glm::vec3 n, glm::vec3 wo, float alpha, gl
178106
return transMat * h;
179107
}
180108

181-
__device__ static glm::vec3 metallicWorkflowBSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material& m) {
182-
float alpha = m.roughness * m.roughness;
183-
glm::vec3 h = glm::normalize(wo + wi);
109+
struct Material {
110+
enum Type {
111+
Lambertian,
112+
MetallicWorkflow,
113+
Dielectric,
114+
Disney,
115+
Light
116+
};
184117

185-
float cosO = glm::dot(n, wo);
186-
float cosI = glm::dot(n, wi);
187-
if (cosI * cosO < 1e-7f) {
188-
return glm::vec3(0.f);
118+
std::string toString() const {
119+
std::stringstream ss;
120+
ss << "[Type = " << type << ", BaseColor = " << vec3ToString(baseColor) << "]";
121+
return ss.str();
189122
}
190123

191-
glm::vec3 f = fresnelSchlick(glm::dot(h, wo), m.baseColor * m.metallic);
192-
float g = smithG(cosO, cosI, alpha);
193-
float d = ggxDistrib(glm::dot(n, h), alpha);
124+
__device__ glm::vec3 lambertianBSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
125+
return baseColor * Math::satDot(n, wi) * PiInv;
126+
}
194127

195-
return glm::mix(m.baseColor * PiInv * (1.f - m.metallic), glm::vec3(g * d / (4.f * cosI * cosO)), f);
196-
}
128+
__device__ float lambertianPdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
129+
return glm::dot(n, wi) * PiInv;
130+
}
197131

198-
__device__ static float metallicWorkflowPdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material& m) {
199-
glm::vec3 h = glm::normalize(wo + wi);
200-
return glm::mix(
201-
Math::satDot(n, wi) * PiInv,
202-
ggxPdf(n, h, wo, m.roughness * m.roughness) / (4.f * Math::absDot(h, wo)),
203-
1.f / (2.f - m.metallic)
204-
);
205-
}
132+
__device__ void lambertianSample(glm::vec3 n, glm::vec3 wo, glm::vec3 r, BSDFSample& sample) {
133+
sample.dir = Math::sampleHemisphereCosine(n, r.x, r.y);
134+
sample.bsdf = baseColor * PiInv;
135+
sample.pdf = glm::dot(n, sample.dir) * PiInv;
136+
sample.type = Diffuse | Reflection;
137+
}
206138

207-
__device__ static void metallicWorkflowSample(glm::vec3 n, glm::vec3 wo, const Material& m, glm::vec3 r, BSDFSample& sample) {
208-
float alpha = m.roughness * m.roughness;
139+
__device__ glm::vec3 dielectricBSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
140+
return glm::vec3(0.f);
141+
}
209142

210-
if (r.z > (1.f / (2.f - m.metallic))) {
211-
sample.dir = Math::sampleHemisphereCosine(n, r.x, r.y);
143+
__device__ float dielectricPdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
144+
return 0.f;
212145
}
213-
else {
214-
glm::vec3 h = ggxSample(n, wo, alpha, glm::vec2(r));
215-
sample.dir = -glm::reflect(wo, h);
146+
147+
__device__ void dielectricSample(glm::vec3 n, glm::vec3 wo, glm::vec3 r, BSDFSample& sample) {
148+
float pdfRefl = fresnel(glm::dot(n, wo), ior);
149+
150+
sample.bsdf = baseColor;
151+
152+
if (r.z < pdfRefl) {
153+
sample.dir = glm::reflect(-wo, n);
154+
sample.type = Specular | Reflection;
155+
sample.pdf = 1.f;
156+
}
157+
else {
158+
bool result = Math::refract(n, wo, ior, sample.dir);
159+
if (!result) {
160+
sample.type = Invalid;
161+
return;
162+
}
163+
if (glm::dot(n, wo) < 0) {
164+
ior = 1.f / ior;
165+
}
166+
sample.bsdf /= ior * ior;
167+
sample.type = Specular | Transmission;
168+
sample.pdf = 1.f;
169+
}
216170
}
217171

218-
if (glm::dot(n, sample.dir) < 0.f) {
219-
sample.type = Invalid;
172+
__device__ glm::vec3 metallicWorkflowBSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
173+
float alpha = roughness * roughness;
174+
glm::vec3 h = glm::normalize(wo + wi);
175+
176+
float cosO = glm::dot(n, wo);
177+
float cosI = glm::dot(n, wi);
178+
if (cosI * cosO < 1e-7f) {
179+
return glm::vec3(0.f);
180+
}
181+
182+
glm::vec3 f = fresnelSchlick(glm::dot(h, wo), baseColor * metallic);
183+
float g = smithG(cosO, cosI, alpha);
184+
float d = ggxDistrib(glm::dot(n, h), alpha);
185+
186+
return glm::mix(baseColor * PiInv * (1.f - metallic), glm::vec3(g * d / (4.f * cosI * cosO)), f);
220187
}
221-
else {
222-
sample.bsdf = metallicWorkflowBSDF(n, wo, sample.dir, m);
223-
sample.pdf = metallicWorkflowPdf(n, wo, sample.dir, m);
224-
sample.type = Glossy | Reflection;
188+
189+
__device__ float metallicWorkflowPdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
190+
glm::vec3 h = glm::normalize(wo + wi);
191+
return glm::mix(
192+
Math::satDot(n, wi) * PiInv,
193+
ggxPdf(n, h, wo, roughness * roughness) / (4.f * Math::absDot(h, wo)),
194+
1.f / (2.f - metallic)
195+
);
225196
}
226-
}
227197

228-
__device__ static glm::vec3 materialBSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material& m) {
229-
switch (m.type) {
230-
case Material::Type::Lambertian:
231-
return lambertianBSDF(n, wo, wi, m);
232-
case Material::Type::MetallicWorkflow:
233-
return metallicWorkflowBSDF(n, wo, wi, m);
234-
case Material::Type::Dielectric:
235-
return dielectricBSDF(n, wo, wi, m);
198+
__device__ void metallicWorkflowSample(glm::vec3 n, glm::vec3 wo, glm::vec3 r, BSDFSample& sample) {
199+
float alpha = roughness * roughness;
200+
201+
if (r.z > (1.f / (2.f - metallic))) {
202+
sample.dir = Math::sampleHemisphereCosine(n, r.x, r.y);
203+
}
204+
else {
205+
glm::vec3 h = ggxSample(n, wo, alpha, glm::vec2(r));
206+
sample.dir = -glm::reflect(wo, h);
207+
}
208+
209+
if (glm::dot(n, sample.dir) < 0.f) {
210+
sample.type = Invalid;
211+
}
212+
else {
213+
sample.bsdf = metallicWorkflowBSDF(n, wo, sample.dir);
214+
sample.pdf = metallicWorkflowPdf(n, wo, sample.dir);
215+
sample.type = Glossy | Reflection;
216+
}
236217
}
237-
return glm::vec3(0.f);
238-
}
239218

240-
__device__ static float materialPdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi, const Material& m) {
241-
switch (m.type) {
242-
case Material::Type::Lambertian:
243-
return lambertianPdf(n, wo, wi, m);
244-
case Material::Type::MetallicWorkflow:
245-
return metallicWorkflowPdf(n, wo, wi, m);
246-
case Material::Dielectric:
247-
return dielectricPdf(n, wo, wi, m);
219+
__device__ glm::vec3 BSDF(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
220+
switch (type) {
221+
case Material::Type::Lambertian:
222+
return lambertianBSDF(n, wo, wi);
223+
case Material::Type::MetallicWorkflow:
224+
return metallicWorkflowBSDF(n, wo, wi);
225+
case Material::Type::Dielectric:
226+
return dielectricBSDF(n, wo, wi);
227+
}
228+
return glm::vec3(0.f);
248229
}
249-
return 0.f;
250-
}
251230

252-
__device__ static void materialSample(glm::vec3 n, glm::vec3 wo, const Material& m, glm::vec3 r, BSDFSample& sample) {
253-
switch (m.type) {
254-
case Material::Type::Lambertian:
255-
lambertianSample(n, wo, m, r, sample);
256-
break;
257-
case Material::Type::MetallicWorkflow:
258-
metallicWorkflowSample(n, wo, m, r, sample);
259-
break;
260-
case Material::Type::Dielectric:
261-
dielectricSample(n, wo, m, r, sample);
262-
break;
263-
default:
264-
sample.type = Invalid;
231+
__device__ float pdf(glm::vec3 n, glm::vec3 wo, glm::vec3 wi) {
232+
switch (type) {
233+
case Material::Type::Lambertian:
234+
return lambertianPdf(n, wo, wi);
235+
case Material::Type::MetallicWorkflow:
236+
return metallicWorkflowPdf(n, wo, wi);
237+
case Material::Dielectric:
238+
return dielectricPdf(n, wo, wi);
239+
}
240+
return 0.f;
265241
}
266-
}
242+
243+
__device__ void sample(glm::vec3 n, glm::vec3 wo, glm::vec3 r, BSDFSample& sample) {
244+
switch (type) {
245+
case Material::Type::Lambertian:
246+
lambertianSample(n, wo, r, sample);
247+
break;
248+
case Material::Type::MetallicWorkflow:
249+
metallicWorkflowSample(n, wo, r, sample);
250+
break;
251+
case Material::Type::Dielectric:
252+
dielectricSample(n, wo, r, sample);
253+
break;
254+
default:
255+
sample.type = Invalid;
256+
}
257+
}
258+
259+
int type;
260+
glm::vec3 baseColor;
261+
float metallic;
262+
float roughness;
263+
float ior;
264+
float emittance;
265+
266+
int textureId;
267+
};

src/mathUtil.h

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,27 @@ namespace Math {
4646
return x * x;
4747
}
4848

49+
__host__ __device__ inline float powerHeuristic(float f, float g) {
50+
float f2 = f * f;
51+
return f2 / (f2 + g * g);
52+
}
53+
54+
__host__ __device__ inline float triangleArea(glm::vec3 v0, glm::vec3 v1, glm::vec3 v2) {
55+
return glm::length(glm::cross(v1 - v0, v2 - v0)) * .5f;
56+
}
57+
58+
__host__ __device__ inline glm::vec3 triangleNormal(glm::vec3 v0, glm::vec3 v1, glm::vec3 v2) {
59+
return glm::normalize(glm::cross(v1 - v0, v2 - v0));
60+
}
61+
62+
__host__ __device__ static glm::vec3 sampleTriangleUniform(
63+
glm::vec3 v0, glm::vec3 v1, glm::vec3 v2, float ru, float rv) {
64+
float r = glm::sqrt(rv);
65+
float u = 1.f - r;
66+
float v = ru * r;
67+
return v1 * u + v2 * v + v0 * (1.f - u - v);
68+
}
69+
4970
template<typename T>
5071
__host__ __device__ inline T calcFilmic(T c) {
5172
return (c * (c * 0.22f + 0.03f) + 0.002f) / (c * (c * 0.22f + 0.3f) + 0.06f) - 1.f / 30.f;
@@ -63,6 +84,12 @@ namespace Math {
6384
return glm::pow(color, glm::vec3(1.f / 2.2f));
6485
}
6586

87+
__host__ __device__ inline float luminance(glm::vec3 color) {
88+
//const glm::vec3 T(.299f, .587f, .114f);
89+
const glm::vec3 T(.2126f, .7152f, .0722f);
90+
return glm::dot(color, T);
91+
}
92+
6693
/**
6794
* Map a pair of evenly distributed [0, 1] coordinate to disc
6895
*/
@@ -108,9 +135,9 @@ namespace Math {
108135
return true;
109136
}
110137

111-
__device__ inline float areaPdfToSolidAngle(float pdf, glm::vec3 ref, glm::vec3 y, glm::vec3 ny) {
112-
glm::vec3 yToRef = ref - y;
113-
return pdf * absDot(ny, glm::normalize(yToRef)) / glm::dot(yToRef, yToRef);
138+
__device__ inline float pdfAreaToSolidAngle(float pdf, glm::vec3 x, glm::vec3 y, glm::vec3 ny) {
139+
glm::vec3 yx = x - y;
140+
return pdf * absDot(ny, glm::normalize(yx)) / glm::dot(yx, yx);
114141
}
115142

116143
/**

0 commit comments

Comments
 (0)