Cycles OSL: most closure code is now shared between OSL and SVM. Also fix

transmission pass and filter glossy option.

The BSDF closure class is now more similar to the SVM closures, and includes
some flags and labels that are needed to properly categorize the BSDF's for
render passes. Phong closure is gone for the moment, needs to be adapated to
the new structure still.
This commit is contained in:
Brecht Van Lommel
2012-10-20 12:18:00 +00:00
parent 3abef3a2e6
commit 9a1c1f132d
38 changed files with 443 additions and 2899 deletions

View File

@@ -46,17 +46,17 @@ set(SRC_HEADERS
) )
set(SRC_SVM_HEADERS set(SRC_SVM_HEADERS
svm/bsdf.h closure/bsdf.h
svm/bsdf_ashikhmin_velvet.h closure/bsdf_ashikhmin_velvet.h
svm/bsdf_diffuse.h closure/bsdf_microfacet.h
svm/bsdf_oren_nayar.h closure/bsdf_reflection.h
svm/bsdf_microfacet.h closure/bsdf_refraction.h
svm/bsdf_reflection.h closure/bsdf_transparent.h
svm/bsdf_refraction.h closure/bsdf_ward.h
svm/bsdf_transparent.h closure/bsdf_westin.h
svm/bsdf_ward.h closure/emissive.h
svm/bsdf_westin.h closure/volume.h
svm/emissive.h
svm/svm.h svm/svm.h
svm/svm_attribute.h svm/svm_attribute.h
svm/svm_bsdf.h svm/svm_bsdf.h
@@ -92,7 +92,6 @@ set(SRC_SVM_HEADERS
svm/svm_value.h svm/svm_value.h
svm/svm_voronoi.h svm/svm_voronoi.h
svm/svm_wave.h svm/svm_wave.h
svm/volume.h
) )
set(SRC_UTIL_HEADERS set(SRC_UTIL_HEADERS

View File

@@ -35,15 +35,17 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, ShaderClosure *sc, float sigma) __device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc)
{ {
float sigma = sc->data0;
sigma = fmaxf(sigma, 0.01f); sigma = fmaxf(sigma, 0.01f);
float m_invsigma2 = 1.0f/(sigma * sigma); float m_invsigma2 = 1.0f/(sigma * sigma);
sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID; sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
sc->data0 = m_invsigma2; sc->data0 = m_invsigma2;
return SD_BSDF|SD_BSDF_HAS_EVAL;
} }
__device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness) __device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness)
@@ -93,11 +95,6 @@ __device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, con
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_ashikhmin_velvet_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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; float m_invsigma2 = sc->data0;

View File

@@ -37,10 +37,10 @@ CCL_NAMESPACE_BEGIN
/* DIFFUSE */ /* DIFFUSE */
__device void bsdf_diffuse_setup(ShaderData *sd, ShaderClosure *sc) __device int bsdf_diffuse_setup(ShaderClosure *sc)
{ {
sc->type = CLOSURE_BSDF_DIFFUSE_ID; sc->type = CLOSURE_BSDF_DIFFUSE_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; return SD_BSDF|SD_BSDF_HAS_EVAL;
} }
__device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness) __device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness)
@@ -61,11 +61,6 @@ __device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc, const float3
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_diffuse_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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 N = sc->N; float3 N = sc->N;
@@ -91,10 +86,10 @@ __device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, f
/* TRANSLUCENT */ /* TRANSLUCENT */
__device void bsdf_translucent_setup(ShaderData *sd, ShaderClosure *sc) __device int bsdf_translucent_setup(ShaderClosure *sc)
{ {
sc->type = CLOSURE_BSDF_TRANSLUCENT_ID; sc->type = CLOSURE_BSDF_TRANSLUCENT_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; return SD_BSDF|SD_BSDF_HAS_EVAL;
} }
__device void bsdf_translucent_blur(ShaderClosure *sc, float roughness) __device void bsdf_translucent_blur(ShaderClosure *sc, float roughness)

View File

@@ -42,20 +42,34 @@ __device_inline float safe_sqrtf(float f)
return sqrtf(max(f, 0.0f)); return sqrtf(max(f, 0.0f));
} }
__device void bsdf_microfacet_ggx_setup(ShaderData *sd, ShaderClosure *sc, float ag, float eta, bool refractive) __device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
{ {
float ag = sc->data0;
float eta = sc->data1;
float m_ag = clamp(ag, 1e-4f, 1.0f); float m_ag = clamp(ag, 1e-4f, 1.0f);
float m_eta = eta; float m_eta = eta;
sc->data0 = m_ag; sc->data0 = m_ag;
sc->data1 = m_eta; sc->data1 = m_eta;
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
if(refractive) return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; }
else
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; __device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
{
float ag = sc->data0;
float eta = sc->data1;
float m_ag = clamp(ag, 1e-4f, 1.0f);
float m_eta = eta;
sc->data0 = m_ag;
sc->data1 = m_eta;
sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
} }
__device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness) __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
@@ -138,11 +152,6 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const
return make_float3 (out, out, out); return make_float3 (out, out, out);
} }
__device float bsdf_microfacet_ggx_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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_ag = sc->data0;
@@ -262,20 +271,32 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa
/* BECKMANN */ /* BECKMANN */
__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive) __device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc)
{ {
float ab = sc->data0;
float eta = sc->data1;
float m_ab = clamp(ab, 1e-4f, 1.0f); float m_ab = clamp(ab, 1e-4f, 1.0f);
float m_eta = eta; float m_eta = eta;
sc->data0 = m_ab; sc->data0 = m_ab;
sc->data1 = m_eta; sc->data1 = m_eta;
if(refractive) sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
else }
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; __device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc)
{
float ab = sc->data0;
float eta = sc->data1;
float m_ab = clamp(ab, 1e-4f, 1.0f);
float m_eta = eta;
sc->data0 = m_ab;
sc->data1 = m_eta;
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
} }
__device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness) __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
@@ -362,11 +383,6 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc,
return make_float3 (out, out, out); return make_float3 (out, out, out);
} }
__device float bsdf_microfacet_beckmann_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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_ab = sc->data0;

View File

@@ -33,10 +33,11 @@ __device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n,
return make_float3(is, is, is); return make_float3(is, is, is);
} }
__device void bsdf_oren_nayar_setup(ShaderData *sd, ShaderClosure *sc, float sigma) __device int bsdf_oren_nayar_setup(ShaderClosure *sc)
{ {
float sigma = sc->data0;
sc->type = CLOSURE_BSDF_OREN_NAYAR_ID; sc->type = CLOSURE_BSDF_OREN_NAYAR_ID;
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL;
sigma = clamp(sigma, 0.0f, 1.0f); sigma = clamp(sigma, 0.0f, 1.0f);
@@ -44,6 +45,8 @@ __device void bsdf_oren_nayar_setup(ShaderData *sd, ShaderClosure *sc, float sig
sc->data0 = 1.0f * div; sc->data0 = 1.0f * div;
sc->data1 = sigma * div; sc->data1 = sigma * div;
return SD_BSDF | SD_BSDF_HAS_EVAL;
} }
__device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness) __device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness)
@@ -67,11 +70,6 @@ __device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc, const flo
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_oren_nayar_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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); sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf);

View File

@@ -37,10 +37,10 @@ CCL_NAMESPACE_BEGIN
/* REFLECTION */ /* REFLECTION */
__device void bsdf_reflection_setup(ShaderData *sd, ShaderClosure *sc) __device int bsdf_reflection_setup(ShaderClosure *sc)
{ {
sc->type = CLOSURE_BSDF_REFLECTION_ID; sc->type = CLOSURE_BSDF_REFLECTION_ID;
sd->flag |= SD_BSDF; return SD_BSDF;
} }
__device void bsdf_reflection_blur(ShaderClosure *sc, float roughness) __device void bsdf_reflection_blur(ShaderClosure *sc, float roughness)
@@ -57,11 +57,6 @@ __device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc, const flo
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_reflection_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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; //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data;

View File

@@ -37,12 +37,10 @@ CCL_NAMESPACE_BEGIN
/* REFRACTION */ /* REFRACTION */
__device void bsdf_refraction_setup(ShaderData *sd, ShaderClosure *sc, float eta) __device int bsdf_refraction_setup(ShaderClosure *sc)
{ {
sc->data0 = eta;
sc->type = CLOSURE_BSDF_REFRACTION_ID; sc->type = CLOSURE_BSDF_REFRACTION_ID;
sd->flag |= SD_BSDF; return SD_BSDF;
} }
__device void bsdf_refraction_blur(ShaderClosure *sc, float roughness) __device void bsdf_refraction_blur(ShaderClosure *sc, float roughness)
@@ -59,11 +57,6 @@ __device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc, const flo
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_refraction_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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; float m_eta = sc->data0;

View File

@@ -35,10 +35,10 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
__device void bsdf_transparent_setup(ShaderData *sd, ShaderClosure *sc) __device int bsdf_transparent_setup(ShaderClosure *sc)
{ {
sc->type = CLOSURE_BSDF_TRANSPARENT_ID; sc->type = CLOSURE_BSDF_TRANSPARENT_ID;
sd->flag |= SD_BSDF; return SD_BSDF;
} }
__device void bsdf_transparent_blur(ShaderClosure *sc, float roughness) __device void bsdf_transparent_blur(ShaderClosure *sc, float roughness)
@@ -55,11 +55,6 @@ __device float3 bsdf_transparent_eval_transmit(const ShaderClosure *sc, const fl
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_transparent_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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 // only one direction is possible

View File

@@ -37,8 +37,11 @@ CCL_NAMESPACE_BEGIN
/* WARD */ /* WARD */
__device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float ax, float ay) __device int bsdf_ward_setup(ShaderClosure *sc)
{ {
float ax = sc->data0;
float ay = sc->data1;
float m_ax = clamp(ax, 1e-4f, 1.0f); float m_ax = clamp(ax, 1e-4f, 1.0f);
float m_ay = clamp(ay, 1e-4f, 1.0f); float m_ay = clamp(ay, 1e-4f, 1.0f);
@@ -46,7 +49,7 @@ __device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float ax, float
sc->data1 = m_ay; sc->data1 = m_ay;
sc->type = CLOSURE_BSDF_WARD_ID; sc->type = CLOSURE_BSDF_WARD_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
} }
__device void bsdf_ward_blur(ShaderClosure *sc, float roughness) __device void bsdf_ward_blur(ShaderClosure *sc, float roughness)
@@ -92,11 +95,6 @@ __device float3 bsdf_ward_eval_transmit(const ShaderClosure *sc, const float3 I,
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_ward_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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_ax = sc->data0;

View File

@@ -37,14 +37,16 @@ CCL_NAMESPACE_BEGIN
/* WESTIN BACKSCATTER */ /* WESTIN BACKSCATTER */
__device void bsdf_westin_backscatter_setup(ShaderData *sd, ShaderClosure *sc, float roughness) __device int bsdf_westin_backscatter_setup(ShaderClosure *sc)
{ {
float roughness = sc->data0;
roughness = clamp(roughness, 1e-5f, 1.0f); roughness = clamp(roughness, 1e-5f, 1.0f);
float m_invroughness = 1.0f/roughness; float m_invroughness = 1.0f/roughness;
sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID; sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sc->data0 = m_invroughness; sc->data0 = m_invroughness;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
} }
__device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness) __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness)
@@ -76,11 +78,6 @@ __device float3 bsdf_westin_backscatter_eval_transmit(const ShaderClosure *sc, c
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_westin_backscatter_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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; float m_invroughness = sc->data0;
@@ -127,11 +124,12 @@ __device int bsdf_westin_backscatter_sample(const ShaderClosure *sc, float3 Ng,
/* WESTIN SHEEN */ /* WESTIN SHEEN */
__device void bsdf_westin_sheen_setup(ShaderData *sd, ShaderClosure *sc, float edginess) __device int bsdf_westin_sheen_setup(ShaderClosure *sc)
{ {
float edginess = sc->data0;
sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID; sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
sc->data0 = edginess; sc->data0 = edginess;
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
} }
__device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness) __device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness)
@@ -160,11 +158,6 @@ __device float3 bsdf_westin_sheen_eval_transmit(const ShaderClosure *sc, const f
return make_float3(0.0f, 0.0f, 0.0f); return make_float3(0.0f, 0.0f, 0.0f);
} }
__device float bsdf_westin_sheen_albedo(const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
__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) __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; float m_edginess = sc->data0;

