Cycles: add Tangent input for Anisotropic BSDF.

Also refactor SVM BSDF code, preparing it to be shared with OSL.
This commit is contained in:
Brecht Van Lommel 2012-10-17 12:17:17 +00:00
parent 0551aa14bb
commit afb75ad2af
18 changed files with 238 additions and 315 deletions

@ -59,7 +59,7 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
/* return result */
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z;
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
}
}

@ -98,7 +98,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#ifdef __DPDU__
/* dPdu/dPdv */
triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
sd->T = make_float3(0.0f, 0.0f, 0.0f);
#endif
#ifdef __INSTANCING__
@ -123,7 +122,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#ifdef __DPDU__
sd->dPdu = -sd->dPdu;
sd->dPdv = -sd->dPdv;
sd->T = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
@ -223,8 +221,6 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
}
#endif
}
sd->T = make_float3(0.0f, 0.0f, 0.0f);
#endif
/* backfacing test */
@ -310,7 +306,6 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
/* dPdu/dPdv */
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
sd->T = make_float3(0.0f, 0.0f, 0.0f);
#endif
#ifdef __RAY_DIFFERENTIALS__

@ -369,7 +369,9 @@ typedef struct ShaderClosure {
#endif
float data0;
float data1;
float3 N;
float3 T;
} ShaderClosure;
@ -440,9 +442,6 @@ typedef struct ShaderData {
/* differential of P w.r.t. parametric coordinates. note that dPdu is
* not readily suitable as a tangent for shading on triangles. */
float3 dPdu, dPdv;
/* tangent for shading */
float3 T;
#endif
#ifdef __OBJECT_MOTION__

@ -35,11 +35,6 @@
CCL_NAMESPACE_BEGIN
typedef struct BsdfAshikhminVelvetClosure {
//float3 m_N;
float m_invsigma2;
} BsdfAshikhminVelvetClosure;
__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, ShaderClosure *sc, float sigma)
{
sigma = fmaxf(sigma, 0.01f);
@ -55,17 +50,17 @@ __device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_invsigma2 = sc->data0;
float3 m_N = sc->N;
float3 N = sc->N;
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
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(m_N, H);
float cosNH = dot(N, H);
float cosHO = fabsf(dot(I, H));
if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f))
@ -93,32 +88,32 @@ __device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const S
return make_float3(0, 0, 0);
}
__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_ashikhmin_velvet_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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)
{
float m_invsigma2 = sc->data0;
float3 m_N = sc->N;
float3 N = sc->N;
// we are viewing the surface from above - send a ray out with uniform
// distribution over the hemisphere
sample_uniform_hemisphere(m_N, randu, randv, omega_in, pdf);
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
if(dot(sd->Ng, *omega_in) > 0) {
float3 H = normalize(*omega_in + sd->I);
if(dot(Ng, *omega_in) > 0) {
float3 H = normalize(*omega_in + I);
float cosNI = dot(m_N, *omega_in);
float cosNO = dot(m_N, sd->I);
float cosNH = dot(m_N, H);
float cosHO = fabsf(dot(sd->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;
@ -140,8 +135,8 @@ __device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClos
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the retroreflective bounce
*domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx;
*domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy;
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
*domega_in_dx *= 125.0f;
*domega_in_dy *= 125.0f;
#endif

@ -37,10 +37,6 @@ CCL_NAMESPACE_BEGIN
/* DIFFUSE */
typedef struct BsdfDiffuseClosure {
//float3 m_N;
} BsdfDiffuseClosure;
__device void bsdf_diffuse_setup(ShaderData *sd, ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_DIFFUSE_ID;
@ -51,38 +47,38 @@ __device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 m_N = sc->N;
float3 N = sc->N;
float cos_pi = fmaxf(dot(m_N, omega_in), 0.0f) * M_1_PI_F;
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);
}
__device float3 bsdf_diffuse_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float bsdf_diffuse_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_diffuse_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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)
{
float3 m_N = sc->N;
float3 N = sc->N;
// distribution over the hemisphere
sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf);
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
if(dot(sd->Ng, *omega_in) > 0.0f) {
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(m_N, sd->dI.dx)) * m_N - sd->dI.dx;
*domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy;
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
*domega_in_dx *= 125.0f;
*domega_in_dy *= 125.0f;
#endif
@ -95,10 +91,6 @@ __device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc,
/* TRANSLUCENT */
typedef struct BsdfTranslucentClosure {
//float3 m_N;
} BsdfTranslucentClosure;
__device void bsdf_translucent_setup(ShaderData *sd, ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_TRANSLUCENT_ID;
@ -109,38 +101,38 @@ __device void bsdf_translucent_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 m_N = sc->N;
float3 N = sc->N;
float cos_pi = fmaxf(-dot(m_N, omega_in), 0.0f) * M_1_PI_F;
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);
}
__device float bsdf_translucent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_translucent_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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)
{
float3 m_N = sc->N;
float3 N = sc->N;
// we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere
sample_cos_hemisphere (-m_N, randu, randv, omega_in, pdf);
if(dot(sd->Ng, *omega_in) < 0) {
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(m_N, sd->dI.dx)) * m_N - sd->dI.dx;
*domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy;
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
*domega_in_dx *= -125.0f;
*domega_in_dy *= -125.0f;
#endif

@ -37,12 +37,6 @@ CCL_NAMESPACE_BEGIN
/* GGX */
typedef struct BsdfMicrofacetGGXClosure {
//float3 m_N;
float m_ag;
float m_eta;
} BsdfMicrofacetGGXClosure;
__device_inline float safe_sqrtf(float f)
{
return sqrtf(max(f, 0.0f));
@ -71,23 +65,23 @@ __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
sc->data0 = m_ag;
}
__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_ag = sc->data0;
//float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sc->N;
float3 N = sc->N;
if(m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNI > 0 && cosNO > 0) {
// get half vector
float3 Hr = normalize(omega_in + I);
// eq. 20: (F*G*D)/(4*in*on)
// eq. 33: first we calculate D(m) with m=Hr:
float alpha2 = m_ag * m_ag;
float cosThetaM = dot(m_N, Hr);
float cosThetaM = dot(N, Hr);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
@ -108,16 +102,16 @@ __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const Sha
return make_float3 (0, 0, 0);
}
__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_ag = sc->data0;
float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sc->N;
float3 N = sc->N;
if(!m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNO <= 0 || cosNI >= 0)
return make_float3 (0, 0, 0); // vectors on same side -- not possible
// compute half-vector of the refraction (eq. 16)
@ -128,7 +122,7 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const Sh
float cosHI = dot(Ht, omega_in);
// eq. 33: first we calculate D(m) with m=Ht:
float alpha2 = m_ag * m_ag;
float cosThetaM = dot(m_N, Ht);
float cosThetaM = dot(N, Ht);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
@ -144,21 +138,21 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const Sh
return make_float3 (out, out, out);
}
__device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_microfacet_ggx_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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 m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sc->N;
float3 N = sc->N;
float cosNO = dot(m_N, sd->I);
float cosNO = dot(N, I);
if(cosNO > 0) {
float3 X, Y, Z = m_N;
float3 X, Y, Z = N;
make_orthonormals(Z, &X, &Y);
// generate a random microfacet normal m
// eq. 35,36:
@ -173,11 +167,11 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
(sinf(phiM) * sinThetaM) * Y +
cosThetaM * Z;
if(!m_refractive) {
float cosMO = dot(m, sd->I);
float cosMO = dot(m, I);
if(cosMO > 0) {
// eq. 39 - compute actual reflected direction
*omega_in = 2 * cosMO * m - sd->I;
if(dot(sd->Ng, *omega_in) > 0) {
*omega_in = 2 * cosMO * m - I;
if(dot(Ng, *omega_in) > 0) {
// microfacet normal is visible to this ray
// eq. 33
float cosThetaM2 = cosThetaM * cosThetaM;
@ -190,7 +184,7 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
*pdf = pm * 0.25f / cosMO;
// eval BRDF*cosNI
float cosNI = dot(m_N, *omega_in);
float cosNI = dot(N, *omega_in);
// 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)));
@ -199,8 +193,8 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
float out = (G * D) * 0.25f / cosNO;
*eval = make_float3(out, out, out);
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx;
*domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy;
*domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
*domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
// Since there is some blur to this reflection, make the
// derivatives a bit bigger. In theory this varies with the
// roughness but the exact relationship is complex and
@ -219,9 +213,9 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
float3 dRdx, dRdy, dTdx, dTdy;
#endif
bool inside;
fresnel_dielectric(m_eta, m, sd->I, &R, &T,
fresnel_dielectric(m_eta, m, I, &R, &T,
#ifdef __RAY_DIFFERENTIALS__
sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy,
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
#endif
&inside);
@ -238,14 +232,14 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
// eq. 24
float pm = D * cosThetaM;
// eval BRDF*cosNI
float cosNI = dot(m_N, *omega_in);
float cosNI = dot(N, *omega_in);
// 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. 21
float cosHI = dot(m, *omega_in);
float cosHO = dot(m, sd->I);
float cosHO = dot(m, I);
float Ht2 = m_eta * cosHI + cosHO;
Ht2 *= Ht2;
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
@ -268,12 +262,6 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur
/* BECKMANN */
typedef struct BsdfMicrofacetBeckmannClosure {
//float3 m_N;
float m_ab;
float m_eta;
} BsdfMicrofacetBeckmannClosure;
__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive)
{
float m_ab = clamp(ab, 1e-4f, 1.0f);
@ -297,23 +285,23 @@ __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
sc->data0 = m_ab;
}
__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_ab = sc->data0;
//float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sc->N;
float3 N = sc->N;
if(m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNO > 0 && cosNI > 0) {
// get half vector
float3 Hr = normalize(omega_in + I);
// eq. 20: (F*G*D)/(4*in*on)
// eq. 25: first we calculate D(m) with m=Hr:
float alpha2 = m_ab * m_ab;
float cosThetaM = dot(m_N, Hr);
float cosThetaM = dot(N, Hr);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
@ -336,16 +324,16 @@ __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, cons
return make_float3 (0, 0, 0);
}
__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_ab = sc->data0;
float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sc->N;
float3 N = sc->N;
if(!m_refractive) return make_float3 (0, 0, 0);
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNO <= 0 || cosNI >= 0)
return make_float3 (0, 0, 0);
// compute half-vector of the refraction (eq. 16)
@ -356,7 +344,7 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con
float cosHI = dot(Ht, omega_in);
// eq. 33: first we calculate D(m) with m=Ht:
float alpha2 = m_ab * m_ab;
float cosThetaM = dot(m_N, Ht);
float cosThetaM = dot(N, Ht);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
@ -374,21 +362,21 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con
return make_float3 (out, out, out);
}
__device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_microfacet_beckmann_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__device int bsdf_microfacet_beckmann_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_ab = sc->data0;
float m_eta = sc->data1;
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sc->N;
float3 N = sc->N;
float cosNO = dot(m_N, sd->I);
float cosNO = dot(N, I);
if(cosNO > 0) {
float3 X, Y, Z = m_N;
float3 X, Y, Z = N;
make_orthonormals(Z, &X, &Y);
// generate a random microfacet normal m
// eq. 35,36:
@ -404,11 +392,11 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
cosThetaM * Z;
if(!m_refractive) {
float cosMO = dot(m, sd->I);
float cosMO = dot(m, I);
if(cosMO > 0) {
// eq. 39 - compute actual reflected direction
*omega_in = 2 * cosMO * m - sd->I;
if(dot(sd->Ng, *omega_in) > 0) {
*omega_in = 2 * cosMO * m - I;
if(dot(Ng, *omega_in) > 0) {
// microfacet normal is visible to this ray
// eq. 25
float cosThetaM2 = cosThetaM * cosThetaM;
@ -422,7 +410,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
*pdf = pm * 0.25f / cosMO;
// Eval BRDF*cosNI
float cosNI = dot(m_N, *omega_in);
float cosNI = dot(N, *omega_in);
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
@ -433,8 +421,8 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
float out = (G * D) * 0.25f / cosNO;
*eval = make_float3(out, out, out);
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx;
*domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy;
*domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
*domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
// Since there is some blur to this reflection, make the
// derivatives a bit bigger. In theory this varies with the
// roughness but the exact relationship is complex and
@ -453,9 +441,9 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
float3 dRdx, dRdy, dTdx, dTdy;
#endif
bool inside;
fresnel_dielectric(m_eta, m, sd->I, &R, &T,
fresnel_dielectric(m_eta, m, I, &R, &T,
#ifdef __RAY_DIFFERENTIALS__
sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy,
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
#endif
&inside);
@ -474,7 +462,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
// eq. 24
float pm = D * cosThetaM;
// eval BRDF*cosNI
float cosNI = dot(m_N, *omega_in);
float cosNI = dot(N, *omega_in);
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
@ -483,7 +471,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC
float G = G1o * G1i;
// eq. 21
float cosHI = dot(m, *omega_in);
float cosHO = dot(m, sd->I);
float cosHO = dot(m, I);
float Ht2 = m_eta * cosHI + cosHO;
Ht2 *= Ht2;
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);

@ -21,11 +21,6 @@
CCL_NAMESPACE_BEGIN
typedef struct BsdfOrenNayarClosure {
float m_a;
float m_b;
} BsdfOrenNayarClosure;
__device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, float3 v, float3 l)
{
float nl = max(dot(n, l), 0.0f);
@ -55,7 +50,7 @@ __device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
if (dot(sc->N, omega_in) > 0.0f) {
*pdf = 0.5f * M_1_PI_F;
@ -67,27 +62,27 @@ __device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderC
}
}
__device float3 bsdf_oren_nayar_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float bsdf_oren_nayar_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_oren_nayar_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_oren_nayar_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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)
{
sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf);
if (dot(sd->Ng, *omega_in) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, sc->N, sd->I, *omega_in);
if (dot(Ng, *omega_in) > 0.0f) {
*eval = bsdf_oren_nayar_get_intensity(sc, sc->N, I, *omega_in);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the bounce
*domega_in_dx = (2.0f * dot(sc->N, sd->dI.dx)) * sc->N - sd->dI.dx;
*domega_in_dy = (2.0f * dot(sc->N, sd->dI.dy)) * sc->N - sd->dI.dy;
*domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
*domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
*domega_in_dx *= 125.0f;
*domega_in_dy *= 125.0f;
#endif

@ -37,10 +37,6 @@ CCL_NAMESPACE_BEGIN
/* REFLECTION */
typedef struct BsdfReflectionClosure {
//float3 m_N;
} BsdfReflectionClosure;
__device void bsdf_reflection_setup(ShaderData *sd, ShaderClosure *sc)
{
sc->type = CLOSURE_BSDF_REFLECTION_ID;
@ -51,34 +47,34 @@ __device void bsdf_reflection_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_reflection_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float3 bsdf_reflection_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float bsdf_reflection_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_reflection_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_reflection_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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 BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data;
float3 m_N = sc->N;
float3 N = sc->N;
// only one direction is possible
float cosNO = dot(m_N, sd->I);
float cosNO = dot(N, I);
if(cosNO > 0) {
*omega_in = (2 * cosNO) * m_N - sd->I;
if(dot(sd->Ng, *omega_in) > 0) {
*omega_in = (2 * cosNO) * N - I;
if(dot(Ng, *omega_in) > 0) {
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = 2 * dot(m_N, sd->dI.dx) * m_N - sd->dI.dx;
*domega_in_dy = 2 * dot(m_N, sd->dI.dy) * m_N - sd->dI.dy;
*domega_in_dx = 2 * dot(N, dIdx) * N - dIdx;
*domega_in_dy = 2 * dot(N, dIdy) * N - dIdy;
#endif
*pdf = 1;
*eval = make_float3(1, 1, 1);

@ -37,10 +37,6 @@ CCL_NAMESPACE_BEGIN
/* REFRACTION */
typedef struct BsdfRefractionClosure {
float m_eta;
} BsdfRefractionClosure;
__device void bsdf_refraction_setup(ShaderData *sd, ShaderClosure *sc, float eta)
{
sc->data0 = eta;
@ -53,34 +49,34 @@ __device void bsdf_refraction_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_refraction_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float3 bsdf_refraction_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float bsdf_refraction_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_refraction_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_refraction_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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)
{
float m_eta = sc->data0;
float3 m_N = sc->N;
float3 N = sc->N;
float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
float3 dRdx, dRdy, dTdx, dTdy;
#endif
bool inside;
fresnel_dielectric(m_eta, m_N, sd->I, &R, &T,
fresnel_dielectric(m_eta, N, I, &R, &T,
#ifdef __RAY_DIFFERENTIALS__
sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy,
dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
#endif
&inside);

@ -45,28 +45,28 @@ __device void bsdf_transparent_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_transparent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float3 bsdf_transparent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__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);
}
__device float bsdf_transparent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_transparent_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_transparent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__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 = -sd->I;
*omega_in = -I;
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = -sd->dI.dx;
*domega_in_dy = -sd->dI.dy;
*domega_in_dx = -dIdx;
*domega_in_dy = -dIdy;
#endif
*pdf = 1;
*eval = make_float3(1, 1, 1);

@ -37,14 +37,7 @@ CCL_NAMESPACE_BEGIN
/* WARD */
typedef struct BsdfWardClosure {
//float3 m_N;
//float3 m_T;
float m_ax;
float m_ay;
} BsdfWardClosure;
__device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float3 T, float ax, float ay)
__device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float ax, float ay)
{
float m_ax = clamp(ax, 1e-5f, 1.0f);
float m_ay = clamp(ay, 1e-5f, 1.0f);
@ -62,25 +55,25 @@ __device void bsdf_ward_blur(ShaderClosure *sc, float roughness)
sc->data1 = fmaxf(roughness, sc->data1);
}
__device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_ax = sc->data0;
float m_ay = sc->data1;
float3 m_N = sc->N;
float3 m_T = sd->T;
float3 N = sc->N;
float3 T = sc->T;
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNI > 0 && cosNO > 0) {
// get half vector and get x,y basis on the surface for anisotropy
float3 H = normalize(omega_in + I); // normalize needed for pdf
float3 X, Y;
make_orthonormals_tangent(m_N, m_T, &X, &Y);
make_orthonormals_tangent(N, T, &X, &Y);
// eq. 4
float dotx = dot(H, X) / m_ax;
float doty = dot(H, Y) / m_ay;
float dotn = dot(H, m_N);
float dotn = dot(H, N);
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
float denom = (4 * M_PI_F * m_ax * m_ay * sqrtf(cosNO * cosNI));
float exp_val = expf(-exp_arg);
@ -94,28 +87,28 @@ __device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure
return make_float3 (0, 0, 0);
}
__device float3 bsdf_ward_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_ward_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
__device float bsdf_ward_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_ward_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__device int bsdf_ward_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_ax = sc->data0;
float m_ay = sc->data1;
float3 m_N = sc->N;
float3 m_T = sd->T;
float3 N = sc->N;
float3 T = sc->T;
float cosNO = dot(m_N, sd->I);
float cosNO = dot(N, I);
if(cosNO > 0) {
// get x,y basis on the surface for anisotropy
float3 X, Y;
make_orthonormals_tangent(m_N, m_T, &X, &Y);
make_orthonormals_tangent(N, T, &X, &Y);
// generate random angles for the half vector
// eq. 7 (taking care around discontinuities to keep
//ttoutput angle in the right quadrant)
@ -167,12 +160,12 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo
float doty = h.y / m_ay;
float dotn = h.z;
// transform to world space
h = h.x * X + h.y * Y + h.z * m_N;
h = h.x * X + h.y * Y + h.z * N;
// generate the final sample
float oh = dot(h, sd->I);
*omega_in = 2.0f * oh * h - sd->I;
if(dot(sd->Ng, *omega_in) > 0) {
float cosNI = dot(m_N, *omega_in);
float oh = dot(h, I);
*omega_in = 2.0f * oh * h - I;
if(dot(Ng, *omega_in) > 0) {
float cosNI = dot(N, *omega_in);
if(cosNI > 0) {
// eq. 9
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
@ -183,8 +176,8 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo
float power = cosNI * expf(-exp_arg) / denom;
*eval = make_float3(power, power, power);
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx;
*domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy;
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
// Since there is some blur to this reflection, make the
// derivatives a bit bigger. In theory this varies with the
// roughness but the exact relationship is complex and

@ -37,11 +37,6 @@ CCL_NAMESPACE_BEGIN
/* WESTIN BACKSCATTER */
typedef struct BsdfWestinBackscatterClosure {
//float3 m_N;
float m_invroughness;
} BsdfWestinBackscatterClosure;
__device void bsdf_westin_backscatter_setup(ShaderData *sd, ShaderClosure *sc, float roughness)
{
roughness = clamp(roughness, 1e-5f, 1.0f);
@ -59,14 +54,14 @@ __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness)
sc->data0 = m_invroughness;
}
__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_invroughness = sc->data0;
float3 m_N = sc->N;
float3 N = sc->N;
// pdf is implicitly 0 (no indirect sampling)
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNO > 0 && cosNI > 0) {
float cosine = dot(I, omega_in);
*pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0;
@ -76,40 +71,40 @@ __device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const
return make_float3 (0, 0, 0);
}
__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
__device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_westin_backscatter_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__device int bsdf_westin_backscatter_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_invroughness = sc->data0;
float3 m_N = sc->N;
float3 N = sc->N;
float cosNO = dot(m_N, sd->I);
float cosNO = dot(N, I);
if(cosNO > 0) {
#ifdef __RAY_DIFFERENTIALS__
*domega_in_dx = sd->dI.dx;
*domega_in_dy = sd->dI.dy;
*domega_in_dx = dIdx;
*domega_in_dy = dIdy;
#endif
float3 T, B;
make_orthonormals (sd->I, &T, &B);
make_orthonormals (I, &T, &B);
float phi = 2 * M_PI_F * randu;
float cosTheta = powf(randv, 1 / (m_invroughness + 1));
float sinTheta2 = 1 - cosTheta * cosTheta;
float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
*omega_in = (cosf(phi) * sinTheta) * T +
(sinf(phi) * sinTheta) * B +
(cosTheta) * sd->I;
if(dot(sd->Ng, *omega_in) > 0)
(cosTheta) * I;
if(dot(Ng, *omega_in) > 0)
{
// common terms for pdf and eval
float cosNI = dot(m_N, *omega_in);
float cosNI = dot(N, *omega_in);
// make sure the direction we chose is still in the right hemisphere
if(cosNI > 0)
{
@ -132,11 +127,6 @@ __device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderCl
/* WESTIN SHEEN */
typedef struct BsdfWestinSheenClosure {
//float3 m_N;
float m_edginess;
} BsdfWestinSheenClosure;
__device void bsdf_westin_sheen_setup(ShaderData *sd, ShaderClosure *sc, float edginess)
{
sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID;
@ -148,14 +138,14 @@ __device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness)
{
}
__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_westin_sheen_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float m_edginess = sc->data0;
float3 m_N = sc->N;
float3 N = sc->N;
// pdf is implicitly 0 (no indirect sampling)
float cosNO = dot(m_N, I);
float cosNI = dot(m_N, omega_in);
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNO > 0 && cosNI > 0) {
float sinNO2 = 1 - cosNO * cosNO;
*pdf = cosNI * M_1_PI_F;
@ -165,34 +155,34 @@ __device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const Shade
return make_float3 (0, 0, 0);
}
__device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
__device float3 bsdf_westin_sheen_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
__device float bsdf_westin_sheen_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
__device float bsdf_westin_sheen_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
__device int bsdf_westin_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)
{
float m_edginess = sc->data0;
float3 m_N = sc->N;
float3 N = sc->N;
// we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere
sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf);
if(dot(sd->Ng, *omega_in) > 0) {
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0) {
// TODO: account for sheen when sampling
float cosNO = dot(m_N, sd->I);
float cosNO = dot(N, I);
float sinNO2 = 1 - cosNO * cosNO;
float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0;
*eval = make_float3(westin, westin, westin);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the diffuse bounce
*domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx;
*domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy;
*domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
*domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
*domega_in_dx *= 125.0f;
*domega_in_dy *= 125.0f;
#endif

@ -205,14 +205,6 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_CLOSURE_WEIGHT:
svm_node_closure_weight(sd, stack, node.y);
break;
#ifdef __DPDU__
case NODE_CLOSURE_SET_TANGENT:
svm_node_closure_set_tangent(sd, node.y, node.z, node.w);
break;
case NODE_CLOSURE_TANGENT:
svm_node_closure_tangent(sd, stack, node.y);
break;
#endif
case NODE_EMISSION_WEIGHT:
svm_node_emission_weight(kg, sd, stack, node);
break;

@ -36,45 +36,57 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
label = bsdf_diffuse_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
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(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
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;
case CLOSURE_BSDF_TRANSLUCENT_ID:
label = bsdf_translucent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
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(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
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(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
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(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
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_REFRACTION_ID:
label = bsdf_microfacet_ggx_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
label = bsdf_microfacet_ggx_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_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
label = bsdf_microfacet_beckmann_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
label = bsdf_microfacet_beckmann_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 __DPDU__
case CLOSURE_BSDF_WARD_ID:
label = bsdf_ward_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
label = bsdf_ward_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_ASHIKHMIN_VELVET_ID:
label = bsdf_ashikhmin_velvet_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
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_WESTIN_BACKSCATTER_ID:
label = bsdf_westin_backscatter_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
label = bsdf_westin_backscatter_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_WESTIN_SHEEN_ID:
label = bsdf_westin_sheen_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
label = bsdf_westin_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
default:
@ -92,45 +104,45 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
if(dot(sd->Ng, omega_in) >= 0.0f) {
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf);
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(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
eval = bsdf_reflection_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
eval = bsdf_refraction_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
eval = bsdf_transparent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID:
eval = bsdf_ward_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
eval = bsdf_westin_backscatter_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#endif
default:
@ -141,45 +153,45 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
else {
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf);
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(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
eval = bsdf_reflection_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
eval = bsdf_refraction_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
eval = bsdf_transparent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
eval = bsdf_microfacet_beckmann_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID:
eval = bsdf_ward_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
eval = bsdf_ashikhmin_velvet_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
eval = bsdf_westin_backscatter_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf);
eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#endif
default:

@ -190,12 +190,13 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
#endif
ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
sc->T = stack_load_float3(stack, data_node.z);
svm_node_closure_set_mix_weight(sc, mix_weight);
float roughness_u = param1;
float roughness_v = param2;
bsdf_ward_setup(sd, sc, sd->T, roughness_u, roughness_v);
bsdf_ward_setup(sd, sc, roughness_u, roughness_v);
break;
}
#endif
@ -442,27 +443,6 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
#endif
}
/* Tangent */
#ifdef __DPDU__
__device_inline void svm_node_closure_store_tangent(ShaderData *sd, float3 tangent)
{
sd->T = normalize(tangent);
}
__device void svm_node_closure_set_tangent(ShaderData *sd, uint x, uint y, uint z)
{
float3 tangent = make_float3(__int_as_float(x), __int_as_float(y), __int_as_float(z));
svm_node_closure_store_tangent(sd, tangent);
}
__device void svm_node_closure_tangent(ShaderData *sd, float *stack, uint tangent_offset)
{
float3 tangent = stack_load_float3(stack, tangent_offset);
svm_node_closure_store_tangent(sd, tangent);
}
#endif
/* (Bump) normal */
__device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)

@ -93,8 +93,6 @@ typedef enum NodeType {
NODE_OBJECT_INFO,
NODE_PARTICLE_INFO,
NODE_TEX_BRICK,
NODE_CLOSURE_SET_TANGENT,
NODE_CLOSURE_TANGENT,
NODE_CLOSURE_SET_NORMAL,
} NodeType;

@ -1184,6 +1184,7 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
{
ShaderInput *color_in = input("Color");
ShaderInput *normal_in = input("Normal");
ShaderInput *tangent_in = input("Tangent");
if(color_in->link) {
compiler.stack_assign(color_in);
@ -1207,7 +1208,16 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
if(normal_in->link)
compiler.stack_assign(normal_in);
compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset);
if(tangent_in) {
if(tangent_in->link)
compiler.stack_assign(tangent_in);
compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, tangent_in->stack_offset);
}
else {
compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset);
}
}
void BsdfNode::compile(SVMCompiler& compiler)
@ -1246,15 +1256,6 @@ void WardBsdfNode::compile(SVMCompiler& compiler)
{
ShaderInput *tangent_in = input("Tangent");
if(tangent_in->link) {
int attr = compiler.attribute(ATTR_STD_TANGENT);
compiler.stack_assign(tangent_in);
compiler.add_node(NODE_ATTR, attr, tangent_in->stack_offset, NODE_ATTR_FLOAT3);
compiler.add_node(NODE_CLOSURE_TANGENT, tangent_in->stack_offset);
}
else
compiler.add_node(NODE_CLOSURE_SET_TANGENT, tangent_in->value);
BsdfNode::compile(compiler, input("Roughness U"), input("Roughness V"));
}

@ -33,7 +33,8 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[]= {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness U"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness V"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_VECTOR, 1, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};