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
3613enum 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+ };
0 commit comments