[Bf-blender-cvs] [ceb68e8] master: Cycles: internal code support for anisotropic Beckmann and GGX reflection
Brecht Van Lommel
noreply at git.blender.org
Sat Jun 14 13:55:36 CEST 2014
Commit: ceb68e809edf37ea3fd010692dc3f4367b78cf61
Author: Brecht Van Lommel
Date: Wed Jun 4 00:39:42 2014 +0200
https://developer.blender.org/rBceb68e809edf37ea3fd010692dc3f4367b78cf61
Cycles: internal code support for anisotropic Beckmann and GGX reflection
Based on:
Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs
E. Heitz, Research Report 2014
===================================================================
M intern/cycles/kernel/closure/bsdf_hair.h
M intern/cycles/kernel/closure/bsdf_microfacet.h
M intern/cycles/kernel/kernel_types.h
M intern/cycles/kernel/osl/osl_closures.cpp
M intern/cycles/kernel/osl/osl_shader.cpp
M intern/cycles/kernel/svm/svm_closure.h
===================================================================
diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index 19cdb77..e0b5454 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -63,7 +63,7 @@ ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc)
ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
#ifdef __HAIR__
- float offset = sc->offset;
+ float offset = sc->data2;
float3 Tg = sc->T;
#else
float offset = 0.0f;
@@ -120,7 +120,7 @@ ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, co
ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
#ifdef __HAIR__
- float offset = sc->offset;
+ float offset = sc->data2;
float3 Tg = sc->T;
#else
float offset = 0.0f;
@@ -166,7 +166,7 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc,
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)
{
#ifdef __HAIR__
- float offset = sc->offset;
+ float offset = sc->data2;
float3 Tg = sc->T;
#else
float offset = 0.0f;
@@ -221,7 +221,7 @@ ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, f
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)
{
#ifdef __HAIR__
- float offset = sc->offset;
+ float offset = sc->data2;
float3 Tg = sc->T;
#else
float offset = 0.0f;
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index ea0894e..b9b682c 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -154,18 +154,18 @@ ccl_device float approx_erfinvf_impl(float p, float q)
ccl_device float approx_erfinvf(float z)
{
- float p, q, s;
+ float p, q, s;
- if(z < 0) {
+ if(z < 0) {
p = -z;
q = 1 - p;
s = -1;
- }
- else {
+ }
+ else {
p = z;
q = 1 - z;
s = 1;
- }
+ }
return s * approx_erfinvf_impl(p, q);
}
@@ -340,11 +340,30 @@ ccl_device_inline float3 microfacet_sample_stretched(const float3 omega_i,
/* GGX microfacet with Smith shadow-masking from:
*
* Microfacet Models for Refraction through Rough Surfaces
- * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007 */
+ * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007
+ *
+ * Anisotropic from:
+ *
+ * Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs
+ * E. Heitz, Research Report 2014
+ *
+ * Anisotropy is only supported for reflection currently, but adding it for
+ * tranmission is just a matter of copying code from reflection if needed. */
ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* m_ag */
+ sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+ sc->data1 = sc->data0; /* alpha_y */
+
+ sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
+
+ return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
+}
+
+ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
+{
+ sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+ sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
@@ -353,7 +372,8 @@ ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
{
- sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* m_ag */
+ sc->data0 = clamp(sc->data0, 0.0f, 1.0f); /* alpha_x */
+ sc->data1 = sc->data1; /* alpha_y */
sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
@@ -362,16 +382,18 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
{
- sc->data0 = fmaxf(roughness, sc->data0); /* m_ag */
+ sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
+ sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
}
ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_ag = max(sc->data0, 1e-4f);
+ float alpha_x = sc->data0;
+ float alpha_y = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
- if(m_refractive || m_ag <= 1e-4f)
+ if(m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
return make_float3(0, 0, 0);
float cosNO = dot(N, I);
@@ -380,18 +402,60 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
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;
+ 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, sc->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));
+ }
- /* eq. 20: (F*G*D)/(4*in*on)
- * eq. 33: first we calculate D(m) */
- float alpha2 = m_ag * m_ag;
- float cosThetaM = dot(N, m);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- /* eq. 34: now calculate G1(i,m) and G1(o,m) */
- float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
float G = G1o * G1i;
/* eq. 20 */
@@ -414,12 +478,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_ag = max(sc->data0, 1e-4f);
- float m_eta = sc->data1;
+ float alpha_x = sc->data0;
+ float alpha_y = sc->data1;
+ float m_eta = sc->data2;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
- if(!m_refractive || m_ag <= 1e-4f)
+ if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
return make_float3(0, 0, 0);
float cosNO = dot(N, I);
@@ -434,17 +499,20 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
float cosHO = dot(Ht, I);
float cosHI = dot(Ht, omega_in);
+ float D, G1o, G1i;
+
/* eq. 33: first we calculate D(m) with m=Ht: */
- float alpha2 = m_ag * m_ag;
+ float alpha2 = alpha_x * alpha_y;
float cosThetaM = dot(N, Ht);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
- float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ 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;
/* probability */
@@ -464,27 +532,27 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
ccl_device int bsdf_microfacet_ggx_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)
{
- float m_ag = sc->data0;
+ float alpha_x = sc->data0;
+ float alpha_y = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 N = sc->N;
float cosNO = dot(N, I);
if(cosNO > 0) {
float3 X, Y, Z = N;
- make_orthonormals(Z, &X, &Y);
+
+ if(alpha_x == alpha_y)
+ make_orthonormals(Z, &X, &Y);
+ else
+ make_orthonormals_tangent(Z, sc->T, &X, &Y);
/* importance sampling with distribution of visible normals. vectors are
* transformed to local space before and a
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list