View File

@@ -34,15 +34,21 @@ CCL_NAMESPACE_BEGIN
/* EMISSION CLOSURE */ /* EMISSION CLOSURE */
/// Return the probability distribution function in the direction I, /* return the probability distribution function in the direction I,
/// given the parameters and the light's surface normal. This MUST match * given the parameters and the light's surface normal. This MUST match
/// the PDF computed by sample(). * the PDF computed by sample(). */
__device float emissive_pdf(const float3 Ng, const float3 I) __device float emissive_pdf(const float3 Ng, const float3 I)
{ {
float cosNO = fabsf(dot(Ng, I)); float cosNO = fabsf(dot(Ng, I));
return (cosNO > 0.0f)? 1.0f: 0.0f; return (cosNO > 0.0f)? 1.0f: 0.0f;
} }
__device void emissive_sample(const float3 Ng, float randu, float randv,
float3 *omega_out, float *pdf)
{
/* todo: not implemented and used yet */
}
__device float3 emissive_eval(const float3 Ng, const float3 I) __device float3 emissive_eval(const float3 Ng, const float3 I)
{ {
float res = emissive_pdf(Ng, I); float res = emissive_pdf(Ng, I);

View File

@@ -23,44 +23,46 @@ CCL_NAMESPACE_BEGIN
/* ISOTROPIC VOLUME CLOSURE */ /* ISOTROPIC VOLUME CLOSURE */
__device void volume_isotropic_setup(ShaderData *sd, ShaderClosure *sc, float density) __device int volume_isotropic_setup(ShaderClosure *sc, float density)
{ {
sc->type = CLOSURE_VOLUME_ISOTROPIC_ID; sc->type = CLOSURE_VOLUME_ISOTROPIC_ID;
sd->flag |= SD_VOLUME;
sc->data0 = density; sc->data0 = density;
return SD_VOLUME;
} }
__device float3 volume_isotropic_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) __device float3 volume_isotropic_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{ {
return make_float3(1.0f, 1.0f, 1.0f); return make_float3(1.0f, 1.0f, 1.0f);
} }
/* TRANSPARENT VOLUME CLOSURE */ /* TRANSPARENT VOLUME CLOSURE */
__device void volume_transparent_setup(ShaderData *sd, ShaderClosure *sc, float density) __device int volume_transparent_setup(ShaderClosure *sc, float density)
{ {
sc->type = CLOSURE_VOLUME_TRANSPARENT_ID; sc->type = CLOSURE_VOLUME_TRANSPARENT_ID;
sd->flag |= SD_VOLUME;
sc->data0 = density; sc->data0 = density;
return SD_VOLUME;
} }
__device float3 volume_transparent_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) __device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{ {
return make_float3(1.0f, 1.0f, 1.0f); return make_float3(1.0f, 1.0f, 1.0f);
} }
/* VOLUME CLOSURE */ /* VOLUME CLOSURE */
__device float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) __device float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{ {
float3 eval; float3 eval;
switch(sc->type) { switch(sc->type) {
case CLOSURE_VOLUME_ISOTROPIC_ID: case CLOSURE_VOLUME_ISOTROPIC_ID:
eval = volume_isotropic_eval_phase(sd, sc, omega_in, omega_out); eval = volume_isotropic_eval_phase(sc, omega_in, omega_out);
break; break;
case CLOSURE_VOLUME_TRANSPARENT_ID: case CLOSURE_VOLUME_TRANSPARENT_ID:
eval = volume_transparent_eval_phase(sd, sc, omega_in, omega_out); eval = volume_transparent_eval_phase(sc, omega_in, omega_out);
break; break;
default: default:
eval = make_float3(0.0f, 0.0f, 0.0f); eval = make_float3(0.0f, 0.0f, 0.0f);

View File

@@ -27,18 +27,16 @@
*/ */
#ifdef __OSL__ #ifdef __OSL__
#include "osl_shader.h" #include "osl_shader.h"
#endif #endif
#include "svm/bsdf.h" #include "closure/bsdf.h"
#include "svm/emissive.h" #include "closure/emissive.h"
#include "svm/volume.h" #include "closure/volume.h"
#include "svm/svm_bsdf.h" #include "svm/svm_bsdf.h"
#include "svm/svm.h" #include "svm/svm.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
/* ShaderData setup from incoming ray */ /* ShaderData setup from incoming ray */
@@ -499,18 +497,22 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd,
__device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness) __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
{ {
#ifndef __OSL__
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__
for(int i = 0; i< sd->num_closure; i++) { for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i]; ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF(sc->type)) if(CLOSURE_IS_BSDF(sc->type)) {
svm_bsdf_blur(sc, roughness); #ifdef __OSL__
if (kernel_osl_use(kg))
OSLShader::bsdf_blur(sc, roughness);
else
#endif
svm_bsdf_blur(sc, roughness);
}
} }
#else #else
svm_bsdf_blur(&sd->closure, roughness); svm_bsdf_blur(&sd->closure, roughness);
#endif #endif
#endif
} }
__device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd) __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
@@ -720,16 +722,16 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
if(CLOSURE_IS_VOLUME(sc->type)) { if(CLOSURE_IS_VOLUME(sc->type)) {
#ifdef __OSL__ #ifdef __OSL__
if (kernel_osl_use(kg)) if (kernel_osl_use(kg))
eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out); eval += OSLShader::volume_eval_phase(sc, omega_in, omega_out);
else else
#endif #endif
eval += volume_eval_phase(sd, sc, omega_in, omega_out); eval += volume_eval_phase(sc, omega_in, omega_out);
} }
} }
return eval; return eval;
#else #else
return volume_eval_phase(sd, &sd->closure, omega_in, omega_out); return volume_eval_phase(&sd->closure, omega_in, omega_out);
#endif #endif
} }

View File

@@ -14,23 +14,10 @@ set(INC_SYS
set(SRC set(SRC
background.cpp background.cpp
bsdf_ashikhmin_velvet.cpp
bsdf_diffuse.cpp
bsdf_oren_nayar.cpp
bsdf_phong.cpp
bsdf_microfacet.cpp
bsdf_reflection.cpp
bsdf_refraction.cpp
bsdf_transparent.cpp
bsdf_ward.cpp
bsdf_westin.cpp
bssrdf.cpp
debug.cpp
emissive.cpp emissive.cpp
osl_closures.cpp osl_closures.cpp
osl_services.cpp osl_services.cpp
osl_shader.cpp osl_shader.cpp
vol_subsurface.cpp
) )
set(HEADER_SRC set(HEADER_SRC

View File

@@ -46,23 +46,16 @@ using namespace OSL;
/// to return a color in background shaders. No methods, /// to return a color in background shaders. No methods,
/// only the weight is taking into account /// only the weight is taking into account
/// ///
class GenericBackgroundClosure : public BackgroundClosure { class GenericBackgroundClosure : public OSL::BackgroundClosure {
public: public:
GenericBackgroundClosure() {} GenericBackgroundClosure() {}
void setup() {}; void setup() {};
size_t memsize() const { return sizeof(*this); } size_t memsize() const { return sizeof(*this); }
const char *name() const { return "background"; } const char *name() const { return "background"; }
void print_on(std::ostream &out) const { out << name() << " ()"; }
void print_on(std::ostream &out) const {
out << name() << " ()";
}
}; };
/// Holdout closure /// Holdout closure
/// ///
/// This will be used by the shader to mark the /// This will be used by the shader to mark the
@@ -75,17 +68,11 @@ public:
HoldoutClosure () : ClosurePrimitive(Holdout) {} HoldoutClosure () : ClosurePrimitive(Holdout) {}
void setup() {}; void setup() {};
size_t memsize() const { return sizeof(*this); } size_t memsize() const { return sizeof(*this); }
const char *name() const { return "holdout"; } const char *name() const { return "holdout"; }
void print_on(std::ostream &out) const { out << name() << " ()"; }
void print_on(std::ostream &out) const {
out << name() << " ()";
}
}; };
ClosureParam *closure_background_params() ClosureParam *closure_background_params()
{ {
static ClosureParam params[] = { static ClosureParam params[] = {

View File

@@ -1,190 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "util_math.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class AshikhminVelvetClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_sigma;
float m_invsigma2;
AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup()
{
m_sigma = max(m_sigma, 0.01f);
m_invsigma2 = 1.0f / (m_sigma * m_sigma);
}
bool mergeable(const ClosurePrimitive *other) const {
const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other;
return m_N == comp->m_N && m_sigma == comp->m_sigma &&
BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "ashikhmin_velvet"; }
void print_on(std::ostream &out) const
{
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_sigma;
out << ")";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNO > 0 && cosNI > 0) {
Vec3 H = omega_in + omega_out;
H.normalize();
float cosNH = m_N.dot(H);
float cosHO = fabsf(omega_out.dot(H));
if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f))
return Color3(0, 0, 0);
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = max(cosNHdivHO, 1e-5f);
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 D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
float out = 0.25f * (D * G) / cosNO;
pdf = 0.5f * (float) M_1_PI;
return Color3(out, out, out);
}
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
// we are viewing the surface from above - send a ray out with uniform
// distribution over the hemisphere
sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
if (Ng.dot(omega_in) > 0) {
Vec3 H = omega_in + omega_out;
H.normalize();
float cosNI = m_N.dot(omega_in);
float cosNO = m_N.dot(omega_out);
float cosNH = m_N.dot(H);
float cosHO = fabsf(omega_out.dot(H));
if(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f) {
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = max(cosNHdivHO, 1e-5f);
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 D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
float power = 0.25f * (D * G) / cosNO;
eval.setValue(power, power, power);
// TODO: find a better approximation for the retroreflective bounce
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
domega_in_dx *= 125;
domega_in_dy *= 125;
}
else
pdf = 0;
}
else
pdf = 0;
return Labels::REFLECT;
}
};
ClosureParam *bsdf_ashikhmin_velvet_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N),
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, m_sigma),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(AshikhminVelvetClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure)
CCL_NAMESPACE_END

