Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/closure')
-rw-r--r--intern/cycles/kernel/closure/alloc.h85
-rw-r--r--intern/cycles/kernel/closure/bsdf.h1015
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h353
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h168
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse.h146
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse_ramp.h101
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair.h365
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair_principled.h679
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h1847
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h972
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h398
-rw-r--r--intern/cycles/kernel/closure/bsdf_oren_nayar.h124
-rw-r--r--intern/cycles/kernel/closure/bsdf_phong_ramp.h171
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_diffuse.h130
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_sheen.h116
-rw-r--r--intern/cycles/kernel/closure/bsdf_reflection.h63
-rw-r--r--intern/cycles/kernel/closure/bsdf_refraction.h80
-rw-r--r--intern/cycles/kernel/closure/bsdf_toon.h242
-rw-r--r--intern/cycles/kernel/closure/bsdf_transparent.h116
-rw-r--r--intern/cycles/kernel/closure/bsdf_util.h183
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h637
-rw-r--r--intern/cycles/kernel/closure/emissive.h42
-rw-r--r--intern/cycles/kernel/closure/volume.h209
23 files changed, 4482 insertions, 3760 deletions
diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h
index acccba9ecec..341d1e16eb1 100644
--- a/intern/cycles/kernel/closure/alloc.h
+++ b/intern/cycles/kernel/closure/alloc.h
@@ -18,69 +18,72 @@ CCL_NAMESPACE_BEGIN
ccl_device ShaderClosure *closure_alloc(ShaderData *sd, int size, ClosureType type, float3 weight)
{
- kernel_assert(size <= sizeof(ShaderClosure));
+ kernel_assert(size <= sizeof(ShaderClosure));
- if(sd->num_closure_left == 0)
- return NULL;
+ if (sd->num_closure_left == 0)
+ return NULL;
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = &sd->closure[sd->num_closure];
- sc->type = type;
- sc->weight = weight;
+ sc->type = type;
+ sc->weight = weight;
- sd->num_closure++;
- sd->num_closure_left--;
+ sd->num_closure++;
+ sd->num_closure_left--;
- return sc;
+ return sc;
}
ccl_device ccl_addr_space void *closure_alloc_extra(ShaderData *sd, int size)
{
- /* Allocate extra space for closure that need more parameters. We allocate
- * in chunks of sizeof(ShaderClosure) starting from the end of the closure
- * array.
- *
- * This lets us keep the same fast array iteration over closures, as we
- * found linked list iteration and iteration with skipping to be slower. */
- int num_extra = ((size + sizeof(ShaderClosure) - 1) / sizeof(ShaderClosure));
-
- if(num_extra > sd->num_closure_left) {
- /* Remove previous closure if it was allocated. */
- sd->num_closure--;
- sd->num_closure_left++;
- return NULL;
- }
-
- sd->num_closure_left -= num_extra;
- return (ccl_addr_space void*)(sd->closure + sd->num_closure + sd->num_closure_left);
+ /* Allocate extra space for closure that need more parameters. We allocate
+ * in chunks of sizeof(ShaderClosure) starting from the end of the closure
+ * array.
+ *
+ * This lets us keep the same fast array iteration over closures, as we
+ * found linked list iteration and iteration with skipping to be slower. */
+ int num_extra = ((size + sizeof(ShaderClosure) - 1) / sizeof(ShaderClosure));
+
+ if (num_extra > sd->num_closure_left) {
+ /* Remove previous closure if it was allocated. */
+ sd->num_closure--;
+ sd->num_closure_left++;
+ return NULL;
+ }
+
+ sd->num_closure_left -= num_extra;
+ return (ccl_addr_space void *)(sd->closure + sd->num_closure + sd->num_closure_left);
}
ccl_device_inline ShaderClosure *bsdf_alloc(ShaderData *sd, int size, float3 weight)
{
- ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
+ ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
- if(sc == NULL)
- return NULL;
+ if (sc == NULL)
+ return NULL;
- float sample_weight = fabsf(average(weight));
- sc->sample_weight = sample_weight;
- return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
+ float sample_weight = fabsf(average(weight));
+ sc->sample_weight = sample_weight;
+ return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
}
#ifdef __OSL__
-ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, int size, float3 weight, void *data)
+ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd,
+ int size,
+ float3 weight,
+ void *data)
{
- ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
+ ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
- if(!sc)
- return NULL;
+ if (!sc)
+ return NULL;
- memcpy((void *)sc, data, size);
+ memcpy((void *)sc, data, size);
- float sample_weight = fabsf(average(weight));
- sc->weight = weight;
- sc->sample_weight = sample_weight;
- return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
+ float sample_weight = fabsf(average(weight));
+ sc->weight = weight;
+ sc->sample_weight = sample_weight;
+ return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
}
#endif
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 3a9629ea9d7..5e26f90a878 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -39,38 +39,38 @@ CCL_NAMESPACE_BEGIN
* 0 for singular closures and 1 otherwise. */
ccl_device_inline float bsdf_get_specular_roughness_squared(const ShaderClosure *sc)
{
- if(CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
- return 0.0f;
- }
+ if (CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
+ return 0.0f;
+ }
- if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
- return bsdf->alpha_x*bsdf->alpha_y;
- }
+ if (CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
+ return bsdf->alpha_x * bsdf->alpha_y;
+ }
- return 1.0f;
+ return 1.0f;
}
ccl_device_inline float bsdf_get_roughness_squared(const ShaderClosure *sc)
{
- /* This version includes diffuse, mainly for baking Principled BSDF
- * where specular and metallic zero otherwise does not bake the
- * specified roughness parameter. */
- if(sc->type == CLOSURE_BSDF_OREN_NAYAR_ID) {
- OrenNayarBsdf *bsdf = (OrenNayarBsdf*)sc;
- return sqr(sqr(bsdf->roughness));
- }
+ /* This version includes diffuse, mainly for baking Principled BSDF
+ * where specular and metallic zero otherwise does not bake the
+ * specified roughness parameter. */
+ if (sc->type == CLOSURE_BSDF_OREN_NAYAR_ID) {
+ OrenNayarBsdf *bsdf = (OrenNayarBsdf *)sc;
+ return sqr(sqr(bsdf->roughness));
+ }
- if(sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)sc;
- return sqr(sqr(bsdf->roughness));
- }
+ if (sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf *)sc;
+ return sqr(sqr(bsdf->roughness));
+ }
- if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
- return 0.0f;
- }
+ if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
+ return 0.0f;
+ }
- return bsdf_get_specular_roughness_squared(sc);
+ return bsdf_get_specular_roughness_squared(sc);
}
ccl_device_inline int bsdf_sample(KernelGlobals *kg,
@@ -83,133 +83,349 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
differential3 *domega_in,
float *pdf)
{
- int label;
+ int label;
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
+ switch (sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ label = bsdf_diffuse_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
#ifdef __SVM__
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#ifdef __OSL__
- case CLOSURE_BSDF_PHONG_RAMP_ID:
- label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#endif
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- label = bsdf_microfacet_multi_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- label = bsdf_microfacet_beckmann_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- label = bsdf_ashikhmin_shirley_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- label = bsdf_diffuse_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- label = bsdf_glossy_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- label = bsdf_principled_hair_sample(kg, sc, sd, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- label = bsdf_principled_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
- label = bsdf_principled_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#endif /* __PRINCIPLED__ */
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ label = bsdf_oren_nayar_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+# ifdef __OSL__
+ case CLOSURE_BSDF_PHONG_RAMP_ID:
+ label = bsdf_phong_ramp_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+ label = bsdf_diffuse_ramp_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+# endif
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ label = bsdf_translucent_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ label = bsdf_reflection_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ label = bsdf_refraction_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ label = bsdf_transparent_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ label = bsdf_microfacet_ggx_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ label = bsdf_microfacet_multi_ggx_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf,
+ &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ label = bsdf_microfacet_multi_ggx_glass_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf,
+ &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ label = bsdf_microfacet_beckmann_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ label = bsdf_ashikhmin_shirley_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ label = bsdf_ashikhmin_velvet_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ label = bsdf_diffuse_toon_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ label = bsdf_glossy_toon_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ label = bsdf_hair_reflection_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ label = bsdf_hair_transmission_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ label = bsdf_principled_hair_sample(
+ kg, sc, sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ break;
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ label = bsdf_principled_diffuse_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ label = bsdf_principled_sheen_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+# endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ label = volume_henyey_greenstein_sample(sc,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
#endif
- default:
- label = LABEL_NONE;
- break;
- }
+ default:
+ label = LABEL_NONE;
+ break;
+ }
- /* Test if BSDF sample should be treated as transparent for background. */
- if(label & LABEL_TRANSMIT) {
- float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
+ /* Test if BSDF sample should be treated as transparent for background. */
+ if (label & LABEL_TRANSMIT) {
+ float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
- if(threshold_squared >= 0.0f) {
- if(bsdf_get_specular_roughness_squared(sc) <= threshold_squared) {
- label |= LABEL_TRANSMIT_TRANSPARENT;
- }
- }
- }
+ if (threshold_squared >= 0.0f) {
+ if (bsdf_get_specular_roughness_squared(sc) <= threshold_squared) {
+ label |= LABEL_TRANSMIT_TRANSPARENT;
+ }
+ }
+ }
- return label;
+ return label;
}
#ifndef __KERNEL_CUDA__
@@ -217,285 +433,288 @@ ccl_device
#else
ccl_device_inline
#endif
-float3 bsdf_eval(KernelGlobals *kg,
- ShaderData *sd,
- const ShaderClosure *sc,
- const float3 omega_in,
- float *pdf)
+ float3
+ bsdf_eval(KernelGlobals *kg,
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ const float3 omega_in,
+ float *pdf)
{
- float3 eval;
+ float3 eval;
- if(dot(sd->Ng, omega_in) >= 0.0f) {
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
+ if (dot(sd->Ng, omega_in) >= 0.0f) {
+ switch (sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
#ifdef __SVM__
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __OSL__
- case CLOSURE_BSDF_PHONG_RAMP_ID:
- eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#endif
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
- eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#endif /* __PRINCIPLED__ */
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# ifdef __OSL__
+ case CLOSURE_BSDF_PHONG_RAMP_ID:
+ eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+ eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# endif
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(
+ sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
- break;
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ break;
#endif
- default:
- eval = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
- }
- else {
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
+ default:
+ eval = make_float3(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ }
+ else {
+ switch (sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
#ifdef __SVM__
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
- eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
-#endif /* __PRINCIPLED__ */
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(
+ sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+# endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
- break;
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ break;
#endif
- default:
- eval = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
- }
+ default:
+ eval = make_float3(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ }
- return eval;
+ return eval;
}
ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
{
- /* ToDo: do we want to blur volume closures? */
+ /* ToDo: do we want to blur volume closures? */
#ifdef __SVM__
- switch(sc->type) {
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- bsdf_microfacet_multi_ggx_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- bsdf_microfacet_ggx_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- bsdf_microfacet_beckmann_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- bsdf_ashikhmin_shirley_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- bsdf_principled_hair_blur(sc, roughness);
- break;
- default:
- break;
- }
+ switch (sc->type) {
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ bsdf_microfacet_multi_ggx_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ bsdf_microfacet_ggx_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ bsdf_microfacet_beckmann_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ bsdf_ashikhmin_shirley_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ bsdf_principled_hair_blur(sc, roughness);
+ break;
+ default:
+ break;
+ }
#endif
}
ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
{
#ifdef __SVM__
- switch(a->type) {
- case CLOSURE_BSDF_TRANSPARENT_ID:
- return true;
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- return bsdf_diffuse_merge(a, b);
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- return bsdf_oren_nayar_merge(a, b);
- case CLOSURE_BSDF_REFLECTION_ID:
- case CLOSURE_BSDF_REFRACTION_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- return bsdf_microfacet_merge(a, b);
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- return bsdf_ashikhmin_velvet_merge(a, b);
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- return bsdf_toon_merge(a, b);
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- return bsdf_hair_merge(a, b);
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- return bsdf_principled_diffuse_merge(a, b);
-#endif
-#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- return volume_henyey_greenstein_merge(a, b);
-#endif
- default:
- return false;
- }
+ switch (a->type) {
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ return true;
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ return bsdf_diffuse_merge(a, b);
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ return bsdf_oren_nayar_merge(a, b);
+ case CLOSURE_BSDF_REFLECTION_ID:
+ case CLOSURE_BSDF_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ return bsdf_microfacet_merge(a, b);
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ return bsdf_ashikhmin_velvet_merge(a, b);
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ return bsdf_toon_merge(a, b);
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ return bsdf_hair_merge(a, b);
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ return bsdf_principled_diffuse_merge(a, b);
+# endif
+# ifdef __VOLUME__
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ return volume_henyey_greenstein_merge(a, b);
+# endif
+ default:
+ return false;
+ }
#else
- return false;
+ return false;
#endif
}
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index 4e7425bd800..b3b1c37748d 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -33,203 +33,226 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_ashikhmin_shirley_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_ashikhmin_shirley_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float roughness)
{
- return 2.0f / (roughness*roughness) - 2.0f;
+ return 2.0f / (roughness * roughness) - 2.0f;
}
-ccl_device_forceinline float3 bsdf_ashikhmin_shirley_eval_reflect(
- const ShaderClosure *sc,
- const float3 I,
- const float3 omega_in,
- float *pdf)
+ccl_device_forceinline float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float3 N = bsdf->N;
-
- float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
- float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */
-
- float out = 0.0f;
-
- if(fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- if(NdotI > 0.0f && NdotO > 0.0f) {
- NdotI = fmaxf(NdotI, 1e-6f);
- NdotO = fmaxf(NdotO, 1e-6f);
- float3 H = normalize(omega_in + I);
- float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
- float HdotN = fmaxf(dot(H, N), 1e-6f);
-
- float pump = 1.0f / fmaxf(1e-6f, (HdotI*fmaxf(NdotO, NdotI))); /* pump from original paper (first derivative disc., but cancels the HdotI in the pdf nicely) */
- /*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ /* pump from d-brdf paper */
-
- float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
- float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
-
- if(n_x == n_y) {
- /* isotropic */
- float e = n_x;
- float lobe = powf(HdotN, e);
- float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
-
- out = NdotO * norm * lobe * pump;
- *pdf = norm * lobe / HdotI; /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper) */
- }
- else {
- /* anisotropic */
- float3 X, Y;
- make_orthonormals_tangent(N, bsdf->T, &X, &Y);
-
- float HdotX = dot(H, X);
- float HdotY = dot(H, Y);
- float lobe;
- if(HdotN < 1.0f) {
- float e = (n_x * HdotX*HdotX + n_y * HdotY*HdotY) / (1.0f - HdotN*HdotN);
- lobe = powf(HdotN, e);
- }
- else {
- lobe = 1.0f;
- }
- float norm = sqrtf((n_x + 1.0f)*(n_y + 1.0f)) / (8.0f * M_PI_F);
-
- out = NdotO * norm * lobe * pump;
- *pdf = norm * lobe / HdotI;
- }
- }
-
- return make_float3(out, out, out);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float3 N = bsdf->N;
+
+ float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
+ float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */
+
+ float out = 0.0f;
+
+ if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ if (NdotI > 0.0f && NdotO > 0.0f) {
+ NdotI = fmaxf(NdotI, 1e-6f);
+ NdotO = fmaxf(NdotO, 1e-6f);
+ float3 H = normalize(omega_in + I);
+ float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
+ float HdotN = fmaxf(dot(H, N), 1e-6f);
+
+ float pump =
+ 1.0f /
+ fmaxf(
+ 1e-6f,
+ (HdotI *
+ fmaxf(
+ NdotO,
+ NdotI))); /* pump from original paper (first derivative disc., but cancels the HdotI in the pdf nicely) */
+ /*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ /* pump from d-brdf paper */
+
+ float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
+ float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
+
+ if (n_x == n_y) {
+ /* isotropic */
+ float e = n_x;
+ float lobe = powf(HdotN, e);
+ float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
+
+ out = NdotO * norm * lobe * pump;
+ *pdf =
+ norm * lobe /
+ HdotI; /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper) */
+ }
+ else {
+ /* anisotropic */
+ float3 X, Y;
+ make_orthonormals_tangent(N, bsdf->T, &X, &Y);
+
+ float HdotX = dot(H, X);
+ float HdotY = dot(H, Y);
+ float lobe;
+ if (HdotN < 1.0f) {
+ float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN);
+ lobe = powf(HdotN, e);
+ }
+ else {
+ lobe = 1.0f;
+ }
+ float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F);
+
+ out = NdotO * norm * lobe * pump;
+ *pdf = norm * lobe / HdotI;
+ }
+ }
+
+ return make_float3(out, out, out);
}
-ccl_device float3 bsdf_ashikhmin_shirley_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_ashikhmin_shirley_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, float n_y, float randu, float randv, float *phi, float *cos_theta)
+ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(
+ float n_x, float n_y, float randu, float randv, float *phi, float *cos_theta)
{
- *phi = atanf(sqrtf((n_x + 1.0f) / (n_y + 1.0f)) * tanf(M_PI_2_F * randu));
- float cos_phi = cosf(*phi);
- float sin_phi = sinf(*phi);
- *cos_theta = powf(randv, 1.0f / (n_x * cos_phi*cos_phi + n_y * sin_phi*sin_phi + 1.0f));
+ *phi = atanf(sqrtf((n_x + 1.0f) / (n_y + 1.0f)) * tanf(M_PI_2_F * randu));
+ float cos_phi = cosf(*phi);
+ float sin_phi = sinf(*phi);
+ *cos_theta = powf(randv, 1.0f / (n_x * cos_phi * cos_phi + n_y * sin_phi * sin_phi + 1.0f));
}
-ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float3 N = bsdf->N;
- int label = LABEL_REFLECT | LABEL_GLOSSY;
-
- float NdotI = dot(N, I);
- if(NdotI > 0.0f) {
-
- float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
- float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
-
- /* get x,y basis on the surface for anisotropy */
- float3 X, Y;
-
- if(n_x == n_y)
- make_orthonormals(N, &X, &Y);
- else
- make_orthonormals_tangent(N, bsdf->T, &X, &Y);
-
- /* sample spherical coords for h in tangent space */
- float phi;
- float cos_theta;
- if(n_x == n_y) {
- /* isotropic sampling */
- phi = M_2PI_F * randu;
- cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
- }
- else {
- /* anisotropic sampling */
- if(randu < 0.25f) { /* first quadrant */
- float remapped_randu = 4.0f * randu;
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- }
- else if(randu < 0.5f) { /* second quadrant */
- float remapped_randu = 4.0f * (.5f - randu);
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- phi = M_PI_F - phi;
- }
- else if(randu < 0.75f) { /* third quadrant */
- float remapped_randu = 4.0f * (randu - 0.5f);
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- phi = M_PI_F + phi;
- }
- else { /* fourth quadrant */
- float remapped_randu = 4.0f * (1.0f - randu);
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- phi = 2.0f * M_PI_F - phi;
- }
- }
-
- /* get half vector in tangent space */
- float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta*cos_theta));
- float cos_phi = cosf(phi);
- float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
- float3 h = make_float3(
- sin_theta * cos_phi,
- sin_theta * sin_phi,
- cos_theta
- );
-
- /* half vector to world space */
- float3 H = h.x*X + h.y*Y + h.z*N;
- float HdotI = dot(H, I);
- if(HdotI < 0.0f) H = -H;
-
- /* reflect I on H to get omega_in */
- *omega_in = -I + (2.0f * HdotI) * H;
-
- if(fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
- /* Some high number for MIS. */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* leave the rest to eval_reflect */
- *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
- }
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float3 N = bsdf->N;
+ int label = LABEL_REFLECT | LABEL_GLOSSY;
+
+ float NdotI = dot(N, I);
+ if (NdotI > 0.0f) {
+
+ float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
+ float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
+
+ /* get x,y basis on the surface for anisotropy */
+ float3 X, Y;
+
+ if (n_x == n_y)
+ make_orthonormals(N, &X, &Y);
+ else
+ make_orthonormals_tangent(N, bsdf->T, &X, &Y);
+
+ /* sample spherical coords for h in tangent space */
+ float phi;
+ float cos_theta;
+ if (n_x == n_y) {
+ /* isotropic sampling */
+ phi = M_2PI_F * randu;
+ cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
+ }
+ else {
+ /* anisotropic sampling */
+ if (randu < 0.25f) { /* first quadrant */
+ float remapped_randu = 4.0f * randu;
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ }
+ else if (randu < 0.5f) { /* second quadrant */
+ float remapped_randu = 4.0f * (.5f - randu);
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ phi = M_PI_F - phi;
+ }
+ else if (randu < 0.75f) { /* third quadrant */
+ float remapped_randu = 4.0f * (randu - 0.5f);
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ phi = M_PI_F + phi;
+ }
+ else { /* fourth quadrant */
+ float remapped_randu = 4.0f * (1.0f - randu);
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ phi = 2.0f * M_PI_F - phi;
+ }
+ }
+
+ /* get half vector in tangent space */
+ float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
+ float cos_phi = cosf(phi);
+ float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
+ float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta);
+
+ /* half vector to world space */
+ float3 H = h.x * X + h.y * Y + h.z * N;
+ float HdotI = dot(H, I);
+ if (HdotI < 0.0f)
+ H = -H;
+
+ /* reflect I on H to get omega_in */
+ *omega_in = -I + (2.0f * HdotI) * H;
+
+ if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ /* leave the rest to eval_reflect */
+ *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
+ }
#ifdef __RAY_DIFFERENTIALS__
- /* just do the reflection thing for now */
- *domega_in_dx = (2.0f * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2.0f * dot(N, dIdy)) * N - dIdy;
+ /* just do the reflection thing for now */
+ *domega_in_dx = (2.0f * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2.0f * dot(N, dIdy)) * N - dIdy;
#endif
- }
+ }
- return label;
+ return label;
}
-
CCL_NAMESPACE_END
-#endif /* __BSDF_ASHIKHMIN_SHIRLEY_H__ */
+#endif /* __BSDF_ASHIKHMIN_SHIRLEY_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
index 80fd9ba2b37..8122bcc1424 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
@@ -36,126 +36,142 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct VelvetBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float sigma;
- float invsigma2;
+ float sigma;
+ float invsigma2;
} VelvetBsdf;
ccl_device int bsdf_ashikhmin_velvet_setup(VelvetBsdf *bsdf)
{
- float sigma = fmaxf(bsdf->sigma, 0.01f);
- bsdf->invsigma2 = 1.0f/(sigma * sigma);
+ float sigma = fmaxf(bsdf->sigma, 0.01f);
+ bsdf->invsigma2 = 1.0f / (sigma * sigma);
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_ashikhmin_velvet_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const VelvetBsdf *bsdf_a = (const VelvetBsdf*)a;
- const VelvetBsdf *bsdf_b = (const VelvetBsdf*)b;
+ const VelvetBsdf *bsdf_a = (const VelvetBsdf *)a;
+ const VelvetBsdf *bsdf_b = (const VelvetBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->sigma == bsdf_b->sigma);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->sigma == bsdf_b->sigma);
}
-ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const VelvetBsdf *bsdf = (const VelvetBsdf*)sc;
- float m_invsigma2 = bsdf->invsigma2;
- float3 N = bsdf->N;
+ const VelvetBsdf *bsdf = (const VelvetBsdf *)sc;
+ float m_invsigma2 = bsdf->invsigma2;
+ float3 N = bsdf->N;
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
- if(cosNO > 0 && cosNI > 0) {
- float3 H = normalize(omega_in + I);
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+ if (cosNO > 0 && cosNI > 0) {
+ float3 H = normalize(omega_in + I);
- float cosNH = dot(N, H);
- float cosHO = fabsf(dot(I, H));
+ float cosNH = dot(N, H);
+ float cosHO = fabsf(dot(I, H));
- if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f))
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f))
+ return make_float3(0.0f, 0.0f, 0.0f);
- float cosNHdivHO = cosNH / cosHO;
- cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
+ float cosNHdivHO = cosNH / cosHO;
+ cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
- float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
- float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
+ float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
+ float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
- float sinNH2 = 1 - cosNH * cosNH;
- float sinNH4 = sinNH2 * sinNH2;
- float cotangent2 = (cosNH * cosNH) / sinNH2;
+ float sinNH2 = 1 - cosNH * cosNH;
+ float sinNH4 = sinNH2 * sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
- float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
- float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
+ float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
+ float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
- float out = 0.25f * (D * G) / cosNO;
+ float out = 0.25f * (D * G) / cosNO;
- *pdf = 0.5f * M_1_PI_F;
- return make_float3(out, out, out);
- }
+ *pdf = 0.5f * M_1_PI_F;
+ return make_float3(out, out, out);
+ }
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const VelvetBsdf *bsdf = (const VelvetBsdf*)sc;
- float m_invsigma2 = bsdf->invsigma2;
- float3 N = bsdf->N;
+ const VelvetBsdf *bsdf = (const VelvetBsdf *)sc;
+ float m_invsigma2 = bsdf->invsigma2;
+ float3 N = bsdf->N;
- // we are viewing the surface from above - send a ray out with uniform
- // distribution over the hemisphere
- sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
+ // we are viewing the surface from above - send a ray out with uniform
+ // distribution over the hemisphere
+ sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0) {
- float3 H = normalize(*omega_in + I);
+ if (dot(Ng, *omega_in) > 0) {
+ float3 H = normalize(*omega_in + I);
- float cosNI = dot(N, *omega_in);
- float cosNO = dot(N, I);
- float cosNH = dot(N, H);
- float cosHO = fabsf(dot(I, H));
+ float cosNI = dot(N, *omega_in);
+ float cosNO = dot(N, I);
+ float cosNH = dot(N, H);
+ float cosHO = fabsf(dot(I, H));
- if(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f) {
- float cosNHdivHO = cosNH / cosHO;
- cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
+ if (fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f) {
+ float cosNHdivHO = cosNH / cosHO;
+ cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
- float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
- float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
+ float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
+ float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
- float sinNH2 = 1 - cosNH * cosNH;
- float sinNH4 = sinNH2 * sinNH2;
- float cotangent2 = (cosNH * cosNH) / sinNH2;
+ float sinNH2 = 1 - cosNH * cosNH;
+ float sinNH4 = sinNH2 * sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
- float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
- float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
+ float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
+ float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
- float power = 0.25f * (D * G) / cosNO;
+ float power = 0.25f * (D * G) / cosNO;
- *eval = make_float3(power, power, power);
+ *eval = make_float3(power, power, power);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the retroreflective bounce
- *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
+ // TODO: find a better approximation for the retroreflective bounce
+ *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
- }
- else
- *pdf = 0.0f;
-
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ }
+ else
+ *pdf = 0.0f;
+ }
+ else
+ *pdf = 0.0f;
+
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_ASHIKHMIN_VELVET_H__ */
+#endif /* __BSDF_ASHIKHMIN_VELVET_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h
index 946c460a70e..76b50548455 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse.h
@@ -36,107 +36,141 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct DiffuseBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
} DiffuseBsdf;
/* DIFFUSE */
ccl_device int bsdf_diffuse_setup(DiffuseBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_DIFFUSE_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_diffuse_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const DiffuseBsdf *bsdf_a = (const DiffuseBsdf*)a;
- const DiffuseBsdf *bsdf_b = (const DiffuseBsdf*)b;
+ const DiffuseBsdf *bsdf_a = (const DiffuseBsdf *)a;
+ const DiffuseBsdf *bsdf_b = (const DiffuseBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N));
+ return (isequal_float3(bsdf_a->N, bsdf_b->N));
}
-ccl_device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
- float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- *pdf = cos_pi;
- return make_float3(cos_pi, cos_pi, cos_pi);
+ float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+ *pdf = cos_pi;
+ return make_float3(cos_pi, cos_pi, cos_pi);
}
-ccl_device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
- // distribution over the hemisphere
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+ // distribution over the hemisphere
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = make_float3(*pdf, *pdf, *pdf);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = make_float3(*pdf, *pdf, *pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
+ }
+ else
+ *pdf = 0.0f;
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
/* TRANSLUCENT */
ccl_device int bsdf_translucent_setup(DiffuseBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_TRANSLUCENT_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_TRANSLUCENT_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
- float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F;
- *pdf = cos_pi;
- return make_float3 (cos_pi, cos_pi, cos_pi);
+ float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F;
+ *pdf = cos_pi;
+ return make_float3(cos_pi, cos_pi, cos_pi);
}
-ccl_device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_translucent_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
-
- // we are viewing the surface from the right side - send a ray out with cosine
- // distribution over the hemisphere
- sample_cos_hemisphere (-N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) < 0) {
- *eval = make_float3(*pdf, *pdf, *pdf);
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
+
+ // we are viewing the surface from the right side - send a ray out with cosine
+ // distribution over the hemisphere
+ sample_cos_hemisphere(-N, randu, randv, omega_in, pdf);
+ if (dot(Ng, *omega_in) < 0) {
+ *eval = make_float3(*pdf, *pdf, *pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
- *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+ *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
#endif
- }
- else {
- *pdf = 0;
- }
- return LABEL_TRANSMIT|LABEL_DIFFUSE;
+ }
+ else {
+ *pdf = 0;
+ }
+ return LABEL_TRANSMIT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_DIFFUSE_H__ */
+#endif /* __BSDF_DIFFUSE_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
index ca33a5b275c..9d13eb8d4e0 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
@@ -38,73 +38,90 @@ CCL_NAMESPACE_BEGIN
#ifdef __OSL__
typedef ccl_addr_space struct DiffuseRampBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float3 *colors;
+ float3 *colors;
} DiffuseRampBsdf;
ccl_device float3 bsdf_diffuse_ramp_get_color(const float3 colors[8], float pos)
{
- int MAXCOLORS = 8;
-
- float npos = pos * (float)(MAXCOLORS - 1);
- int ipos = float_to_int(npos);
- if(ipos < 0)
- return colors[0];
- if(ipos >= (MAXCOLORS - 1))
- return colors[MAXCOLORS - 1];
- float offset = npos - (float)ipos;
- return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
+ int MAXCOLORS = 8;
+
+ float npos = pos * (float)(MAXCOLORS - 1);
+ int ipos = float_to_int(npos);
+ if (ipos < 0)
+ return colors[0];
+ if (ipos >= (MAXCOLORS - 1))
+ return colors[MAXCOLORS - 1];
+ float offset = npos - (float)ipos;
+ return colors[ipos] * (1.0f - offset) + colors[ipos + 1] * offset;
}
ccl_device int bsdf_diffuse_ramp_setup(DiffuseRampBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_diffuse_ramp_blur(ShaderClosure *sc, float roughness)
{
}
-ccl_device float3 bsdf_diffuse_ramp_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_ramp_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
+ float3 N = bsdf->N;
- float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
- *pdf = cos_pi * M_1_PI_F;
- return bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F;
+ float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
+ *pdf = cos_pi * M_1_PI_F;
+ return bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F;
}
-ccl_device float3 bsdf_diffuse_ramp_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_ramp_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf*)sc;
- float3 N = bsdf->N;
-
- // distribution over the hemisphere
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
-
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F;
-#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
-#endif
- }
- else
- *pdf = 0.0f;
-
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
+ float3 N = bsdf->N;
+
+ // distribution over the hemisphere
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F;
+# ifdef __RAY_DIFFERENTIALS__
+ *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
+# endif
+ }
+ else
+ *pdf = 0.0f;
+
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
-#endif /* __OSL__ */
+#endif /* __OSL__ */
CCL_NAMESPACE_END
-#endif /* __BSDF_DIFFUSE_RAMP_H__ */
+#endif /* __BSDF_DIFFUSE_RAMP_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index e1a0cfaa3f5..6b2a9a97d30 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -36,245 +36,276 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct HairBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float3 T;
- float roughness1;
- float roughness2;
- float offset;
+ float3 T;
+ float roughness1;
+ float roughness2;
+ float offset;
} HairBsdf;
ccl_device int bsdf_hair_reflection_setup(HairBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
- bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
- bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
+ bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
+ bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_hair_transmission_setup(HairBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
- bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
- bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
+ bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
+ bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_hair_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const HairBsdf *bsdf_a = (const HairBsdf*)a;
- const HairBsdf *bsdf_b = (const HairBsdf*)b;
+ const HairBsdf *bsdf_a = (const HairBsdf *)a;
+ const HairBsdf *bsdf_b = (const HairBsdf *)b;
- return (isequal_float3(bsdf_a->T, bsdf_b->T)) &&
- (bsdf_a->roughness1 == bsdf_b->roughness1) &&
- (bsdf_a->roughness2 == bsdf_b->roughness2) &&
- (bsdf_a->offset == bsdf_b->offset);
+ return (isequal_float3(bsdf_a->T, bsdf_b->T)) && (bsdf_a->roughness1 == bsdf_b->roughness1) &&
+ (bsdf_a->roughness2 == bsdf_b->roughness2) && (bsdf_a->offset == bsdf_b->offset);
}
-ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float omega_in_z = dot(Tg, omega_in);
- float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
+ float omega_in_z = dot(Tg, omega_in);
+ float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
- float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
- float cosphi_i = dot(omega_in_y, locy);
+ float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
+ float cosphi_i = dot(omega_in_y, locy);
- if(M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) {
- *pdf = 0.0f;
- return make_float3(*pdf, *pdf, *pdf);
- }
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) {
+ *pdf = 0.0f;
+ return make_float3(*pdf, *pdf, *pdf);
+ }
- float roughness1_inv = 1.0f / roughness1;
- float roughness2_inv = 1.0f / roughness2;
- float phi_i = fast_acosf(cosphi_i) * roughness2_inv;
- phi_i = fabsf(phi_i) < M_PI_F ? phi_i : M_PI_F;
- float costheta_i = fast_cosf(theta_i);
+ float roughness1_inv = 1.0f / roughness1;
+ float roughness2_inv = 1.0f / roughness2;
+ float phi_i = fast_acosf(cosphi_i) * roughness2_inv;
+ phi_i = fabsf(phi_i) < M_PI_F ? phi_i : M_PI_F;
+ float costheta_i = fast_cosf(theta_i);
- float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float theta_h = (theta_i + theta_r) * 0.5f;
- float t = theta_h - offset;
+ float theta_h = (theta_i + theta_r) * 0.5f;
+ float t = theta_h - offset;
- float phi_pdf = fast_cosf(phi_i * 0.5f) * 0.25f * roughness2_inv;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)* costheta_i);
- *pdf = phi_pdf * theta_pdf;
+ float phi_pdf = fast_cosf(phi_i * 0.5f) * 0.25f * roughness2_inv;
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i);
+ *pdf = phi_pdf * theta_pdf;
- return make_float3(*pdf, *pdf, *pdf);
+ return make_float3(*pdf, *pdf, *pdf);
}
-ccl_device float3 bsdf_hair_transmission_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_transmission_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-
-ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float omega_in_z = dot(Tg, omega_in);
- float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
+ float omega_in_z = dot(Tg, omega_in);
+ float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
- float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
- float phi_i = fast_acosf(dot(omega_in_y, locy));
+ float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
+ float phi_i = fast_acosf(dot(omega_in_y, locy));
- if(M_PI_2_F - fabsf(theta_i) < 0.001f) {
- *pdf = 0.0f;
- return make_float3(*pdf, *pdf, *pdf);
- }
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f) {
+ *pdf = 0.0f;
+ return make_float3(*pdf, *pdf, *pdf);
+ }
- float costheta_i = fast_cosf(theta_i);
+ float costheta_i = fast_cosf(theta_i);
- float roughness1_inv = 1.0f / roughness1;
- float a_TT = fast_atan2f(((M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float b_TT = fast_atan2f(((-M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
+ float roughness1_inv = 1.0f / roughness1;
+ float a_TT = fast_atan2f(((M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float b_TT = fast_atan2f(((-M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
- float theta_h = (theta_i + theta_r) / 2;
- float t = theta_h - offset;
- float phi = fabsf(phi_i);
+ float theta_h = (theta_i + theta_r) / 2;
+ float t = theta_h - offset;
+ float phi = fabsf(phi_i);
- float p = M_PI_F - phi;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1 * roughness1) * (a_TT - b_TT)*costheta_i);
- float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
+ float p = M_PI_F - phi;
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i);
+ float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
- *pdf = phi_pdf * theta_pdf;
- return make_float3(*pdf, *pdf, *pdf);
+ *pdf = phi_pdf * theta_pdf;
+ return make_float3(*pdf, *pdf, *pdf);
}
-ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
- float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
+ float3 locx = cross(locy, Tg);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float roughness1_inv = 1.0f / roughness1;
- float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float roughness1_inv = 1.0f / roughness1;
+ float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float t = roughness1 * tanf(randu * (a_R - b_R) + b_R);
+ float t = roughness1 * tanf(randu * (a_R - b_R) + b_R);
- float theta_h = t + offset;
- float theta_i = 2 * theta_h - theta_r;
+ float theta_h = t + offset;
+ float theta_i = 2 * theta_h - theta_r;
- float costheta_i, sintheta_i;
- fast_sincosf(theta_i, &sintheta_i, &costheta_i);
+ float costheta_i, sintheta_i;
+ fast_sincosf(theta_i, &sintheta_i, &costheta_i);
- float phi = 2 * safe_asinf(1 - 2 * randv) * roughness2;
+ float phi = 2 * safe_asinf(1 - 2 * randv) * roughness2;
- float phi_pdf = fast_cosf(phi * 0.5f) * 0.25f / roughness2;
+ float phi_pdf = fast_cosf(phi * 0.5f) * 0.25f / roughness2;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)*costheta_i);
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i);
- float sinphi, cosphi;
- fast_sincosf(phi, &sinphi, &cosphi);
- *omega_in =(cosphi * costheta_i) * locy -
- (sinphi * costheta_i) * locx +
- ( sintheta_i) * Tg;
+ float sinphi, cosphi;
+ fast_sincosf(phi, &sinphi, &cosphi);
+ *omega_in = (cosphi * costheta_i) * locy - (sinphi * costheta_i) * locx + (sintheta_i)*Tg;
- //differentials - TODO: find a better approximation for the reflective bounce
+ //differentials - TODO: find a better approximation for the reflective bounce
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
- *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
+ *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
+ *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
#endif
- *pdf = fabsf(phi_pdf * theta_pdf);
- if(M_PI_2_F - fabsf(theta_i) < 0.001f)
- *pdf = 0.0f;
+ *pdf = fabsf(phi_pdf * theta_pdf);
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f)
+ *pdf = 0.0f;
- *eval = make_float3(*pdf, *pdf, *pdf);
+ *eval = make_float3(*pdf, *pdf, *pdf);
- return LABEL_REFLECT|LABEL_GLOSSY;
+ return LABEL_REFLECT | LABEL_GLOSSY;
}
-ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
- float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
-
- float roughness1_inv = 1.0f / roughness1;
- float a_TT = fast_atan2f(((M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float b_TT = fast_atan2f(((-M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
-
- float t = roughness1 * tanf(randu * (a_TT - b_TT) + b_TT);
-
- float theta_h = t + offset;
- float theta_i = 2 * theta_h - theta_r;
-
- float costheta_i, sintheta_i;
- fast_sincosf(theta_i, &sintheta_i, &costheta_i);
-
- float p = roughness2 * tanf(c_TT * (randv - 0.5f));
- float phi = p + M_PI_F;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_TT - b_TT) * costheta_i);
- float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
-
- float sinphi, cosphi;
- fast_sincosf(phi, &sinphi, &cosphi);
- *omega_in =(cosphi * costheta_i) * locy -
- (sinphi * costheta_i) * locx +
- ( sintheta_i) * Tg;
-
- //differentials - TODO: find a better approximation for the transmission bounce
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
+ float3 locx = cross(locy, Tg);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
+
+ float roughness1_inv = 1.0f / roughness1;
+ float a_TT = fast_atan2f(((M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float b_TT = fast_atan2f(((-M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
+
+ float t = roughness1 * tanf(randu * (a_TT - b_TT) + b_TT);
+
+ float theta_h = t + offset;
+ float theta_i = 2 * theta_h - theta_r;
+
+ float costheta_i, sintheta_i;
+ fast_sincosf(theta_i, &sintheta_i, &costheta_i);
+
+ float p = roughness2 * tanf(c_TT * (randv - 0.5f));
+ float phi = p + M_PI_F;
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i);
+ float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
+
+ float sinphi, cosphi;
+ fast_sincosf(phi, &sinphi, &cosphi);
+ *omega_in = (cosphi * costheta_i) * locy - (sinphi * costheta_i) * locx + (sintheta_i)*Tg;
+
+ //differentials - TODO: find a better approximation for the transmission bounce
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
- *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
+ *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
+ *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
#endif
- *pdf = fabsf(phi_pdf * theta_pdf);
- if(M_PI_2_F - fabsf(theta_i) < 0.001f) {
- *pdf = 0.0f;
- }
+ *pdf = fabsf(phi_pdf * theta_pdf);
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f) {
+ *pdf = 0.0f;
+ }
- *eval = make_float3(*pdf, *pdf, *pdf);
+ *eval = make_float3(*pdf, *pdf, *pdf);
- /* TODO(sergey): Should always be negative, but seems some precision issue
- * is involved here.
- */
- kernel_assert(dot(locy, *omega_in) < 1e-4f);
+ /* TODO(sergey): Should always be negative, but seems some precision issue
+ * is involved here.
+ */
+ kernel_assert(dot(locy, *omega_in) < 1e-4f);
- return LABEL_TRANSMIT|LABEL_GLOSSY;
+ return LABEL_TRANSMIT | LABEL_GLOSSY;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_HAIR_H__ */
+#endif /* __BSDF_HAIR_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
index 68335ee887a..a4bba2fbf6c 100644
--- a/intern/cycles/kernel/closure/bsdf_hair_principled.h
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -15,251 +15,245 @@
*/
#ifdef __KERNEL_CPU__
-#include <fenv.h>
+# include <fenv.h>
#endif
#include "kernel/kernel_color.h"
#ifndef __BSDF_HAIR_PRINCIPLED_H__
-#define __BSDF_HAIR_PRINCIPLED_H__
+# define __BSDF_HAIR_PRINCIPLED_H__
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct PrincipledHairExtra {
- /* Geometry data. */
- float4 geom;
+ /* Geometry data. */
+ float4 geom;
} PrincipledHairExtra;
typedef ccl_addr_space struct PrincipledHairBSDF {
- SHADER_CLOSURE_BASE;
-
- /* Absorption coefficient. */
- float3 sigma;
- /* Variance of the underlying logistic distribution. */
- float v;
- /* Scale factor of the underlying logistic distribution. */
- float s;
- /* Cuticle tilt angle. */
- float alpha;
- /* IOR. */
- float eta;
- /* Effective variance for the diffuse bounce only. */
- float m0_roughness;
-
- /* Extra closure. */
- PrincipledHairExtra *extra;
+ SHADER_CLOSURE_BASE;
+
+ /* Absorption coefficient. */
+ float3 sigma;
+ /* Variance of the underlying logistic distribution. */
+ float v;
+ /* Scale factor of the underlying logistic distribution. */
+ float s;
+ /* Cuticle tilt angle. */
+ float alpha;
+ /* IOR. */
+ float eta;
+ /* Effective variance for the diffuse bounce only. */
+ float m0_roughness;
+
+ /* Extra closure. */
+ PrincipledHairExtra *extra;
} PrincipledHairBSDF;
-static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF), "PrincipledHairBSDF is too large!");
-static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra), "PrincipledHairExtra is too large!");
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF),
+ "PrincipledHairBSDF is too large!");
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra),
+ "PrincipledHairExtra is too large!");
ccl_device_inline float cos_from_sin(const float s)
{
- return safe_sqrtf(1.0f - s*s);
+ return safe_sqrtf(1.0f - s * s);
}
/* Gives the change in direction in the normal plane for the given angles and p-th-order scattering. */
ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
{
- return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
+ return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
}
/* Remaps the given angle to [-pi, pi]. */
ccl_device_inline float wrap_angle(float a)
{
- while(a > M_PI_F) {
- a -= M_2PI_F;
- }
- while(a < -M_PI_F) {
- a += M_2PI_F;
- }
- return a;
+ while (a > M_PI_F) {
+ a -= M_2PI_F;
+ }
+ while (a < -M_PI_F) {
+ a += M_2PI_F;
+ }
+ return a;
}
/* Logistic distribution function. */
ccl_device_inline float logistic(float x, float s)
{
- float v = expf(-fabsf(x)/s);
- return v / (s * sqr(1.0f + v));
+ float v = expf(-fabsf(x) / s);
+ return v / (s * sqr(1.0f + v));
}
/* Logistic cumulative density function. */
ccl_device_inline float logistic_cdf(float x, float s)
{
- float arg = -x/s;
- /* expf() overflows if arg >= 89.0. */
- if(arg > 88.0f) {
- return 0.0f;
- }
- else {
- return 1.0f / (1.0f + expf(arg));
- }
+ float arg = -x / s;
+ /* expf() overflows if arg >= 89.0. */
+ if (arg > 88.0f) {
+ return 0.0f;
+ }
+ else {
+ return 1.0f / (1.0f + expf(arg));
+ }
}
/* Numerical approximation to the Bessel function of the first kind. */
ccl_device_inline float bessel_I0(float x)
{
- x = sqr(x);
- float val = 1.0f + 0.25f*x;
- float pow_x_2i = sqr(x);
- uint64_t i_fac_2 = 1;
- int pow_4_i = 16;
- for(int i = 2; i < 10; i++) {
- i_fac_2 *= i*i;
- float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
- if(val == newval) {
- return val;
- }
- val = newval;
- pow_x_2i *= x;
- pow_4_i *= 4;
- }
- return val;
+ x = sqr(x);
+ float val = 1.0f + 0.25f * x;
+ float pow_x_2i = sqr(x);
+ uint64_t i_fac_2 = 1;
+ int pow_4_i = 16;
+ for (int i = 2; i < 10; i++) {
+ i_fac_2 *= i * i;
+ float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
+ if (val == newval) {
+ return val;
+ }
+ val = newval;
+ pow_x_2i *= x;
+ pow_4_i *= 4;
+ }
+ return val;
}
/* Logarithm of the Bessel function of the first kind. */
ccl_device_inline float log_bessel_I0(float x)
{
- if(x > 12.0f) {
- /* log(1/x) == -log(x) iff x > 0.
- * This is only used with positive cosines */
- return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
- }
- else {
- return logf(bessel_I0(x));
- }
+ if (x > 12.0f) {
+ /* log(1/x) == -log(x) iff x > 0.
+ * This is only used with positive cosines */
+ return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
+ }
+ else {
+ return logf(bessel_I0(x));
+ }
}
/* Logistic distribution limited to the interval [-pi, pi]. */
ccl_device_inline float trimmed_logistic(float x, float s)
{
- /* The logistic distribution is symmetric and centered around zero,
- * so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
- * Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
- float scaling_fac = 1.0f - 2.0f*logistic_cdf(-M_PI_F, s);
- float val = logistic(x, s);
- return safe_divide(val, scaling_fac);
+ /* The logistic distribution is symmetric and centered around zero,
+ * so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
+ * Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
+ float scaling_fac = 1.0f - 2.0f * logistic_cdf(-M_PI_F, s);
+ float val = logistic(x, s);
+ return safe_divide(val, scaling_fac);
}
/* Sampling function for the trimmed logistic function. */
ccl_device_inline float sample_trimmed_logistic(float u, float s)
{
- float cdf_minuspi = logistic_cdf(-M_PI_F, s);
- float x = -s*logf(1.0f / (u*(1.0f - 2.0f*cdf_minuspi) + cdf_minuspi) - 1.0f);
- return clamp(x, -M_PI_F, M_PI_F);
+ float cdf_minuspi = logistic_cdf(-M_PI_F, s);
+ float x = -s * logf(1.0f / (u * (1.0f - 2.0f * cdf_minuspi) + cdf_minuspi) - 1.0f);
+ return clamp(x, -M_PI_F, M_PI_F);
}
/* Azimuthal scattering function Np. */
-ccl_device_inline float azimuthal_scattering(float phi,
- int p,
- float s,
- float gamma_o,
- float gamma_t)
+ccl_device_inline float azimuthal_scattering(
+ float phi, int p, float s, float gamma_o, float gamma_t)
{
- float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
- float val = trimmed_logistic(phi_o, s);
- return val;
+ float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
+ float val = trimmed_logistic(phi_o, s);
+ return val;
}
/* Longitudinal scattering function Mp. */
-ccl_device_inline float longitudinal_scattering(float sin_theta_i,
- float cos_theta_i,
- float sin_theta_o,
- float cos_theta_o,
- float v)
+ccl_device_inline float longitudinal_scattering(
+ float sin_theta_i, float cos_theta_i, float sin_theta_o, float cos_theta_o, float v)
{
- float inv_v = 1.0f/v;
- float cos_arg = cos_theta_i * cos_theta_o * inv_v;
- float sin_arg = sin_theta_i * sin_theta_o * inv_v;
- if(v <= 0.1f) {
- float i0 = log_bessel_I0(cos_arg);
- float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f*inv_v));
- return val;
- }
- else {
- float i0 = bessel_I0(cos_arg);
- float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
- return val;
- }
+ float inv_v = 1.0f / v;
+ float cos_arg = cos_theta_i * cos_theta_o * inv_v;
+ float sin_arg = sin_theta_i * sin_theta_o * inv_v;
+ if (v <= 0.1f) {
+ float i0 = log_bessel_I0(cos_arg);
+ float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f * inv_v));
+ return val;
+ }
+ else {
+ float i0 = bessel_I0(cos_arg);
+ float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
+ return val;
+ }
}
/* Combine the three values using their luminances. */
ccl_device_inline float4 combine_with_energy(KernelGlobals *kg, float3 c)
{
- return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
+ return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
}
-#ifdef __HAIR__
+# ifdef __HAIR__
/* Set up the hair closure. */
ccl_device int bsdf_principled_hair_setup(ShaderData *sd, PrincipledHairBSDF *bsdf)
{
- bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
- bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
- bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
- /* Apply Primary Reflection Roughness modifier. */
- bsdf->m0_roughness = clamp(bsdf->m0_roughness*bsdf->v, 0.001f, 1.0f);
-
- /* Map from roughness_u and roughness_v to variance and scale factor. */
- bsdf->v = sqr(0.726f*bsdf->v + 0.812f*sqr(bsdf->v) + 3.700f*pow20(bsdf->v));
- bsdf->s = (0.265f*bsdf->s + 1.194f*sqr(bsdf->s) + 5.372f*pow22(bsdf->s))*M_SQRT_PI_8_F;
- bsdf->m0_roughness = sqr(0.726f*bsdf->m0_roughness + 0.812f*sqr(bsdf->m0_roughness) + 3.700f*pow20(bsdf->m0_roughness));
-
- /* Compute local frame, aligned to curve tangent and ray direction. */
- float3 X = safe_normalize(sd->dPdu);
- float3 Y = safe_normalize(cross(X, sd->I));
- float3 Z = safe_normalize(cross(X, Y));
- /* TODO: the solution below works where sd->Ng is the normal
- * pointing from the center of the curve to the shading point.
- * It doesn't work for triangles, see https://developer.blender.org/T43625 */
-
- /* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
- * the center, to grazing the other edge. This is the sine of the angle
- * between sd->Ng and Z, as seen from the tangent X. */
-
- /* TODO: we convert this value to a cosine later and discard the sign, so
- * we could probably save some operations. */
- float h = dot(cross(sd->Ng, X), Z);
-
- kernel_assert(fabsf(h) < 1.0f + 1e-4f);
- kernel_assert(isfinite3_safe(Y));
- kernel_assert(isfinite_safe(h));
-
- bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
-
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+ bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+ bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
+ bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
+ /* Apply Primary Reflection Roughness modifier. */
+ bsdf->m0_roughness = clamp(bsdf->m0_roughness * bsdf->v, 0.001f, 1.0f);
+
+ /* Map from roughness_u and roughness_v to variance and scale factor. */
+ bsdf->v = sqr(0.726f * bsdf->v + 0.812f * sqr(bsdf->v) + 3.700f * pow20(bsdf->v));
+ bsdf->s = (0.265f * bsdf->s + 1.194f * sqr(bsdf->s) + 5.372f * pow22(bsdf->s)) * M_SQRT_PI_8_F;
+ bsdf->m0_roughness = sqr(0.726f * bsdf->m0_roughness + 0.812f * sqr(bsdf->m0_roughness) +
+ 3.700f * pow20(bsdf->m0_roughness));
+
+ /* Compute local frame, aligned to curve tangent and ray direction. */
+ float3 X = safe_normalize(sd->dPdu);
+ float3 Y = safe_normalize(cross(X, sd->I));
+ float3 Z = safe_normalize(cross(X, Y));
+ /* TODO: the solution below works where sd->Ng is the normal
+ * pointing from the center of the curve to the shading point.
+ * It doesn't work for triangles, see https://developer.blender.org/T43625 */
+
+ /* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
+ * the center, to grazing the other edge. This is the sine of the angle
+ * between sd->Ng and Z, as seen from the tangent X. */
+
+ /* TODO: we convert this value to a cosine later and discard the sign, so
+ * we could probably save some operations. */
+ float h = dot(cross(sd->Ng, X), Z);
+
+ kernel_assert(fabsf(h) < 1.0f + 1e-4f);
+ kernel_assert(isfinite3_safe(Y));
+ kernel_assert(isfinite_safe(h));
+
+ bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
-#endif /* __HAIR__ */
+# endif /* __HAIR__ */
/* Given the Fresnel term and transmittance, generate the attenuation terms for each bounce. */
-ccl_device_inline void hair_attenuation(KernelGlobals *kg,
- float f,
- float3 T,
- float4 *Ap)
+ccl_device_inline void hair_attenuation(KernelGlobals *kg, float f, float3 T, float4 *Ap)
{
- /* Primary specular (R). */
- Ap[0] = make_float4(f, f, f, f);
+ /* Primary specular (R). */
+ Ap[0] = make_float4(f, f, f, f);
- /* Transmission (TT). */
- float3 col = sqr(1.0f - f) * T;
- Ap[1] = combine_with_energy(kg, col);
+ /* Transmission (TT). */
+ float3 col = sqr(1.0f - f) * T;
+ Ap[1] = combine_with_energy(kg, col);
- /* Secondary specular (TRT). */
- col *= T*f;
- Ap[2] = combine_with_energy(kg, col);
+ /* Secondary specular (TRT). */
+ col *= T * f;
+ Ap[2] = combine_with_energy(kg, col);
- /* Residual component (TRRT+). */
- col *= safe_divide_color(T*f, make_float3(1.0f, 1.0f, 1.0f) - T*f);
- Ap[3] = combine_with_energy(kg, col);
+ /* Residual component (TRRT+). */
+ col *= safe_divide_color(T * f, make_float3(1.0f, 1.0f, 1.0f) - T * f);
+ Ap[3] = combine_with_energy(kg, col);
- /* Normalize sampling weights. */
- float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
- float fac = safe_divide(1.0f, totweight);
+ /* Normalize sampling weights. */
+ float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
+ float fac = safe_divide(1.0f, totweight);
- Ap[0].w *= fac;
- Ap[1].w *= fac;
- Ap[2].w *= fac;
- Ap[3].w *= fac;
+ Ap[0].w *= fac;
+ Ap[1].w *= fac;
+ Ap[2].w *= fac;
+ Ap[3].w *= fac;
}
/* Given the tilt angle, generate the rotated theta_i for the different bounces. */
@@ -268,19 +262,19 @@ ccl_device_inline void hair_alpha_angles(float sin_theta_i,
float alpha,
float *angles)
{
- float sin_1alpha = sinf(alpha);
- float cos_1alpha = cos_from_sin(sin_1alpha);
- float sin_2alpha = 2.0f*sin_1alpha*cos_1alpha;
- float cos_2alpha = sqr(cos_1alpha) - sqr(sin_1alpha);
- float sin_4alpha = 2.0f*sin_2alpha*cos_2alpha;
- float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
-
- angles[0] = sin_theta_i*cos_2alpha + cos_theta_i*sin_2alpha;
- angles[1] = fabsf(cos_theta_i*cos_2alpha - sin_theta_i*sin_2alpha);
- angles[2] = sin_theta_i*cos_1alpha - cos_theta_i*sin_1alpha;
- angles[3] = fabsf(cos_theta_i*cos_1alpha + sin_theta_i*sin_1alpha);
- angles[4] = sin_theta_i*cos_4alpha - cos_theta_i*sin_4alpha;
- angles[5] = fabsf(cos_theta_i*cos_4alpha + sin_theta_i*sin_4alpha);
+ float sin_1alpha = sinf(alpha);
+ float cos_1alpha = cos_from_sin(sin_1alpha);
+ float sin_2alpha = 2.0f * sin_1alpha * cos_1alpha;
+ float cos_2alpha = sqr(cos_1alpha) - sqr(sin_1alpha);
+ float sin_4alpha = 2.0f * sin_2alpha * cos_2alpha;
+ float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
+
+ angles[0] = sin_theta_i * cos_2alpha + cos_theta_i * sin_2alpha;
+ angles[1] = fabsf(cos_theta_i * cos_2alpha - sin_theta_i * sin_2alpha);
+ angles[2] = sin_theta_i * cos_1alpha - cos_theta_i * sin_1alpha;
+ angles[3] = fabsf(cos_theta_i * cos_1alpha + sin_theta_i * sin_1alpha);
+ angles[4] = sin_theta_i * cos_4alpha - cos_theta_i * sin_4alpha;
+ angles[5] = fabsf(cos_theta_i * cos_4alpha + sin_theta_i * sin_4alpha);
}
/* Evaluation function for our shader. */
@@ -290,75 +284,75 @@ ccl_device float3 bsdf_principled_hair_eval(KernelGlobals *kg,
const float3 omega_in,
float *pdf)
{
- kernel_assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
+ kernel_assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
- const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF*) sc;
- float3 Y = float4_to_float3(bsdf->extra->geom);
+ const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF *)sc;
+ float3 Y = float4_to_float3(bsdf->extra->geom);
- float3 X = safe_normalize(sd->dPdu);
- kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
- float3 Z = safe_normalize(cross(X, Y));
+ float3 X = safe_normalize(sd->dPdu);
+ kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
+ float3 Z = safe_normalize(cross(X, Y));
- float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
- float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+ float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
+ float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
- float sin_theta_o = wo.x;
- float cos_theta_o = cos_from_sin(sin_theta_o);
- float phi_o = atan2f(wo.z, wo.y);
+ float sin_theta_o = wo.x;
+ float cos_theta_o = cos_from_sin(sin_theta_o);
+ float phi_o = atan2f(wo.z, wo.y);
- float sin_theta_t = sin_theta_o / bsdf->eta;
- float cos_theta_t = cos_from_sin(sin_theta_t);
+ float sin_theta_t = sin_theta_o / bsdf->eta;
+ float cos_theta_t = cos_from_sin(sin_theta_t);
- float sin_gamma_o = bsdf->extra->geom.w;
- float cos_gamma_o = cos_from_sin(sin_gamma_o);
- float gamma_o = safe_asinf(sin_gamma_o);
+ float sin_gamma_o = bsdf->extra->geom.w;
+ float cos_gamma_o = cos_from_sin(sin_gamma_o);
+ float gamma_o = safe_asinf(sin_gamma_o);
- float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
- float cos_gamma_t = cos_from_sin(sin_gamma_t);
- float gamma_t = safe_asinf(sin_gamma_t);
+ float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
+ float cos_gamma_t = cos_from_sin(sin_gamma_t);
+ float gamma_t = safe_asinf(sin_gamma_t);
- float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
- float4 Ap[4];
- hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
+ float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
+ float4 Ap[4];
+ hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
- float sin_theta_i = wi.x;
- float cos_theta_i = cos_from_sin(sin_theta_i);
- float phi_i = atan2f(wi.z, wi.y);
+ float sin_theta_i = wi.x;
+ float cos_theta_i = cos_from_sin(sin_theta_i);
+ float phi_i = atan2f(wi.z, wi.y);
- float phi = phi_i - phi_o;
+ float phi = phi_i - phi_o;
- float angles[6];
- hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
+ float angles[6];
+ hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
- float4 F;
- float Mp, Np;
+ float4 F;
+ float Mp, Np;
- /* Primary specular (R). */
- Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
- Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
- F = Ap[0] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Primary specular (R). */
+ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
+ Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
+ F = Ap[0] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- /* Transmission (TT). */
- Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
- Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
- F += Ap[1] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Transmission (TT). */
+ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
+ Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
+ F += Ap[1] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- /* Secondary specular (TRT). */
- Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
- F += Ap[2] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Secondary specular (TRT). */
+ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
+ F += Ap[2] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- /* Residual component (TRRT+). */
- Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = M_1_2PI_F;
- F += Ap[3] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Residual component (TRRT+). */
+ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = M_1_2PI_F;
+ F += Ap[3] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- *pdf = F.w;
- return float4_to_float3(F);
+ *pdf = F.w;
+ return float4_to_float3(F);
}
/* Sampling function for the hair shader. */
@@ -373,130 +367,131 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals *kg,
float3 *domega_in_dy,
float *pdf)
{
- PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*) sc;
-
- float3 Y = float4_to_float3(bsdf->extra->geom);
-
- float3 X = safe_normalize(sd->dPdu);
- kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
- float3 Z = safe_normalize(cross(X, Y));
-
- float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
-
- float2 u[2];
- u[0] = make_float2(randu, randv);
- u[1].x = lcg_step_float_addrspace(&sd->lcg_state);
- u[1].y = lcg_step_float_addrspace(&sd->lcg_state);
-
- float sin_theta_o = wo.x;
- float cos_theta_o = cos_from_sin(sin_theta_o);
- float phi_o = atan2f(wo.z, wo.y);
-
- float sin_theta_t = sin_theta_o / bsdf->eta;
- float cos_theta_t = cos_from_sin(sin_theta_t);
-
- float sin_gamma_o = bsdf->extra->geom.w;
- float cos_gamma_o = cos_from_sin(sin_gamma_o);
- float gamma_o = safe_asinf(sin_gamma_o);
-
- float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
- float cos_gamma_t = cos_from_sin(sin_gamma_t);
- float gamma_t = safe_asinf(sin_gamma_t);
-
- float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
- float4 Ap[4];
- hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
-
- int p = 0;
- for(; p < 3; p++) {
- if(u[0].x < Ap[p].w) {
- break;
- }
- u[0].x -= Ap[p].w;
- }
-
- float v = bsdf->v;
- if(p == 1) {
- v *= 0.25f;
- }
- if(p >= 2) {
- v *= 4.0f;
- }
-
- u[1].x = max(u[1].x, 1e-5f);
- float fac = 1.0f + v*logf(u[1].x + (1.0f - u[1].x)*expf(-2.0f/v));
- float sin_theta_i = -fac * sin_theta_o + cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
- float cos_theta_i = cos_from_sin(sin_theta_i);
-
- float angles[6];
- if(p < 3) {
- hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
- sin_theta_i = angles[2*p];
- cos_theta_i = angles[2*p+1];
- }
-
- float phi;
- if(p < 3) {
- phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(u[0].y, bsdf->s);
- }
- else {
- phi = M_2PI_F*u[0].y;
- }
- float phi_i = phi_o + phi;
-
- hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
-
- float4 F;
- float Mp, Np;
-
- /* Primary specular (R). */
- Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
- Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
- F = Ap[0] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- /* Transmission (TT). */
- Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
- Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
- F += Ap[1] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- /* Secondary specular (TRT). */
- Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
- F += Ap[2] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- /* Residual component (TRRT+). */
- Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = M_1_2PI_F;
- F += Ap[3] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- *eval = float4_to_float3(F);
- *pdf = F.w;
-
- *omega_in = X*sin_theta_i + Y*cos_theta_i*cosf(phi_i) + Z*cos_theta_i*sinf(phi_i);
-
-#ifdef __RAY_DIFFERENTIALS__
- float3 N = safe_normalize(sd->I + *omega_in);
- *domega_in_dx = (2 * dot(N, sd->dI.dx)) * N - sd->dI.dx;
- *domega_in_dy = (2 * dot(N, sd->dI.dy)) * N - sd->dI.dy;
-#endif
-
- return LABEL_GLOSSY|((p == 0)? LABEL_REFLECT : LABEL_TRANSMIT);
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)sc;
+
+ float3 Y = float4_to_float3(bsdf->extra->geom);
+
+ float3 X = safe_normalize(sd->dPdu);
+ kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
+ float3 Z = safe_normalize(cross(X, Y));
+
+ float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
+
+ float2 u[2];
+ u[0] = make_float2(randu, randv);
+ u[1].x = lcg_step_float_addrspace(&sd->lcg_state);
+ u[1].y = lcg_step_float_addrspace(&sd->lcg_state);
+
+ float sin_theta_o = wo.x;
+ float cos_theta_o = cos_from_sin(sin_theta_o);
+ float phi_o = atan2f(wo.z, wo.y);
+
+ float sin_theta_t = sin_theta_o / bsdf->eta;
+ float cos_theta_t = cos_from_sin(sin_theta_t);
+
+ float sin_gamma_o = bsdf->extra->geom.w;
+ float cos_gamma_o = cos_from_sin(sin_gamma_o);
+ float gamma_o = safe_asinf(sin_gamma_o);
+
+ float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
+ float cos_gamma_t = cos_from_sin(sin_gamma_t);
+ float gamma_t = safe_asinf(sin_gamma_t);
+
+ float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
+ float4 Ap[4];
+ hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
+
+ int p = 0;
+ for (; p < 3; p++) {
+ if (u[0].x < Ap[p].w) {
+ break;
+ }
+ u[0].x -= Ap[p].w;
+ }
+
+ float v = bsdf->v;
+ if (p == 1) {
+ v *= 0.25f;
+ }
+ if (p >= 2) {
+ v *= 4.0f;
+ }
+
+ u[1].x = max(u[1].x, 1e-5f);
+ float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v));
+ float sin_theta_i = -fac * sin_theta_o +
+ cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
+ float cos_theta_i = cos_from_sin(sin_theta_i);
+
+ float angles[6];
+ if (p < 3) {
+ hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
+ sin_theta_i = angles[2 * p];
+ cos_theta_i = angles[2 * p + 1];
+ }
+
+ float phi;
+ if (p < 3) {
+ phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(u[0].y, bsdf->s);
+ }
+ else {
+ phi = M_2PI_F * u[0].y;
+ }
+ float phi_i = phi_o + phi;
+
+ hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
+
+ float4 F;
+ float Mp, Np;
+
+ /* Primary specular (R). */
+ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
+ Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
+ F = Ap[0] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Transmission (TT). */
+ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
+ Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
+ F += Ap[1] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Secondary specular (TRT). */
+ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
+ F += Ap[2] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Residual component (TRRT+). */
+ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = M_1_2PI_F;
+ F += Ap[3] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ *eval = float4_to_float3(F);
+ *pdf = F.w;
+
+ *omega_in = X * sin_theta_i + Y * cos_theta_i * cosf(phi_i) + Z * cos_theta_i * sinf(phi_i);
+
+# ifdef __RAY_DIFFERENTIALS__
+ float3 N = safe_normalize(sd->I + *omega_in);
+ *domega_in_dx = (2 * dot(N, sd->dI.dx)) * N - sd->dI.dx;
+ *domega_in_dy = (2 * dot(N, sd->dI.dy)) * N - sd->dI.dy;
+# endif
+
+ return LABEL_GLOSSY | ((p == 0) ? LABEL_REFLECT : LABEL_TRANSMIT);
}
/* Implements Filter Glossy by capping the effective roughness. */
ccl_device void bsdf_principled_hair_blur(ShaderClosure *sc, float roughness)
{
- PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)sc;
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)sc;
- bsdf->v = fmaxf(roughness, bsdf->v);
- bsdf->s = fmaxf(roughness, bsdf->s);
- bsdf->m0_roughness = fmaxf(roughness, bsdf->m0_roughness);
+ bsdf->v = fmaxf(roughness, bsdf->v);
+ bsdf->s = fmaxf(roughness, bsdf->s);
+ bsdf->m0_roughness = fmaxf(roughness, bsdf->m0_roughness);
}
CCL_NAMESPACE_END
-#endif /* __BSDF_HAIR_PRINCIPLED_H__ */
+#endif /* __BSDF_HAIR_PRINCIPLED_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 32b6e50b09a..b4da3123f28 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -36,95 +36,98 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct MicrofacetExtra {
- float3 color, cspec0;
- float clearcoat;
+ float3 color, cspec0;
+ float clearcoat;
} MicrofacetExtra;
typedef ccl_addr_space struct MicrofacetBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float alpha_x, alpha_y, ior;
- MicrofacetExtra *extra;
- float3 T;
+ float alpha_x, alpha_y, ior;
+ MicrofacetExtra *extra;
+ float3 T;
} MicrofacetBsdf;
/* Beckmann and GGX microfacet importance sampling. */
-ccl_device_inline void microfacet_beckmann_sample_slopes(
- KernelGlobals *kg,
- const float cos_theta_i, const float sin_theta_i,
- float randu, float randv, float *slope_x, float *slope_y,
- float *G1i)
+ccl_device_inline void microfacet_beckmann_sample_slopes(KernelGlobals *kg,
+ const float cos_theta_i,
+ const float sin_theta_i,
+ float randu,
+ float randv,
+ float *slope_x,
+ float *slope_y,
+ float *G1i)
{
- /* special case (normal incidence) */
- if(cos_theta_i >= 0.99999f) {
- const float r = sqrtf(-logf(randu));
- const float phi = M_2PI_F * randv;
- *slope_x = r * cosf(phi);
- *slope_y = r * sinf(phi);
- *G1i = 1.0f;
- return;
- }
-
- /* precomputations */
- const float tan_theta_i = sin_theta_i/cos_theta_i;
- const float inv_a = tan_theta_i;
- const float cot_theta_i = 1.0f/tan_theta_i;
- const float erf_a = fast_erff(cot_theta_i);
- const float exp_a2 = expf(-cot_theta_i*cot_theta_i);
- const float SQRT_PI_INV = 0.56418958354f;
- const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a);
- const float G1 = 1.0f/(1.0f + Lambda); /* masking */
-
- *G1i = G1;
+ /* special case (normal incidence) */
+ if (cos_theta_i >= 0.99999f) {
+ const float r = sqrtf(-logf(randu));
+ const float phi = M_2PI_F * randv;
+ *slope_x = r * cosf(phi);
+ *slope_y = r * sinf(phi);
+ *G1i = 1.0f;
+ return;
+ }
+
+ /* precomputations */
+ const float tan_theta_i = sin_theta_i / cos_theta_i;
+ const float inv_a = tan_theta_i;
+ const float cot_theta_i = 1.0f / tan_theta_i;
+ const float erf_a = fast_erff(cot_theta_i);
+ const float exp_a2 = expf(-cot_theta_i * cot_theta_i);
+ const float SQRT_PI_INV = 0.56418958354f;
+ const float Lambda = 0.5f * (erf_a - 1.0f) + (0.5f * SQRT_PI_INV) * (exp_a2 * inv_a);
+ const float G1 = 1.0f / (1.0f + Lambda); /* masking */
+
+ *G1i = G1;
#if defined(__KERNEL_GPU__)
- /* Based on paper from Wenzel Jakob
- * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
- *
- * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
- *
- * Reformulation from OpenShadingLanguage which avoids using inverse
- * trigonometric functions.
- */
-
- /* Sample slope X.
- *
- * Compute a coarse approximation using the approximation:
- * exp(-ierf(x)^2) ~= 1 - x * x
- * solve y = 1 + b + K * (1 - b * b)
- */
- float K = tan_theta_i * SQRT_PI_INV;
- float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
- float y_exact = randu * (1.0f + erf_a + K * exp_a2);
- float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
-
- /* Perform newton step to refine toward the true root. */
- float inv_erf = fast_ierff(b);
- float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
- /* Check if we are close enough already,
- * this also avoids NaNs as we get close to the root.
- */
- if(fabsf(value) > 1e-6f) {
- b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
- inv_erf = fast_ierff(b);
- value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
- b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
- /* Compute the slope from the refined value. */
- *slope_x = fast_ierff(b);
- }
- else {
- /* We are close enough already. */
- *slope_x = inv_erf;
- }
- *slope_y = fast_ierff(2.0f*randv - 1.0f);
+ /* Based on paper from Wenzel Jakob
+ * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
+ *
+ * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
+ *
+ * Reformulation from OpenShadingLanguage which avoids using inverse
+ * trigonometric functions.
+ */
+
+ /* Sample slope X.
+ *
+ * Compute a coarse approximation using the approximation:
+ * exp(-ierf(x)^2) ~= 1 - x * x
+ * solve y = 1 + b + K * (1 - b * b)
+ */
+ float K = tan_theta_i * SQRT_PI_INV;
+ float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
+ float y_exact = randu * (1.0f + erf_a + K * exp_a2);
+ float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
+
+ /* Perform newton step to refine toward the true root. */
+ float inv_erf = fast_ierff(b);
+ float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ /* Check if we are close enough already,
+ * this also avoids NaNs as we get close to the root.
+ */
+ if (fabsf(value) > 1e-6f) {
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
+ inv_erf = fast_ierff(b);
+ value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
+ /* Compute the slope from the refined value. */
+ *slope_x = fast_ierff(b);
+ }
+ else {
+ /* We are close enough already. */
+ *slope_x = inv_erf;
+ }
+ *slope_y = fast_ierff(2.0f * randv - 1.0f);
#else
- /* Use precomputed table on CPU, it gives better perfomance. */
- int beckmann_table_offset = kernel_data.tables.beckmann_offset;
+ /* Use precomputed table on CPU, it gives better perfomance. */
+ int beckmann_table_offset = kernel_data.tables.beckmann_offset;
- *slope_x = lookup_table_read_2D(kg, randu, cos_theta_i,
- beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
- *slope_y = fast_ierff(2.0f*randv - 1.0f);
+ *slope_x = lookup_table_read_2D(
+ kg, randu, cos_theta_i, beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
+ *slope_y = fast_ierff(2.0f * randv - 1.0f);
#endif
}
@@ -134,103 +137,109 @@ ccl_device_inline void microfacet_beckmann_sample_slopes(
* E. Heitz and E. d'Eon, EGSR 2014
*/
-ccl_device_inline void microfacet_ggx_sample_slopes(
- const float cos_theta_i, const float sin_theta_i,
- float randu, float randv, float *slope_x, float *slope_y,
- float *G1i)
+ccl_device_inline void microfacet_ggx_sample_slopes(const float cos_theta_i,
+ const float sin_theta_i,
+ float randu,
+ float randv,
+ float *slope_x,
+ float *slope_y,
+ float *G1i)
{
- /* special case (normal incidence) */
- if(cos_theta_i >= 0.99999f) {
- const float r = sqrtf(randu/(1.0f - randu));
- const float phi = M_2PI_F * randv;
- *slope_x = r * cosf(phi);
- *slope_y = r * sinf(phi);
- *G1i = 1.0f;
-
- return;
- }
-
- /* precomputations */
- const float tan_theta_i = sin_theta_i/cos_theta_i;
- const float G1_inv = 0.5f * (1.0f + safe_sqrtf(1.0f + tan_theta_i*tan_theta_i));
-
- *G1i = 1.0f/G1_inv;
-
- /* sample slope_x */
- const float A = 2.0f*randu*G1_inv - 1.0f;
- const float AA = A*A;
- const float tmp = 1.0f/(AA - 1.0f);
- const float B = tan_theta_i;
- const float BB = B*B;
- const float D = safe_sqrtf(BB*(tmp*tmp) - (AA - BB)*tmp);
- const float slope_x_1 = B*tmp - D;
- const float slope_x_2 = B*tmp + D;
- *slope_x = (A < 0.0f || slope_x_2*tan_theta_i > 1.0f)? slope_x_1: slope_x_2;
-
- /* sample slope_y */
- float S;
-
- if(randv > 0.5f) {
- S = 1.0f;
- randv = 2.0f*(randv - 0.5f);
- }
- else {
- S = -1.0f;
- randv = 2.0f*(0.5f - randv);
- }
-
- const float z = (randv*(randv*(randv*0.27385f - 0.73369f) + 0.46341f)) / (randv*(randv*(randv*0.093073f + 0.309420f) - 1.000000f) + 0.597999f);
- *slope_y = S * z * safe_sqrtf(1.0f + (*slope_x)*(*slope_x));
+ /* special case (normal incidence) */
+ if (cos_theta_i >= 0.99999f) {
+ const float r = sqrtf(randu / (1.0f - randu));
+ const float phi = M_2PI_F * randv;
+ *slope_x = r * cosf(phi);
+ *slope_y = r * sinf(phi);
+ *G1i = 1.0f;
+
+ return;
+ }
+
+ /* precomputations */
+ const float tan_theta_i = sin_theta_i / cos_theta_i;
+ const float G1_inv = 0.5f * (1.0f + safe_sqrtf(1.0f + tan_theta_i * tan_theta_i));
+
+ *G1i = 1.0f / G1_inv;
+
+ /* sample slope_x */
+ const float A = 2.0f * randu * G1_inv - 1.0f;
+ const float AA = A * A;
+ const float tmp = 1.0f / (AA - 1.0f);
+ const float B = tan_theta_i;
+ const float BB = B * B;
+ const float D = safe_sqrtf(BB * (tmp * tmp) - (AA - BB) * tmp);
+ const float slope_x_1 = B * tmp - D;
+ const float slope_x_2 = B * tmp + D;
+ *slope_x = (A < 0.0f || slope_x_2 * tan_theta_i > 1.0f) ? slope_x_1 : slope_x_2;
+
+ /* sample slope_y */
+ float S;
+
+ if (randv > 0.5f) {
+ S = 1.0f;
+ randv = 2.0f * (randv - 0.5f);
+ }
+ else {
+ S = -1.0f;
+ randv = 2.0f * (0.5f - randv);
+ }
+
+ const float z = (randv * (randv * (randv * 0.27385f - 0.73369f) + 0.46341f)) /
+ (randv * (randv * (randv * 0.093073f + 0.309420f) - 1.000000f) + 0.597999f);
+ *slope_y = S * z * safe_sqrtf(1.0f + (*slope_x) * (*slope_x));
}
-ccl_device_forceinline float3 microfacet_sample_stretched(
- KernelGlobals *kg, const float3 omega_i,
- const float alpha_x, const float alpha_y,
- const float randu, const float randv,
- bool beckmann, float *G1i)
+ccl_device_forceinline float3 microfacet_sample_stretched(KernelGlobals *kg,
+ const float3 omega_i,
+ const float alpha_x,
+ const float alpha_y,
+ const float randu,
+ const float randv,
+ bool beckmann,
+ float *G1i)
{
- /* 1. stretch omega_i */
- float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z);
- omega_i_ = normalize(omega_i_);
-
- /* get polar coordinates of omega_i_ */
- float costheta_ = 1.0f;
- float sintheta_ = 0.0f;
- float cosphi_ = 1.0f;
- float sinphi_ = 0.0f;
-
- if(omega_i_.z < 0.99999f) {
- costheta_ = omega_i_.z;
- sintheta_ = safe_sqrtf(1.0f - costheta_*costheta_);
-
- float invlen = 1.0f/sintheta_;
- cosphi_ = omega_i_.x * invlen;
- sinphi_ = omega_i_.y * invlen;
- }
-
- /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */
- float slope_x, slope_y;
-
- if(beckmann) {
- microfacet_beckmann_sample_slopes(kg, costheta_, sintheta_,
- randu, randv, &slope_x, &slope_y, G1i);
- }
- else {
- microfacet_ggx_sample_slopes(costheta_, sintheta_,
- randu, randv, &slope_x, &slope_y, G1i);
- }
-
- /* 3. rotate */
- float tmp = cosphi_*slope_x - sinphi_*slope_y;
- slope_y = sinphi_*slope_x + cosphi_*slope_y;
- slope_x = tmp;
-
- /* 4. unstretch */
- slope_x = alpha_x * slope_x;
- slope_y = alpha_y * slope_y;
-
- /* 5. compute normal */
- return normalize(make_float3(-slope_x, -slope_y, 1.0f));
+ /* 1. stretch omega_i */
+ float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z);
+ omega_i_ = normalize(omega_i_);
+
+ /* get polar coordinates of omega_i_ */
+ float costheta_ = 1.0f;
+ float sintheta_ = 0.0f;
+ float cosphi_ = 1.0f;
+ float sinphi_ = 0.0f;
+
+ if (omega_i_.z < 0.99999f) {
+ costheta_ = omega_i_.z;
+ sintheta_ = safe_sqrtf(1.0f - costheta_ * costheta_);
+
+ float invlen = 1.0f / sintheta_;
+ cosphi_ = omega_i_.x * invlen;
+ sinphi_ = omega_i_.y * invlen;
+ }
+
+ /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */
+ float slope_x, slope_y;
+
+ if (beckmann) {
+ microfacet_beckmann_sample_slopes(
+ kg, costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
+ }
+ else {
+ microfacet_ggx_sample_slopes(costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
+ }
+
+ /* 3. rotate */
+ float tmp = cosphi_ * slope_x - sinphi_ * slope_y;
+ slope_y = sinphi_ * slope_x + cosphi_ * slope_y;
+ slope_x = tmp;
+
+ /* 4. unstretch */
+ slope_x = alpha_x * slope_x;
+ slope_y = alpha_y * slope_y;
+
+ /* 5. compute normal */
+ return normalize(make_float3(-slope_x, -slope_y, 1.0f));
}
/* Calculate the reflection color
@@ -240,27 +249,29 @@ ccl_device_forceinline float3 microfacet_sample_stretched(
*
* Else it is simply white
*/
-ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float3 L, float3 H) {
- float3 F = make_float3(1.0f, 1.0f, 1.0f);
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
+ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float3 L, float3 H)
+{
+ float3 F = make_float3(1.0f, 1.0f, 1.0f);
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
- if(use_fresnel) {
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ if (use_fresnel) {
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
- }
+ F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
+ }
- return F;
+ return F;
}
ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
{
- if(alpha >= 1.0f) return M_1_PI_F;
- float alpha2 = alpha*alpha;
- float t = 1.0f + (alpha2 - 1.0f) * NdotH*NdotH;
- return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
+ if (alpha >= 1.0f)
+ return M_1_PI_F;
+ float alpha2 = alpha * alpha;
+ float t = 1.0f + (alpha2 - 1.0f) * NdotH * NdotH;
+ return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
}
/* GGX microfacet with Smith shadow-masking from:
@@ -278,483 +289,511 @@ ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
{
- bsdf->extra = NULL;
+ bsdf->extra = NULL;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const MicrofacetBsdf *bsdf_a = (const MicrofacetBsdf*)a;
- const MicrofacetBsdf *bsdf_b = (const MicrofacetBsdf*)b;
-
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->alpha_x == bsdf_b->alpha_x) &&
- (bsdf_a->alpha_y == bsdf_b->alpha_y) &&
- (isequal_float3(bsdf_a->T, bsdf_b->T)) &&
- (bsdf_a->ior == bsdf_b->ior) &&
- ((bsdf_a->extra == NULL && bsdf_b->extra == NULL) ||
- ((bsdf_a->extra && bsdf_b->extra) &&
- (isequal_float3(bsdf_a->extra->color, bsdf_b->extra->color)) &&
- (isequal_float3(bsdf_a->extra->cspec0, bsdf_b->extra->cspec0)) &&
- (bsdf_a->extra->clearcoat == bsdf_b->extra->clearcoat)));
+ const MicrofacetBsdf *bsdf_a = (const MicrofacetBsdf *)a;
+ const MicrofacetBsdf *bsdf_b = (const MicrofacetBsdf *)b;
+
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->alpha_x == bsdf_b->alpha_x) &&
+ (bsdf_a->alpha_y == bsdf_b->alpha_y) && (isequal_float3(bsdf_a->T, bsdf_b->T)) &&
+ (bsdf_a->ior == bsdf_b->ior) &&
+ ((bsdf_a->extra == NULL && bsdf_b->extra == NULL) ||
+ ((bsdf_a->extra && bsdf_b->extra) &&
+ (isequal_float3(bsdf_a->extra->color, bsdf_b->extra->color)) &&
+ (isequal_float3(bsdf_a->extra->cspec0, bsdf_b->extra->cspec0)) &&
+ (bsdf_a->extra->clearcoat == bsdf_b->extra->clearcoat)));
}
ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
{
- bsdf->extra = NULL;
+ bsdf->extra = NULL;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->extra = NULL;
+ bsdf->extra = NULL;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
-ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = bsdf->N;
-
- if(m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
-
- if(cosNI > 0 && cosNO > 0) {
- /* get half vector */
- float3 m = normalize(omega_in + I);
- float alpha2 = alpha_x * alpha_y;
- float D, G1o, G1i;
-
- if(alpha_x == alpha_y) {
- /* isotropic
- * eq. 20: (F*G*D)/(4*in*on)
- * eq. 33: first we calculate D(m) */
- float cosThetaM = dot(N, m);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
-
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- /* use GTR1 for clearcoat */
- D = D_GTR1(cosThetaM, bsdf->alpha_x);
-
- /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
- alpha2 = 0.0625f;
- }
- else {
- /* use GTR2 otherwise */
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- }
-
- /* eq. 34: now calculate G1(i,m) and G1(o,m) */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
- }
- else {
- /* anisotropic */
- float3 X, Y, Z = N;
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
- float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) and G1(o,m) */
- float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
- float cosPhiO = dot(I, X);
- float sinPhiO = dot(I, Y);
-
- float alphaO2 = (cosPhiO*cosPhiO)*(alpha_x*alpha_x) + (sinPhiO*sinPhiO)*(alpha_y*alpha_y);
- alphaO2 /= cosPhiO*cosPhiO + sinPhiO*sinPhiO;
-
- G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
-
- float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
- float cosPhiI = dot(omega_in, X);
- float sinPhiI = dot(omega_in, Y);
-
- float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y);
- alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
-
- G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
- }
-
- float G = G1o * G1i;
-
- /* eq. 20 */
- float common = D * 0.25f / cosNO;
-
- float3 F = reflection_color(bsdf, omega_in, m);
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- F *= 0.25f * bsdf->extra->clearcoat;
- }
-
- float3 out = F * G * common;
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* eq. 38 - but see also:
- * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
- * pdf = pm * 0.25 / dot(m, I); */
- *pdf = G1o * common;
-
- return out;
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float3 N = bsdf->N;
+
+ if (m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+
+ if (cosNI > 0 && cosNO > 0) {
+ /* get half vector */
+ float3 m = normalize(omega_in + I);
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1o, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* isotropic
+ * eq. 20: (F*G*D)/(4*in*on)
+ * eq. 33: first we calculate D(m) */
+ float cosThetaM = dot(N, m);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ /* use GTR1 for clearcoat */
+ D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
+ /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+ alpha2 = 0.0625f;
+ }
+ else {
+ /* use GTR2 otherwise */
+ D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ }
+
+ /* eq. 34: now calculate G1(i,m) and G1(o,m) */
+ G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ }
+ else {
+ /* anisotropic */
+ float3 X, Y, Z = N;
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+ float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) and G1(o,m) */
+ float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
+ float cosPhiO = dot(I, X);
+ float sinPhiO = dot(I, Y);
+
+ float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
+ (sinPhiO * sinPhiO) * (alpha_y * alpha_y);
+ alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
+
+ G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
+
+ float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
+ float cosPhiI = dot(omega_in, X);
+ float sinPhiI = dot(omega_in, Y);
+
+ float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
+ (sinPhiI * sinPhiI) * (alpha_y * alpha_y);
+ alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
+
+ G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
+ }
+
+ float G = G1o * G1i;
+
+ /* eq. 20 */
+ float common = D * 0.25f / cosNO;
+
+ float3 F = reflection_color(bsdf, omega_in, m);
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ F *= 0.25f * bsdf->extra->clearcoat;
+ }
+
+ float3 out = F * G * common;
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* eq. 38 - but see also:
+ * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
+ * pdf = pm * 0.25 / dot(m, I); */
+ *pdf = G1o * common;
+
+ return out;
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- float m_eta = bsdf->ior;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = bsdf->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ float m_eta = bsdf->ior;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float3 N = bsdf->N;
- if(!m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (!m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
- if(cosNO <= 0 || cosNI >= 0)
- return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */
+ if (cosNO <= 0 || cosNI >= 0)
+ return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */
- /* compute half-vector of the refraction (eq. 16) */
- float3 ht = -(m_eta * omega_in + I);
- float3 Ht = normalize(ht);
- float cosHO = dot(Ht, I);
- float cosHI = dot(Ht, omega_in);
+ /* compute half-vector of the refraction (eq. 16) */
+ float3 ht = -(m_eta * omega_in + I);
+ float3 Ht = normalize(ht);
+ float cosHO = dot(Ht, I);
+ float cosHI = dot(Ht, omega_in);
- float D, G1o, G1i;
+ float D, G1o, G1i;
- /* eq. 33: first we calculate D(m) with m=Ht: */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM = dot(N, Ht);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ /* eq. 33: first we calculate D(m) with m=Ht: */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM = dot(N, Ht);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- /* eq. 34: now calculate G1(i,m) and G1(o,m) */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ /* eq. 34: now calculate G1(i,m) and G1(o,m) */
+ G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
- float G = G1o * G1i;
+ float G = G1o * G1i;
- /* probability */
- float Ht2 = dot(ht, ht);
+ /* probability */
+ float Ht2 = dot(ht, ht);
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
- /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
- * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * fabsf(cosHO * cosHI) * common;
+ /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
+ * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * fabsf(cosHO * cosHI) * common;
- return make_float3(out, out, out);
+ return make_float3(out, out, out);
}
-ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = bsdf->N;
- int label;
-
- float cosNO = dot(N, I);
- if(cosNO > 0) {
- float3 X, Y, Z = N;
-
- if(alpha_x == alpha_y)
- make_orthonormals(Z, &X, &Y);
- else
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* importance sampling with distribution of visible normals. vectors are
- * transformed to local space before and after */
- float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
- float3 local_m;
- float G1o;
-
- local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_y,
- randu, randv, false, &G1o);
-
- float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z;
- float cosThetaM = local_m.z;
-
- /* reflection or refraction? */
- if(!m_refractive) {
- float cosMO = dot(m, I);
- label = LABEL_REFLECT | LABEL_GLOSSY;
-
- if(cosMO > 0) {
- /* eq. 39 - compute actual reflected direction */
- *omega_in = 2 * cosMO * m - I;
-
- if(dot(Ng, *omega_in) > 0) {
- if(alpha_x*alpha_y <= 1e-7f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
-
- /* if fresnel is used, calculate the color with reflection_color(...) */
- if(use_fresnel) {
- *eval *= reflection_color(bsdf, *omega_in, m);
- }
-
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* microfacet normal is visible to this ray */
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float D, G1i;
-
- if(alpha_x == alpha_y) {
- /* isotropic */
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- /* use GTR1 for clearcoat */
- D = D_GTR1(cosThetaM, bsdf->alpha_x);
-
- /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
- alpha2 = 0.0625f;
-
- /* recalculate G1o */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- }
- else {
- /* use GTR2 otherwise */
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- }
-
- /* eq. 34: now calculate G1(i,m) */
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
- }
- else {
- /* anisotropic distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
- float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
-
- /* calculate G1(i,m) */
- float cosNI = dot(N, *omega_in);
-
- float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
- float cosPhiI = dot(*omega_in, X);
- float sinPhiI = dot(*omega_in, Y);
-
- float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y);
- alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
-
- G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
- }
-
- /* see eval function for derivation */
- float common = (G1o * D) * 0.25f / cosNO;
- *pdf = common;
-
- float3 F = reflection_color(bsdf, *omega_in, m);
-
- *eval = G1i * common * F;
- }
-
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- *eval *= 0.25f * bsdf->extra->clearcoat;
- }
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float3 N = bsdf->N;
+ int label;
+
+ float cosNO = dot(N, I);
+ if (cosNO > 0) {
+ float3 X, Y, Z = N;
+
+ if (alpha_x == alpha_y)
+ make_orthonormals(Z, &X, &Y);
+ else
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* importance sampling with distribution of visible normals. vectors are
+ * transformed to local space before and after */
+ float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_m;
+ float G1o;
+
+ local_m = microfacet_sample_stretched(
+ kg, local_I, alpha_x, alpha_y, randu, randv, false, &G1o);
+
+ float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
+ float cosThetaM = local_m.z;
+
+ /* reflection or refraction? */
+ if (!m_refractive) {
+ float cosMO = dot(m, I);
+ label = LABEL_REFLECT | LABEL_GLOSSY;
+
+ if (cosMO > 0) {
+ /* eq. 39 - compute actual reflected direction */
+ *omega_in = 2 * cosMO * m - I;
+
+ if (dot(Ng, *omega_in) > 0) {
+ if (alpha_x * alpha_y <= 1e-7f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
+
+ /* if fresnel is used, calculate the color with reflection_color(...) */
+ if (use_fresnel) {
+ *eval *= reflection_color(bsdf, *omega_in, m);
+ }
+
+ label = LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ /* microfacet normal is visible to this ray */
+ /* eq. 33 */
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* isotropic */
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ /* use GTR1 for clearcoat */
+ D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
+ /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+ alpha2 = 0.0625f;
+
+ /* recalculate G1o */
+ G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ }
+ else {
+ /* use GTR2 otherwise */
+ D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ }
+
+ /* eq. 34: now calculate G1(i,m) */
+ G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ }
+ else {
+ /* anisotropic distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+ float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
+
+ /* calculate G1(i,m) */
+ float cosNI = dot(N, *omega_in);
+
+ float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
+ float cosPhiI = dot(*omega_in, X);
+ float sinPhiI = dot(*omega_in, Y);
+
+ float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
+ (sinPhiI * sinPhiI) * (alpha_y * alpha_y);
+ alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
+
+ G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
+ }
+
+ /* see eval function for derivation */
+ float common = (G1o * D) * 0.25f / cosNO;
+ *pdf = common;
+
+ float3 F = reflection_color(bsdf, *omega_in, m);
+
+ *eval = G1i * common * F;
+ }
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ *eval *= 0.25f * bsdf->extra->clearcoat;
+ }
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
- *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
+ *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
+ *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
#endif
- }
- }
- }
- else {
- label = LABEL_TRANSMIT | LABEL_GLOSSY;
-
- /* CAUTION: the i and o variables are inverted relative to the paper
- * eq. 39 - compute actual refractive direction */
- float3 R, T;
+ }
+ }
+ }
+ else {
+ label = LABEL_TRANSMIT | LABEL_GLOSSY;
+
+ /* CAUTION: the i and o variables are inverted relative to the paper
+ * eq. 39 - compute actual refractive direction */
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = bsdf->ior, fresnel;
- bool inside;
-
- fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
+ float m_eta = bsdf->ior, fresnel;
+ bool inside;
+
+ fresnel = fresnel_dielectric(m_eta,
+ m,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- if(!inside && fresnel != 1.0f) {
+ if (!inside && fresnel != 1.0f) {
- *omega_in = T;
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- if(alpha_x*alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_TRANSMIT | LABEL_SINGULAR;
- }
- else {
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
- float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 34: now calculate G1(i,m) */
- float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
-
- /* eq. 21 */
- float cosHI = dot(m, *omega_in);
- float cosHO = dot(m, I);
- float Ht2 = m_eta * cosHI + cosHO;
- Ht2 *= Ht2;
-
- /* see eval function for derivation */
- float common = (G1o * D) * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G1i * fabsf(cosHI * cosHO) * common;
- *pdf = cosHO * fabsf(cosHI) * common;
-
- *eval = make_float3(out, out, out);
- }
- }
- }
- }
- else {
- label = (m_refractive) ? LABEL_TRANSMIT|LABEL_GLOSSY : LABEL_REFLECT|LABEL_GLOSSY;
- }
- return label;
+ if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
+ else {
+ /* eq. 33 */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 34: now calculate G1(i,m) */
+ float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+
+ /* eq. 21 */
+ float cosHI = dot(m, *omega_in);
+ float cosHO = dot(m, I);
+ float Ht2 = m_eta * cosHI + cosHO;
+ Ht2 *= Ht2;
+
+ /* see eval function for derivation */
+ float common = (G1o * D) * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G1i * fabsf(cosHI * cosHO) * common;
+ *pdf = cosHO * fabsf(cosHI) * common;
+
+ *eval = make_float3(out, out, out);
+ }
+ }
+ }
+ }
+ else {
+ label = (m_refractive) ? LABEL_TRANSMIT | LABEL_GLOSSY : LABEL_REFLECT | LABEL_GLOSSY;
+ }
+ return label;
}
/* Beckmann microfacet with Smith shadow-masking from:
@@ -764,364 +803,392 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
ccl_device int bsdf_microfacet_beckmann_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_aniso_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n)
{
- cos_n *= cos_n;
- float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n);
- if(invA < 0.625f) {
- return 1.0f;
- }
-
- float a = 1.0f / invA;
- return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f);
+ cos_n *= cos_n;
+ float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n);
+ if (invA < 0.625f) {
+ return 1.0f;
+ }
+
+ float a = 1.0f / invA;
+ return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
}
-ccl_device_inline float bsdf_beckmann_aniso_G1(float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi)
+ccl_device_inline float bsdf_beckmann_aniso_G1(
+ float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi)
{
- cos_n *= cos_n;
- sin_phi *= sin_phi;
- cos_phi *= cos_phi;
- alpha_x *= alpha_x;
- alpha_y *= alpha_y;
-
- float alphaO2 = (cos_phi*alpha_x + sin_phi*alpha_y) / (cos_phi + sin_phi);
- float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n);
- if(invA < 0.625f) {
- return 1.0f;
- }
-
- float a = 1.0f / invA;
- return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f);
+ cos_n *= cos_n;
+ sin_phi *= sin_phi;
+ cos_phi *= cos_phi;
+ alpha_x *= alpha_x;
+ alpha_y *= alpha_y;
+
+ float alphaO2 = (cos_phi * alpha_x + sin_phi * alpha_y) / (cos_phi + sin_phi);
+ float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n);
+ if (invA < 0.625f) {
+ return 1.0f;
+ }
+
+ float a = 1.0f / invA;
+ return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
}
-ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = bsdf->N;
-
- if(m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
-
- if(cosNO > 0 && cosNI > 0) {
- /* get half vector */
- float3 m = normalize(omega_in + I);
-
- float alpha2 = alpha_x * alpha_y;
- float D, G1o, G1i;
-
- if(alpha_x == alpha_y) {
- /* isotropic
- * eq. 20: (F*G*D)/(4*in*on)
- * eq. 25: first we calculate D(m) */
- float cosThetaM = dot(N, m);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- G1o = bsdf_beckmann_G1(alpha_x, cosNO);
- G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- }
- else {
- /* anisotropic */
- float3 X, Y, Z = N;
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) and G1(o,m) */
- G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
- G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
- }
-
- float G = G1o * G1i;
-
- /* eq. 20 */
- float common = D * 0.25f / cosNO;
- float out = G * common;
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* eq. 38 - but see also:
- * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
- * pdf = pm * 0.25 / dot(m, I); */
- *pdf = G1o * common;
-
- return make_float3(out, out, out);
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float3 N = bsdf->N;
+
+ if (m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+
+ if (cosNO > 0 && cosNI > 0) {
+ /* get half vector */
+ float3 m = normalize(omega_in + I);
+
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1o, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* isotropic
+ * eq. 20: (F*G*D)/(4*in*on)
+ * eq. 25: first we calculate D(m) */
+ float cosThetaM = dot(N, m);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
+ G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+ G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ }
+ else {
+ /* anisotropic */
+ float3 X, Y, Z = N;
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) and G1(o,m) */
+ G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
+ G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
+ }
+
+ float G = G1o * G1i;
+
+ /* eq. 20 */
+ float common = D * 0.25f / cosNO;
+ float out = G * common;
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* eq. 38 - but see also:
+ * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
+ * pdf = pm * 0.25 / dot(m, I); */
+ *pdf = G1o * common;
+
+ return make_float3(out, out, out);
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- float m_eta = bsdf->ior;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = bsdf->N;
-
- if(!m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
-
- if(cosNO <= 0 || cosNI >= 0)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- /* compute half-vector of the refraction (eq. 16) */
- float3 ht = -(m_eta * omega_in + I);
- float3 Ht = normalize(ht);
- float cosHO = dot(Ht, I);
- float cosHI = dot(Ht, omega_in);
-
- /* eq. 25: first we calculate D(m) with m=Ht: */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM = min(dot(N, Ht), 1.0f);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
- float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- float G = G1o * G1i;
-
- /* probability */
- float Ht2 = dot(ht, ht);
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
- * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * fabsf(cosHO * cosHI) * common;
-
- return make_float3(out, out, out);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ float m_eta = bsdf->ior;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float3 N = bsdf->N;
+
+ if (!m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+
+ if (cosNO <= 0 || cosNI >= 0)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ /* compute half-vector of the refraction (eq. 16) */
+ float3 ht = -(m_eta * omega_in + I);
+ float3 Ht = normalize(ht);
+ float cosHO = dot(Ht, I);
+ float cosHI = dot(Ht, omega_in);
+
+ /* eq. 25: first we calculate D(m) with m=Ht: */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM = min(dot(N, Ht), 1.0f);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
+ float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ float G = G1o * G1i;
+
+ /* probability */
+ float Ht2 = dot(ht, ht);
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
+ * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * fabsf(cosHO * cosHI) * common;
+
+ return make_float3(out, out, out);
}
-ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = bsdf->N;
- int label;
-
- float cosNO = dot(N, I);
- if(cosNO > 0) {
- float3 X, Y, Z = N;
-
- if(alpha_x == alpha_y)
- make_orthonormals(Z, &X, &Y);
- else
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* importance sampling with distribution of visible normals. vectors are
- * transformed to local space before and after */
- float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
- float3 local_m;
- float G1o;
-
- local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_x,
- randu, randv, true, &G1o);
-
- float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z;
- float cosThetaM = local_m.z;
-
- /* reflection or refraction? */
- if(!m_refractive) {
- label = LABEL_REFLECT | LABEL_GLOSSY;
- float cosMO = dot(m, I);
-
- if(cosMO > 0) {
- /* eq. 39 - compute actual reflected direction */
- *omega_in = 2 * cosMO * m - I;
-
- if(dot(Ng, *omega_in) > 0) {
- if(alpha_x*alpha_y <= 1e-7f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* microfacet normal is visible to this ray
- * eq. 25 */
- float alpha2 = alpha_x * alpha_y;
- float D, G1i;
-
- if(alpha_x == alpha_y) {
- /* istropic distribution */
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
- D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 26, 27: now calculate G1(i,m) */
- G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- }
- else {
- /* anisotropic distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) */
- G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y));
- }
-
- float G = G1o * G1i;
-
- /* see eval function for derivation */
- float common = D * 0.25f / cosNO;
- float out = G * common;
- *pdf = G1o * common;
-
- *eval = make_float3(out, out, out);
- }
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float3 N = bsdf->N;
+ int label;
+
+ float cosNO = dot(N, I);
+ if (cosNO > 0) {
+ float3 X, Y, Z = N;
+
+ if (alpha_x == alpha_y)
+ make_orthonormals(Z, &X, &Y);
+ else
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* importance sampling with distribution of visible normals. vectors are
+ * transformed to local space before and after */
+ float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_m;
+ float G1o;
+
+ local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_x, randu, randv, true, &G1o);
+
+ float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
+ float cosThetaM = local_m.z;
+
+ /* reflection or refraction? */
+ if (!m_refractive) {
+ label = LABEL_REFLECT | LABEL_GLOSSY;
+ float cosMO = dot(m, I);
+
+ if (cosMO > 0) {
+ /* eq. 39 - compute actual reflected direction */
+ *omega_in = 2 * cosMO * m - I;
+
+ if (dot(Ng, *omega_in) > 0) {
+ if (alpha_x * alpha_y <= 1e-7f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ /* microfacet normal is visible to this ray
+ * eq. 25 */
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* istropic distribution */
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 26, 27: now calculate G1(i,m) */
+ G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ }
+ else {
+ /* anisotropic distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) */
+ G1i = bsdf_beckmann_aniso_G1(
+ alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y));
+ }
+
+ float G = G1o * G1i;
+
+ /* see eval function for derivation */
+ float common = D * 0.25f / cosNO;
+ float out = G * common;
+ *pdf = G1o * common;
+
+ *eval = make_float3(out, out, out);
+ }
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
- *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
+ *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
+ *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
#endif
- }
- }
- }
- else {
- label = LABEL_TRANSMIT | LABEL_GLOSSY;
-
- /* CAUTION: the i and o variables are inverted relative to the paper
- * eq. 39 - compute actual refractive direction */
- float3 R, T;
+ }
+ }
+ }
+ else {
+ label = LABEL_TRANSMIT | LABEL_GLOSSY;
+
+ /* CAUTION: the i and o variables are inverted relative to the paper
+ * eq. 39 - compute actual refractive direction */
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = bsdf->ior, fresnel;
- bool inside;
-
- fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
+ float m_eta = bsdf->ior, fresnel;
+ bool inside;
+
+ fresnel = fresnel_dielectric(m_eta,
+ m,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- if(!inside && fresnel != 1.0f) {
- *omega_in = T;
+ if (!inside && fresnel != 1.0f) {
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- if(alpha_x*alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_TRANSMIT | LABEL_SINGULAR;
- }
- else {
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
- float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 26, 27: now calculate G1(i,m) */
- float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- float G = G1o * G1i;
-
- /* eq. 21 */
- float cosHI = dot(m, *omega_in);
- float cosHO = dot(m, I);
- float Ht2 = m_eta * cosHI + cosHO;
- Ht2 *= Ht2;
-
- /* see eval function for derivation */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * cosHO * fabsf(cosHI) * common;
-
- *eval = make_float3(out, out, out);
- }
- }
- }
- }
- else {
- label = (m_refractive) ? LABEL_TRANSMIT|LABEL_GLOSSY : LABEL_REFLECT|LABEL_GLOSSY;
- }
- return label;
+ if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
+ else {
+ /* eq. 33 */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 26, 27: now calculate G1(i,m) */
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ float G = G1o * G1i;
+
+ /* eq. 21 */
+ float cosHI = dot(m, *omega_in);
+ float cosHO = dot(m, I);
+ float Ht2 = m_eta * cosHI + cosHO;
+ Ht2 *= Ht2;
+
+ /* see eval function for derivation */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * cosHO * fabsf(cosHI) * common;
+
+ *eval = make_float3(out, out, out);
+ }
+ }
+ }
+ }
+ else {
+ label = (m_refractive) ? LABEL_TRANSMIT | LABEL_GLOSSY : LABEL_REFLECT | LABEL_GLOSSY;
+ }
+ return label;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_MICROFACET_H__ */
+#endif /* __BSDF_MICROFACET_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
index 2f2c35d5d1f..2cc1a9c5299 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -23,149 +23,168 @@ CCL_NAMESPACE_BEGIN
/* Isotropic GGX microfacet distribution */
ccl_device_forceinline float D_ggx(float3 wm, float alpha)
{
- wm.z *= wm.z;
- alpha *= alpha;
- float tmp = (1.0f - wm.z) + alpha * wm.z;
- return alpha / max(M_PI_F * tmp*tmp, 1e-7f);
+ wm.z *= wm.z;
+ alpha *= alpha;
+ float tmp = (1.0f - wm.z) + alpha * wm.z;
+ return alpha / max(M_PI_F * tmp * tmp, 1e-7f);
}
/* Anisotropic GGX microfacet distribution */
ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
{
- float slope_x = -wm.x/alpha.x;
- float slope_y = -wm.y/alpha.y;
- float tmp = wm.z*wm.z + slope_x*slope_x + slope_y*slope_y;
+ float slope_x = -wm.x / alpha.x;
+ float slope_y = -wm.y / alpha.y;
+ float tmp = wm.z * wm.z + slope_x * slope_x + slope_y * slope_y;
- return 1.0f / max(M_PI_F * tmp*tmp * alpha.x*alpha.y, 1e-7f);
+ return 1.0f / max(M_PI_F * tmp * tmp * alpha.x * alpha.y, 1e-7f);
}
/* Sample slope distribution (based on page 14 of the supplemental implementation). */
-ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float randx, const float randy)
-{
- if(cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
- const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
- const float phi = M_2PI_F * randy;
- return make_float2(r*cosf(phi), r*sinf(phi));
- }
-
- const float sinI = safe_sqrtf(1.0f - cosI*cosI);
- const float tanI = sinI/cosI;
- const float projA = 0.5f * (cosI + 1.0f);
- if(projA < 0.0001f)
- return make_float2(0.0f, 0.0f);
- const float A = 2.0f*randx*projA / cosI - 1.0f;
- float tmp = A*A-1.0f;
- if(fabsf(tmp) < 1e-7f)
- return make_float2(0.0f, 0.0f);
- tmp = 1.0f / tmp;
- const float D = safe_sqrtf(tanI*tanI*tmp*tmp - (A*A-tanI*tanI)*tmp);
-
- const float slopeX2 = tanI*tmp + D;
- const float slopeX = (A < 0.0f || slopeX2 > 1.0f/tanI)? (tanI*tmp - D) : slopeX2;
-
- float U2;
- if(randy >= 0.5f)
- U2 = 2.0f*(randy - 0.5f);
- else
- U2 = 2.0f*(0.5f - randy);
- const float z = (U2*(U2*(U2*0.27385f-0.73369f)+0.46341f)) / (U2*(U2*(U2*0.093073f+0.309420f)-1.0f)+0.597999f);
- const float slopeY = z * sqrtf(1.0f + slopeX*slopeX);
-
- if(randy >= 0.5f)
- return make_float2(slopeX, slopeY);
- else
- return make_float2(slopeX, -slopeY);
+ccl_device_forceinline float2 mf_sampleP22_11(const float cosI,
+ const float randx,
+ const float randy)
+{
+ if (cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
+ const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
+ const float phi = M_2PI_F * randy;
+ return make_float2(r * cosf(phi), r * sinf(phi));
+ }
+
+ const float sinI = safe_sqrtf(1.0f - cosI * cosI);
+ const float tanI = sinI / cosI;
+ const float projA = 0.5f * (cosI + 1.0f);
+ if (projA < 0.0001f)
+ return make_float2(0.0f, 0.0f);
+ const float A = 2.0f * randx * projA / cosI - 1.0f;
+ float tmp = A * A - 1.0f;
+ if (fabsf(tmp) < 1e-7f)
+ return make_float2(0.0f, 0.0f);
+ tmp = 1.0f / tmp;
+ const float D = safe_sqrtf(tanI * tanI * tmp * tmp - (A * A - tanI * tanI) * tmp);
+
+ const float slopeX2 = tanI * tmp + D;
+ const float slopeX = (A < 0.0f || slopeX2 > 1.0f / tanI) ? (tanI * tmp - D) : slopeX2;
+
+ float U2;
+ if (randy >= 0.5f)
+ U2 = 2.0f * (randy - 0.5f);
+ else
+ U2 = 2.0f * (0.5f - randy);
+ const float z = (U2 * (U2 * (U2 * 0.27385f - 0.73369f) + 0.46341f)) /
+ (U2 * (U2 * (U2 * 0.093073f + 0.309420f) - 1.0f) + 0.597999f);
+ const float slopeY = z * sqrtf(1.0f + slopeX * slopeX);
+
+ if (randy >= 0.5f)
+ return make_float2(slopeX, slopeY);
+ else
+ return make_float2(slopeX, -slopeY);
}
/* Visible normal sampling for the GGX distribution (based on page 7 of the supplemental implementation). */
-ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float randx, const float randy)
+ccl_device_forceinline float3 mf_sample_vndf(const float3 wi,
+ const float2 alpha,
+ const float randx,
+ const float randy)
{
- const float3 wi_11 = normalize(make_float3(alpha.x*wi.x, alpha.y*wi.y, wi.z));
- const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
+ const float3 wi_11 = normalize(make_float3(alpha.x * wi.x, alpha.y * wi.y, wi.z));
+ const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
- const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
- const float slope_x = alpha.x*(cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
- const float slope_y = alpha.y*(cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
+ const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
+ const float slope_x = alpha.x * (cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
+ const float slope_y = alpha.y * (cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
- kernel_assert(isfinite(slope_x));
- return normalize(make_float3(-slope_x, -slope_y, 1.0f));
+ kernel_assert(isfinite(slope_x));
+ return normalize(make_float3(-slope_x, -slope_y, 1.0f));
}
/* === Phase functions: Glossy and Glass === */
/* Phase function for reflective materials. */
-ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi, float3 *weight, const float3 wm)
+ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi,
+ float3 *weight,
+ const float3 wm)
{
- return -wi + 2.0f * wm * dot(wi, wm);
+ return -wi + 2.0f * wm * dot(wi, wm);
}
-ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha)
+ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w,
+ const float lambda,
+ const float3 wo,
+ const float2 alpha)
{
- if(w.z > 0.9999f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (w.z > 0.9999f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- const float3 wh = normalize(wo - w);
- if(wh.z < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ const float3 wh = normalize(wo - w);
+ if (wh.z < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
+ float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
- const float dotW_WH = dot(-w, wh);
- if(dotW_WH < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ const float dotW_WH = dot(-w, wh);
+ if (dotW_WH < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
- if(alpha.x == alpha.y)
- phase *= D_ggx(wh, alpha.x);
- else
- phase *= D_ggx_aniso(wh, alpha);
+ float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
+ if (alpha.x == alpha.y)
+ phase *= D_ggx(wh, alpha.x);
+ else
+ phase *= D_ggx_aniso(wh, alpha);
- return make_float3(phase, phase, phase);
+ return make_float3(phase, phase, phase);
}
/* Phase function for dielectric transmissive materials, including both reflection and refraction according to the dielectric fresnel term. */
-ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
-{
- float cosI = dot(wi, wm);
- float f = fresnel_dielectric_cos(cosI, eta);
- if(randV < f) {
- *outside = true;
- return -wi + 2.0f * wm * cosI;
- }
- *outside = false;
- float inv_eta = 1.0f/eta;
- float cosT = -safe_sqrtf(1.0f - (1.0f - cosI*cosI) * inv_eta*inv_eta);
- return normalize(wm*(cosI*inv_eta + cosT) - wi*inv_eta);
-}
-
-ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, const float lambda, const float3 wo, const bool wo_outside, const float2 alpha, const float eta)
-{
- if(w.z > 0.9999f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
- float v;
- if(wo_outside) {
- const float3 wh = normalize(wo - w);
- if(wh.z < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- const float dotW_WH = dot(-w, wh);
- v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f / (pArea * dotW_WH);
- }
- else {
- float3 wh = normalize(wo*eta - w);
- if(wh.z < 0.0f)
- wh = -wh;
- const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
- if(dotW_WH < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float temp = dotW_WH + eta*dotWO_WH;
- v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) * D_ggx(wh, alpha.x) / (pArea * temp * temp);
- }
-
- return make_float3(v, v, v);
+ccl_device_forceinline float3 mf_sample_phase_glass(
+ const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
+{
+ float cosI = dot(wi, wm);
+ float f = fresnel_dielectric_cos(cosI, eta);
+ if (randV < f) {
+ *outside = true;
+ return -wi + 2.0f * wm * cosI;
+ }
+ *outside = false;
+ float inv_eta = 1.0f / eta;
+ float cosT = -safe_sqrtf(1.0f - (1.0f - cosI * cosI) * inv_eta * inv_eta);
+ return normalize(wm * (cosI * inv_eta + cosT) - wi * inv_eta);
+}
+
+ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w,
+ const float lambda,
+ const float3 wo,
+ const bool wo_outside,
+ const float2 alpha,
+ const float eta)
+{
+ if (w.z > 0.9999f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
+ float v;
+ if (wo_outside) {
+ const float3 wh = normalize(wo - w);
+ if (wh.z < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ const float dotW_WH = dot(-w, wh);
+ v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f /
+ (pArea * dotW_WH);
+ }
+ else {
+ float3 wh = normalize(wo * eta - w);
+ if (wh.z < 0.0f)
+ wh = -wh;
+ const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
+ if (dotW_WH < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float temp = dotW_WH + eta * dotWO_WH;
+ v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) *
+ D_ggx(wh, alpha.x) / (pArea * temp * temp);
+ }
+
+ return make_float3(v, v, v);
}
/* === Utility functions for the random walks === */
@@ -173,64 +192,65 @@ ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, const float la
/* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha)
{
- if(w.z > 0.9999f)
- return 0.0f;
- else if(w.z < -0.9999f)
- return -0.9999f;
+ if (w.z > 0.9999f)
+ return 0.0f;
+ else if (w.z < -0.9999f)
+ return -0.9999f;
- const float inv_wz2 = 1.0f / max(w.z*w.z, 1e-7f);
- const float2 wa = make_float2(w.x, w.y)*alpha;
- float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
- if(w.z <= 0.0f)
- v = -v;
+ const float inv_wz2 = 1.0f / max(w.z * w.z, 1e-7f);
+ const float2 wa = make_float2(w.x, w.y) * alpha;
+ float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
+ if (w.z <= 0.0f)
+ v = -v;
- return 0.5f*(v - 1.0f);
+ return 0.5f * (v - 1.0f);
}
/* Height distribution CDF (based on page 4 of the supplemental implementation). */
ccl_device_forceinline float mf_invC1(const float h)
{
- return 2.0f * saturate(h) - 1.0f;
+ return 2.0f * saturate(h) - 1.0f;
}
ccl_device_forceinline float mf_C1(const float h)
{
- return saturate(0.5f * (h + 1.0f));
+ return saturate(0.5f * (h + 1.0f));
}
/* Masking function (based on page 16 of the supplemental implementation). */
ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
{
- if(w.z > 0.9999f)
- return 1.0f;
- if(w.z < 1e-5f)
- return 0.0f;
- return powf(C1, lambda);
+ if (w.z > 0.9999f)
+ return 1.0f;
+ if (w.z < 1e-5f)
+ return 0.0f;
+ return powf(C1, lambda);
}
/* Sampling from the visible height distribution (based on page 17 of the supplemental implementation). */
-ccl_device_forceinline bool mf_sample_height(const float3 w, float *h, float *C1, float *G1, float *lambda, const float U)
-{
- if(w.z > 0.9999f)
- return false;
- if(w.z < -0.9999f) {
- *C1 *= U;
- *h = mf_invC1(*C1);
- *G1 = mf_G1(w, *C1, *lambda);
- }
- else if(fabsf(w.z) >= 0.0001f) {
- if(U > 1.0f - *G1)
- return false;
- if(*lambda >= 0.0f) {
- *C1 = 1.0f;
- }
- else {
- *C1 *= powf(1.0f-U, -1.0f / *lambda);
- }
- *h = mf_invC1(*C1);
- *G1 = mf_G1(w, *C1, *lambda);
- }
- return true;
+ccl_device_forceinline bool mf_sample_height(
+ const float3 w, float *h, float *C1, float *G1, float *lambda, const float U)
+{
+ if (w.z > 0.9999f)
+ return false;
+ if (w.z < -0.9999f) {
+ *C1 *= U;
+ *h = mf_invC1(*C1);
+ *G1 = mf_G1(w, *C1, *lambda);
+ }
+ else if (fabsf(w.z) >= 0.0001f) {
+ if (U > 1.0f - *G1)
+ return false;
+ if (*lambda >= 0.0f) {
+ *C1 = 1.0f;
+ }
+ else {
+ *C1 *= powf(1.0f - U, -1.0f / *lambda);
+ }
+ *h = mf_invC1(*C1);
+ *G1 = mf_G1(w, *C1, *lambda);
+ }
+ return true;
}
/* === PDF approximations for the different phase functions. ===
@@ -240,80 +260,92 @@ ccl_device_forceinline bool mf_sample_height(const float3 w, float *h, float *C1
* the missing energy is then approximated as a diffuse reflection for the PDF. */
ccl_device_forceinline float mf_ggx_albedo(float r)
{
- float albedo = 0.806495f*expf(-1.98712f*r*r) + 0.199531f;
- albedo -= ((((((1.76741f*r - 8.43891f)*r + 15.784f)*r - 14.398f)*r + 6.45221f)*r - 1.19722f)*r + 0.027803f)*r + 0.00568739f;
- return saturate(albedo);
+ float albedo = 0.806495f * expf(-1.98712f * r * r) + 0.199531f;
+ albedo -= ((((((1.76741f * r - 8.43891f) * r + 15.784f) * r - 14.398f) * r + 6.45221f) * r -
+ 1.19722f) *
+ r +
+ 0.027803f) *
+ r +
+ 0.00568739f;
+ return saturate(albedo);
}
ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior)
{
- if(ior < 1.0f) {
- ior = 1.0f/ior;
- }
- a = saturate(a);
- ior = clamp(ior, 1.0f, 3.0f);
- float I_1 = 0.0476898f*expf(-0.978352f*(ior-0.65657f)*(ior-0.65657f)) - 0.033756f*ior + 0.993261f;
- float R_1 = (((0.116991f*a - 0.270369f)*a + 0.0501366f)*a - 0.00411511f)*a + 1.00008f;
- float I_2 = (((-2.08704f*ior + 26.3298f)*ior - 127.906f)*ior + 292.958f)*ior - 287.946f + 199.803f/(ior*ior) - 101.668f/(ior*ior*ior);
- float R_2 = ((((5.3725f*a -24.9307f)*a + 22.7437f)*a - 3.40751f)*a + 0.0986325f)*a + 0.00493504f;
-
- return saturate(1.0f + I_2*R_2*0.0019127f - (1.0f - I_1)*(1.0f - R_1)*9.3205f);
+ if (ior < 1.0f) {
+ ior = 1.0f / ior;
+ }
+ a = saturate(a);
+ ior = clamp(ior, 1.0f, 3.0f);
+ float I_1 = 0.0476898f * expf(-0.978352f * (ior - 0.65657f) * (ior - 0.65657f)) -
+ 0.033756f * ior + 0.993261f;
+ float R_1 = (((0.116991f * a - 0.270369f) * a + 0.0501366f) * a - 0.00411511f) * a + 1.00008f;
+ float I_2 = (((-2.08704f * ior + 26.3298f) * ior - 127.906f) * ior + 292.958f) * ior - 287.946f +
+ 199.803f / (ior * ior) - 101.668f / (ior * ior * ior);
+ float R_2 = ((((5.3725f * a - 24.9307f) * a + 22.7437f) * a - 3.40751f) * a + 0.0986325f) * a +
+ 0.00493504f;
+
+ return saturate(1.0f + I_2 * R_2 * 0.0019127f - (1.0f - I_1) * (1.0f - R_1) * 9.3205f);
}
ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
{
- float D = D_ggx(normalize(wi+wo), alpha);
- float lambda = mf_lambda(wi, make_float2(alpha, alpha));
- float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
+ float D = D_ggx(normalize(wi + wo), alpha);
+ float lambda = mf_lambda(wi, make_float2(alpha, alpha));
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
- float multiscatter = wo.z * M_1_PI_F;
+ float multiscatter = wo.z * M_1_PI_F;
- float albedo = mf_ggx_albedo(alpha);
- return albedo*singlescatter + (1.0f - albedo)*multiscatter;
+ float albedo = mf_ggx_albedo(alpha);
+ return albedo * singlescatter + (1.0f - albedo) * multiscatter;
}
ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
{
- float D = D_ggx_aniso(normalize(wi+wo), alpha);
- float lambda = mf_lambda(wi, alpha);
- float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
+ float D = D_ggx_aniso(normalize(wi + wo), alpha);
+ float lambda = mf_lambda(wi, alpha);
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
- float multiscatter = wo.z * M_1_PI_F;
+ float multiscatter = wo.z * M_1_PI_F;
- float albedo = mf_ggx_albedo(sqrtf(alpha.x*alpha.y));
- return albedo*singlescatter + (1.0f - albedo)*multiscatter;
+ float albedo = mf_ggx_albedo(sqrtf(alpha.x * alpha.y));
+ return albedo * singlescatter + (1.0f - albedo) * multiscatter;
}
-ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
+ccl_device_forceinline float mf_glass_pdf(const float3 wi,
+ const float3 wo,
+ const float alpha,
+ const float eta)
{
- bool reflective = (wi.z*wo.z > 0.0f);
-
- float wh_len;
- float3 wh = normalize_len(wi + (reflective? wo : (wo*eta)), &wh_len);
- if(wh.z < 0.0f)
- wh = -wh;
- float3 r_wi = (wi.z < 0.0f)? -wi: wi;
- float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
- float D = D_ggx(wh, alpha);
- float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
-
- float multiscatter = fabsf(wo.z * M_1_PI_F);
- if(reflective) {
- float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
- float albedo = mf_ggx_albedo(alpha);
- return fresnel * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
- }
- else {
- float singlescatter = fabsf(dot(r_wi, wh)*dot(wo, wh) * D * eta*eta / max((1.0f + lambda) * r_wi.z * wh_len*wh_len, 1e-7f));
- float albedo = mf_ggx_transmission_albedo(alpha, eta);
- return (1.0f - fresnel) * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
- }
+ bool reflective = (wi.z * wo.z > 0.0f);
+
+ float wh_len;
+ float3 wh = normalize_len(wi + (reflective ? wo : (wo * eta)), &wh_len);
+ if (wh.z < 0.0f)
+ wh = -wh;
+ float3 r_wi = (wi.z < 0.0f) ? -wi : wi;
+ float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
+ float D = D_ggx(wh, alpha);
+ float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
+
+ float multiscatter = fabsf(wo.z * M_1_PI_F);
+ if (reflective) {
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
+ float albedo = mf_ggx_albedo(alpha);
+ return fresnel * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
+ }
+ else {
+ float singlescatter = fabsf(dot(r_wi, wh) * dot(wo, wh) * D * eta * eta /
+ max((1.0f + lambda) * r_wi.z * wh_len * wh_len, 1e-7f));
+ float albedo = mf_ggx_transmission_albedo(alpha, eta);
+ return (1.0f - fresnel) * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
+ }
}
/* === Actual random walk implementations, one version of mf_eval and mf_sample per phase function. === */
-#define MF_NAME_JOIN(x,y) x ## _ ## y
-#define MF_NAME_EVAL(x,y) MF_NAME_JOIN(x,y)
+#define MF_NAME_JOIN(x, y) x##_##y
+#define MF_NAME_EVAL(x, y) MF_NAME_JOIN(x, y)
#define MF_FUNCTION_FULL_NAME(prefix) MF_NAME_EVAL(prefix, MF_PHASE_FUNCTION)
#define MF_PHASE_FUNCTION glass
@@ -326,10 +358,10 @@ ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, cons
ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
/* === Closure implementations === */
@@ -338,293 +370,395 @@ ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughnes
ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
- bsdf->extra->color.x = saturate(bsdf->extra->color.x);
- bsdf->extra->color.y = saturate(bsdf->extra->color.y);
- bsdf->extra->color.z = saturate(bsdf->extra->color.z);
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
+ bsdf->extra->color.x = saturate(bsdf->extra->color.x);
+ bsdf->extra->color.y = saturate(bsdf->extra->color.y);
+ bsdf->extra->color.z = saturate(bsdf->extra->color.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
{
- if(is_zero(bsdf->T))
- bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
+ if (is_zero(bsdf->T))
+ bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
+ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf,
+ const ShaderData *sd)
{
- if(is_zero(bsdf->T))
- bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
+ if (is_zero(bsdf->T))
+ bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_y = bsdf->alpha_x;
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ bsdf->alpha_y = bsdf->alpha_x;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
-}
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
-ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
-
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
-
- bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
- float3 X, Y, Z;
- Z = bsdf->N;
- if(is_aniso)
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- else
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- if(is_aniso)
- *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
- else
- *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
- return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
+ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
+ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
+
+ bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
+ float3 X, Y, Z;
+ Z = bsdf->N;
+ if (is_aniso)
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+ else
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+
+ if (is_aniso)
+ *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
+ else
+ *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
+ return mf_eval_glossy(localI,
+ localO,
+ true,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
- float3 X, Y, Z;
- Z = bsdf->N;
+ float3 X, Y, Z;
+ Z = bsdf->N;
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- *omega_in = 2*dot(Z, I)*Z - I;
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ *omega_in = 2 * dot(Z, I) * Z - I;
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
- *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
+ *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
+ *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
#endif
- return LABEL_REFLECT|LABEL_SINGULAR;
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
-
- bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
- if(is_aniso)
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- else
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO;
-
- *eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
- if(is_aniso)
- *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
- else
- *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
- *eval *= *pdf;
-
- *omega_in = X*localO.x + Y*localO.y + Z*localO.z;
+ return LABEL_REFLECT | LABEL_SINGULAR;
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
+
+ bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
+ if (is_aniso)
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+ else
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO;
+
+ *eval = mf_sample_glossy(localI,
+ &localO,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+ if (is_aniso)
+ *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
+ else
+ *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
+ *eval *= *pdf;
+
+ *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
- *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
+ *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
+ *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
#endif
- return LABEL_REFLECT|LABEL_GLOSSY;
+ return LABEL_REFLECT | LABEL_GLOSSY;
}
/* Multiscattering GGX Glass closure */
ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- bsdf->ior = max(0.0f, bsdf->ior);
- bsdf->extra->color.x = saturate(bsdf->extra->color.x);
- bsdf->extra->color.y = saturate(bsdf->extra->color.y);
- bsdf->extra->color.z = saturate(bsdf->extra->color.z);
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = max(0.0f, bsdf->ior);
+ bsdf->extra->color.x = saturate(bsdf->extra->color.x);
+ bsdf->extra->color.y = saturate(bsdf->extra->color.y);
+ bsdf->extra->color.z = saturate(bsdf->extra->color.z);
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
-ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
+ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf,
+ const ShaderData *sd)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- bsdf->ior = max(0.0f, bsdf->ior);
- bsdf->extra->color.x = saturate(bsdf->extra->color.x);
- bsdf->extra->color.y = saturate(bsdf->extra->color.y);
- bsdf->extra->color.z = saturate(bsdf->extra->color.z);
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
-
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
-
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
-}
-
-ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
-
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
-
- float3 X, Y, Z;
- Z = bsdf->N;
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, false, bsdf->extra->color);
-}
-
-ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
-
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
-
- float3 X, Y, Z;
- Z = bsdf->N;
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = max(0.0f, bsdf->ior);
+ bsdf->extra->color.x = saturate(bsdf->extra->color.x);
+ bsdf->extra->color.y = saturate(bsdf->extra->color.y);
+ bsdf->extra->color.z = saturate(bsdf->extra->color.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
+
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
+}
+
+ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ float3 X, Y, Z;
+ Z = bsdf->N;
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+
+ *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
+ return mf_eval_glass(localI,
+ localO,
+ false,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ false,
+ bsdf->extra->color);
+}
+
+ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+
+ float3 X, Y, Z;
+ Z = bsdf->N;
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+
+ *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
+ return mf_eval_glass(localI,
+ localO,
+ true,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
- float3 X, Y, Z;
- Z = bsdf->N;
+ float3 X, Y, Z;
+ Z = bsdf->N;
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- float3 R, T;
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- bool inside;
- float fresnel = fresnel_dielectric(bsdf->ior, Z, I, &R, &T,
+ bool inside;
+ float fresnel = fresnel_dielectric(bsdf->ior,
+ Z,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- if(randu < fresnel) {
- *omega_in = R;
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ if (randu < fresnel) {
+ *omega_in = R;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dRdx;
- *domega_in_dy = dRdy;
+ *domega_in_dx = dRdx;
+ *domega_in_dy = dRdy;
#endif
- return LABEL_REFLECT|LABEL_SINGULAR;
- }
- else {
- *omega_in = T;
+ return LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- return LABEL_TRANSMIT|LABEL_SINGULAR;
- }
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
-
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO;
-
- *eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- *eval *= *pdf;
-
- *omega_in = X*localO.x + Y*localO.y + Z*localO.z;
- if(localO.z*localI.z > 0.0f) {
+ return LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO;
+
+ *eval = mf_sample_glass(localI,
+ &localO,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+ *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
+ *eval *= *pdf;
+
+ *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
+ if (localO.z * localI.z > 0.0f) {
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
- *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
+ *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
+ *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
#endif
- return LABEL_REFLECT|LABEL_GLOSSY;
- }
- else {
+ return LABEL_REFLECT | LABEL_GLOSSY;
+ }
+ else {
#ifdef __RAY_DIFFERENTIALS__
- float cosI = dot(Z, I);
- float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI*cosI))), 1e-7f);
- *domega_in_dx = -(bsdf->ior * dIdx) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
- *domega_in_dy = -(bsdf->ior * dIdy) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
+ float cosI = dot(Z, I);
+ float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI * cosI))), 1e-7f);
+ *domega_in_dx = -(bsdf->ior * dIdx) +
+ ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
+ *domega_in_dy = -(bsdf->ior * dIdy) +
+ ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
#endif
- return LABEL_TRANSMIT|LABEL_GLOSSY;
- }
+ return LABEL_TRANSMIT | LABEL_GLOSSY;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
index 5d300ef6db5..79247ee8057 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
@@ -25,247 +25,251 @@
* energy is used. In combination with MIS, that is enough to produce an unbiased result, although
* the balance heuristic isn't necessarily optimal anymore.
*/
-ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
- float3 wi,
- float3 wo,
- const bool wo_outside,
- const float3 color,
- const float alpha_x,
- const float alpha_y,
- ccl_addr_space uint *lcg_state,
- const float eta,
- bool use_fresnel,
- const float3 cspec0)
+ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
+ float3 wo,
+ const bool wo_outside,
+ const float3 color,
+ const float alpha_x,
+ const float alpha_y,
+ ccl_addr_space uint *lcg_state,
+ const float eta,
+ bool use_fresnel,
+ const float3 cspec0)
{
- /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
- bool swapped = false;
+ /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
+ bool swapped = false;
#ifdef MF_MULTI_GLASS
- if(wi.z*wo.z < 0.0f) {
- /* Glass transmission is a special case and requires the directions to change hemisphere. */
- if(-wo.z < wi.z) {
- swapped = true;
- float3 tmp = -wo;
- wo = -wi;
- wi = tmp;
- }
- }
- else
+ if (wi.z * wo.z < 0.0f) {
+ /* Glass transmission is a special case and requires the directions to change hemisphere. */
+ if (-wo.z < wi.z) {
+ swapped = true;
+ float3 tmp = -wo;
+ wo = -wi;
+ wi = tmp;
+ }
+ }
+ else
#endif
- if(wo.z < wi.z) {
- swapped = true;
- float3 tmp = wo;
- wo = wi;
- wi = tmp;
- }
+ if (wo.z < wi.z) {
+ swapped = true;
+ float3 tmp = wo;
+ wo = wi;
+ wi = tmp;
+ }
- if(wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
+ return make_float3(0.0f, 0.0f, 0.0f);
- const float2 alpha = make_float2(alpha_x, alpha_y);
+ const float2 alpha = make_float2(alpha_x, alpha_y);
- float lambda_r = mf_lambda(-wi, alpha);
- float shadowing_lambda = mf_lambda(wo_outside? wo: -wo, alpha);
+ float lambda_r = mf_lambda(-wi, alpha);
+ float shadowing_lambda = mf_lambda(wo_outside ? wo : -wo, alpha);
- /* Analytically compute single scattering for lower noise. */
- float3 eval;
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- const float3 wh = normalize(wi+wo);
+ /* Analytically compute single scattering for lower noise. */
+ float3 eval;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ const float3 wh = normalize(wi + wo);
#ifdef MF_MULTI_GLASS
- eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
- if(wo_outside)
- eval *= -lambda_r / (shadowing_lambda - lambda_r);
- else
- eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
-#else /* MF_MULTI_GLOSSY */
- const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
- float val = G2 * 0.25f / wi.z;
- if(alpha.x == alpha.y)
- val *= D_ggx(wh, alpha.x);
- else
- val *= D_ggx_aniso(wh, alpha);
- eval = make_float3(val, val, val);
+ eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
+ if (wo_outside)
+ eval *= -lambda_r / (shadowing_lambda - lambda_r);
+ else
+ eval *= -lambda_r * beta(-lambda_r, shadowing_lambda + 1.0f);
+#else /* MF_MULTI_GLOSSY */
+ const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
+ float val = G2 * 0.25f / wi.z;
+ if (alpha.x == alpha.y)
+ val *= D_ggx(wh, alpha.x);
+ else
+ val *= D_ggx_aniso(wh, alpha);
+ eval = make_float3(val, val, val);
#endif
- float F0 = fresnel_dielectric_cos(1.0f, eta);
- if(use_fresnel) {
- throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
+ float F0 = fresnel_dielectric_cos(1.0f, eta);
+ if (use_fresnel) {
+ throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
- eval *= throughput;
- }
+ eval *= throughput;
+ }
- float3 wr = -wi;
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
+ float3 wr = -wi;
+ float hr = 1.0f;
+ float C1_r = 1.0f;
+ float G1_r = 0.0f;
+ bool outside = true;
- for(int order = 0; order < 10; order++) {
- /* Sample microfacet height. */
- float height_rand = lcg_step_float_addrspace(lcg_state);
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
- break;
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
- float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
+ for (int order = 0; order < 10; order++) {
+ /* Sample microfacet height. */
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
+ break;
+ /* Sample microfacet normal. */
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
#ifdef MF_MULTI_GLASS
- if(order == 0 && use_fresnel) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- float3 phase;
- if(outside)
- phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
- else
- phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
+ if (order == 0 && use_fresnel) {
+ /* Evaluate amount of scattering towards wo on this microfacet. */
+ float3 phase;
+ if (outside)
+ phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
+ else
+ phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
- eval = throughput * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda);
- }
+ eval = throughput * phase *
+ mf_G1(wo_outside ? wo : -wo,
+ mf_C1((outside == wo_outside) ? hr : -hr),
+ shadowing_lambda);
+ }
#endif
- if(order > 0) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- float3 phase;
+ if (order > 0) {
+ /* Evaluate amount of scattering towards wo on this microfacet. */
+ float3 phase;
#ifdef MF_MULTI_GLASS
- if(outside)
- phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
- else
- phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f/eta);
-#else /* MF_MULTI_GLOSSY */
- phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
+ if (outside)
+ phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
+ else
+ phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
+#else /* MF_MULTI_GLOSSY */
+ phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
#endif
- eval += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda);
- }
- if(order+1 < 10) {
- /* Bounce from the microfacet. */
+ eval += throughput * phase *
+ mf_G1(wo_outside ? wo : -wo,
+ mf_C1((outside == wo_outside) ? hr : -hr),
+ shadowing_lambda);
+ }
+ if (order + 1 < 10) {
+ /* Bounce from the microfacet. */
#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float_addrspace(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
- if(!next_outside) {
- outside = !outside;
- wr = -wr;
- hr = -hr;
- }
+ bool next_outside;
+ float3 wi_prev = -wr;
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
+ if (!next_outside) {
+ outside = !outside;
+ wr = -wr;
+ hr = -hr;
+ }
- if(use_fresnel && !next_outside) {
- throughput *= color;
- }
- else if(use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
- }
-#else /* MF_MULTI_GLOSSY */
- if(use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
+ if (use_fresnel && !next_outside) {
+ throughput *= color;
+ }
+ else if (use_fresnel && order > 0) {
+ throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+ }
+#else /* MF_MULTI_GLOSSY */
+ if (use_fresnel && order > 0) {
+ throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+ }
+ wr = mf_sample_phase_glossy(-wr, &throughput, wm);
#endif
- lambda_r = mf_lambda(wr, alpha);
+ lambda_r = mf_lambda(wr, alpha);
- if(!use_fresnel)
- throughput *= color;
+ if (!use_fresnel)
+ throughput *= color;
- C1_r = mf_C1(hr);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- }
+ C1_r = mf_C1(hr);
+ G1_r = mf_G1(wr, C1_r, lambda_r);
+ }
+ }
- if(swapped)
- eval *= fabsf(wi.z / wo.z);
- return eval;
+ if (swapped)
+ eval *= fabsf(wi.z / wo.z);
+ return eval;
}
/* Perform a random walk on the microsurface starting from wi, returning the direction in which the walk
* escaped the surface in wo. The function returns the throughput between wi and wo.
* Without reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal.
*/
-ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(
- float3 wi,
- float3 *wo,
- const float3 color,
- const float alpha_x,
- const float alpha_y,
- ccl_addr_space uint *lcg_state,
- const float eta,
- bool use_fresnel,
- const float3 cspec0)
+ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
+ float3 *wo,
+ const float3 color,
+ const float alpha_x,
+ const float alpha_y,
+ ccl_addr_space uint *lcg_state,
+ const float eta,
+ bool use_fresnel,
+ const float3 cspec0)
{
- const float2 alpha = make_float2(alpha_x, alpha_y);
+ const float2 alpha = make_float2(alpha_x, alpha_y);
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 wr = -wi;
- float lambda_r = mf_lambda(wr, alpha);
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 wr = -wi;
+ float lambda_r = mf_lambda(wr, alpha);
+ float hr = 1.0f;
+ float C1_r = 1.0f;
+ float G1_r = 0.0f;
+ bool outside = true;
- float F0 = fresnel_dielectric_cos(1.0f, eta);
- if(use_fresnel) {
- throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
- }
+ float F0 = fresnel_dielectric_cos(1.0f, eta);
+ if (use_fresnel) {
+ throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
+ }
- int order;
- for(order = 0; order < 10; order++) {
- /* Sample microfacet height. */
- float height_rand = lcg_step_float_addrspace(lcg_state);
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
- /* The random walk has left the surface. */
- *wo = outside? wr: -wr;
- return throughput;
- }
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
- float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
+ int order;
+ for (order = 0; order < 10; order++) {
+ /* Sample microfacet height. */
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
+ /* The random walk has left the surface. */
+ *wo = outside ? wr : -wr;
+ return throughput;
+ }
+ /* Sample microfacet normal. */
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
- /* First-bounce color is already accounted for in mix weight. */
- if(!use_fresnel && order > 0)
- throughput *= color;
+ /* First-bounce color is already accounted for in mix weight. */
+ if (!use_fresnel && order > 0)
+ throughput *= color;
- /* Bounce from the microfacet. */
+ /* Bounce from the microfacet. */
#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float_addrspace(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
- if(!next_outside) {
- hr = -hr;
- wr = -wr;
- outside = !outside;
- }
+ bool next_outside;
+ float3 wi_prev = -wr;
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
+ if (!next_outside) {
+ hr = -hr;
+ wr = -wr;
+ outside = !outside;
+ }
- if(use_fresnel) {
- if(!next_outside) {
- throughput *= color;
- }
- else {
- float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+ if (use_fresnel) {
+ if (!next_outside) {
+ throughput *= color;
+ }
+ else {
+ float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
- if(order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- }
-#else /* MF_MULTI_GLOSSY */
- if(use_fresnel) {
- float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+ if (order == 0)
+ throughput = t_color;
+ else
+ throughput *= t_color;
+ }
+ }
+#else /* MF_MULTI_GLOSSY */
+ if (use_fresnel) {
+ float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
- if(order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
+ if (order == 0)
+ throughput = t_color;
+ else
+ throughput *= t_color;
+ }
+ wr = mf_sample_phase_glossy(-wr, &throughput, wm);
#endif
- /* Update random walk parameters. */
- lambda_r = mf_lambda(wr, alpha);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- *wo = make_float3(0.0f, 0.0f, 1.0f);
- return make_float3(0.0f, 0.0f, 0.0f);
+ /* Update random walk parameters. */
+ lambda_r = mf_lambda(wr, alpha);
+ G1_r = mf_G1(wr, C1_r, lambda_r);
+ }
+ *wo = make_float3(0.0f, 0.0f, 1.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
#undef MF_MULTI_GLASS
diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
index 3446d1609d9..104ed5b2818 100644
--- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h
+++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
@@ -20,92 +20,110 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct OrenNayarBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float roughness;
- float a;
- float b;
+ float roughness;
+ float a;
+ float b;
} OrenNayarBsdf;
-ccl_device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, float3 v, float3 l)
+ccl_device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc,
+ float3 n,
+ float3 v,
+ float3 l)
{
- const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
- float nl = max(dot(n, l), 0.0f);
- float nv = max(dot(n, v), 0.0f);
- float t = dot(l, v) - nl * nv;
-
- if(t > 0.0f)
- t /= max(nl, nv) + FLT_MIN;
- float is = nl * (bsdf->a + bsdf->b * t);
- return make_float3(is, is, is);
+ const OrenNayarBsdf *bsdf = (const OrenNayarBsdf *)sc;
+ float nl = max(dot(n, l), 0.0f);
+ float nv = max(dot(n, v), 0.0f);
+ float t = dot(l, v) - nl * nv;
+
+ if (t > 0.0f)
+ t /= max(nl, nv) + FLT_MIN;
+ float is = nl * (bsdf->a + bsdf->b * t);
+ return make_float3(is, is, is);
}
ccl_device int bsdf_oren_nayar_setup(OrenNayarBsdf *bsdf)
{
- float sigma = bsdf->roughness;
+ float sigma = bsdf->roughness;
- bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID;
+ bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID;
- sigma = saturate(sigma);
+ sigma = saturate(sigma);
- float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma);
+ float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma);
- bsdf->a = 1.0f * div;
- bsdf->b = sigma * div;
+ bsdf->a = 1.0f * div;
+ bsdf->b = sigma * div;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_oren_nayar_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const OrenNayarBsdf *bsdf_a = (const OrenNayarBsdf*)a;
- const OrenNayarBsdf *bsdf_b = (const OrenNayarBsdf*)b;
+ const OrenNayarBsdf *bsdf_a = (const OrenNayarBsdf *)a;
+ const OrenNayarBsdf *bsdf_b = (const OrenNayarBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->roughness == bsdf_b->roughness);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->roughness == bsdf_b->roughness);
}
-ccl_device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
- if(dot(bsdf->N, omega_in) > 0.0f) {
- *pdf = 0.5f * M_1_PI_F;
- return bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, omega_in);
- }
- else {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ const OrenNayarBsdf *bsdf = (const OrenNayarBsdf *)sc;
+ if (dot(bsdf->N, omega_in) > 0.0f) {
+ *pdf = 0.5f * M_1_PI_F;
+ return bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, omega_in);
+ }
+ else {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
-ccl_device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
- sample_uniform_hemisphere(bsdf->N, randu, randv, omega_in, pdf);
+ const OrenNayarBsdf *bsdf = (const OrenNayarBsdf *)sc;
+ sample_uniform_hemisphere(bsdf->N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, *omega_in);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, *omega_in);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the bounce
- *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+ // TODO: find a better approximation for the bounce
+ *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
- }
- else {
- *pdf = 0.0f;
- *eval = make_float3(0.0f, 0.0f, 0.0f);
- }
+ }
+ else {
+ *pdf = 0.0f;
+ *eval = make_float3(0.0f, 0.0f, 0.0f);
+ }
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
-
CCL_NAMESPACE_END
-#endif /* __BSDF_OREN_NAYAR_H__ */
+#endif /* __BSDF_OREN_NAYAR_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
index 83da05ac435..b6fd0e68681 100644
--- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
@@ -38,105 +38,118 @@ CCL_NAMESPACE_BEGIN
#ifdef __OSL__
typedef ccl_addr_space struct PhongRampBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float exponent;
- float3 *colors;
+ float exponent;
+ float3 *colors;
} PhongRampBsdf;
ccl_device float3 bsdf_phong_ramp_get_color(const float3 colors[8], float pos)
{
- int MAXCOLORS = 8;
-
- float npos = pos * (float)(MAXCOLORS - 1);
- int ipos = float_to_int(npos);
- if(ipos < 0)
- return colors[0];
- if(ipos >= (MAXCOLORS - 1))
- return colors[MAXCOLORS - 1];
- float offset = npos - (float)ipos;
- return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
+ int MAXCOLORS = 8;
+
+ float npos = pos * (float)(MAXCOLORS - 1);
+ int ipos = float_to_int(npos);
+ if (ipos < 0)
+ return colors[0];
+ if (ipos >= (MAXCOLORS - 1))
+ return colors[MAXCOLORS - 1];
+ float offset = npos - (float)ipos;
+ return colors[ipos] * (1.0f - offset) + colors[ipos + 1] * offset;
}
ccl_device int bsdf_phong_ramp_setup(PhongRampBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_PHONG_RAMP_ID;
- bsdf->exponent = max(bsdf->exponent, 0.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_PHONG_RAMP_ID;
+ bsdf->exponent = max(bsdf->exponent, 0.0f);
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const PhongRampBsdf *bsdf = (const PhongRampBsdf*)sc;
- float m_exponent = bsdf->exponent;
- float cosNI = dot(bsdf->N, omega_in);
- float cosNO = dot(bsdf->N, I);
-
- if(cosNI > 0 && cosNO > 0) {
- // reflect the view vector
- float3 R = (2 * cosNO) * bsdf->N - I;
- float cosRI = dot(R, omega_in);
- if(cosRI > 0) {
- float cosp = powf(cosRI, m_exponent);
- float common = 0.5f * M_1_PI_F * cosp;
- float out = cosNI * (m_exponent + 2) * common;
- *pdf = (m_exponent + 1) * common;
- return bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
- }
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ const PhongRampBsdf *bsdf = (const PhongRampBsdf *)sc;
+ float m_exponent = bsdf->exponent;
+ float cosNI = dot(bsdf->N, omega_in);
+ float cosNO = dot(bsdf->N, I);
+
+ if (cosNI > 0 && cosNO > 0) {
+ // reflect the view vector
+ float3 R = (2 * cosNO) * bsdf->N - I;
+ float cosRI = dot(R, omega_in);
+ if (cosRI > 0) {
+ float cosp = powf(cosRI, m_exponent);
+ float common = 0.5f * M_1_PI_F * cosp;
+ float out = cosNI * (m_exponent + 2) * common;
+ *pdf = (m_exponent + 1) * common;
+ return bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
+ }
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const PhongRampBsdf *bsdf = (const PhongRampBsdf*)sc;
- float cosNO = dot(bsdf->N, I);
- float m_exponent = bsdf->exponent;
-
- if(cosNO > 0) {
- // reflect the view vector
- float3 R = (2 * cosNO) * bsdf->N - I;
-
-#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
-#endif
-
- float3 T, B;
- make_orthonormals (R, &T, &B);
- float phi = M_2PI_F * randu;
- float cosTheta = powf(randv, 1 / (m_exponent + 1));
- float sinTheta2 = 1 - cosTheta * cosTheta;
- float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
- *omega_in = (cosf(phi) * sinTheta) * T +
- (sinf(phi) * sinTheta) * B +
- ( cosTheta) * R;
- if(dot(Ng, *omega_in) > 0.0f)
- {
- // common terms for pdf and eval
- float cosNI = dot(bsdf->N, *omega_in);
- // make sure the direction we chose is still in the right hemisphere
- if(cosNI > 0)
- {
- float cosp = powf(cosTheta, m_exponent);
- float common = 0.5f * M_1_PI_F * cosp;
- *pdf = (m_exponent + 1) * common;
- float out = cosNI * (m_exponent + 2) * common;
- *eval = bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
- }
- }
- }
- return LABEL_REFLECT|LABEL_GLOSSY;
+ const PhongRampBsdf *bsdf = (const PhongRampBsdf *)sc;
+ float cosNO = dot(bsdf->N, I);
+ float m_exponent = bsdf->exponent;
+
+ if (cosNO > 0) {
+ // reflect the view vector
+ float3 R = (2 * cosNO) * bsdf->N - I;
+
+# ifdef __RAY_DIFFERENTIALS__
+ *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+# endif
+
+ float3 T, B;
+ make_orthonormals(R, &T, &B);
+ float phi = M_2PI_F * randu;
+ float cosTheta = powf(randv, 1 / (m_exponent + 1));
+ float sinTheta2 = 1 - cosTheta * cosTheta;
+ float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
+ *omega_in = (cosf(phi) * sinTheta) * T + (sinf(phi) * sinTheta) * B + (cosTheta)*R;
+ if (dot(Ng, *omega_in) > 0.0f) {
+ // common terms for pdf and eval
+ float cosNI = dot(bsdf->N, *omega_in);
+ // make sure the direction we chose is still in the right hemisphere
+ if (cosNI > 0) {
+ float cosp = powf(cosTheta, m_exponent);
+ float common = 0.5f * M_1_PI_F * cosp;
+ *pdf = (m_exponent + 1) * common;
+ float out = cosNI * (m_exponent + 2) * common;
+ *eval = bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
+ }
+ }
+ }
+ return LABEL_REFLECT | LABEL_GLOSSY;
}
-#endif /* __OSL__ */
+#endif /* __OSL__ */
CCL_NAMESPACE_END
-#endif /* __BSDF_PHONG_RAMP_H__ */
+#endif /* __BSDF_PHONG_RAMP_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
index 2f65fd54be2..d7795974ef5 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
@@ -25,101 +25,113 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct PrincipledDiffuseBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float roughness;
+ float roughness;
} PrincipledDiffuseBsdf;
-ccl_device float3 calculate_principled_diffuse_brdf(const PrincipledDiffuseBsdf *bsdf,
- float3 N, float3 V, float3 L, float3 H, float *pdf)
+ccl_device float3 calculate_principled_diffuse_brdf(
+ const PrincipledDiffuseBsdf *bsdf, float3 N, float3 V, float3 L, float3 H, float *pdf)
{
- float NdotL = max(dot(N, L), 0.0f);
- float NdotV = max(dot(N, V), 0.0f);
+ float NdotL = max(dot(N, L), 0.0f);
+ float NdotV = max(dot(N, V), 0.0f);
- if(NdotL < 0 || NdotV < 0) {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (NdotL < 0 || NdotV < 0) {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
- float LdotH = dot(L, H);
+ float LdotH = dot(L, H);
- float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
- const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * bsdf->roughness;
- float Fd = (1.0f * (1.0f - FL) + Fd90 * FL) * (1.0f * (1.0f - FV) + Fd90 * FV);
+ float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
+ const float Fd90 = 0.5f + 2.0f * LdotH * LdotH * bsdf->roughness;
+ float Fd = (1.0f * (1.0f - FL) + Fd90 * FL) * (1.0f * (1.0f - FV) + Fd90 * FV);
- float value = M_1_PI_F * NdotL * Fd;
+ float value = M_1_PI_F * NdotL * Fd;
- return make_float3(value, value, value);
+ return make_float3(value, value, value);
}
ccl_device int bsdf_principled_diffuse_setup(PrincipledDiffuseBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_principled_diffuse_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const PrincipledDiffuseBsdf *bsdf_a = (const PrincipledDiffuseBsdf*)a;
- const PrincipledDiffuseBsdf *bsdf_b = (const PrincipledDiffuseBsdf*)b;
+ const PrincipledDiffuseBsdf *bsdf_a = (const PrincipledDiffuseBsdf *)a;
+ const PrincipledDiffuseBsdf *bsdf_b = (const PrincipledDiffuseBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N) && bsdf_a->roughness == bsdf_b->roughness);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N) && bsdf_a->roughness == bsdf_b->roughness);
}
-ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
-
- float3 N = bsdf->N;
- float3 V = I; // outgoing
- float3 L = omega_in; // incoming
- float3 H = normalize(L + V);
-
- if(dot(N, omega_in) > 0.0f) {
- *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- return calculate_principled_diffuse_brdf(bsdf, N, V, L, H, pdf);
- }
- else {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
+
+ float3 N = bsdf->N;
+ float3 V = I; // outgoing
+ float3 L = omega_in; // incoming
+ float3 H = normalize(L + V);
+
+ if (dot(N, omega_in) > 0.0f) {
+ *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+ return calculate_principled_diffuse_brdf(bsdf, N, V, L, H, pdf);
+ }
+ else {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
-ccl_device float3 bsdf_principled_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_diffuse_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device int bsdf_principled_diffuse_sample(const ShaderClosure *sc,
- float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
- float3 *eval, float3 *omega_in, float3 *domega_in_dx,
- float3 *domega_in_dy, float *pdf)
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
+ const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
- float3 N = bsdf->N;
+ float3 N = bsdf->N;
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0) {
- float3 H = normalize(I + *omega_in);
+ if (dot(Ng, *omega_in) > 0) {
+ float3 H = normalize(I + *omega_in);
- *eval = calculate_principled_diffuse_brdf(bsdf, N, I, *omega_in, H, pdf);
+ *eval = calculate_principled_diffuse_brdf(bsdf, N, I, *omega_in, H, pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
- *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+ *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
#endif
- }
- else {
- *pdf = 0.0f;
- }
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ }
+ else {
+ *pdf = 0.0f;
+ }
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_PRINCIPLED_DIFFUSE_H__ */
+#endif /* __BSDF_PRINCIPLED_DIFFUSE_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
index ccdcb1babd2..bc522095b3b 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
@@ -25,87 +25,99 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct PrincipledSheenBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
} PrincipledSheenBsdf;
-ccl_device float3 calculate_principled_sheen_brdf(const PrincipledSheenBsdf *bsdf,
- float3 N, float3 V, float3 L, float3 H, float *pdf)
+ccl_device float3 calculate_principled_sheen_brdf(
+ const PrincipledSheenBsdf *bsdf, float3 N, float3 V, float3 L, float3 H, float *pdf)
{
- float NdotL = dot(N, L);
- float NdotV = dot(N, V);
+ float NdotL = dot(N, L);
+ float NdotV = dot(N, V);
- if(NdotL < 0 || NdotV < 0) {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (NdotL < 0 || NdotV < 0) {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
- float LdotH = dot(L, H);
+ float LdotH = dot(L, H);
- float value = schlick_fresnel(LdotH) * NdotL;
+ float value = schlick_fresnel(LdotH) * NdotL;
- return make_float3(value, value, value);
+ return make_float3(value, value, value);
}
ccl_device int bsdf_principled_sheen_setup(PrincipledSheenBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_principled_sheen_eval_reflect(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_sheen_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
-
- float3 N = bsdf->N;
- float3 V = I; // outgoing
- float3 L = omega_in; // incoming
- float3 H = normalize(L + V);
-
- if(dot(N, omega_in) > 0.0f) {
- *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- return calculate_principled_sheen_brdf(bsdf, N, V, L, H, pdf);
- }
- else {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
+
+ float3 N = bsdf->N;
+ float3 V = I; // outgoing
+ float3 L = omega_in; // incoming
+ float3 H = normalize(L + V);
+
+ if (dot(N, omega_in) > 0.0f) {
+ *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+ return calculate_principled_sheen_brdf(bsdf, N, V, L, H, pdf);
+ }
+ else {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
-ccl_device float3 bsdf_principled_sheen_eval_transmit(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_sheen_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device int bsdf_principled_sheen_sample(const ShaderClosure *sc,
- float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
- float3 *eval, float3 *omega_in, float3 *domega_in_dx,
- float3 *domega_in_dy, float *pdf)
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
+ const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
- float3 N = bsdf->N;
+ float3 N = bsdf->N;
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0) {
- float3 H = normalize(I + *omega_in);
+ if (dot(Ng, *omega_in) > 0) {
+ float3 H = normalize(I + *omega_in);
- *eval = calculate_principled_sheen_brdf(bsdf, N, I, *omega_in, H, pdf);
+ *eval = calculate_principled_sheen_brdf(bsdf, N, I, *omega_in, H, pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
- *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+ *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
#endif
- }
- else {
- *pdf = 0.0f;
- }
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ }
+ else {
+ *pdf = 0.0f;
+ }
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_PRINCIPLED_SHEEN_H__ */
+#endif /* __BSDF_PRINCIPLED_SHEEN_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h
index 94f1c283af7..c24ba170915 100644
--- a/intern/cycles/kernel/closure/bsdf_reflection.h
+++ b/intern/cycles/kernel/closure/bsdf_reflection.h
@@ -39,42 +39,59 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_reflection_setup(MicrofacetBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
- return SD_BSDF;
+ bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
+ return SD_BSDF;
}
-ccl_device float3 bsdf_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_reflection_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_reflection_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float3 N = bsdf->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float3 N = bsdf->N;
- // only one direction is possible
- float cosNO = dot(N, I);
- if(cosNO > 0) {
- *omega_in = (2 * cosNO) * N - I;
- if(dot(Ng, *omega_in) > 0) {
+ // only one direction is possible
+ float cosNO = dot(N, I);
+ if (cosNO > 0) {
+ *omega_in = (2 * cosNO) * N - I;
+ if (dot(Ng, *omega_in) > 0) {
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = 2 * dot(N, dIdx) * N - dIdx;
- *domega_in_dy = 2 * dot(N, dIdy) * N - dIdy;
+ *domega_in_dx = 2 * dot(N, dIdx) * N - dIdx;
+ *domega_in_dy = 2 * dot(N, dIdy) * N - dIdy;
#endif
- /* Some high number for MIS. */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- }
- }
- return LABEL_REFLECT|LABEL_SINGULAR;
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ }
+ }
+ return LABEL_REFLECT | LABEL_SINGULAR;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_REFLECTION_H__ */
+#endif /* __BSDF_REFLECTION_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h
index abdd01c7a1d..d4fbe86dac0 100644
--- a/intern/cycles/kernel/closure/bsdf_refraction.h
+++ b/intern/cycles/kernel/closure/bsdf_refraction.h
@@ -39,51 +39,77 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
- return SD_BSDF;
+ bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
+ return SD_BSDF;
}
-ccl_device float3 bsdf_refraction_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_refraction_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_refraction_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_refraction_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float m_eta = bsdf->ior;
- float3 N = bsdf->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float m_eta = bsdf->ior;
+ float3 N = bsdf->N;
- float3 R, T;
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- bool inside;
- float fresnel;
- fresnel = fresnel_dielectric(m_eta, N, I, &R, &T,
+ bool inside;
+ float fresnel;
+ fresnel = fresnel_dielectric(m_eta,
+ N,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- if(!inside && fresnel != 1.0f) {
- /* Some high number for MIS. */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- *omega_in = T;
+ if (!inside && fresnel != 1.0f) {
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- }
- return LABEL_TRANSMIT|LABEL_SINGULAR;
+ }
+ return LABEL_TRANSMIT | LABEL_SINGULAR;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_REFRACTION_H__ */
+#endif /* __BSDF_REFRACTION_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h
index 097a56f22eb..f37fd228087 100644
--- a/intern/cycles/kernel/closure/bsdf_toon.h
+++ b/intern/cycles/kernel/closure/bsdf_toon.h
@@ -36,183 +36,215 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct ToonBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float size;
- float smooth;
+ float size;
+ float smooth;
} ToonBsdf;
/* DIFFUSE TOON */
ccl_device int bsdf_diffuse_toon_setup(ToonBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- bsdf->size = saturate(bsdf->size);
- bsdf->smooth = saturate(bsdf->smooth);
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
+ bsdf->size = saturate(bsdf->size);
+ bsdf->smooth = saturate(bsdf->smooth);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_toon_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const ToonBsdf *bsdf_a = (const ToonBsdf*)a;
- const ToonBsdf *bsdf_b = (const ToonBsdf*)b;
+ const ToonBsdf *bsdf_a = (const ToonBsdf *)a;
+ const ToonBsdf *bsdf_b = (const ToonBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->size == bsdf_b->size) &&
- (bsdf_a->smooth == bsdf_b->smooth);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->size == bsdf_b->size) &&
+ (bsdf_a->smooth == bsdf_b->smooth);
}
ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
{
- float is;
+ float is;
- if(angle < max_angle)
- is = 1.0f;
- else if(angle < (max_angle + smooth) && smooth != 0.0f)
- is = (1.0f - (angle - max_angle)/smooth);
- else
- is = 0.0f;
+ if (angle < max_angle)
+ is = 1.0f;
+ else if (angle < (max_angle + smooth) && smooth != 0.0f)
+ is = (1.0f - (angle - max_angle) / smooth);
+ else
+ is = 0.0f;
- return make_float3(is, is, is);
+ return make_float3(is, is, is);
}
ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
{
- return fminf(max_angle + smooth, M_PI_2_F);
+ return fminf(max_angle + smooth, M_PI_2_F);
}
-ccl_device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
- float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
+ float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
- if(eval.x > 0.0f) {
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ if (eval.x > 0.0f) {
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
- return *pdf * eval;
- }
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
+ return *pdf * eval;
+ }
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- float angle = sample_angle*randu;
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float angle = sample_angle * randu;
- if(sample_angle > 0.0f) {
- sample_uniform_cone(bsdf->N, sample_angle, randu, randv, omega_in, pdf);
+ if (sample_angle > 0.0f) {
+ sample_uniform_cone(bsdf->N, sample_angle, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the bounce
- *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+ // TODO: find a better approximation for the bounce
+ *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
- }
-
- return LABEL_REFLECT | LABEL_DIFFUSE;
+ }
+ else
+ *pdf = 0.0f;
+ }
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
/* GLOSSY TOON */
ccl_device int bsdf_glossy_toon_setup(ToonBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
- bsdf->size = saturate(bsdf->size);
- bsdf->smooth = saturate(bsdf->smooth);
+ bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
+ bsdf->size = saturate(bsdf->size);
+ bsdf->smooth = saturate(bsdf->smooth);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float cosNI = dot(bsdf->N, omega_in);
- float cosNO = dot(bsdf->N, I);
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float cosNI = dot(bsdf->N, omega_in);
+ float cosNO = dot(bsdf->N, I);
- if(cosNI > 0 && cosNO > 0) {
- /* reflect the view vector */
- float3 R = (2 * cosNO) * bsdf->N - I;
- float cosRI = dot(R, omega_in);
+ if (cosNI > 0 && cosNO > 0) {
+ /* reflect the view vector */
+ float3 R = (2 * cosNO) * bsdf->N - I;
+ float cosRI = dot(R, omega_in);
- float angle = safe_acosf(fmaxf(cosRI, 0.0f));
+ float angle = safe_acosf(fmaxf(cosRI, 0.0f));
- float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
- return *pdf * eval;
- }
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
+ return *pdf * eval;
+ }
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_glossy_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_glossy_toon_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float cosNO = dot(bsdf->N, I);
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float cosNO = dot(bsdf->N, I);
- if(cosNO > 0) {
- /* reflect the view vector */
- float3 R = (2 * cosNO) * bsdf->N - I;
+ if (cosNO > 0) {
+ /* reflect the view vector */
+ float3 R = (2 * cosNO) * bsdf->N - I;
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- float angle = sample_angle*randu;
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float angle = sample_angle * randu;
- sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
+ sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- float cosNI = dot(bsdf->N, *omega_in);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ float cosNI = dot(bsdf->N, *omega_in);
- /* make sure the direction we chose is still in the right hemisphere */
- if(cosNI > 0) {
- *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
+ /* make sure the direction we chose is still in the right hemisphere */
+ if (cosNI > 0) {
+ *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+ *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
- }
- else
- *pdf = 0.0f;
- }
-
- return LABEL_GLOSSY | LABEL_REFLECT;
+ }
+ else
+ *pdf = 0.0f;
+ }
+ else
+ *pdf = 0.0f;
+ }
+
+ return LABEL_GLOSSY | LABEL_REFLECT;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_TOON_H__ */
+#endif /* __BSDF_TOON_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h
index 060dff69f52..4e5513499e8 100644
--- a/intern/cycles/kernel/closure/bsdf_transparent.h
+++ b/intern/cycles/kernel/closure/bsdf_transparent.h
@@ -37,73 +37,91 @@ CCL_NAMESPACE_BEGIN
ccl_device void bsdf_transparent_setup(ShaderData *sd, const float3 weight, int path_flag)
{
- /* Check cutoff weight. */
- float sample_weight = fabsf(average(weight));
- if(!(sample_weight >= CLOSURE_WEIGHT_CUTOFF)) {
- return;
- }
+ /* Check cutoff weight. */
+ float sample_weight = fabsf(average(weight));
+ if (!(sample_weight >= CLOSURE_WEIGHT_CUTOFF)) {
+ return;
+ }
- if(sd->flag & SD_TRANSPARENT) {
- sd->closure_transparent_extinction += weight;
+ if (sd->flag & SD_TRANSPARENT) {
+ sd->closure_transparent_extinction += weight;
- /* Add weight to existing transparent BSDF. */
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ /* Add weight to existing transparent BSDF. */
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
- sc->weight += weight;
- sc->sample_weight += sample_weight;
- break;
- }
- }
- }
- else {
- sd->flag |= SD_BSDF|SD_TRANSPARENT;
- sd->closure_transparent_extinction = weight;
+ if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
+ sc->weight += weight;
+ sc->sample_weight += sample_weight;
+ break;
+ }
+ }
+ }
+ else {
+ sd->flag |= SD_BSDF | SD_TRANSPARENT;
+ sd->closure_transparent_extinction = weight;
- if(path_flag & PATH_RAY_TERMINATE) {
- /* In this case the number of closures is set to zero to disable
- * all others, but we still want to get transparency so increase
- * the number just for this. */
- sd->num_closure_left = 1;
- }
+ if (path_flag & PATH_RAY_TERMINATE) {
+ /* In this case the number of closures is set to zero to disable
+ * all others, but we still want to get transparency so increase
+ * the number just for this. */
+ sd->num_closure_left = 1;
+ }
- /* Create new transparent BSDF. */
- ShaderClosure *bsdf = closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BSDF_TRANSPARENT_ID, weight);
+ /* Create new transparent BSDF. */
+ ShaderClosure *bsdf = closure_alloc(
+ sd, sizeof(ShaderClosure), CLOSURE_BSDF_TRANSPARENT_ID, weight);
- if(bsdf) {
- bsdf->sample_weight = sample_weight;
- bsdf->N = sd->N;
- }
- else if(path_flag & PATH_RAY_TERMINATE) {
- sd->num_closure_left = 0;
- }
- }
+ if (bsdf) {
+ bsdf->sample_weight = sample_weight;
+ bsdf->N = sd->N;
+ }
+ else if (path_flag & PATH_RAY_TERMINATE) {
+ sd->num_closure_left = 0;
+ }
+ }
}
-ccl_device float3 bsdf_transparent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_transparent_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_transparent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_transparent_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_transparent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_transparent_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- // only one direction is possible
- *omega_in = -I;
+ // only one direction is possible
+ *omega_in = -I;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = -dIdx;
- *domega_in_dy = -dIdy;
+ *domega_in_dx = -dIdx;
+ *domega_in_dy = -dIdy;
#endif
- *pdf = 1;
- *eval = make_float3(1, 1, 1);
- return LABEL_TRANSMIT|LABEL_TRANSPARENT;
+ *pdf = 1;
+ *eval = make_float3(1, 1, 1);
+ return LABEL_TRANSMIT | LABEL_TRANSPARENT;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_TRANSPARENT_H__ */
+#endif /* __BSDF_TRANSPARENT_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index 4f3453675c7..a9a27edd7de 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -35,127 +35,134 @@
CCL_NAMESPACE_BEGIN
-ccl_device float fresnel_dielectric(
- float eta, const float3 N,
- const float3 I, float3 *R, float3 *T,
+ccl_device float fresnel_dielectric(float eta,
+ const float3 N,
+ const float3 I,
+ float3 *R,
+ float3 *T,
#ifdef __RAY_DIFFERENTIALS__
- const float3 dIdx, const float3 dIdy,
- float3 *dRdx, float3 *dRdy,
- float3 *dTdx, float3 *dTdy,
+ const float3 dIdx,
+ const float3 dIdy,
+ float3 *dRdx,
+ float3 *dRdy,
+ float3 *dTdx,
+ float3 *dTdy,
#endif
- bool *is_inside)
+ bool *is_inside)
{
- float cos = dot(N, I), neta;
- float3 Nn;
+ float cos = dot(N, I), neta;
+ float3 Nn;
- // check which side of the surface we are on
- if(cos > 0) {
- // we are on the outside of the surface, going in
- neta = 1 / eta;
- Nn = N;
- *is_inside = false;
- }
- else {
- // we are inside the surface
- cos = -cos;
- neta = eta;
- Nn = -N;
- *is_inside = true;
- }
+ // check which side of the surface we are on
+ if (cos > 0) {
+ // we are on the outside of the surface, going in
+ neta = 1 / eta;
+ Nn = N;
+ *is_inside = false;
+ }
+ else {
+ // we are inside the surface
+ cos = -cos;
+ neta = eta;
+ Nn = -N;
+ *is_inside = true;
+ }
- // compute reflection
- *R = (2 * cos)* Nn - I;
+ // compute reflection
+ *R = (2 * cos) * Nn - I;
#ifdef __RAY_DIFFERENTIALS__
- *dRdx = (2 * dot(Nn, dIdx)) * Nn - dIdx;
- *dRdy = (2 * dot(Nn, dIdy)) * Nn - dIdy;
+ *dRdx = (2 * dot(Nn, dIdx)) * Nn - dIdx;
+ *dRdy = (2 * dot(Nn, dIdy)) * Nn - dIdy;
#endif
- float arg = 1 -(neta * neta *(1 -(cos * cos)));
- if(arg < 0) {
- *T = make_float3(0.0f, 0.0f, 0.0f);
+ float arg = 1 - (neta * neta * (1 - (cos * cos)));
+ if (arg < 0) {
+ *T = make_float3(0.0f, 0.0f, 0.0f);
#ifdef __RAY_DIFFERENTIALS__
- *dTdx = make_float3(0.0f, 0.0f, 0.0f);
- *dTdy = make_float3(0.0f, 0.0f, 0.0f);
+ *dTdx = make_float3(0.0f, 0.0f, 0.0f);
+ *dTdy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return 1; // total internal reflection
- }
- else {
- float dnp = max(sqrtf(arg), 1e-7f);
- float nK = (neta * cos)- dnp;
- *T = -(neta * I)+(nK * Nn);
+ return 1; // total internal reflection
+ }
+ else {
+ float dnp = max(sqrtf(arg), 1e-7f);
+ float nK = (neta * cos) - dnp;
+ *T = -(neta * I) + (nK * Nn);
#ifdef __RAY_DIFFERENTIALS__
- *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
- *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
+ *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
+ *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
#endif
- // compute Fresnel terms
- float cosTheta1 = cos; // N.R
- float cosTheta2 = -dot(Nn, *T);
- float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2);
- float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2);
- return 0.5f * (pPara * pPara + pPerp * pPerp);
- }
+ // compute Fresnel terms
+ float cosTheta1 = cos; // N.R
+ float cosTheta2 = -dot(Nn, *T);
+ float pPara = (cosTheta1 - eta * cosTheta2) / (cosTheta1 + eta * cosTheta2);
+ float pPerp = (eta * cosTheta1 - cosTheta2) / (eta * cosTheta1 + cosTheta2);
+ return 0.5f * (pPara * pPara + pPerp * pPerp);
+ }
}
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
{
- // compute fresnel reflectance without explicitly computing
- // the refracted direction
- float c = fabsf(cosi);
- float g = eta * eta - 1 + c * c;
- if(g > 0) {
- g = sqrtf(g);
- float A = (g - c)/(g + c);
- float B = (c *(g + c)- 1)/(c *(g - c)+ 1);
- return 0.5f * A * A *(1 + B * B);
- }
- return 1.0f; // TIR(no refracted component)
+ // compute fresnel reflectance without explicitly computing
+ // the refracted direction
+ float c = fabsf(cosi);
+ float g = eta * eta - 1 + c * c;
+ if (g > 0) {
+ g = sqrtf(g);
+ float A = (g - c) / (g + c);
+ float B = (c * (g + c) - 1) / (c * (g - c) + 1);
+ return 0.5f * A * A * (1 + B * B);
+ }
+ return 1.0f; // TIR(no refracted component)
}
ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k)
{
- float3 cosi2 = make_float3(cosi*cosi, cosi*cosi, cosi*cosi);
- float3 one = make_float3(1.0f, 1.0f, 1.0f);
- float3 tmp_f = eta * eta + k * k;
- float3 tmp = tmp_f * cosi2;
- float3 Rparl2 = (tmp - (2.0f * eta * cosi) + one) /
- (tmp + (2.0f * eta * cosi) + one);
- float3 Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) /
- (tmp_f + (2.0f * eta * cosi) + cosi2);
- return(Rparl2 + Rperp2) * 0.5f;
+ float3 cosi2 = make_float3(cosi * cosi, cosi * cosi, cosi * cosi);
+ float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ float3 tmp_f = eta * eta + k * k;
+ float3 tmp = tmp_f * cosi2;
+ float3 Rparl2 = (tmp - (2.0f * eta * cosi) + one) / (tmp + (2.0f * eta * cosi) + one);
+ float3 Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) / (tmp_f + (2.0f * eta * cosi) + cosi2);
+ return (Rparl2 + Rperp2) * 0.5f;
}
ccl_device float schlick_fresnel(float u)
{
- float m = clamp(1.0f - u, 0.0f, 1.0f);
- float m2 = m * m;
- return m2 * m2 * m; // pow(m, 5)
+ float m = clamp(1.0f - u, 0.0f, 1.0f);
+ float m2 = m * m;
+ return m2 * m2 * m; // pow(m, 5)
}
ccl_device float smooth_step(float edge0, float edge1, float x)
{
- float result;
- if(x < edge0) result = 0.0f;
- else if(x >= edge1) result = 1.0f;
- else {
- float t = (x - edge0)/(edge1 - edge0);
- result = (3.0f-2.0f*t)*(t*t);
- }
- return result;
+ float result;
+ if (x < edge0)
+ result = 0.0f;
+ else if (x >= edge1)
+ result = 1.0f;
+ else {
+ float t = (x - edge0) / (edge1 - edge0);
+ result = (3.0f - 2.0f * t) * (t * t);
+ }
+ return result;
}
/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
-ccl_device_forceinline float3 interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0) {
- /* Calculate the fresnel interpolation factor
- * The value from fresnel_dielectric_cos(...) has to be normalized because
- * the cspec0 keeps the F0 color
- */
- float F0_norm = 1.0f / (1.0f - F0);
- float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
+ccl_device_forceinline float3
+interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0)
+{
+ /* Calculate the fresnel interpolation factor
+ * The value from fresnel_dielectric_cos(...) has to be normalized because
+ * the cspec0 keeps the F0 color
+ */
+ float F0_norm = 1.0f / (1.0f - F0);
+ float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
- /* Blend between white and a specular color with respect to the fresnel */
- return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
+ /* Blend between white and a specular color with respect to the fresnel */
+ return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_UTIL_H__ */
+#endif /* __BSDF_UTIL_H__ */
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index 98c7f23c288..57804eca269 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -20,14 +20,14 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct Bssrdf {
- SHADER_CLOSURE_BASE;
-
- float3 radius;
- float3 albedo;
- float sharpness;
- float texture_blur;
- float roughness;
- float channels;
+ SHADER_CLOSURE_BASE;
+
+ float3 radius;
+ float3 albedo;
+ float sharpness;
+ float texture_blur;
+ float roughness;
+ float channels;
} Bssrdf;
/* Planar Truncated Gaussian
@@ -41,41 +41,41 @@ typedef ccl_addr_space struct Bssrdf {
ccl_device float bssrdf_gaussian_eval(const float radius, float r)
{
- /* integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) from 0 to Rm
- * = 1 - exp(-Rm*Rm/(2*v)) */
- const float v = radius*radius*(0.25f*0.25f);
- const float Rm = sqrtf(v*GAUSS_TRUNCATE);
+ /* integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) from 0 to Rm
+ * = 1 - exp(-Rm*Rm/(2*v)) */
+ const float v = radius * radius * (0.25f * 0.25f);
+ const float Rm = sqrtf(v * GAUSS_TRUNCATE);
- if(r >= Rm)
- return 0.0f;
+ if (r >= Rm)
+ return 0.0f;
- return expf(-r*r/(2.0f*v))/(2.0f*M_PI_F*v);
+ return expf(-r * r / (2.0f * v)) / (2.0f * M_PI_F * v);
}
ccl_device float bssrdf_gaussian_pdf(const float radius, float r)
{
- /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
- const float area_truncated = 1.0f - expf(-0.5f*GAUSS_TRUNCATE);
+ /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
+ const float area_truncated = 1.0f - expf(-0.5f * GAUSS_TRUNCATE);
- return bssrdf_gaussian_eval(radius, r) * (1.0f/(area_truncated));
+ return bssrdf_gaussian_eval(radius, r) * (1.0f / (area_truncated));
}
ccl_device void bssrdf_gaussian_sample(const float radius, float xi, float *r, float *h)
{
- /* xi = integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) = -exp(-r^2/(2*v))
- * r = sqrt(-2*v*logf(xi)) */
- const float v = radius*radius*(0.25f*0.25f);
- const float Rm = sqrtf(v*GAUSS_TRUNCATE);
+ /* xi = integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) = -exp(-r^2/(2*v))
+ * r = sqrt(-2*v*logf(xi)) */
+ const float v = radius * radius * (0.25f * 0.25f);
+ const float Rm = sqrtf(v * GAUSS_TRUNCATE);
- /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
- const float area_truncated = 1.0f - expf(-0.5f*GAUSS_TRUNCATE);
+ /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
+ const float area_truncated = 1.0f - expf(-0.5f * GAUSS_TRUNCATE);
- /* r(xi) */
- const float r_squared = -2.0f*v*logf(1.0f - xi*area_truncated);
- *r = sqrtf(r_squared);
+ /* r(xi) */
+ const float r_squared = -2.0f * v * logf(1.0f - xi * area_truncated);
+ *r = sqrtf(r_squared);
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_squared);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_squared);
}
/* Planar Cubic BSSRDF falloff
@@ -87,97 +87,97 @@ ccl_device void bssrdf_gaussian_sample(const float radius, float xi, float *r, f
ccl_device float bssrdf_cubic_eval(const float radius, const float sharpness, float r)
{
- if(sharpness == 0.0f) {
- const float Rm = radius;
-
- if(r >= Rm)
- return 0.0f;
-
- /* integrate (2*pi*r * 10*(R - r)^3)/(pi * R^5) from 0 to R = 1 */
- const float Rm5 = (Rm*Rm) * (Rm*Rm) * Rm;
- const float f = Rm - r;
- const float num = f*f*f;
-
- return (10.0f * num) / (Rm5 * M_PI_F);
-
- }
- else {
- float Rm = radius*(1.0f + sharpness);
-
- if(r >= Rm)
- return 0.0f;
-
- /* custom variation with extra sharpness, to match the previous code */
- const float y = 1.0f/(1.0f + sharpness);
- float Rmy, ry, ryinv;
-
- if(sharpness == 1.0f) {
- Rmy = sqrtf(Rm);
- ry = sqrtf(r);
- ryinv = (ry > 0.0f)? 1.0f/ry: 0.0f;
- }
- else {
- Rmy = powf(Rm, y);
- ry = powf(r, y);
- ryinv = (r > 0.0f)? powf(r, y - 1.0f): 0.0f;
- }
-
- const float Rmy5 = (Rmy*Rmy) * (Rmy*Rmy) * Rmy;
- const float f = Rmy - ry;
- const float num = f*(f*f)*(y*ryinv);
-
- return (10.0f * num) / (Rmy5 * M_PI_F);
- }
+ if (sharpness == 0.0f) {
+ const float Rm = radius;
+
+ if (r >= Rm)
+ return 0.0f;
+
+ /* integrate (2*pi*r * 10*(R - r)^3)/(pi * R^5) from 0 to R = 1 */
+ const float Rm5 = (Rm * Rm) * (Rm * Rm) * Rm;
+ const float f = Rm - r;
+ const float num = f * f * f;
+
+ return (10.0f * num) / (Rm5 * M_PI_F);
+ }
+ else {
+ float Rm = radius * (1.0f + sharpness);
+
+ if (r >= Rm)
+ return 0.0f;
+
+ /* custom variation with extra sharpness, to match the previous code */
+ const float y = 1.0f / (1.0f + sharpness);
+ float Rmy, ry, ryinv;
+
+ if (sharpness == 1.0f) {
+ Rmy = sqrtf(Rm);
+ ry = sqrtf(r);
+ ryinv = (ry > 0.0f) ? 1.0f / ry : 0.0f;
+ }
+ else {
+ Rmy = powf(Rm, y);
+ ry = powf(r, y);
+ ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f;
+ }
+
+ const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy;
+ const float f = Rmy - ry;
+ const float num = f * (f * f) * (y * ryinv);
+
+ return (10.0f * num) / (Rmy5 * M_PI_F);
+ }
}
ccl_device float bssrdf_cubic_pdf(const float radius, const float sharpness, float r)
{
- return bssrdf_cubic_eval(radius, sharpness, r);
+ return bssrdf_cubic_eval(radius, sharpness, r);
}
/* solve 10x^2 - 20x^3 + 15x^4 - 4x^5 - xi == 0 */
ccl_device_forceinline float bssrdf_cubic_quintic_root_find(float xi)
{
- /* newton-raphson iteration, usually succeeds in 2-4 iterations, except
- * outside 0.02 ... 0.98 where it can go up to 10, so overall performance
- * should not be too bad */
- const float tolerance = 1e-6f;
- const int max_iteration_count = 10;
- float x = 0.25f;
- int i;
+ /* newton-raphson iteration, usually succeeds in 2-4 iterations, except
+ * outside 0.02 ... 0.98 where it can go up to 10, so overall performance
+ * should not be too bad */
+ const float tolerance = 1e-6f;
+ const int max_iteration_count = 10;
+ float x = 0.25f;
+ int i;
- for(i = 0; i < max_iteration_count; i++) {
- float x2 = x*x;
- float x3 = x2*x;
- float nx = (1.0f - x);
+ for (i = 0; i < max_iteration_count; i++) {
+ float x2 = x * x;
+ float x3 = x2 * x;
+ float nx = (1.0f - x);
- float f = 10.0f*x2 - 20.0f*x3 + 15.0f*x2*x2 - 4.0f*x2*x3 - xi;
- float f_ = 20.0f*(x*nx)*(nx*nx);
+ float f = 10.0f * x2 - 20.0f * x3 + 15.0f * x2 * x2 - 4.0f * x2 * x3 - xi;
+ float f_ = 20.0f * (x * nx) * (nx * nx);
- if(fabsf(f) < tolerance || f_ == 0.0f)
- break;
+ if (fabsf(f) < tolerance || f_ == 0.0f)
+ break;
- x = saturate(x - f/f_);
- }
+ x = saturate(x - f / f_);
+ }
- return x;
+ return x;
}
-ccl_device void bssrdf_cubic_sample(const float radius, const float sharpness, float xi, float *r, float *h)
+ccl_device void bssrdf_cubic_sample(
+ const float radius, const float sharpness, float xi, float *r, float *h)
{
- float Rm = radius;
- float r_ = bssrdf_cubic_quintic_root_find(xi);
+ float Rm = radius;
+ float r_ = bssrdf_cubic_quintic_root_find(xi);
- if(sharpness != 0.0f) {
- r_ = powf(r_, 1.0f + sharpness);
- Rm *= (1.0f + sharpness);
- }
+ if (sharpness != 0.0f) {
+ r_ = powf(r_, 1.0f + sharpness);
+ Rm *= (1.0f + sharpness);
+ }
- r_ *= Rm;
- *r = r_;
+ r_ *= Rm;
+ *r = r_;
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_*r_);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_ * r_);
}
/* Approximate Reflectance Profiles
@@ -188,13 +188,13 @@ ccl_device void bssrdf_cubic_sample(const float radius, const float sharpness, f
* the mean free length, but still not too big so sampling is still
* effective. Might need some further tweaks.
*/
-#define BURLEY_TRUNCATE 16.0f
-#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
+#define BURLEY_TRUNCATE 16.0f
+#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
ccl_device_inline float bssrdf_burley_fitting(float A)
{
- /* Diffuse surface transmission, equation (6). */
- return 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
+ /* Diffuse surface transmission, equation (6). */
+ return 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
}
/* Scale mean free path length so it gives similar looking result
@@ -202,45 +202,44 @@ ccl_device_inline float bssrdf_burley_fitting(float A)
*/
ccl_device_inline float3 bssrdf_burley_compatible_mfp(float3 r)
{
- return 0.25f * M_1_PI_F * r;
+ return 0.25f * M_1_PI_F * r;
}
ccl_device void bssrdf_burley_setup(Bssrdf *bssrdf)
{
- /* Mean free path length. */
- const float3 l = bssrdf_burley_compatible_mfp(bssrdf->radius);
- /* Surface albedo. */
- const float3 A = bssrdf->albedo;
- const float3 s = make_float3(bssrdf_burley_fitting(A.x),
- bssrdf_burley_fitting(A.y),
- bssrdf_burley_fitting(A.z));
-
- bssrdf->radius = l / s;
+ /* Mean free path length. */
+ const float3 l = bssrdf_burley_compatible_mfp(bssrdf->radius);
+ /* Surface albedo. */
+ const float3 A = bssrdf->albedo;
+ const float3 s = make_float3(
+ bssrdf_burley_fitting(A.x), bssrdf_burley_fitting(A.y), bssrdf_burley_fitting(A.z));
+
+ bssrdf->radius = l / s;
}
ccl_device float bssrdf_burley_eval(const float d, float r)
{
- const float Rm = BURLEY_TRUNCATE * d;
-
- if(r >= Rm)
- return 0.0f;
-
- /* Burley refletance profile, equation (3).
- *
- * NOTES:
- * - Surface albedo is already included into sc->weight, no need to
- * multiply by this term here.
- * - This is normalized diffuse model, so the equation is mutliplied
- * by 2*pi, which also matches cdf().
- */
- float exp_r_3_d = expf(-r / (3.0f * d));
- float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
- return (exp_r_d + exp_r_3_d) / (4.0f*d);
+ const float Rm = BURLEY_TRUNCATE * d;
+
+ if (r >= Rm)
+ return 0.0f;
+
+ /* Burley refletance profile, equation (3).
+ *
+ * NOTES:
+ * - Surface albedo is already included into sc->weight, no need to
+ * multiply by this term here.
+ * - This is normalized diffuse model, so the equation is mutliplied
+ * by 2*pi, which also matches cdf().
+ */
+ float exp_r_3_d = expf(-r / (3.0f * d));
+ float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
+ return (exp_r_d + exp_r_3_d) / (4.0f * d);
}
ccl_device float bssrdf_burley_pdf(const float d, float r)
{
- return bssrdf_burley_eval(d, r) * (1.0f/BURLEY_TRUNCATE_CDF);
+ return bssrdf_burley_eval(d, r) * (1.0f / BURLEY_TRUNCATE_CDF);
}
/* Find the radius for desired CDF value.
@@ -249,52 +248,49 @@ ccl_device float bssrdf_burley_pdf(const float d, float r)
*/
ccl_device_forceinline float bssrdf_burley_root_find(float xi)
{
- const float tolerance = 1e-6f;
- const int max_iteration_count = 10;
- /* Do initial guess based on manual curve fitting, this allows us to reduce
- * number of iterations to maximum 4 across the [0..1] range. We keep maximum
- * number of iteration higher just to be sure we didn't miss root in some
- * corner case.
- */
- float r;
- if(xi <= 0.9f) {
- r = expf(xi * xi * 2.4f) - 1.0f;
- }
- else {
- /* TODO(sergey): Some nicer curve fit is possible here. */
- r = 15.0f;
- }
- /* Solve against scaled radius. */
- for(int i = 0; i < max_iteration_count; i++) {
- float exp_r_3 = expf(-r / 3.0f);
- float exp_r = exp_r_3 * exp_r_3 * exp_r_3;
- float f = 1.0f - 0.25f * exp_r - 0.75f * exp_r_3 - xi;
- float f_ = 0.25f * exp_r + 0.25f * exp_r_3;
-
- if(fabsf(f) < tolerance || f_ == 0.0f) {
- break;
- }
-
- r = r - f/f_;
- if(r < 0.0f) {
- r = 0.0f;
- }
- }
- return r;
+ const float tolerance = 1e-6f;
+ const int max_iteration_count = 10;
+ /* Do initial guess based on manual curve fitting, this allows us to reduce
+ * number of iterations to maximum 4 across the [0..1] range. We keep maximum
+ * number of iteration higher just to be sure we didn't miss root in some
+ * corner case.
+ */
+ float r;
+ if (xi <= 0.9f) {
+ r = expf(xi * xi * 2.4f) - 1.0f;
+ }
+ else {
+ /* TODO(sergey): Some nicer curve fit is possible here. */
+ r = 15.0f;
+ }
+ /* Solve against scaled radius. */
+ for (int i = 0; i < max_iteration_count; i++) {
+ float exp_r_3 = expf(-r / 3.0f);
+ float exp_r = exp_r_3 * exp_r_3 * exp_r_3;
+ float f = 1.0f - 0.25f * exp_r - 0.75f * exp_r_3 - xi;
+ float f_ = 0.25f * exp_r + 0.25f * exp_r_3;
+
+ if (fabsf(f) < tolerance || f_ == 0.0f) {
+ break;
+ }
+
+ r = r - f / f_;
+ if (r < 0.0f) {
+ r = 0.0f;
+ }
+ }
+ return r;
}
-ccl_device void bssrdf_burley_sample(const float d,
- float xi,
- float *r,
- float *h)
+ccl_device void bssrdf_burley_sample(const float d, float xi, float *r, float *h)
{
- const float Rm = BURLEY_TRUNCATE * d;
- const float r_ = bssrdf_burley_root_find(xi * BURLEY_TRUNCATE_CDF) * d;
+ const float Rm = BURLEY_TRUNCATE * d;
+ const float r_ = bssrdf_burley_root_find(xi * BURLEY_TRUNCATE_CDF) * d;
- *r = r_;
+ *r = r_;
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_*r_);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_ * r_);
}
/* None BSSRDF falloff
@@ -303,200 +299,195 @@ ccl_device void bssrdf_burley_sample(const float d,
ccl_device float bssrdf_none_eval(const float radius, float r)
{
- const float Rm = radius;
- return (r < Rm)? 1.0f: 0.0f;
+ const float Rm = radius;
+ return (r < Rm) ? 1.0f : 0.0f;
}
ccl_device float bssrdf_none_pdf(const float radius, float r)
{
- /* integrate (2*pi*r)/(pi*Rm*Rm) from 0 to Rm = 1 */
- const float Rm = radius;
- const float area = (M_PI_F*Rm*Rm);
+ /* integrate (2*pi*r)/(pi*Rm*Rm) from 0 to Rm = 1 */
+ const float Rm = radius;
+ const float area = (M_PI_F * Rm * Rm);
- return bssrdf_none_eval(radius, r) / area;
+ return bssrdf_none_eval(radius, r) / area;
}
ccl_device void bssrdf_none_sample(const float radius, float xi, float *r, float *h)
{
- /* xi = integrate (2*pi*r)/(pi*Rm*Rm) = r^2/Rm^2
- * r = sqrt(xi)*Rm */
- const float Rm = radius;
- const float r_ = sqrtf(xi)*Rm;
+ /* xi = integrate (2*pi*r)/(pi*Rm*Rm) = r^2/Rm^2
+ * r = sqrt(xi)*Rm */
+ const float Rm = radius;
+ const float r_ = sqrtf(xi) * Rm;
- *r = r_;
+ *r = r_;
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_*r_);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_ * r_);
}
/* Generic */
ccl_device_inline Bssrdf *bssrdf_alloc(ShaderData *sd, float3 weight)
{
- Bssrdf *bssrdf = (Bssrdf*)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
+ Bssrdf *bssrdf = (Bssrdf *)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
- if(bssrdf == NULL) {
- return NULL;
- }
+ if (bssrdf == NULL) {
+ return NULL;
+ }
- float sample_weight = fabsf(average(weight));
- bssrdf->sample_weight = sample_weight;
- return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? bssrdf : NULL;
+ float sample_weight = fabsf(average(weight));
+ bssrdf->sample_weight = sample_weight;
+ return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? bssrdf : NULL;
}
ccl_device int bssrdf_setup(ShaderData *sd, Bssrdf *bssrdf, ClosureType type)
{
- int flag = 0;
- int bssrdf_channels = 3;
- float3 diffuse_weight = make_float3(0.0f, 0.0f, 0.0f);
-
- /* Verify if the radii are large enough to sample without precision issues. */
- if(bssrdf->radius.x < BSSRDF_MIN_RADIUS) {
- diffuse_weight.x = bssrdf->weight.x;
- bssrdf->weight.x = 0.0f;
- bssrdf->radius.x = 0.0f;
- bssrdf_channels--;
- }
- if(bssrdf->radius.y < BSSRDF_MIN_RADIUS) {
- diffuse_weight.y = bssrdf->weight.y;
- bssrdf->weight.y = 0.0f;
- bssrdf->radius.y = 0.0f;
- bssrdf_channels--;
- }
- if(bssrdf->radius.z < BSSRDF_MIN_RADIUS) {
- diffuse_weight.z = bssrdf->weight.z;
- bssrdf->weight.z = 0.0f;
- bssrdf->radius.z = 0.0f;
- bssrdf_channels--;
- }
-
- if(bssrdf_channels < 3) {
- /* Add diffuse BSDF if any radius too small. */
+ int flag = 0;
+ int bssrdf_channels = 3;
+ float3 diffuse_weight = make_float3(0.0f, 0.0f, 0.0f);
+
+ /* Verify if the radii are large enough to sample without precision issues. */
+ if (bssrdf->radius.x < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.x = bssrdf->weight.x;
+ bssrdf->weight.x = 0.0f;
+ bssrdf->radius.x = 0.0f;
+ bssrdf_channels--;
+ }
+ if (bssrdf->radius.y < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.y = bssrdf->weight.y;
+ bssrdf->weight.y = 0.0f;
+ bssrdf->radius.y = 0.0f;
+ bssrdf_channels--;
+ }
+ if (bssrdf->radius.z < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.z = bssrdf->weight.z;
+ bssrdf->weight.z = 0.0f;
+ bssrdf->radius.z = 0.0f;
+ bssrdf_channels--;
+ }
+
+ if (bssrdf_channels < 3) {
+ /* Add diffuse BSDF if any radius too small. */
#ifdef __PRINCIPLED__
- if(type == CLOSURE_BSSRDF_PRINCIPLED_ID ||
- type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
- {
- float roughness = bssrdf->roughness;
- float3 N = bssrdf->N;
-
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diffuse_weight);
-
- if(bsdf) {
- bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
- bsdf->N = N;
- bsdf->roughness = roughness;
- flag |= bsdf_principled_diffuse_setup(bsdf);
- }
- }
- else
-#endif /* __PRINCIPLED__ */
- {
- DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), diffuse_weight);
-
- if(bsdf) {
- bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
- bsdf->N = bssrdf->N;
- flag |= bsdf_diffuse_setup(bsdf);
- }
- }
- }
-
- /* Setup BSSRDF if radius is large enough. */
- if(bssrdf_channels > 0) {
- bssrdf->type = type;
- bssrdf->channels = bssrdf_channels;
- bssrdf->sample_weight = fabsf(average(bssrdf->weight)) * bssrdf->channels;
- bssrdf->texture_blur = saturate(bssrdf->texture_blur);
- bssrdf->sharpness = saturate(bssrdf->sharpness);
-
- if(type == CLOSURE_BSSRDF_BURLEY_ID ||
- type == CLOSURE_BSSRDF_PRINCIPLED_ID ||
- type == CLOSURE_BSSRDF_RANDOM_WALK_ID ||
- type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
- {
- bssrdf_burley_setup(bssrdf);
- }
-
- flag |= SD_BSSRDF;
- }
- else {
- bssrdf->type = type;
- bssrdf->sample_weight = 0.0f;
- }
-
- return flag;
+ if (type == CLOSURE_BSSRDF_PRINCIPLED_ID || type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) {
+ float roughness = bssrdf->roughness;
+ float3 N = bssrdf->N;
+
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledDiffuseBsdf), diffuse_weight);
+
+ if (bsdf) {
+ bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
+ bsdf->N = N;
+ bsdf->roughness = roughness;
+ flag |= bsdf_principled_diffuse_setup(bsdf);
+ }
+ }
+ else
+#endif /* __PRINCIPLED__ */
+ {
+ DiffuseBsdf *bsdf = (DiffuseBsdf *)bsdf_alloc(sd, sizeof(DiffuseBsdf), diffuse_weight);
+
+ if (bsdf) {
+ bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+ bsdf->N = bssrdf->N;
+ flag |= bsdf_diffuse_setup(bsdf);
+ }
+ }
+ }
+
+ /* Setup BSSRDF if radius is large enough. */
+ if (bssrdf_channels > 0) {
+ bssrdf->type = type;
+ bssrdf->channels = bssrdf_channels;
+ bssrdf->sample_weight = fabsf(average(bssrdf->weight)) * bssrdf->channels;
+ bssrdf->texture_blur = saturate(bssrdf->texture_blur);
+ bssrdf->sharpness = saturate(bssrdf->sharpness);
+
+ if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_PRINCIPLED_ID ||
+ type == CLOSURE_BSSRDF_RANDOM_WALK_ID ||
+ type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) {
+ bssrdf_burley_setup(bssrdf);
+ }
+
+ flag |= SD_BSSRDF;
+ }
+ else {
+ bssrdf->type = type;
+ bssrdf->sample_weight = 0.0f;
+ }
+
+ return flag;
}
ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
- float radius;
-
- /* Sample color channel and reuse random number. Only a subset of channels
- * may be used if their radius was too small to handle as BSSRDF. */
- xi *= bssrdf->channels;
-
- if(xi < 1.0f) {
- radius = (bssrdf->radius.x > 0.0f)? bssrdf->radius.x:
- (bssrdf->radius.y > 0.0f)? bssrdf->radius.y:
- bssrdf->radius.z;
- }
- else if(xi < 2.0f) {
- xi -= 1.0f;
- radius = (bssrdf->radius.x > 0.0f)? bssrdf->radius.y:
- bssrdf->radius.z;
- }
- else {
- xi -= 2.0f;
- radius = bssrdf->radius.z;
- }
-
- /* Sample BSSRDF. */
- if(bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
- bssrdf_cubic_sample(radius, bssrdf->sharpness, xi, r, h);
- }
- else if(bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID){
- bssrdf_gaussian_sample(radius, xi, r, h);
- }
- else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
- bssrdf_burley_sample(radius, xi, r, h);
- }
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
+ float radius;
+
+ /* Sample color channel and reuse random number. Only a subset of channels
+ * may be used if their radius was too small to handle as BSSRDF. */
+ xi *= bssrdf->channels;
+
+ if (xi < 1.0f) {
+ radius = (bssrdf->radius.x > 0.0f) ?
+ bssrdf->radius.x :
+ (bssrdf->radius.y > 0.0f) ? bssrdf->radius.y : bssrdf->radius.z;
+ }
+ else if (xi < 2.0f) {
+ xi -= 1.0f;
+ radius = (bssrdf->radius.x > 0.0f) ? bssrdf->radius.y : bssrdf->radius.z;
+ }
+ else {
+ xi -= 2.0f;
+ radius = bssrdf->radius.z;
+ }
+
+ /* Sample BSSRDF. */
+ if (bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
+ bssrdf_cubic_sample(radius, bssrdf->sharpness, xi, r, h);
+ }
+ else if (bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID) {
+ bssrdf_gaussian_sample(radius, xi, r, h);
+ }
+ else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
+ bssrdf_burley_sample(radius, xi, r, h);
+ }
}
ccl_device float bssrdf_channel_pdf(const Bssrdf *bssrdf, float radius, float r)
{
- if(radius == 0.0f) {
- return 0.0f;
- }
- else if(bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
- return bssrdf_cubic_pdf(radius, bssrdf->sharpness, r);
- }
- else if(bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID) {
- return bssrdf_gaussian_pdf(radius, r);
- }
- else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
- return bssrdf_burley_pdf(radius, r);
- }
+ if (radius == 0.0f) {
+ return 0.0f;
+ }
+ else if (bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
+ return bssrdf_cubic_pdf(radius, bssrdf->sharpness, r);
+ }
+ else if (bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID) {
+ return bssrdf_gaussian_pdf(radius, r);
+ }
+ else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
+ return bssrdf_burley_pdf(radius, r);
+ }
}
ccl_device_forceinline float3 bssrdf_eval(const ShaderClosure *sc, float r)
{
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
- return make_float3(
- bssrdf_channel_pdf(bssrdf, bssrdf->radius.x, r),
- bssrdf_channel_pdf(bssrdf, bssrdf->radius.y, r),
- bssrdf_channel_pdf(bssrdf, bssrdf->radius.z, r));
+ return make_float3(bssrdf_channel_pdf(bssrdf, bssrdf->radius.x, r),
+ bssrdf_channel_pdf(bssrdf, bssrdf->radius.y, r),
+ bssrdf_channel_pdf(bssrdf, bssrdf->radius.z, r));
}
ccl_device_forceinline float bssrdf_pdf(const ShaderClosure *sc, float r)
{
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
- float3 pdf = bssrdf_eval(sc, r);
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
+ float3 pdf = bssrdf_eval(sc, r);
- return (pdf.x + pdf.y + pdf.z) / bssrdf->channels;
+ return (pdf.x + pdf.y + pdf.z) / bssrdf->channels;
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_BSSRDF_H__ */
+#endif /* __KERNEL_BSSRDF_H__ */
diff --git a/intern/cycles/kernel/closure/emissive.h b/intern/cycles/kernel/closure/emissive.h
index a7f4a2a7327..911382e6865 100644
--- a/intern/cycles/kernel/closure/emissive.h
+++ b/intern/cycles/kernel/closure/emissive.h
@@ -36,26 +36,26 @@ CCL_NAMESPACE_BEGIN
ccl_device void background_setup(ShaderData *sd, const float3 weight)
{
- if(sd->flag & SD_EMISSION) {
- sd->closure_emission_background += weight;
- }
- else {
- sd->flag |= SD_EMISSION;
- sd->closure_emission_background = weight;
- }
+ if (sd->flag & SD_EMISSION) {
+ sd->closure_emission_background += weight;
+ }
+ else {
+ sd->flag |= SD_EMISSION;
+ sd->closure_emission_background = weight;
+ }
}
/* EMISSION CLOSURE */
ccl_device void emission_setup(ShaderData *sd, const float3 weight)
{
- if(sd->flag & SD_EMISSION) {
- sd->closure_emission_background += weight;
- }
- else {
- sd->flag |= SD_EMISSION;
- sd->closure_emission_background = weight;
- }
+ if (sd->flag & SD_EMISSION) {
+ sd->closure_emission_background += weight;
+ }
+ else {
+ sd->flag |= SD_EMISSION;
+ sd->closure_emission_background = weight;
+ }
}
/* return the probability distribution function in the direction I,
@@ -63,21 +63,21 @@ ccl_device void emission_setup(ShaderData *sd, const float3 weight)
* the PDF computed by sample(). */
ccl_device float emissive_pdf(const float3 Ng, const float3 I)
{
- float cosNO = fabsf(dot(Ng, I));
- return (cosNO > 0.0f)? 1.0f: 0.0f;
+ float cosNO = fabsf(dot(Ng, I));
+ return (cosNO > 0.0f) ? 1.0f : 0.0f;
}
-ccl_device void emissive_sample(const float3 Ng, float randu, float randv,
- float3 *omega_out, float *pdf)
+ccl_device void emissive_sample(
+ const float3 Ng, float randu, float randv, float3 *omega_out, float *pdf)
{
- /* todo: not implemented and used yet */
+ /* todo: not implemented and used yet */
}
ccl_device float3 emissive_simple_eval(const float3 Ng, const float3 I)
{
- float res = emissive_pdf(Ng, I);
+ float res = emissive_pdf(Ng, I);
- return make_float3(res, res, res);
+ return make_float3(res, res, res);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 872d06c936a..473bc0e8a82 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -23,21 +23,21 @@ CCL_NAMESPACE_BEGIN
ccl_device void volume_extinction_setup(ShaderData *sd, float3 weight)
{
- if(sd->flag & SD_EXTINCTION) {
- sd->closure_transparent_extinction += weight;
- }
- else {
- sd->flag |= SD_EXTINCTION;
- sd->closure_transparent_extinction = weight;
- }
+ if (sd->flag & SD_EXTINCTION) {
+ sd->closure_transparent_extinction += weight;
+ }
+ else {
+ sd->flag |= SD_EXTINCTION;
+ sd->closure_transparent_extinction = weight;
+ }
}
/* HENYEY-GREENSTEIN CLOSURE */
typedef ccl_addr_space struct HenyeyGreensteinVolume {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float g;
+ float g;
} HenyeyGreensteinVolume;
/* Given cosine between rays, return probability density that a photon bounces
@@ -45,119 +45,152 @@ typedef ccl_addr_space struct HenyeyGreensteinVolume {
* uniform sphere. g=0 uniform diffuse-like, g=1 close to sharp single ray. */
ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g)
{
- return ((1.0f - g * g) / safe_powf(1.0f + g * g - 2.0f * g * cos_theta, 1.5f)) * (M_1_PI_F * 0.25f);
+ return ((1.0f - g * g) / safe_powf(1.0f + g * g - 2.0f * g * cos_theta, 1.5f)) *
+ (M_1_PI_F * 0.25f);
};
ccl_device int volume_henyey_greenstein_setup(HenyeyGreensteinVolume *volume)
{
- volume->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ volume->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
- /* clamp anisotropy to avoid delta function */
- volume->g = signf(volume->g) * min(fabsf(volume->g), 1.0f - 1e-3f);
+ /* clamp anisotropy to avoid delta function */
+ volume->g = signf(volume->g) * min(fabsf(volume->g), 1.0f - 1e-3f);
- return SD_SCATTER;
+ return SD_SCATTER;
}
ccl_device bool volume_henyey_greenstein_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const HenyeyGreensteinVolume *volume_a = (const HenyeyGreensteinVolume*)a;
- const HenyeyGreensteinVolume *volume_b = (const HenyeyGreensteinVolume*)b;
+ const HenyeyGreensteinVolume *volume_a = (const HenyeyGreensteinVolume *)a;
+ const HenyeyGreensteinVolume *volume_b = (const HenyeyGreensteinVolume *)b;
- return (volume_a->g == volume_b->g);
+ return (volume_a->g == volume_b->g);
}
-ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
+ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc,
+ const float3 I,
+ float3 omega_in,
+ float *pdf)
{
- const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
- float g = volume->g;
-
- /* note that I points towards the viewer */
- if(fabsf(g) < 1e-3f) {
- *pdf = M_1_PI_F * 0.25f;
- }
- else {
- float cos_theta = dot(-I, omega_in);
- *pdf = single_peaked_henyey_greenstein(cos_theta, g);
- }
-
- return make_float3(*pdf, *pdf, *pdf);
+ const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume *)sc;
+ float g = volume->g;
+
+ /* note that I points towards the viewer */
+ if (fabsf(g) < 1e-3f) {
+ *pdf = M_1_PI_F * 0.25f;
+ }
+ else {
+ float cos_theta = dot(-I, omega_in);
+ *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+ }
+
+ return make_float3(*pdf, *pdf, *pdf);
}
-ccl_device float3 henyey_greenstrein_sample(float3 D, float g, float randu, float randv, float *pdf)
+ccl_device float3
+henyey_greenstrein_sample(float3 D, float g, float randu, float randv, float *pdf)
{
- /* match pdf for small g */
- float cos_theta;
- bool isotropic = fabsf(g) < 1e-3f;
-
- if(isotropic) {
- cos_theta = (1.0f - 2.0f * randu);
- if(pdf) {
- *pdf = M_1_PI_F * 0.25f;
- }
- }
- else {
- float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu);
- cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
- if(pdf) {
- *pdf = single_peaked_henyey_greenstein(cos_theta, g);
- }
- }
-
- float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
- float phi = M_2PI_F * randv;
- float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
-
- float3 T, B;
- make_orthonormals(D, &T, &B);
- dir = dir.x * T + dir.y * B + dir.z * D;
-
- return dir;
+ /* match pdf for small g */
+ float cos_theta;
+ bool isotropic = fabsf(g) < 1e-3f;
+
+ if (isotropic) {
+ cos_theta = (1.0f - 2.0f * randu);
+ if (pdf) {
+ *pdf = M_1_PI_F * 0.25f;
+ }
+ }
+ else {
+ float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu);
+ cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
+ if (pdf) {
+ *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+ }
+ }
+
+ float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
+ float phi = M_2PI_F * randv;
+ float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
+
+ float3 T, B;
+ make_orthonormals(D, &T, &B);
+ dir = dir.x * T + dir.y * B + dir.z * D;
+
+ return dir;
}
-ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
- float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
- float g = volume->g;
+ const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume *)sc;
+ float g = volume->g;
- /* note that I points towards the viewer and so is used negated */
- *omega_in = henyey_greenstrein_sample(-I, g, randu, randv, pdf);
- *eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */
+ /* note that I points towards the viewer and so is used negated */
+ *omega_in = henyey_greenstrein_sample(-I, g, randu, randv, pdf);
+ *eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */
#ifdef __RAY_DIFFERENTIALS__
- /* todo: implement ray differential estimation */
- *domega_in_dx = make_float3(0.0f, 0.0f, 0.0f);
- *domega_in_dy = make_float3(0.0f, 0.0f, 0.0f);
+ /* todo: implement ray differential estimation */
+ *domega_in_dx = make_float3(0.0f, 0.0f, 0.0f);
+ *domega_in_dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return LABEL_VOLUME_SCATTER;
+ return LABEL_VOLUME_SCATTER;
}
/* VOLUME CLOSURE */
-ccl_device float3 volume_phase_eval(const ShaderData *sd, const ShaderClosure *sc, float3 omega_in, float *pdf)
+ccl_device float3 volume_phase_eval(const ShaderData *sd,
+ const ShaderClosure *sc,
+ float3 omega_in,
+ float *pdf)
{
- kernel_assert(sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
+ kernel_assert(sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
- return volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ return volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
}
-ccl_device int volume_phase_sample(const ShaderData *sd, const ShaderClosure *sc, float randu,
- float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
+ccl_device int volume_phase_sample(const ShaderData *sd,
+ const ShaderClosure *sc,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
{
- int label;
-
- switch(sc->type) {
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- default:
- *eval = make_float3(0.0f, 0.0f, 0.0f);
- label = LABEL_NONE;
- break;
- }
-
- return label;
+ int label;
+
+ switch (sc->type) {
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ label = volume_henyey_greenstein_sample(sc,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ default:
+ *eval = make_float3(0.0f, 0.0f, 0.0f);
+ label = LABEL_NONE;
+ break;
+ }
+
+ return label;
}
CCL_NAMESPACE_END