-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmaterial.cc
128 lines (110 loc) · 2.7 KB
/
material.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "material.h"
Material::~Material() {}
void Material::scatter(
Randomness& rng,
const Intersection& isect,
Ray* rayOut,
Vec* betaInOut
) const {
Vec outgoingWorld;
Vec bsdf;
float pdf;
sampleWorld(isect, rng, -isect.incomingRay.direction, &outgoingWorld, &bsdf, &pdf);
Vec scale;
if (pdf > 0.0f) {
scale = bsdf * fabsf(isect.normal.dot(outgoingWorld)) / pdf;
} else {
scale = Vec(0, 0, 0);
}
*rayOut = Ray(
isect.position + outgoingWorld * math::VERY_SMALL,
outgoingWorld
);
*betaInOut = betaInOut->cwiseProduct(scale);
}
float Material::evalPDFLocal(const Vec& incoming, const Vec& outgoing) const {
if (!math::localSameHemisphere(incoming, outgoing)) {
return 0.0f;
}
return math::cosineSampleHemispherePDF(outgoing);
}
void Material::evalLocal(
const Vec& incoming,
const Vec& outgoing,
Vec* bsdfOut,
float* pdfOut
) const {
*bsdfOut = evalBSDFLocal(incoming, outgoing);
*pdfOut = evalPDFLocal(incoming, outgoing);
}
void Material::evalWorld(
const Intersection& isect,
const Vec& incoming,
const Vec& outgoing,
Vec* bsdfOut,
float* pdfOut
) const {
Vec tangent;
Vec binormal;
math::coordSystem(isect.normal, &tangent, &binormal);
// BSDF and PDF computation expects rays to be in local-space.
Vec incomingLocal = math::worldToLocal(
incoming,
tangent,
binormal,
isect.normal
);
Vec outgoingLocal = math::worldToLocal(
outgoing,
tangent,
binormal,
isect.normal
);
evalLocal(incomingLocal, outgoingLocal, bsdfOut, pdfOut);
}
void Material::sampleLocal(
Randomness& rng,
const Vec& incoming,
Vec* outgoingOut,
Vec* bsdfOut,
float* pdfOut
) const {
Vec outgoing = math::cosineSampleHemisphere(rng, incoming.z() < 0.0f);
*outgoingOut = outgoing;
*bsdfOut = evalBSDFLocal(incoming, outgoing);
*pdfOut = math::cosineSampleHemispherePDF(outgoing);
}
void Material::sampleWorld(
const Intersection& isect,
Randomness& rng,
const Vec& incoming,
Vec* outgoingOut,
Vec* bsdfOut,
float* pdfOut
) const {
Vec tangent;
Vec binormal;
math::coordSystem(isect.normal, &tangent, &binormal);
// BSDF computation expects incoming ray to be in local-space.
Vec incomingLocal = math::worldToLocal(
incoming,
tangent,
binormal,
isect.normal
);
// Sample BSDF for direction, color, and probability.
Vec outgoingLocal;
Vec tempBsdf;
float tempPdf;
sampleLocal(rng, incomingLocal, &outgoingLocal, &tempBsdf, &tempPdf);
// Rendering expects outgoing ray to be in world-space.
Vec outgoingWorld = math::localToWorld(
outgoingLocal,
tangent,
binormal,
isect.normal
);
*outgoingOut = outgoingWorld;
*bsdfOut = tempBsdf;
*pdfOut = tempPdf;
}