View File

@@ -1,195 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "util_math.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class DiffuseClosure : public BSDFClosure {
public:
Vec3 m_N;
DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup() {};
bool mergeable(const ClosurePrimitive *other) const {
const DiffuseClosure *comp = (const DiffuseClosure *)other;
return m_N == comp->m_N && BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "diffuse"; }
void print_on(std::ostream &out) const
{
out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
float cos_pi = max(m_N.dot(omega_in), 0.0f) * (float) M_1_PI;
pdf = cos_pi;
return Color3(cos_pi, cos_pi, cos_pi);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
// we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere
sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
if (Ng.dot(omega_in) > 0) {
eval.setValue(pdf, pdf, pdf);
// TODO: find a better approximation for the diffuse bounce
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
domega_in_dx *= 125;
domega_in_dy *= 125;
}
else
pdf = 0;
return Labels::REFLECT;
}
};
class TranslucentClosure : public BSDFClosure {
public:
Vec3 m_N;
TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) {}
void setup() {};
bool mergeable(const ClosurePrimitive *other) const {
const TranslucentClosure *comp = (const TranslucentClosure *)other;
return m_N == comp->m_N && BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "translucent"; }
void print_on(std::ostream &out) const
{
out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
float cos_pi = max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI;
pdf = cos_pi;
return Color3(cos_pi, cos_pi, cos_pi);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
// we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere
sample_cos_hemisphere(-m_N, omega_out, randu, randv, omega_in, pdf);
if (Ng.dot(omega_in) < 0) {
eval.setValue(pdf, pdf, pdf);
// TODO: find a better approximation for the diffuse bounce
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
domega_in_dx *= -125;
domega_in_dy *= -125;
}
else
pdf = 0;
return Labels::TRANSMIT;
}
};
ClosureParam *bsdf_diffuse_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(DiffuseClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(DiffuseClosure)
};
return params;
}
ClosureParam *bsdf_translucent_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(TranslucentClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(TranslucentClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure)
CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure)
CCL_NAMESPACE_END

View File

@@ -1,558 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "util_math.h"
using namespace OSL;
CCL_NAMESPACE_BEGIN
// TODO: fresnel_dielectric is only used for derivatives, could be optimized
// TODO: refactor these two classes so they share everything by the microfacet
// distribution terms
// microfacet model with GGX facet distribution
// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf
template <int Refractive = 0>
class MicrofacetGGXClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_ag; // width parameter (roughness)
float m_eta; // index of refraction (for fresnel term)
MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; }
void setup()
{
m_ag = clamp(m_ag, 1e-5f, 1.0f);
}
bool mergeable(const ClosurePrimitive *other) const {
const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other;
return m_N == comp->m_N && m_ag == comp->m_ag &&
m_eta == comp->m_eta && BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const {
return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx";
}
void print_on(std::ostream &out) const {
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_ag << ", ";
out << m_eta;
out << ")";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
if (Refractive == 1) return Color3(0, 0, 0);
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNI > 0 && cosNO > 0) {
// get half vector
Vec3 Hr = omega_in + omega_out;
Hr.normalize();
// 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 = m_N.dot(Hr);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
// eq. 34: now calculate G1(i,m) and G1(o,m)
float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
float G = G1o * G1i;
float out = (G * D) * 0.25f / cosNO;
// eq. 24
float pm = D * cosThetaM;
// convert into pdf of the sampled direction
// eq. 38 - but see also:
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
pdf = pm * 0.25f / Hr.dot(omega_out);
return Color3(out, out, out);
}
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
if (Refractive == 0) return Color3(0, 0, 0);
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNO <= 0 || cosNI >= 0)
return Color3(0, 0, 0); // vectors on same side -- not possible
// compute half-vector of the refraction (eq. 16)
Vec3 ht = -(m_eta * omega_in + omega_out);
Vec3 Ht = ht; Ht.normalize();
float cosHO = Ht.dot(omega_out);
float cosHI = Ht.dot(omega_in);
// eq. 33: first we calculate D(m) with m=Ht:
float alpha2 = m_ag * m_ag;
float cosThetaM = m_N.dot(Ht);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
// eq. 34: now calculate G1(i,m) and G1(o,m)
float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
float G = G1o * G1i;
// probability
float invHt2 = 1 / ht.dot(ht);
pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
return Color3(out, out, out);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
float cosNO = m_N.dot(omega_out);
if (cosNO > 0) {
Vec3 X, Y, Z = m_N;
make_orthonormals(Z, X, Y);
// generate a random microfacet normal m
// eq. 35,36:
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
// and sin(atan(x)) == x/sqrt(1+x^2)
float alpha2 = m_ag * m_ag;
float tanThetaM2 = alpha2 * randu / (1 - randu);
float cosThetaM = 1 / sqrtf(1 + tanThetaM2);
float sinThetaM = cosThetaM * sqrtf(tanThetaM2);
float phiM = 2 * float(M_PI) * randv;
Vec3 m = (cosf(phiM) * sinThetaM) * X +
(sinf(phiM) * sinThetaM) * Y +
cosThetaM * Z;
if (Refractive == 0) {
float cosMO = m.dot(omega_out);
if (cosMO > 0) {
// eq. 39 - compute actual reflected direction
omega_in = 2 * cosMO * m - omega_out;
if (Ng.dot(omega_in) > 0) {
// microfacet normal is visible to this ray
// eq. 33
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
// eq. 24
float pm = D * cosThetaM;
// convert into pdf of the sampled direction
// eq. 38 - but see also:
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
pdf = pm * 0.25f / cosMO;
// eval BRDF*cosNI
float cosNI = m_N.dot(omega_in);
// eq. 34: now calculate G1(i,m) and G1(o,m)
float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
float G = G1o * G1i;
// eq. 20: (F*G*D)/(4*in*on)
float out = (G * D) * 0.25f / cosNO;
eval.setValue(out, out, out);
domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx;
domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy;
/* disabled for now - gives texture filtering problems */
#if 0
// 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
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
#endif
}
}
}
else {
// CAUTION: the i and o variables are inverted relative to the paper
// eq. 39 - compute actual refractive direction
Vec3 R, dRdx, dRdy;
Vec3 T, dTdx, dTdy;
bool inside;
fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
R, dRdx, dRdy,
T, dTdx, dTdy,
inside);
if (!inside) {
omega_in = T;
domega_in_dx = dTdx;
domega_in_dy = dTdy;
// eq. 33
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
// eq. 24
float pm = D * cosThetaM;
// eval BRDF*cosNI
float cosNI = m_N.dot(omega_in);
// eq. 34: now calculate G1(i,m) and G1(o,m)
float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
float G = G1o * G1i;
// eq. 21
float cosHI = m.dot(omega_in);
float cosHO = m.dot(omega_out);
float Ht2 = m_eta * cosHI + cosHO;
Ht2 *= Ht2;
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
// eq. 38 and eq. 17
pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
eval.setValue(out, out, out);
/* disabled for now - gives texture filtering problems */
#if 0
// Since there is some blur to this refraction, make the
// derivatives a bit bigger. In theory this varies with the
// roughness but the exact relationship is complex and
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
#endif
}
}
}
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
}
};
// microfacet model with Beckmann facet distribution
// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf
template <int Refractive = 0>
class MicrofacetBeckmannClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_ab; // width parameter (roughness)
float m_eta; // index of refraction (for fresnel term)
MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) {
}
void setup()
{
m_ab = clamp(m_ab, 1e-5f, 1.0f);
}
bool mergeable(const ClosurePrimitive *other) const {
const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other;
return m_N == comp->m_N && m_ab == comp->m_ab &&
m_eta == comp->m_eta && BSDFClosure::mergeable(other);
}
size_t memsize() const {
return sizeof(*this);
}
const char *name() const {
return Refractive ? "microfacet_beckmann_refraction"
: "microfacet_beckmann";
}
void print_on(std::ostream &out) const
{
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_ab << ", ";
out << m_eta;
out << ")";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
if (Refractive == 1) return Color3(0, 0, 0);
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNO > 0 && cosNI > 0) {
// get half vector
Vec3 Hr = omega_in + omega_out;
Hr.normalize();
// 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 = m_N.dot(Hr);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
float G = G1o * G1i;
float out = (G * D) * 0.25f / cosNO;
// eq. 24
float pm = D * cosThetaM;
// convert into pdf of the sampled direction
// eq. 38 - but see also:
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
pdf = pm * 0.25f / Hr.dot(omega_out);
return Color3(out, out, out);
}
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
if (Refractive == 0) return Color3(0, 0, 0);
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNO <= 0 || cosNI >= 0)
return Color3(0, 0, 0);
// compute half-vector of the refraction (eq. 16)
Vec3 ht = -(m_eta * omega_in + omega_out);
Vec3 Ht = ht; Ht.normalize();
float cosHO = Ht.dot(omega_out);
float cosHI = Ht.dot(omega_in);
// eq. 33: first we calculate D(m) with m=Ht:
float alpha2 = m_ab * m_ab;
float cosThetaM = m_N.dot(Ht);
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
float G = G1o * G1i;
// probability
float invHt2 = 1 / ht.dot(ht);
pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
return Color3(out, out, out);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
float cosNO = m_N.dot(omega_out);
if (cosNO > 0) {
Vec3 X, Y, Z = m_N;
make_orthonormals(Z, X, Y);
// generate a random microfacet normal m
// eq. 35,36:
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
// and sin(atan(x)) == x/sqrt(1+x^2)
float alpha2 = m_ab * m_ab;
float tanThetaM = sqrtf(-alpha2 * logf(1 - randu));
float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM);
float sinThetaM = cosThetaM * tanThetaM;
float phiM = 2 * float(M_PI) * randv;
Vec3 m = (cosf(phiM) * sinThetaM) * X +
(sinf(phiM) * sinThetaM) * Y +
cosThetaM * Z;
if (Refractive == 0) {
float cosMO = m.dot(omega_out);
if (cosMO > 0) {
// eq. 39 - compute actual reflected direction
omega_in = 2 * cosMO * m - omega_out;
if (Ng.dot(omega_in) > 0) {
// microfacet normal is visible to this ray
// eq. 25
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = tanThetaM * tanThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
// eq. 24
float pm = D * cosThetaM;
// convert into pdf of the sampled direction
// eq. 38 - but see also:
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
pdf = pm * 0.25f / cosMO;
// Eval BRDF*cosNI
float cosNI = m_N.dot(omega_in);
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
float G = G1o * G1i;
// eq. 20: (F*G*D)/(4*in*on)
float out = (G * D) * 0.25f / cosNO;
eval.setValue(out, out, out);
domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx;
domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy;
/* disabled for now - gives texture filtering problems */
#if 0
// 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
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
#endif
}
}
}
else {
// CAUTION: the i and o variables are inverted relative to the paper
// eq. 39 - compute actual refractive direction
Vec3 R, dRdx, dRdy;
Vec3 T, dTdx, dTdy;
bool inside;
fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
R, dRdx, dRdy,
T, dTdx, dTdy,
inside);
if (!inside) {
omega_in = T;
domega_in_dx = dTdx;
domega_in_dy = dTdy;
// eq. 33
float cosThetaM2 = cosThetaM * cosThetaM;
float tanThetaM2 = tanThetaM * tanThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
// eq. 24
float pm = D * cosThetaM;
// eval BRDF*cosNI
float cosNI = m_N.dot(omega_in);
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
float G = G1o * G1i;
// eq. 21
float cosHI = m.dot(omega_in);
float cosHO = m.dot(omega_out);
float Ht2 = m_eta * cosHI + cosHO;
Ht2 *= Ht2;
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
// eq. 38 and eq. 17
pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
eval.setValue(out, out, out);
/* disabled for now - gives texture filtering problems */
#if 0
// Since there is some blur to this refraction, make the
// derivatives a bit bigger. In theory this varies with the
// roughness but the exact relationship is complex and
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
#endif
}
}
}
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
}
};
ClosureParam *bsdf_microfacet_ggx_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<0>, m_ag),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>)
};
return params;
}
ClosureParam *bsdf_microfacet_ggx_refraction_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_ag),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_eta),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>)
};
return params;
}
ClosureParam *bsdf_microfacet_beckmann_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<0>, m_ab),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>)
};
return params;
}
ClosureParam *bsdf_microfacet_beckmann_refraction_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_ab),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_eta),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>)
};
return params;
}
CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>)
CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>)
CLOSURE_PREPARE(bsdf_microfacet_beckmann_prepare, MicrofacetBeckmannClosure<0>)
CLOSURE_PREPARE(bsdf_microfacet_beckmann_refraction_prepare, MicrofacetBeckmannClosure<1>)
CCL_NAMESPACE_END

View File

@@ -1,142 +0,0 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "util_math.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class OrenNayarClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_sigma;
float m_a, m_b;
OrenNayarClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup() {
m_sigma = clamp(m_sigma, 0.0f, 1.0f);
float div = 1.0f / (M_PI + ((3.0f * M_PI - 4.0f) / 6.0f) * m_sigma);
m_a = 1.0f * div;
m_b = m_sigma * div;
}
bool mergeable(const ClosurePrimitive *other) const {
const OrenNayarClosure *comp = static_cast<const OrenNayarClosure *>(other);
return
m_N == comp->m_N &&
m_sigma == comp->m_sigma &&
BSDFClosure::mergeable(other);
}
size_t memsize() const {
return sizeof(*this);
}
const char *name() const {
return "oren_nayar";
}
void print_on(std::ostream& out) const {
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_sigma;
out << ")";
}
float albedo(const Vec3& omega_out) const {
return 1.0f;
}
Color3 eval_reflect(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const {
if (m_N.dot(omega_in) > 0.0f) {
pdf = float(0.5 * M_1_PI);
float is = get_intensity(m_N, omega_out, omega_in);
return Color3(is, is, is);
}
else {
pdf = 0.0f;
return Color3(0.0f, 0.0f, 0.0f);
}
}
Color3 eval_transmit(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const {
return Color3(0.0f, 0.0f, 0.0f);
}
ustring sample(
const Vec3& Ng,
const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy,
float randu, float randv,
Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy,
float& pdf, Color3& eval
) const {
sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
if (Ng.dot(omega_in) > 0.0f) {
float is = get_intensity(m_N, omega_out, omega_in);
eval.setValue(is, is, is);
// TODO: find a better approximation for the bounce
domega_in_dx = (2.0f * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2.0f * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
domega_in_dx *= 125.0f;
domega_in_dy *= 125.0f;
}
else {
pdf = 0.0f;
}
return Labels::REFLECT;
}
private:
float get_intensity(Vec3 const& n, Vec3 const& v, Vec3 const& l) const {
float nl = max(n.dot(l), 0.0f);
float nv = max(n.dot(v), 0.0f);
float t = l.dot(v) - nl * nv;
if (t > 0.0f) {
t /= max(nl, nv) + 1e-8f;
}
return nl * (m_a + m_b * t);
}
};
ClosureParam *bsdf_oren_nayar_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(OrenNayarClosure, m_N),
CLOSURE_FLOAT_PARAM(OrenNayarClosure, m_sigma),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(OrenNayarClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure)
CCL_NAMESPACE_END

View File

@@ -1,287 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2012, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "util_math.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
// vanilla phong - leaks energy at grazing angles
// see Global Illumination Compendium entry (66)
class PhongClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_exponent;
PhongClosure() : BSDFClosure(Labels::GLOSSY) { }
void setup() {};
bool mergeable (const ClosurePrimitive *other) const {
const PhongClosure *comp = (const PhongClosure *)other;
return m_N == comp->m_N && m_exponent == comp->m_exponent &&
BSDFClosure::mergeable(other);
}
size_t memsize () const { return sizeof(*this); }
const char *name () const { return "phong"; }
void print_on (std::ostream &out) const {
out << name() << " ((";
out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_exponent << ")";
}
float albedo (const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
float cosNI = m_N.dot(omega_in);
float cosNO = m_N.dot(omega_out);
if (cosNI > 0 && cosNO > 0) {
// reflect the view vector
Vec3 R = (2 * cosNO) * m_N - omega_out;
float cosRI = R.dot(omega_in);
if (cosRI > 0) {
float common = 0.5f * (float) M_1_PI * powf(cosRI, m_exponent);
float out = cosNI * (m_exponent + 2) * common;
pdf = (m_exponent + 1) * common;
return Color3 (out, out, out);
}
}
return Color3 (0, 0, 0);
}
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3 (0, 0, 0);
}
ustring sample (const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
float cosNO = m_N.dot(omega_out);
if (cosNO > 0) {
// reflect the view vector
Vec3 R = (2 * cosNO) * m_N - omega_out;
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
Vec3 T, B;
make_orthonormals (R, T, B);
float phi = 2 * (float) M_PI * 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 (Ng.dot(omega_in) > 0)
{
// common terms for pdf and eval
float cosNI = m_N.dot(omega_in);
// make sure the direction we chose is still in the right hemisphere
if (cosNI > 0)
{
float common = 0.5f * (float) M_1_PI * powf(cosTheta, m_exponent);
pdf = (m_exponent + 1) * common;
float out = cosNI * (m_exponent + 2) * common;
eval.setValue(out, out, out);
// Since there is some blur to this reflection, make the
// derivatives a bit bigger. In theory this varies with the
// exponent but the exact relationship is complex and
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
}
}
}
return Labels::REFLECT;
}
};
class PhongRampClosure : public BSDFClosure {
public:
static const int MAXCOLORS = 8;
Vec3 m_N;
float m_exponent;
Color3 m_colors[MAXCOLORS];
PhongRampClosure() : BSDFClosure(Labels::GLOSSY) { }
void setup() {};
bool mergeable (const ClosurePrimitive *other) const {
const PhongRampClosure *comp = (const PhongRampClosure *)other;
if (! (m_N == comp->m_N && m_exponent == comp->m_exponent &&
BSDFClosure::mergeable(other)))
return false;
for (int i = 0; i < MAXCOLORS; ++i)
if (m_colors[i] != comp->m_colors[i])
return false;
return true;
}
size_t memsize () const { return sizeof(*this); }
const char *name () const { return "phong_ramp"; }
void print_on (std::ostream &out) const {
out << name() << " ((";
out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_exponent << ")";
}
Color3 get_color (float pos) const
{
float npos = pos * (float)(MAXCOLORS - 1);
int ipos = (int)npos;
if (ipos >= (MAXCOLORS - 1))
return m_colors[MAXCOLORS - 1];
float offset = npos - (float)ipos;
return m_colors[ipos] * (1.0f - offset) + m_colors[ipos+1] * offset;
}
float albedo (const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
float cosNI = m_N.dot(omega_in);
float cosNO = m_N.dot(omega_out);
if (cosNI > 0 && cosNO > 0) {
// reflect the view vector
Vec3 R = (2 * cosNO) * m_N - omega_out;
float cosRI = R.dot(omega_in);
if (cosRI > 0) {
float cosp = powf(cosRI, m_exponent);
float common = 0.5f * (float) M_1_PI * cosp;
float out = cosNI * (m_exponent + 2) * common;
pdf = (m_exponent + 1) * common;
return get_color(cosp) * out;
}
}
return Color3 (0, 0, 0);
}
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3 (0, 0, 0);
}
ustring sample (const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
float cosNO = m_N.dot(omega_out);
if (cosNO > 0) {
// reflect the view vector
Vec3 R = (2 * cosNO) * m_N - omega_out;
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
Vec3 T, B;
make_orthonormals (R, T, B);
float phi = 2 * (float) M_PI * 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 (Ng.dot(omega_in) > 0)
{
// common terms for pdf and eval
float cosNI = m_N.dot(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 * (float) M_1_PI * cosp;
pdf = (m_exponent + 1) * common;
float out = cosNI * (m_exponent + 2) * common;
eval = get_color(cosp) * out;
// Since there is some blur to this reflection, make the
// derivatives a bit bigger. In theory this varies with the
// exponent but the exact relationship is complex and
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
}
}
}
return Labels::REFLECT;
}
};
ClosureParam *bsdf_phong_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(PhongClosure, m_N),
CLOSURE_FLOAT_PARAM (PhongClosure, m_exponent),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(PhongClosure)
};
return params;
}
ClosureParam *bsdf_phong_ramp_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM (PhongRampClosure, m_N),
CLOSURE_FLOAT_PARAM (PhongRampClosure, m_exponent),
CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, m_colors, PhongRampClosure::MAXCOLORS),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM (PhongRampClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_phong_prepare, PhongClosure)
CLOSURE_PREPARE(bsdf_phong_ramp_prepare, PhongRampClosure)
CCL_NAMESPACE_END

View File

@@ -1,113 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class ReflectionClosure : public BSDFClosure {
public:
Vec3 m_N; // shading normal
ReflectionClosure() : BSDFClosure(Labels::SINGULAR) {}
void setup() {};
bool mergeable(const ClosurePrimitive *other) const {
const ReflectionClosure *comp = (const ReflectionClosure *)other;
return m_N == comp->m_N && BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "reflection"; }
void print_on(std::ostream &out) const {
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
// only one direction is possible
float cosNO = m_N.dot(omega_out);
if (cosNO > 0) {
omega_in = (2 * cosNO) * m_N - omega_out;
if (Ng.dot(omega_in) > 0) {
domega_in_dx = 2 * m_N.dot(domega_out_dx) * m_N - domega_out_dx;
domega_in_dy = 2 * m_N.dot(domega_out_dy) * m_N - domega_out_dy;
pdf = 1;
eval.setValue(1, 1, 1);
}
}
return Labels::REFLECT;
}
};
ClosureParam *bsdf_reflection_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(ReflectionClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure)
CCL_NAMESPACE_END

View File

@@ -1,125 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class RefractionClosure : public BSDFClosure {
public:
Vec3 m_N; // shading normal
float m_eta; // ratio of indices of refraction (inside / outside)
RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) {}
void setup() {}
bool mergeable(const ClosurePrimitive *other) const {
const RefractionClosure *comp = (const RefractionClosure *)other;
return m_N == comp->m_N && m_eta == comp->m_eta &&
BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "refraction"; }
void print_on(std::ostream &out) const {
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_eta;
out << ")";
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
Vec3 R, dRdx, dRdy;
Vec3 T, dTdx, dTdy;
bool inside;
fresnel_dielectric(m_eta, m_N,
omega_out, domega_out_dx, domega_out_dy,
R, dRdx, dRdy,
T, dTdx, dTdy,
inside);
if (!inside) {
pdf = 1;
eval.setValue(1.0f, 1.0f, 1.0f);
omega_in = T;
domega_in_dx = dTdx;
domega_in_dy = dTdy;
}
return Labels::TRANSMIT;
}
};
ClosureParam *bsdf_refraction_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(RefractionClosure, m_N),
CLOSURE_FLOAT_PARAM(RefractionClosure, m_eta),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(RefractionClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure)
CCL_NAMESPACE_END

View File

@@ -1,102 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class TransparentClosure : public BSDFClosure {
public:
TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) {}
void setup() {}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "transparent"; }
void print_on(std::ostream &out) const {
out << name() << " ()";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
// only one direction is possible
omega_in = -omega_out;
domega_in_dx = -domega_out_dx;
domega_in_dy = -domega_out_dy;
pdf = 1;
eval.setValue(1, 1, 1);
return Labels::TRANSMIT;
}
};
ClosureParam *bsdf_transparent_params()
{
static ClosureParam params[] = {
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(TransparentClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure)
CCL_NAMESPACE_END

View File

@@ -1,230 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "util_math.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
// anisotropic ward - leaks energy at grazing angles
// see http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
class WardClosure : public BSDFClosure {
public:
Vec3 m_N;
Vec3 m_T;
float m_ax, m_ay;
WardClosure() : BSDFClosure(Labels::GLOSSY) {}
void setup()
{
m_ax = clamp(m_ax, 1e-5f, 1.0f);
m_ay = clamp(m_ay, 1e-5f, 1.0f);
}
bool mergeable(const ClosurePrimitive *other) const {
const WardClosure *comp = (const WardClosure *)other;
return m_N == comp->m_N && m_T == comp->m_T &&
m_ax == comp->m_ax && m_ay == comp->m_ay &&
BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "ward"; }
void print_on(std::ostream &out) const {
out << name() << " ((";
out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), (";
out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), ";
out << m_ax << ", " << m_ay << ")";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNI > 0 && cosNO > 0) {
// get half vector and get x,y basis on the surface for anisotropy
Vec3 H = omega_in + omega_out;
H.normalize(); // normalize needed for pdf
Vec3 X, Y;
make_orthonormals(m_N, m_T, X, Y);
// eq. 4
float dotx = H.dot(X) / m_ax;
float doty = H.dot(Y) / m_ay;
float dotn = H.dot(m_N);
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
float exp_val = expf(-exp_arg);
float out = cosNI * exp_val / denom;
float oh = H.dot(omega_out);
denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
pdf = exp_val / denom;
return Color3(out, out, out);
}
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
{
return Color3(0, 0, 0);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
float cosNO = m_N.dot(omega_out);
if (cosNO > 0) {
// get x,y basis on the surface for anisotropy
Vec3 X, Y;
make_orthonormals(m_N, m_T, X, Y);
// generate random angles for the half vector
// eq. 7 (taking care around discontinuities to keep
// output angle in the right quadrant)
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
// and sin(atan(x)) == x/sqrt(1+x^2)
float alphaRatio = m_ay / m_ax;
float cosPhi, sinPhi;
if (randu < 0.25f) {
float val = 4 * randu;
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = tanPhi * cosPhi;
}
else if (randu < 0.5) {
float val = 1 - 4 * (0.5f - randu);
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
// phi = (float) M_PI - phi;
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = -tanPhi * cosPhi;
}
else if (randu < 0.75f) {
float val = 4 * (randu - 0.5f);
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
//phi = (float) M_PI + phi;
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = tanPhi * cosPhi;
}
else {
float val = 1 - 4 * (1 - randu);
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
// phi = 2 * (float) M_PI - phi;
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
sinPhi = -tanPhi * cosPhi;
}
// eq. 6
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
// and sin(atan(x)) == x/sqrt(1+x^2)
float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay);
float tanTheta2 = -logf(1 - randv) / thetaDenom;
float cosTheta = 1 / sqrtf(1 + tanTheta2);
float sinTheta = cosTheta * sqrtf(tanTheta2);
Vec3 h; // already normalized becaused expressed from spherical coordinates
h.x = sinTheta * cosPhi;
h.y = sinTheta * sinPhi;
h.z = cosTheta;
// compute terms that are easier in local space
float dotx = h.x / m_ax;
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;
// generate the final sample
float oh = h.dot(omega_out);
omega_in.x = 2 * oh * h.x - omega_out.x;
omega_in.y = 2 * oh * h.y - omega_out.y;
omega_in.z = 2 * oh * h.z - omega_out.z;
if (Ng.dot(omega_in) > 0) {
float cosNI = m_N.dot(omega_in);
if (cosNI > 0) {
// eq. 9
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
pdf = expf(-exp_arg) / denom;
// compiler will reuse expressions already computed
denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
float power = cosNI * expf(-exp_arg) / denom;
eval.setValue(power, power, power);
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
/* disabled for now - gives texture filtering problems */
#if 0
// 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
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
#endif
}
}
}
return Labels::REFLECT;
}
};
ClosureParam *bsdf_ward_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(WardClosure, m_N),
CLOSURE_VECTOR_PARAM(WardClosure, m_T),
CLOSURE_FLOAT_PARAM(WardClosure, m_ax),
CLOSURE_FLOAT_PARAM(WardClosure, m_ay),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(WardClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure)
CCL_NAMESPACE_END

View File

@@ -1,251 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
#include "util_math.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class WestinBackscatterClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_roughness;
float m_invroughness;
WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) {}
void setup()
{
m_roughness = clamp(m_roughness, 1e-5f, 1.0f);
m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0;
}
bool mergeable(const ClosurePrimitive *other) const {
const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other;
return m_N == comp->m_N && m_roughness == comp->m_roughness &&
BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "westin_backscatter"; }
void print_on(std::ostream &out) const
{
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_roughness;
out << ")";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
{
// pdf is implicitly 0 (no indirect sampling)
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNO > 0 && cosNI > 0) {
float cosine = omega_out.dot(omega_in);
pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0;
pdf *= 0.5f * float(M_1_PI);
return Color3(pdf, pdf, pdf);
}
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
{
return Color3(0, 0, 0);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
float cosNO = m_N.dot(omega_out);
if (cosNO > 0) {
domega_in_dx = domega_out_dx;
domega_in_dy = domega_out_dy;
Vec3 T, B;
make_orthonormals(omega_out, T, B);
float phi = 2 * (float) M_PI * 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) * omega_out;
if (Ng.dot(omega_in) > 0)
{
// common terms for pdf and eval
float cosNI = m_N.dot(omega_in);
// make sure the direction we chose is still in the right hemisphere
if (cosNI > 0)
{
pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness);
pdf = (m_invroughness + 1) * pdf;
eval.setValue(pdf, pdf, pdf);
// Since there is some blur to this reflection, make the
// derivatives a bit bigger. In theory this varies with the
// exponent but the exact relationship is complex and
// requires more ops than are practical.
domega_in_dx *= 10;
domega_in_dy *= 10;
}
}
}
return Labels::REFLECT;
}
};
class WestinSheenClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_edginess;
// float m_normalization;
WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup() {};
bool mergeable(const ClosurePrimitive *other) const {
const WestinSheenClosure *comp = (const WestinSheenClosure *)other;
return m_N == comp->m_N && m_edginess == comp->m_edginess &&
BSDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "westin_sheen"; }
void print_on(std::ostream &out) const
{
out << name() << " (";
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
out << m_edginess;
out << ")";
}
float albedo(const Vec3 &omega_out) const
{
return 1.0f;
}
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
{
// pdf is implicitly 0 (no indirect sampling)
float cosNO = m_N.dot(omega_out);
float cosNI = m_N.dot(omega_in);
if (cosNO > 0 && cosNI > 0) {
float sinNO2 = 1 - cosNO * cosNO;
pdf = cosNI * float(M_1_PI);
float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0;
return Color3(westin, westin, westin);
}
return Color3(0, 0, 0);
}
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
{
return Color3(0, 0, 0);
}
ustring sample(const Vec3 &Ng,
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
float randu, float randv,
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
float &pdf, Color3 &eval) const
{
// we are viewing the surface from the right side - send a ray out with cosine
// distribution over the hemisphere
sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
if (Ng.dot(omega_in) > 0) {
// TODO: account for sheen when sampling
float cosNO = m_N.dot(omega_out);
float sinNO2 = 1 - cosNO * cosNO;
float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0;
eval.setValue(westin, westin, westin);
// TODO: find a better approximation for the diffuse bounce
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
domega_in_dx *= 125;
domega_in_dy *= 125;
}
else {
pdf = 0;
}
return Labels::REFLECT;
}
};
ClosureParam *bsdf_westin_backscatter_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N),
CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, m_roughness),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(WestinBackscatterClosure)
};
return params;
}
ClosureParam *bsdf_westin_sheen_params()
{
static ClosureParam params[] = {
CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N),
CLOSURE_FLOAT_PARAM(WestinSheenClosure, m_edginess),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(WestinSheenClosure)
};
return params;
}
CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure)
CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure)
CCL_NAMESPACE_END

View File

@@ -1,110 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
class BSSRDFCubicClosure : public BSSRDFClosure {
public:
Color3 m_radius;
Color3 m_scale;
float m_max_radius;
template <typename T>
static inline T pow3(const T &x) { return x * x * x; }
template <typename T>
static inline T pow5(const T &x) { T x2 = x * x; return x2 * x2 * x; }
BSSRDFCubicClosure() {}
void setup()
{
// pre-compute some terms
m_max_radius = 0;
for (int i = 0; i < 3; i++) {
m_scale[i] = m_radius[i] > 0 ? 4 / pow5(m_radius[i]) : 0;
m_max_radius = std::max(m_max_radius, m_radius[i]);
}
}
bool mergeable(const ClosurePrimitive *other) const {
const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other;
return m_radius == comp->m_radius && BSSRDFClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "bssrdf_cubic"; }
void print_on(std::ostream &out) const
{
out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), ("
<< m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))";
}
Color3 eval(float r) const
{
return Color3((r < m_radius.x) ? pow3(m_radius.x - r) * m_scale.x : 0,
(r < m_radius.y) ? pow3(m_radius.y - r) * m_scale.y : 0,
(r < m_radius.z) ? pow3(m_radius.z - r) * m_scale.z : 0);
}
float max_radius() const
{
return m_max_radius;
}
};
ClosureParam *closure_bssrdf_cubic_params()
{
static ClosureParam params[] = {
CLOSURE_COLOR_PARAM(BSSRDFCubicClosure, m_radius),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(BSSRDFCubicClosure)
};
return params;
}
CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure)
CCL_NAMESPACE_END

View File

@@ -1,85 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
/// Debug closure
///
/// This is going to be used for mask AOV's and similar
/// purposes. A tag (string) is always associated with
/// this closure, that "selects: the channel where the
/// weight should be sent.
class DebugClosure : public ClosurePrimitive {
public:
ustring m_tag;
DebugClosure () : ClosurePrimitive(Debug) {}
bool mergeable(const ClosurePrimitive *other) const {
const DebugClosure *comp = (const DebugClosure *)other;
return m_tag == comp->m_tag &&
ClosurePrimitive::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "debug"; }
void print_on(std::ostream &out) const {
out << name() << " (\"" << m_tag.c_str() << "\")";
}
};
ClosureParam *closure_debug_params()
{
static ClosureParam params[] = {
CLOSURE_STRING_PARAM(DebugClosure, m_tag),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(DebugClosure)
};
return params;
}
CLOSURE_PREPARE(closure_debug_prepare, DebugClosure)
CCL_NAMESPACE_END

View File

@@ -36,6 +36,9 @@
#include "osl_closures.h" #include "osl_closures.h"
#include "kernel_types.h"
#include "closure/emissive.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
using namespace OSL; using namespace OSL;
@@ -52,51 +55,34 @@ public:
GenericEmissiveClosure() { } GenericEmissiveClosure() { }
void setup() {} void setup() {}
size_t memsize() const { return sizeof(*this); } size_t memsize() const { return sizeof(*this); }
const char *name() const { return "emission"; } const char *name() const { return "emission"; }
void print_on(std::ostream &out) const { void print_on(std::ostream &out) const
{
out << name() << "()"; out << name() << "()";
} }
Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
{ {
float cosNO = fabsf(Ng.dot(omega_out)); float3 result = emissive_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
float res = cosNO > 0 ? 1.0f : 0.0f; return TO_COLOR3(result);
return Color3(res, res, res);
} }
void sample(const Vec3 &Ng, float randu, float randv, void sample(const Vec3 &Ng, float randu, float randv,
Vec3 &omega_out, float &pdf) const Vec3 &omega_out, float &pdf) const
{ {
// We don't do anything sophisticated here for the step float3 omega_out_;
// We just sample the whole cone uniformly to the cosine emissive_sample(TO_FLOAT3(Ng), randu, randv, &omega_out_, &pdf);
Vec3 T, B; omega_out = TO_VEC3(omega_out_);
make_orthonormals(Ng, T, B);
float phi = 2 * (float) M_PI * randu;
float cosTheta = sqrtf(1.0f - 1.0f * randv);
float sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
omega_out = (cosf(phi) * sinTheta) * T +
(sinf(phi) * sinTheta) * B +
cosTheta * Ng;
pdf = 1.0f / float(M_PI);
} }
/// Return the probability distribution function in the direction omega_out, float pdf(const Vec3 &Ng, const Vec3 &omega_out) const
/// given the parameters and the light's surface normal. This MUST match
/// the PDF computed by sample().
float pdf(const Vec3 &Ng,
const Vec3 &omega_out) const
{ {
float cosNO = Ng.dot(omega_out); return emissive_pdf(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
return cosNO > 0 ? 1.0f : 0.0f;
} }
}; };
ClosureParam *closure_emission_params() ClosureParam *closure_emission_params()
{ {
static ClosureParam params[] = { static ClosureParam params[] = {

View File

@@ -37,10 +37,100 @@
#include "osl_shader.h" #include "osl_shader.h"
#include "util_debug.h" #include "util_debug.h"
#include "util_math.h"
#include "util_param.h" #include "util_param.h"
#include "kernel_types.h"
#include "kernel_montecarlo.h"
#include "closure/bsdf.h"
#include "closure/bsdf_ashikhmin_velvet.h"
#include "closure/bsdf_diffuse.h"
#include "closure/bsdf_microfacet.h"
#include "closure/bsdf_oren_nayar.h"
#include "closure/bsdf_reflection.h"
#include "closure/bsdf_refraction.h"
#include "closure/bsdf_transparent.h"
#include "closure/bsdf_ward.h"
#include "closure/bsdf_westin.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
using namespace OSL;
/* BSDF class definitions */
BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, diffuse, LABEL_DIFFUSE)
CLOSURE_VECTOR_PARAM(DiffuseClosure, N),
BSDF_CLOSURE_CLASS_END(Diffuse, diffuse)
BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, translucent, LABEL_DIFFUSE)
CLOSURE_VECTOR_PARAM(TranslucentClosure, N),
BSDF_CLOSURE_CLASS_END(Translucent, translucent)
BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, oren_nayar, LABEL_DIFFUSE)
CLOSURE_VECTOR_PARAM(OrenNayarClosure, N),
CLOSURE_FLOAT_PARAM(OrenNayarClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar)
BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, reflection, LABEL_SINGULAR)
CLOSURE_VECTOR_PARAM(ReflectionClosure, N),
BSDF_CLOSURE_CLASS_END(Reflection, reflection)
BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR)
CLOSURE_VECTOR_PARAM(RefractionClosure, N),
CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(Refraction, refraction)
BSDF_CLOSURE_CLASS_BEGIN(WestinBackscatter, westin_backscatter, westin_backscatter, LABEL_GLOSSY)
CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, N),
CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(WestinBackscatter, westin_backscatter)
BSDF_CLOSURE_CLASS_BEGIN(WestinSheen, westin_sheen, westin_sheen, LABEL_DIFFUSE)
CLOSURE_VECTOR_PARAM(WestinSheenClosure, N),
CLOSURE_FLOAT_PARAM(WestinSheenClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(WestinSheen, westin_sheen)
BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR)
BSDF_CLOSURE_CLASS_END(Transparent, transparent)
BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LABEL_DIFFUSE)
CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, N),
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
BSDF_CLOSURE_CLASS_BEGIN(Ward, ward, ward, LABEL_GLOSSY)
CLOSURE_VECTOR_PARAM(WardClosure, N),
CLOSURE_VECTOR_PARAM(WardClosure, T),
CLOSURE_FLOAT_PARAM(WardClosure, sc.data0),
CLOSURE_FLOAT_PARAM(WardClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(Ward, ward)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY)
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure, N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY)
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure, N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY)
CLOSURE_VECTOR_PARAM(MicrofacetGGXRefractionClosure, N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY)
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannRefractionClosure, N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data1),
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
/* Registration */
static void generic_closure_setup(OSL::RendererServices *, int id, void *data) static void generic_closure_setup(OSL::RendererServices *, int id, void *data)
{ {
assert(data); assert(data);
@@ -64,28 +154,42 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O
void OSLShader::register_closures(OSL::ShadingSystem *ss) void OSLShader::register_closures(OSL::ShadingSystem *ss)
{ {
register_closure(ss, "diffuse", OSL_CLOSURE_BSDF_DIFFUSE_ID, bsdf_diffuse_params(), bsdf_diffuse_prepare); int id = 0;
register_closure(ss, "oren_nayar", OSL_CLOSURE_BSDF_OREN_NAYAR_ID, bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare);
register_closure(ss, "translucent", OSL_CLOSURE_BSDF_TRANSLUCENT_ID, bsdf_translucent_params(), bsdf_translucent_prepare); register_closure(ss, "diffuse", id++,
register_closure(ss, "reflection", OSL_CLOSURE_BSDF_REFLECTION_ID, bsdf_reflection_params(), bsdf_reflection_prepare); bsdf_diffuse_params(), bsdf_diffuse_prepare);
register_closure(ss, "refraction", OSL_CLOSURE_BSDF_REFRACTION_ID, bsdf_refraction_params(), bsdf_refraction_prepare); register_closure(ss, "oren_nayar", id++,
register_closure(ss, "transparent", OSL_CLOSURE_BSDF_TRANSPARENT_ID, bsdf_transparent_params(), bsdf_transparent_prepare); bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare);
register_closure(ss, "microfacet_ggx", OSL_CLOSURE_BSDF_MICROFACET_GGX_ID, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare); register_closure(ss, "translucent", id++,
register_closure(ss, "microfacet_ggx_refraction", OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare); bsdf_translucent_params(), bsdf_translucent_prepare);
register_closure(ss, "microfacet_beckmann", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare); register_closure(ss, "reflection", id++,
register_closure(ss, "microfacet_beckmann_refraction", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare); bsdf_reflection_params(), bsdf_reflection_prepare);
register_closure(ss, "ward", OSL_CLOSURE_BSDF_WARD_ID, bsdf_ward_params(), bsdf_ward_prepare); register_closure(ss, "refraction", id++,
register_closure(ss, "phong", OSL_CLOSURE_BSDF_PHONG_ID, bsdf_phong_params(), bsdf_phong_prepare); bsdf_refraction_params(), bsdf_refraction_prepare);
register_closure(ss, "phong_ramp", OSL_CLOSURE_BSDF_PHONG_RAMP_ID, bsdf_phong_ramp_params(), bsdf_phong_ramp_prepare); register_closure(ss, "transparent", id++,
register_closure(ss, "ashikhmin_velvet", OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare); bsdf_transparent_params(), bsdf_transparent_prepare);
register_closure(ss, "westin_backscatter", OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare); register_closure(ss, "microfacet_ggx", id++,
register_closure(ss, "westin_sheen", OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, bsdf_westin_sheen_params(), bsdf_westin_sheen_prepare); bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
register_closure(ss, "bssrdf_cubic", OSL_CLOSURE_BSSRDF_CUBIC_ID, closure_bssrdf_cubic_params(), closure_bssrdf_cubic_prepare); register_closure(ss, "microfacet_ggx_refraction", id++,
register_closure(ss, "emission", OSL_CLOSURE_EMISSION_ID, closure_emission_params(), closure_emission_prepare); bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare);
register_closure(ss, "debug", OSL_CLOSURE_DEBUG_ID, closure_debug_params(), closure_debug_prepare); register_closure(ss, "microfacet_beckmann", id++,
register_closure(ss, "background", OSL_CLOSURE_BACKGROUND_ID, closure_background_params(), closure_background_prepare); bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
register_closure(ss, "holdout", OSL_CLOSURE_HOLDOUT_ID, closure_holdout_params(), closure_holdout_prepare); register_closure(ss, "microfacet_beckmann_refraction", id++,
register_closure(ss, "subsurface", OSL_CLOSURE_SUBSURFACE_ID, closure_subsurface_params(), closure_subsurface_prepare); bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare);
register_closure(ss, "ward", id++,
bsdf_ward_params(), bsdf_ward_prepare);
register_closure(ss, "ashikhmin_velvet", id++,
bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
register_closure(ss, "westin_backscatter", id++,
bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare);
register_closure(ss, "westin_sheen", id++,
bsdf_westin_sheen_params(), bsdf_westin_sheen_prepare);
register_closure(ss, "emission", id++,
closure_emission_params(), closure_emission_prepare);
register_closure(ss, "background", id++,
closure_background_params(), closure_background_prepare);
register_closure(ss, "holdout", id++,
closure_holdout_params(), closure_holdout_prepare);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -37,78 +37,19 @@
#include <OSL/oslexec.h> #include <OSL/oslexec.h>
#include <OSL/genclosure.h> #include <OSL/genclosure.h>
#include "kernel_types.h"
#include "util_types.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
enum {
OSL_CLOSURE_BSDF_DIFFUSE_ID,
OSL_CLOSURE_BSDF_OREN_NAYAR_ID,
OSL_CLOSURE_BSDF_TRANSLUCENT_ID,
OSL_CLOSURE_BSDF_REFLECTION_ID,
OSL_CLOSURE_BSDF_REFRACTION_ID,
OSL_CLOSURE_BSDF_TRANSPARENT_ID,
OSL_CLOSURE_BSDF_MICROFACET_GGX_ID,
OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
OSL_CLOSURE_BSDF_WARD_ID,
OSL_CLOSURE_BSDF_PHONG_ID,
OSL_CLOSURE_BSDF_PHONG_RAMP_ID,
OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID,
OSL_CLOSURE_BSSRDF_CUBIC_ID,
OSL_CLOSURE_EMISSION_ID,
OSL_CLOSURE_DEBUG_ID,
OSL_CLOSURE_BACKGROUND_ID,
OSL_CLOSURE_HOLDOUT_ID,
OSL_CLOSURE_SUBSURFACE_ID
};
OSL::ClosureParam *bsdf_diffuse_params();
OSL::ClosureParam *bsdf_oren_nayar_params();
OSL::ClosureParam *bsdf_translucent_params();
OSL::ClosureParam *bsdf_reflection_params();
OSL::ClosureParam *bsdf_refraction_params();
OSL::ClosureParam *bsdf_transparent_params();
OSL::ClosureParam *bsdf_microfacet_ggx_params();
OSL::ClosureParam *bsdf_microfacet_ggx_refraction_params();
OSL::ClosureParam *bsdf_microfacet_beckmann_params();
OSL::ClosureParam *bsdf_microfacet_beckmann_refraction_params();
OSL::ClosureParam *bsdf_ward_params();
OSL::ClosureParam *bsdf_phong_params();
OSL::ClosureParam *bsdf_phong_ramp_params();
OSL::ClosureParam *bsdf_ashikhmin_velvet_params();
OSL::ClosureParam *bsdf_westin_backscatter_params();
OSL::ClosureParam *bsdf_westin_sheen_params();
OSL::ClosureParam *closure_bssrdf_cubic_params();
OSL::ClosureParam *closure_emission_params(); OSL::ClosureParam *closure_emission_params();
OSL::ClosureParam *closure_debug_params();
OSL::ClosureParam *closure_background_params(); OSL::ClosureParam *closure_background_params();
OSL::ClosureParam *closure_holdout_params(); OSL::ClosureParam *closure_holdout_params();
OSL::ClosureParam *closure_subsurface_params();
void bsdf_diffuse_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_oren_nayar_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_translucent_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_reflection_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_refraction_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_microfacet_ggx_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_microfacet_ggx_refraction_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_microfacet_beckmann_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_microfacet_beckmann_refraction_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_ward_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_phong_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_ashikhmin_velvet_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data);
void bsdf_westin_sheen_prepare(OSL::RendererServices *, int id, void *data);
void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
void closure_emission_prepare(OSL::RendererServices *, int id, void *data); void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_debug_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data); void closure_background_prepare(OSL::RendererServices *, int id, void *data);
void closure_holdout_prepare(OSL::RendererServices *, int id, void *data); void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
void closure_subsurface_prepare(OSL::RendererServices *, int id, void *data);
#define CLOSURE_PREPARE(name, classname) \ #define CLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \ void name(RendererServices *, int id, void *data) \
@@ -117,6 +58,106 @@ void name(RendererServices *, int id, void *data) \
new (data) classname(); \ new (data) classname(); \
} }
#define TO_VEC3(v) (*(OSL::Vec3 *)&(v))
#define TO_COLOR3(v) (*(OSL::Color3 *)&(v))
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
/* BSDF */
class CBSDFClosure : public OSL::ClosurePrimitive {
public:
ShaderClosure sc;
OSL::Vec3 N, T;
CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF),
m_scattering_label(scattering), m_shaderdata_flag(0) { }
~CBSDFClosure() { }
int scattering() const { return m_scattering_label; }
int shaderdata_flag() const { return m_shaderdata_flag; }
ClosureType shaderclosure_type() const { return sc.type; }
virtual void blur(float roughness);
virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0;
virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0;
virtual int sample(const float3 &Ng,
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
float randu, float randv,
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
float &pdf, float3 &eval) const = 0;
protected:
int m_scattering_label;
int m_shaderdata_flag;
};
#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, svmlower, TYPE) \
\
class Upper##Closure : public CBSDFClosure { \
public: \
Upper##Closure() : CBSDFClosure(TYPE) {} \
size_t memsize() const { return sizeof(*this); } \
const char *name() const { return #lower; } \
\
void setup() \
{ \
sc.N = TO_FLOAT3(N); \
sc.T = TO_FLOAT3(T); \
m_shaderdata_flag = bsdf_##lower##_setup(&sc); \
} \
\
bool mergeable(const ClosurePrimitive *other) const \
{ \
return false; \
} \
\
void blur(float roughness) \
{ \
bsdf_##svmlower##_blur(&sc, roughness); \
} \
\
void print_on(std::ostream &out) const \
{ \
out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; \
} \
\
float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
return bsdf_##svmlower##_eval_reflect(&sc, omega_out, omega_in, &pdf); \
} \
\
float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
{ \
return bsdf_##svmlower##_eval_transmit(&sc, omega_out, omega_in, &pdf); \
} \
\
int sample(const float3 &Ng, \
const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, \
float randu, float randv, \
float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, \
float &pdf, float3 &eval) const \
{ \
return bsdf_##svmlower##_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy, \
randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf); \
} \
}; \
\
ClosureParam *bsdf_##lower##_params() \
{ \
static ClosureParam params[] = {
/* parameters */
#define BSDF_CLOSURE_CLASS_END(Upper, lower) \
CLOSURE_STRING_KEYPARAM("label"), \
CLOSURE_FINISH_PARAM(Upper##Closure) \
}; \
return params; \
} \
\
CLOSURE_PREPARE(bsdf_##lower##_prepare, Upper##Closure)
CCL_NAMESPACE_END CCL_NAMESPACE_END
#endif /* __OSL_CLOSURES_H__ */ #endif /* __OSL_CLOSURES_H__ */

View File

@@ -174,7 +174,6 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr
/* this is only used for shader and object space, we don't really have /* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */ * a concept of shader space, so we just use object space for both. */
if (xform) { if (xform) {
KernelGlobals *kg = kernel_globals;
const ShaderData *sd = (const ShaderData *)xform; const ShaderData *sd = (const ShaderData *)xform;
int object = sd->object; int object = sd->object;
@@ -182,6 +181,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
Transform tfm = sd->ob_tfm; Transform tfm = sd->ob_tfm;
#else #else
KernelGlobals *kg = kernel_globals;
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
#endif #endif
tfm = transform_transpose(tfm); tfm = transform_transpose(tfm);
@@ -199,7 +199,6 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform
/* this is only used for shader and object space, we don't really have /* this is only used for shader and object space, we don't really have
* a concept of shader space, so we just use object space for both. */ * a concept of shader space, so we just use object space for both. */
if (xform) { if (xform) {
KernelGlobals *kg = kernel_globals;
const ShaderData *sd = (const ShaderData *)xform; const ShaderData *sd = (const ShaderData *)xform;
int object = sd->object; int object = sd->object;
@@ -207,6 +206,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform
#ifdef __OBJECT_MOTION__ #ifdef __OBJECT_MOTION__
Transform tfm = sd->ob_itfm; Transform tfm = sd->ob_itfm;
#else #else
KernelGlobals *kg = kernel_globals;
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
#endif #endif
tfm = transform_transpose(tfm); tfm = transform_transpose(tfm);

View File

@@ -21,6 +21,7 @@
#include "kernel_globals.h" #include "kernel_globals.h"
#include "kernel_object.h" #include "kernel_object.h"
#include "osl_closures.h"
#include "osl_services.h" #include "osl_services.h"
#include "osl_shader.h" #include "osl_shader.h"
@@ -61,10 +62,6 @@ void OSLShader::thread_free(KernelGlobals *kg)
/* Globals */ /* Globals */
#define TO_VEC3(v) (*(OSL::Vec3 *)&(v))
#define TO_COLOR3(v) (*(OSL::Color3 *)&(v))
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
int path_flag, OSL::ShaderGlobals *globals) int path_flag, OSL::ShaderGlobals *globals)
{ {
@@ -127,39 +124,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
if (sd->num_closure == MAX_CLOSURE) if (sd->num_closure == MAX_CLOSURE)
return; return;
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)prim; CBSDFClosure *bsdf = (CBSDFClosure *)prim;
ustring scattering = bsdf->scattering(); int scattering = bsdf->scattering();
/* no caustics option */ /* no caustics option */
if (no_glossy && scattering == OSL::Labels::GLOSSY) if (no_glossy && scattering == LABEL_GLOSSY)
return; return;
/* sample weight */ /* sample weight */
float albedo = bsdf->albedo(TO_VEC3(sd->I)); float sample_weight = fabsf(average(weight));
float sample_weight = fabsf(average(weight)) * albedo;
sd->flag |= bsdf->shaderdata_flag();
sc.sample_weight = sample_weight; sc.sample_weight = sample_weight;
sc.type = bsdf->shaderclosure_type();
/* scattering flags */
if (scattering == OSL::Labels::DIFFUSE) {
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL;
sc.type = CLOSURE_BSDF_DIFFUSE_ID;
}
else if (scattering == OSL::Labels::GLOSSY) {
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
sc.type = CLOSURE_BSDF_GLOSSY_ID;
}
else if (scattering == OSL::Labels::STRAIGHT) {
sd->flag |= SD_BSDF;
sc.type = CLOSURE_BSDF_TRANSPARENT_ID;
}
else {
/* todo: we don't actually have a way to determine if
* this closure will reflect/transmit. could add our own
* own scattering flag that do give this info */
sd->flag |= SD_BSDF;
sc.type = CLOSURE_BSDF_GLOSSY_ID;
}
/* add */ /* add */
sd->closure[sd->num_closure++] = sc; sd->closure[sd->num_closure++] = sc;
@@ -406,54 +384,34 @@ void OSLShader::release(KernelGlobals *kg, ShaderData *sd)
int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf) int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
{ {
OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure *)sc->prim; CBSDFClosure *sample_bsdf = (CBSDFClosure *)sc->prim;
int label = LABEL_NONE;
pdf = 0.0f; pdf = 0.0f;
/* sample BSDF closure */ return sample_bsdf->sample(sd->Ng,
ustring ulabel; sd->I, sd->dI.dx, sd->dI.dy,
randu, randv,
ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng), omega_in, domega_in.dx, domega_in.dy,
TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy), pdf, eval);
randu, randv,
TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
pdf, TO_COLOR3(eval));
/* convert OSL label */
if (ulabel == OSL::Labels::REFLECT)
label = LABEL_REFLECT;
else if (ulabel == OSL::Labels::TRANSMIT)
label = LABEL_TRANSMIT;
else
return LABEL_NONE; /* sampling failed */
/* convert scattering to our bitflag label */
ustring uscattering = sample_bsdf->scattering();
if (uscattering == OSL::Labels::DIFFUSE)
label |= LABEL_DIFFUSE;
else if (uscattering == OSL::Labels::GLOSSY)
label |= LABEL_GLOSSY;
else if (uscattering == OSL::Labels::SINGULAR)
label |= LABEL_SINGULAR;
else
label |= LABEL_TRANSPARENT;
return label;
} }
float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf) float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
{ {
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)sc->prim; CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
OSL::Color3 bsdf_eval; float3 bsdf_eval;
if (dot(sd->Ng, omega_in) >= 0.0f) if (dot(sd->Ng, omega_in) >= 0.0f)
bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf);
else else
bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf);
return TO_FLOAT3(bsdf_eval); return bsdf_eval;
}
void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness)
{
CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
bsdf->blur(roughness);
} }
/* Emissive Closure */ /* Emissive Closure */
@@ -468,7 +426,7 @@ float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
/* Volume Closure */ /* Volume Closure */
float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{ {
OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim; OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim;
OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out)); OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));

View File

@@ -72,10 +72,11 @@ public:
float3& eval, float3& omega_in, differential3& domega_in, float& pdf); float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
const float3& omega_in, float& pdf); const float3& omega_in, float& pdf);
static void bsdf_blur(ShaderClosure *sc, float roughness);
static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc); static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, static float3 volume_eval_phase(const ShaderClosure *sc,
const float3 omega_in, const float3 omega_out); const float3 omega_in, const float3 omega_out);
/* release */ /* release */

View File

@@ -1,141 +0,0 @@
/*
* Adapted from Open Shading Language with this license:
*
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
* All Rights Reserved.
*
* Modifications Copyright 2011, Blender Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <OpenImageIO/fmath.h>
#include <OSL/genclosure.h>
#include "osl_closures.h"
CCL_NAMESPACE_BEGIN
using namespace OSL;
// Computes scattering properties based on Jensen's reparameterization
// described in:
// http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/
class SubsurfaceClosure : public VolumeClosure {
public:
float m_g;
float m_eta;
Color3 m_mfp, m_albedo;
static float root_find_Rd(const float Rd0, const float A) {
// quick exit for trivial cases
if (Rd0 <= 0) return 0;
const float A43 = A * 4.0f / 3.0f;
// Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection
// method can be used because this function is monotonicaly increasing.
float lo = 0, hi = 1;
for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient
// eval function at midpoint
float alpha = 0.5f * (lo + hi);
float a1 = sqrtf(3 * (1 - alpha));
float e1 = expf(-a1);
float e2 = expf(-A43 * a1);
float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0;
if (fabsf(Rd) < 1e-6f)
return alpha; // close enough
else if (Rd > 0)
hi = alpha; // root is on left side
else
lo = alpha; // root is on right side
}
// didn't quite converge, pick result in the middle of remaining interval
return 0.5f * (lo + hi);
}
SubsurfaceClosure() {
}
void setup()
{
ior(m_eta);
if (m_g >= 0.99f) m_g = 0.99f;
if (m_g <= -0.99f) m_g = -0.99f;
// eq.10
float inv_eta = 1 / m_eta;
float Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta;
float A = (1 + Fdr) / (1 - Fdr);
// compute sigma_s, sigma_a (eq.16)
Color3 alpha_prime = Color3(root_find_Rd(m_albedo[0], A),
root_find_Rd(m_albedo[1], A),
root_find_Rd(m_albedo[2], A));
Color3 sigma_t_prime = Color3(m_mfp.x > 0 ? 1.0f / (m_mfp[0] * sqrtf(3 * (1 - alpha_prime[0]))) : 0.0f,
m_mfp.y > 0 ? 1.0f / (m_mfp[1] * sqrtf(3 * (1 - alpha_prime[1]))) : 0.0f,
m_mfp.z > 0 ? 1.0f / (m_mfp[2] * sqrtf(3 * (1 - alpha_prime[2]))) : 0.0f);
Color3 sigma_s_prime = alpha_prime * sigma_t_prime;
sigma_s((1.0f / (1 - m_g)) * sigma_s_prime);
sigma_a(sigma_t_prime - sigma_s_prime);
}
bool mergeable(const ClosurePrimitive *other) const {
const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other;
return m_g == comp->m_g && VolumeClosure::mergeable(other);
}
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "subsurface"; }
void print_on(std::ostream &out) const {
out << name() << " ()";
}
virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const {
float costheta = omega_in.dot(omega_out);
float ph = 0.25f * float(M_1_PI) * ((1 - m_g * m_g) / powf(1 + m_g * m_g - 2.0f * m_g * costheta, 1.5f));
return Color3(ph, ph, ph);
}
};
ClosureParam *closure_subsurface_params()
{
static ClosureParam params[] = {
CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_eta),
CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_g),
CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_mfp),
CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_albedo),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(SubsurfaceClosure)
};
return params;
}
CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure)
CCL_NAMESPACE_END

View File

@@ -16,17 +16,17 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "bsdf_ashikhmin_velvet.h" #include "../closure/bsdf_ashikhmin_velvet.h"
#include "bsdf_diffuse.h" #include "../closure/bsdf_diffuse.h"
#include "bsdf_oren_nayar.h" #include "../closure/bsdf_oren_nayar.h"
#include "bsdf_microfacet.h" #include "../closure/bsdf_microfacet.h"
#include "bsdf_reflection.h" #include "../closure/bsdf_reflection.h"
#include "bsdf_refraction.h" #include "../closure/bsdf_refraction.h"
#include "bsdf_transparent.h" #include "../closure/bsdf_transparent.h"
#ifdef __DPDU__ #ifdef __DPDU__
#include "bsdf_ward.h" #include "../closure/bsdf_ward.h"
#endif #endif
#include "bsdf_westin.h" #include "../closure/bsdf_westin.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN

View File

@@ -23,16 +23,31 @@ CCL_NAMESPACE_BEGIN
__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
{ {
if(type == CLOSURE_BSDF_REFRACTION_ID) { if(type == CLOSURE_BSDF_REFRACTION_ID) {
if(refract) if(refract) {
bsdf_refraction_setup(sd, sc, eta); sc->data0 = eta;
sd->flag |= bsdf_refraction_setup(sc);
}
else else
bsdf_reflection_setup(sd, sc); sd->flag |= bsdf_reflection_setup(sc);
} }
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
bsdf_microfacet_beckmann_setup(sd, sc, roughness, eta, refract); sc->data0 = roughness;
sc->data1 = eta;
if(refract)
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
else
sd->flag |= bsdf_microfacet_beckmann_setup(sc);
}
else {
sc->data0 = roughness;
sc->data1 = eta;
if(refract)
sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
else
sd->flag |= bsdf_microfacet_ggx_setup(sc);
} }
else
bsdf_microfacet_ggx_setup(sd, sc, roughness, eta, refract);
} }
__device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd) __device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd)
@@ -91,24 +106,28 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float roughness = param1; float roughness = param1;
if(roughness == 0.0f)
bsdf_diffuse_setup(sd, sc); if(roughness == 0.0f) {
else sd->flag |= bsdf_diffuse_setup(sc);
bsdf_oren_nayar_setup(sd, sc, roughness); }
else {
sc->data0 = roughness;
sd->flag |= bsdf_oren_nayar_setup(sc);
}
break; break;
} }
case CLOSURE_BSDF_TRANSLUCENT_ID: { case CLOSURE_BSDF_TRANSLUCENT_ID: {
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N; sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
bsdf_translucent_setup(sd, sc); sd->flag |= bsdf_translucent_setup(sc);
break; break;
} }
case CLOSURE_BSDF_TRANSPARENT_ID: { case CLOSURE_BSDF_TRANSPARENT_ID: {
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N; sc->N = N;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
bsdf_transparent_setup(sd, sc); sd->flag |= bsdf_transparent_setup(sc);
break; break;
} }
case CLOSURE_BSDF_REFLECTION_ID: case CLOSURE_BSDF_REFLECTION_ID:
@@ -120,17 +139,16 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
#endif #endif
ShaderClosure *sc = svm_node_closure_get(sd); ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N; sc->N = N;
sc->data0 = param1;
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float roughness = param1;
/* setup bsdf */ /* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID) if(type == CLOSURE_BSDF_REFLECTION_ID)
bsdf_reflection_setup(sd, sc); sd->flag |= bsdf_reflection_setup(sc);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
bsdf_microfacet_beckmann_setup(sd, sc, roughness, 1.0f, false); sd->flag |= bsdf_microfacet_beckmann_setup(sc);
else else
bsdf_microfacet_ggx_setup(sd, sc, roughness, 1.0f, false); sd->flag |= bsdf_microfacet_ggx_setup(sc);
break; break;
} }
@@ -193,10 +211,10 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
sc->T = stack_load_float3(stack, data_node.z); sc->T = stack_load_float3(stack, data_node.z);
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float roughness_u = param1; sc->data0 = param1;
float roughness_v = param2; sc->data1 = param2;
bsdf_ward_setup(sd, sc, roughness_u, roughness_v); sd->flag |= bsdf_ward_setup(sc);
break; break;
} }
#endif #endif
@@ -206,8 +224,8 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
/* sigma */ /* sigma */
float sigma = clamp(param1, 0.0f, 1.0f); sc->data0 = clamp(param1, 0.0f, 1.0f);
bsdf_ashikhmin_velvet_setup(sd, sc, sigma); sd->flag |= bsdf_ashikhmin_velvet_setup(sc);
break; break;
} }
default: default:
@@ -240,7 +258,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float density = param1; float density = param1;
volume_transparent_setup(sd, sc, density); sd->flag |= volume_transparent_setup(sc, density);
break; break;
} }
case CLOSURE_VOLUME_ISOTROPIC_ID: { case CLOSURE_VOLUME_ISOTROPIC_ID: {
@@ -248,7 +266,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *
svm_node_closure_set_mix_weight(sc, mix_weight); svm_node_closure_set_mix_weight(sc, mix_weight);
float density = param1; float density = param1;
volume_isotropic_setup(sd, sc, density); sd->flag |= volume_isotropic_setup(sc, density);
break; break;
} }
default: default:

View File

@@ -206,6 +206,8 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
return true; return true;
if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT) if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT)
return true; return true;
if(strcmp(input->name, "Normal") == 0)
return true;
} }
else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump"))
return true; return true;