style cleanup

This commit is contained in:
Campbell Barton
2012-06-04 22:44:58 +00:00
parent f94123a5c6
commit 2d290040a1
22 changed files with 1682 additions and 1635 deletions

View File

@@ -48,17 +48,17 @@ using namespace OSL;
///
class GenericBackgroundClosure : public BackgroundClosure {
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() << " ()";
}
};
@@ -72,27 +72,29 @@ public:
///
class HoldoutClosure : ClosurePrimitive {
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[] = {
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(GenericBackgroundClosure) };
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(GenericBackgroundClosure)
};
CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
ClosureParam closure_holdout_params[] = {
CLOSURE_FINISH_PARAM(HoldoutClosure) };
CLOSURE_FINISH_PARAM(HoldoutClosure)
};
CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)

View File

@@ -44,132 +44,134 @@ using namespace OSL;
class AshikhminVelvetClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_sigma;
float m_invsigma2;
Vec3 m_N;
float m_sigma;
float m_invsigma2;
AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) { }
AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup()
{
m_sigma = max(m_sigma, 0.01f);
m_invsigma2 = 1.0f/(m_sigma * m_sigma);
}
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "ashikhmin_velvet"; }
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 << ")";
}
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
{
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();
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));
float cosNH = m_N.dot(H);
float cosHO = fabsf(omega_out.dot(H));
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = max(cosNHdivHO, 0.00001f);
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = max(cosNHdivHO, 0.00001f);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
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;
float out = 0.25f * (D * G) / cosNO;
pdf = 0.5f * (float) M_1_PI;
return Color3 (out, out, out);
}
return Color3 (0, 0, 0);
}
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);
}
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();
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));
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));
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = max(cosNHdivHO, 0.00001f);
float cosNHdivHO = cosNH / cosHO;
cosNHdivHO = max(cosNHdivHO, 0.00001f);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float sinNH2 = 1 - cosNH * cosNH;
float sinNH4 = sinNH2 * sinNH2;
float cotangent2 = (cosNH * cosNH) / sinNH2;
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
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;
float power = 0.25f * (D * G) / cosNO;
eval.setValue(power, power, power);
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;
return Labels::REFLECT;
}
// 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;
return Labels::REFLECT;
}
};
ClosureParam bsdf_ashikhmin_velvet_params[] = {
CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N),
CLOSURE_FLOAT_PARAM (AshikhminVelvetClosure, m_sigma),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(AshikhminVelvetClosure) };
CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N),
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, m_sigma),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(AshikhminVelvetClosure)
};
CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure)

View File

@@ -44,137 +44,141 @@ using namespace OSL;
class DiffuseClosure : public BSDFClosure {
public:
Vec3 m_N;
Vec3 m_N;
DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) { }
DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup() {};
void setup() {};
bool mergeable (const ClosurePrimitive *other) const {
const DiffuseClosure *comp = (const DiffuseClosure *)other;
return m_N == comp->m_N && BSDFClosure::mergeable(other);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "diffuse"; }
const char *name() const { return "diffuse"; }
void print_on (std::ostream &out) const
{
out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
}
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;
}
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_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);
}
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;
}
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;
Vec3 m_N;
TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) { }
TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) {}
void setup() {};
void setup() {};
bool mergeable (const ClosurePrimitive *other) const {
const TranslucentClosure *comp = (const TranslucentClosure *)other;
return m_N == comp->m_N && BSDFClosure::mergeable(other);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "translucent"; }
const char *name() const { return "translucent"; }
void print_on (std::ostream &out) const
{
out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
}
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);
}
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;
}
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);
}
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;
}
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[] = {
CLOSURE_VECTOR_PARAM (DiffuseClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM (DiffuseClosure) };
CLOSURE_VECTOR_PARAM(DiffuseClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(DiffuseClosure)
};
ClosureParam bsdf_translucent_params[] = {
CLOSURE_VECTOR_PARAM (TranslucentClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM (TranslucentClosure) };
CLOSURE_VECTOR_PARAM(TranslucentClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(TranslucentClosure)
};
CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure)
CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure)

View File

@@ -52,85 +52,85 @@ CCL_NAMESPACE_BEGIN
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; }
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()
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const {
return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx";
}
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 << ")";
}
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
{
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_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);
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:
@@ -148,122 +148,123 @@ public:
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);
}
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;
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;
// 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);
}
}
}
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);
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;
// 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;
}
}
}
}
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
}
};
// microfacet model with Beckmann facet distribution
@@ -271,89 +272,92 @@ public:
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) { }
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()
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);
}
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); }
size_t memsize() const {
return sizeof(*this);
}
const char * name () const {
return Refractive ? "microfacet_beckmann_refraction"
: "microfacet_beckmann";
}
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 << ")";
}
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
{
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_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);
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:
@@ -373,156 +377,161 @@ public:
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);
}
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;
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;
// 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);
}
}
}
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;
// 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;
}
}
}
}
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
}
};
ClosureParam bsdf_microfacet_ggx_params[] = {
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N),
CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<0>, m_ag),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>) };
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N),
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<0>, m_ag),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>)
};
ClosureParam bsdf_microfacet_ggx_refraction_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>) };
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>)
};
ClosureParam bsdf_microfacet_beckmann_params[] = {
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N),
CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<0>, m_ab),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>) };
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N),
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<0>, m_ab),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>)
};
ClosureParam bsdf_microfacet_beckmann_refraction_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>) };
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>)
};
CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>)
CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>)

View File

@@ -26,13 +26,13 @@ CCL_NAMESPACE_BEGIN
using namespace OSL;
class OrenNayarClosure: public BSDFClosure {
class OrenNayarClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_sigma;
float m_a, m_b;
OrenNayarClosure(): BSDFClosure(Labels::DIFFUSE) {}
OrenNayarClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup() {
m_sigma = clamp(m_sigma, 0.0f, 1.0f);
@@ -43,19 +43,19 @@ public:
m_b = m_sigma * div;
}
bool mergeable(const ClosurePrimitive* other) const {
const OrenNayarClosure* comp = static_cast<const OrenNayarClosure*>(other);
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);
m_N == comp->m_N &&
m_sigma == comp->m_sigma &&
BSDFClosure::mergeable(other);
}
size_t memsize() const {
return sizeof(*this);
}
const char* name() const {
const char *name() const {
return "oren_nayar";
}
@@ -87,13 +87,13 @@ public:
}
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);
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);
@@ -118,7 +118,7 @@ private:
float nv = max(n.dot(v), 0.0f);
float t = l.dot(v) - nl * nv;
if(t > 0.0f) {
if (t > 0.0f) {
t /= max(nl, nv) + 1e-8f;
}
return nl * (m_a + m_b * t);
@@ -126,10 +126,10 @@ private:
};
ClosureParam bsdf_oren_nayar_params[] = {
CLOSURE_VECTOR_PARAM (OrenNayarClosure, m_N),
CLOSURE_FLOAT_PARAM (OrenNayarClosure, m_sigma),
CLOSURE_STRING_KEYPARAM ("label"),
CLOSURE_FINISH_PARAM (OrenNayarClosure)
CLOSURE_VECTOR_PARAM(OrenNayarClosure, m_N),
CLOSURE_FLOAT_PARAM(OrenNayarClosure, m_sigma),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(OrenNayarClosure)
};
CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure)

View File

@@ -42,65 +42,66 @@ using namespace OSL;
class ReflectionClosure : public BSDFClosure {
public:
Vec3 m_N; // shading normal
ReflectionClosure() : BSDFClosure(Labels::SINGULAR) { }
Vec3 m_N; // shading normal
ReflectionClosure() : BSDFClosure(Labels::SINGULAR) {}
void setup() {};
void setup() {};
bool mergeable (const ClosurePrimitive *other) const {
const ReflectionClosure *comp = (const ReflectionClosure *)other;
return m_N == comp->m_N && BSDFClosure::mergeable(other);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "reflection"; }
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] << "))";
}
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;
}
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_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);
}
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;
}
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[] = {
CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(ReflectionClosure) };
CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(ReflectionClosure)
};
CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure)

View File

@@ -42,77 +42,78 @@ 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) { }
Vec3 m_N; // shading normal
float m_eta; // ratio of indices of refraction (inside / outside)
RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) {}
void setup() {}
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "refraction"; }
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 << ")";
}
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_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);
}
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
{
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;
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);
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;
}
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;
}
return Labels::TRANSMIT;
}
};
ClosureParam bsdf_refraction_params[] = {
CLOSURE_VECTOR_PARAM(RefractionClosure, m_N),
CLOSURE_FLOAT_PARAM (RefractionClosure, m_eta),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(RefractionClosure) };
CLOSURE_VECTOR_PARAM(RefractionClosure, m_N),
CLOSURE_FLOAT_PARAM(RefractionClosure, m_eta),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(RefractionClosure)
};
CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure)

View File

@@ -42,54 +42,55 @@ using namespace OSL;
class TransparentClosure : public BSDFClosure {
public:
TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) { }
TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) {}
void setup() {}
void setup() {}
size_t memsize () const { return sizeof(*this); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "transparent"; }
const char *name() const { return "transparent"; }
void print_on (std::ostream &out) const {
out << name() << " ()";
}
void print_on(std::ostream &out) const {
out << name() << " ()";
}
float albedo (const Vec3 &omega_out) const
{
return 1.0f;
}
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_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);
}
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;
}
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[] = {
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(TransparentClosure) };
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(TransparentClosure)
};
CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure)

View File

@@ -46,175 +46,179 @@ using namespace OSL;
// 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) { }
Vec3 m_N;
Vec3 m_T;
float m_ax, m_ay;
WardClosure() : BSDFClosure(Labels::GLOSSY) {}
void setup()
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "ward"; }
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 << ")";
}
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;
}
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_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);
}
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);
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;
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;
// 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;
}
}
}
}
return Labels::REFLECT;
}
};
ClosureParam bsdf_ward_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) };
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)
};
CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure)

View File

@@ -44,193 +44,197 @@ using namespace OSL;
class WestinBackscatterClosure : public BSDFClosure {
public:
Vec3 m_N;
float m_roughness;
float m_invroughness;
WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) { }
Vec3 m_N;
float m_roughness;
float m_invroughness;
WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) {}
void setup()
{
void setup()
{
m_roughness = clamp(m_roughness, 1e-5f, 1.0f);
m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0;
}
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "westin_backscatter"; }
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 << ")";
}
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;
}
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_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);
}
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;
}
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;
Vec3 m_N;
float m_edginess;
// float m_normalization;
WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) { }
WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) {}
void setup() {};
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "westin_sheen"; }
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 << ")";
}
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;
}
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_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);
}
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;
}
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[] = {
CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N),
CLOSURE_FLOAT_PARAM (WestinBackscatterClosure, m_roughness),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(WestinBackscatterClosure) };
CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N),
CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, m_roughness),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(WestinBackscatterClosure)
};
ClosureParam bsdf_westin_sheen_params[] = {
CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N),
CLOSURE_FLOAT_PARAM (WestinSheenClosure, m_edginess),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(WestinSheenClosure) };
CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N),
CLOSURE_FLOAT_PARAM(WestinSheenClosure, m_edginess),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(WestinSheenClosure)
};
CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure)
CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure)

View File

@@ -42,62 +42,63 @@ using namespace OSL;
class BSSRDFCubicClosure : public BSSRDFClosure {
public:
Color3 m_radius;
Color3 m_scale;
float m_max_radius;
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 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; }
template <typename T>
static inline T pow5(const T &x) { T x2 = x * x; return x2 * x2 * x; }
BSSRDFCubicClosure() { }
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]);
}
}
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "bssrdf_cubic"; }
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] << "))";
}
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);
}
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;
}
float max_radius() const
{
return m_max_radius;
}
};
ClosureParam closure_bssrdf_cubic_params[] = {
CLOSURE_COLOR_PARAM (BSSRDFCubicClosure, m_radius),
CLOSURE_STRING_KEYPARAM ("label"),
CLOSURE_FINISH_PARAM(BSSRDFCubicClosure) };
CLOSURE_COLOR_PARAM(BSSRDFCubicClosure, m_radius),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(BSSRDFCubicClosure)
};
CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure)

View File

@@ -49,30 +49,31 @@ using namespace OSL;
class DebugClosure : public ClosurePrimitive {
public:
ustring m_tag;
ustring m_tag;
DebugClosure () : ClosurePrimitive (Debug) { }
DebugClosure () : ClosurePrimitive(Debug) {}
bool mergeable (const ClosurePrimitive *other) const {
const DebugClosure *comp = (const DebugClosure *)other;
return m_tag == comp->m_tag &&
ClosurePrimitive::mergeable(other);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "debug"; }
const char *name() const { return "debug"; }
void print_on (std::ostream &out) const {
out << name() << " (\"" << m_tag.c_str() << "\")";
}
void print_on(std::ostream &out) const {
out << name() << " (\"" << m_tag.c_str() << "\")";
}
};
ClosureParam closure_debug_params[] = {
CLOSURE_STRING_PARAM(DebugClosure, m_tag),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(DebugClosure) };
CLOSURE_STRING_PARAM(DebugClosure, m_tag),
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(DebugClosure)
};
CLOSURE_PREPARE(closure_debug_prepare, DebugClosure)

View File

@@ -49,57 +49,58 @@ using namespace OSL;
///
class GenericEmissiveClosure : public EmissiveClosure {
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 {
out << name() << "()";
}
void print_on(std::ostream &out) const {
out << name() << "()";
}
Color3 eval (const Vec3 &Ng, const Vec3 &omega_out) const
{
float cosNO = fabsf(Ng.dot(omega_out));
float res = cosNO > 0 ? 1.0f: 0.0f;
return Color3(res, res, res);
}
Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
{
float cosNO = fabsf(Ng.dot(omega_out));
float res = cosNO > 0 ? 1.0f : 0.0f;
return Color3(res, res, res);
}
void sample (const Vec3 &Ng, float randu, float randv,
Vec3 &omega_out, float &pdf) const
{
// We don't do anything sophisticated here for the step
// We just sample the whole cone uniformly to the cosine
Vec3 T, B;
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);
}
void sample(const Vec3 &Ng, float randu, float randv,
Vec3 &omega_out, float &pdf) const
{
// We don't do anything sophisticated here for the step
// We just sample the whole cone uniformly to the cosine
Vec3 T, B;
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,
/// 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 cosNO > 0 ? 1.0f: 0.0f;
}
/// Return the probability distribution function in the direction omega_out,
/// 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 cosNO > 0 ? 1.0f : 0.0f;
}
};
ClosureParam closure_emission_params[] = {
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(GenericEmissiveClosure) };
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(GenericEmissiveClosure)
};
CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)

View File

@@ -18,18 +18,18 @@
float color_srgb_to_scene_linear(float c)
{
if(c < 0.04045)
return (c < 0.0)? 0.0: c * (1.0/12.92);
if (c < 0.04045)
return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
else
return pow((c + 0.055)*(1.0/1.055), 2.4);
return pow((c + 0.055) * (1.0 / 1.055), 2.4);
}
float color_scene_linear_to_srgb(float c)
{
if(c < 0.0031308)
return (c < 0.0)? 0.0: c * 12.92;
else
return 1.055 * pow(c, 1.0/2.4) - 0.055;
if (c < 0.0031308)
return (c < 0.0) ? 0.0 : c * 12.92;
else
return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
}
color color_srgb_to_scene_linear(color c)
@@ -61,27 +61,27 @@ color rgb_to_hsv(color rgb)
v = cmax;
if(cmax != 0.0) {
s = cdelta/cmax;
if (cmax != 0.0) {
s = cdelta / cmax;
}
else {
s = 0.0;
h = 0.0;
}
if(s == 0.0) {
if (s == 0.0) {
h = 0.0;
}
else {
c = (color(cmax, cmax, cmax) - rgb)/cdelta;
c = (color(cmax, cmax, cmax) - rgb) / cdelta;
if(rgb[0] == cmax) h = c[2] - c[1];
else if(rgb[1] == cmax) h = 2.0 + c[0] - c[2];
if (rgb[0] == cmax) h = c[2] - c[1];
else if (rgb[1] == cmax) h = 2.0 + c[0] - c[2];
else h = 4.0 + c[1] - c[0];
h /= 6.0;
if(h < 0.0)
if (h < 0.0)
h += 1.0;
}
@@ -97,26 +97,26 @@ color hsv_to_rgb(color hsv)
s = hsv[1];
v = hsv[2];
if(s==0.0) {
if (s == 0.0) {
rgb = color(v, v, v);
}
else {
if(h==1.0)
if (h == 1.0)
h = 0.0;
h *= 6.0;
i = floor(h);
f = h - i;
rgb = color(f, f, f);
p = v*(1.0-s);
q = v*(1.0-(s*f));
t = v*(1.0-(s*(1.0-f)));
if(i == 0.0) rgb = color(v, t, p);
else if(i == 1.0) rgb = color(q, v, p);
else if(i == 2.0) rgb = color(p, v, t);
else if(i == 3.0) rgb = color(p, q, v);
else if(i == 4.0) rgb = color(t, p, v);
p = v * (1.0 - s);
q = v * (1.0 - (s * f));
t = v * (1.0 - (s * (1.0 - f)));
if (i == 0.0) rgb = color(v, t, p);
else if (i == 1.0) rgb = color(q, v, p);
else if (i == 2.0) rgb = color(p, v, t);
else if (i == 3.0) rgb = color(p, q, v);
else if (i == 4.0) rgb = color(t, p, v);
else rgb = color(v, p, q);
}

View File

@@ -7,11 +7,11 @@ float fresnel_dielectric(vector Incoming, normal Normal, float eta)
float g = eta * eta - 1 + c * c;
float result;
if(g > 0) {
if (g > 0) {
g = sqrt(g);
float A =(g - c)/(g + c);
float B =(c *(g + c)- 1)/(c *(g - c)+ 1);
result = 0.5 * A * A *(1 + B * B);
float A = (g - c) / (g + c);
float B = (c * (g + c) - 1) / (c * (g - c) + 1);
result = 0.5 * A * A * (1 + B * B);
}
else
result = 1.0; /* TIR (no refracted component) */

View File

@@ -20,20 +20,20 @@ float voronoi_distance(string distance_metric, vector d, float e)
{
float result = 0.0;
if(distance_metric == "Distance Squared")
if (distance_metric == "Distance Squared")
result = dot(d, d);
if(distance_metric == "Actual Distance")
if (distance_metric == "Actual Distance")
result = length(d);
if(distance_metric == "Manhattan")
if (distance_metric == "Manhattan")
result = fabs(d[0]) + fabs(d[1]) + fabs(d[2]);
if(distance_metric == "Chebychev")
if (distance_metric == "Chebychev")
result = max(fabs(d[0]), max(fabs(d[1]), fabs(d[2])));
if(distance_metric == "Minkovsky 1/2")
if (distance_metric == "Minkovsky 1/2")
result = sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1]));
if(distance_metric == "Minkovsky 4")
result = sqrt(sqrt(dot(d*d, d*d)));
if(distance_metric == "Minkovsky")
result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0/e);
if (distance_metric == "Minkovsky 4")
result = sqrt(sqrt(dot(d * d, d * d)));
if (distance_metric == "Minkovsky")
result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0 / e);
return result;
}
@@ -63,9 +63,9 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
da[2] = 1e10;
da[3] = 1e10;
for(xx = xi-1; xx <= xi+1; xx++) {
for(yy = yi-1; yy <= yi+1; yy++) {
for(zz = zi-1; zz <= zi+1; zz++) {
for (xx = xi - 1; xx <= xi + 1; xx++) {
for (yy = yi - 1; yy <= yi + 1; yy++) {
for (zz = zi - 1; zz <= zi + 1; zz++) {
point ip = point(xx, yy, zz);
point vp = (point)cellnoise_color(ip);
point pd = p - (vp + ip);
@@ -73,7 +73,7 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
vp += point(xx, yy, zz);
if(d < da[0]) {
if (d < da[0]) {
da[3] = da[2];
da[2] = da[1];
da[1] = da[0];
@@ -84,7 +84,7 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
pa[1] = pa[0];
pa[0] = vp;
}
else if(d < da[1]) {
else if (d < da[1]) {
da[3] = da[2];
da[2] = da[1];
da[1] = d;
@@ -93,14 +93,14 @@ void voronoi(point p, string distance_metric, float e, float da[4], point pa[4])
pa[2] = pa[1];
pa[1] = vp;
}
else if(d < da[2]) {
else if (d < da[2]) {
da[3] = da[2];
da[2] = d;
pa[3] = pa[2];
pa[2] = vp;
}
else if(d < da[3]) {
else if (d < da[3]) {
da[3] = d;
pa[3] = vp;
}
@@ -138,16 +138,16 @@ float voronoi_F1F2(point p) { return voronoi_FnFn(p, 0, 1); }
float voronoi_Cr(point p)
{
/* crackle type pattern, just a scale/clamp of F2-F1 */
float t = 10.0*voronoi_F1F2(p);
return (t > 1.0)? 1.0: t;
float t = 10.0 * voronoi_F1F2(p);
return (t > 1.0) ? 1.0 : t;
}
float voronoi_F1S(point p) { return 2.0*voronoi_F1(p) - 1.0; }
float voronoi_F2S(point p) { return 2.0*voronoi_F2(p) - 1.0; }
float voronoi_F3S(point p) { return 2.0*voronoi_F3(p) - 1.0; }
float voronoi_F4S(point p) { return 2.0*voronoi_F4(p) - 1.0; }
float voronoi_F1F2S(point p) { return 2.0*voronoi_F1F2(p) - 1.0; }
float voronoi_CrS(point p) { return 2.0*voronoi_Cr(p) - 1.0; }
float voronoi_F1S(point p) { return 2.0 * voronoi_F1(p) - 1.0; }
float voronoi_F2S(point p) { return 2.0 * voronoi_F2(p) - 1.0; }
float voronoi_F3S(point p) { return 2.0 * voronoi_F3(p) - 1.0; }
float voronoi_F4S(point p) { return 2.0 * voronoi_F4(p) - 1.0; }
float voronoi_F1F2S(point p) { return 2.0 * voronoi_F1F2(p) - 1.0; }
float voronoi_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; }
/* Noise Bases */
@@ -155,21 +155,21 @@ float noise_basis(point p, string basis)
{
float result = 0.0;
if(basis == "Perlin")
if (basis == "Perlin")
result = noise(p);
if(basis == "Voronoi F1")
if (basis == "Voronoi F1")
result = voronoi_F1S(p);
if(basis == "Voronoi F2")
if (basis == "Voronoi F2")
result = voronoi_F2S(p);
if(basis == "Voronoi F3")
if (basis == "Voronoi F3")
result = voronoi_F3S(p);
if(basis == "Voronoi F4")
if (basis == "Voronoi F4")
result = voronoi_F4S(p);
if(basis == "Voronoi F2-F1")
if (basis == "Voronoi F2-F1")
result = voronoi_F1F2S(p);
if(basis == "Voronoi Crackle")
if (basis == "Voronoi Crackle")
result = voronoi_CrS(p);
if(basis == "Cell Noise")
if (basis == "Cell Noise")
result = cellnoise(p);
return result;
@@ -180,7 +180,7 @@ float noise_basis(point p, string basis)
float noise_basis_hard(point p, string basis, int hard)
{
float t = noise_basis(p, basis);
return (hard)? fabs(2.0*t - 1.0): t;
return (hard) ? fabs(2.0 * t - 1.0) : t;
}
/* Waves */
@@ -189,22 +189,22 @@ float noise_wave(string wave, float a)
{
float result = 0.0;
if(wave == "Sine") {
result = 0.5 + 0.5*sin(a);
if (wave == "Sine") {
result = 0.5 + 0.5 * sin(a);
}
else if(wave == "Saw") {
float b = 2*M_PI;
else if (wave == "Saw") {
float b = 2 * M_PI;
int n = (int)(a / b);
a -= n*b;
if(a < 0) a += b;
a -= n * b;
if (a < 0) a += b;
result = a / b;
}
else if(wave == "Tri") {
float b = 2*M_PI;
else if (wave == "Tri") {
float b = 2 * M_PI;
float rmax = 1.0;
result = rmax - 2.0*fabs(floor((a*(1.0/b))+0.5) - (a*(1.0/b)));
result = rmax - 2.0 * fabs(floor((a * (1.0 / b)) + 0.5) - (a * (1.0 / b)));
}
return result;
@@ -219,18 +219,18 @@ float noise_turbulence(point p, string basis, int octaves, int hard)
float sum = 0.0;
int i;
for(i = 0; i <= octaves; i++) {
float t = noise_basis(fscale*p, basis);
for (i = 0; i <= octaves; i++) {
float t = noise_basis(fscale * p, basis);
if(hard)
t = fabs(2.0*t - 1.0);
if (hard)
t = fabs(2.0 * t - 1.0);
sum += t*amp;
sum += t * amp;
amp *= 0.5;
fscale *= 2.0;
}
sum *= ((float)(1 << octaves)/(float)((1 << (octaves+1)) - 1));
sum *= ((float)(1 << octaves) / (float)((1 << (octaves + 1)) - 1));
return sum;
}
@@ -241,8 +241,8 @@ float nonzero(float f, float eps)
{
float r;
if(abs(f) < eps)
r = sign(f)*eps;
if (abs(f) < eps)
r = sign(f) * eps;
else
r = f;

View File

@@ -163,241 +163,246 @@ vector normalize (vector v) BUILTIN;
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
vector faceforward (vector N, vector I) BUILTIN;
vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; }
vector refract (vector I, vector N, float eta) {
float IdotN = dot (I, N);
float k = 1 - eta*eta * (1 - IdotN*IdotN);
return (k < 0) ? vector(0,0,0) : (eta*I - N * (eta*IdotN + sqrt(k)));
vector refract(vector I, vector N, float eta) {
float IdotN = dot(I, N);
float k = 1 - eta * eta * (1 - IdotN * IdotN);
return (k < 0) ? vector(0, 0, 0) : (eta * I - N * (eta * IdotN + sqrt(k)));
}
void fresnel (vector I, normal N, float eta,
output float Kr, output float Kt,
output vector R, output vector T)
void fresnel(vector I, normal N, float eta,
output float Kr, output float Kt,
output vector R, output vector T)
{
float sqr(float x) { return x*x; }
float c = dot(I, N);
if (c < 0)
c = -c;
R = reflect(I, N);
float g = 1.0 / sqr(eta) - 1.0 + c * c;
if (g >= 0.0) {
g = sqrt (g);
float beta = g - c;
float F = (c * (g+c) - 1.0) / (c * beta + 1.0);
F = 0.5 * (1.0 + sqr(F));
F *= sqr (beta / (g+c));
Kr = F;
Kt = (1.0 - Kr) * eta*eta;
// OPT: the following recomputes some of the above values, but it
// gives us the same result as if the shader-writer called refract()
T = refract(I, N, eta);
} else {
// total internal reflection
Kr = 1.0;
Kt = 0.0;
T = vector (0,0,0);
}
float sqr(float x) {
return x * x;
}
float c = dot(I, N);
if (c < 0)
c = -c;
R = reflect(I, N);
float g = 1.0 / sqr(eta) - 1.0 + c * c;
if (g >= 0.0) {
g = sqrt(g);
float beta = g - c;
float F = (c * (g + c) - 1.0) / (c * beta + 1.0);
F = 0.5 * (1.0 + sqr(F));
F *= sqr(beta / (g + c));
Kr = F;
Kt = (1.0 - Kr) * eta * eta;
// OPT: the following recomputes some of the above values, but it
// gives us the same result as if the shader-writer called refract()
T = refract(I, N, eta);
}
else {
// total internal reflection
Kr = 1.0;
Kt = 0.0;
T = vector(0, 0, 0);
}
#undef sqr
}
void fresnel (vector I, normal N, float eta,
output float Kr, output float Kt)
void fresnel(vector I, normal N, float eta,
output float Kr, output float Kt)
{
vector R, T;
fresnel(I, N, eta, Kr, Kt, R, T);
vector R, T;
fresnel(I, N, eta, Kr, Kt, R, T);
}
point rotate (point q, float angle, point a, point b) BUILTIN;
point rotate(point q, float angle, point a, point b) BUILTIN;
normal transform (matrix Mto, normal p) BUILTIN;
vector transform (matrix Mto, vector p) BUILTIN;
point transform (matrix Mto, point p) BUILTIN;
normal transform(matrix Mto, normal p) BUILTIN;
vector transform(matrix Mto, vector p) BUILTIN;
point transform(matrix Mto, point p) BUILTIN;
// Implementation of transform-with-named-space in terms of matrices:
point transform (string tospace, point x)
point transform(string tospace, point x)
{
return transform (matrix ("common", tospace), x);
return transform(matrix("common", tospace), x);
}
point transform (string fromspace, string tospace, point x)
point transform(string fromspace, string tospace, point x)
{
return transform (matrix (fromspace, tospace), x);
return transform(matrix(fromspace, tospace), x);
}
vector transform (string tospace, vector x)
vector transform(string tospace, vector x)
{
return transform (matrix ("common", tospace), x);
return transform(matrix("common", tospace), x);
}
vector transform (string fromspace, string tospace, vector x)
vector transform(string fromspace, string tospace, vector x)
{
return transform (matrix (fromspace, tospace), x);
return transform(matrix(fromspace, tospace), x);
}
normal transform (string tospace, normal x)
normal transform(string tospace, normal x)
{
return transform (matrix ("common", tospace), x);
return transform(matrix("common", tospace), x);
}
normal transform (string fromspace, string tospace, normal x)
normal transform(string fromspace, string tospace, normal x)
{
return transform (matrix (fromspace, tospace), x);
return transform(matrix(fromspace, tospace), x);
}
float transformu (string tounits, float x) BUILTIN;
float transformu (string fromunits, string tounits, float x) BUILTIN;
float transformu(string tounits, float x) BUILTIN;
float transformu(string fromunits, string tounits, float x) BUILTIN;
// Color functions
float luminance (color c) {
return dot ((vector)c, vector(0.2126, 0.7152, 0.0722));
float luminance(color c) {
return dot((vector)c, vector(0.2126, 0.7152, 0.0722));
}
color transformc (string to, color x)
color transformc(string to, color x)
{
color rgb_to_hsv (color rgb) { // See Foley & van Dam
float r = rgb[0], g = rgb[1], b = rgb[2];
float mincomp = min (r, min (g, b));
float maxcomp = max (r, max (g, b));
float delta = maxcomp - mincomp; // chroma
float h, s, v;
v = maxcomp;
if (maxcomp > 0)
s = delta / maxcomp;
else s = 0;
if (s <= 0)
h = 0;
else {
if (r >= maxcomp) h = (g-b) / delta;
else if (g >= maxcomp) h = 2 + (b-r) / delta;
else h = 4 + (r-g) / delta;
h /= 6;
if (h < 0)
h += 1;
}
return color (h, s, v);
}
color rgb_to_hsv(color rgb) { // See Foley & van Dam
float r = rgb[0], g = rgb[1], b = rgb[2];
float mincomp = min(r, min(g, b));
float maxcomp = max(r, max(g, b));
float delta = maxcomp - mincomp; // chroma
float h, s, v;
v = maxcomp;
if (maxcomp > 0)
s = delta / maxcomp;
else s = 0;
if (s <= 0)
h = 0;
else {
if (r >= maxcomp) h = (g - b) / delta;
else if (g >= maxcomp) h = 2 + (b - r) / delta;
else h = 4 + (r - g) / delta;
h /= 6;
if (h < 0)
h += 1;
}
return color(h, s, v);
}
color rgb_to_hsl (color rgb) { // See Foley & van Dam
// First convert rgb to hsv, then to hsl
float minval = min (rgb[0], min (rgb[1], rgb[2]));
color hsv = rgb_to_hsv (rgb);
float maxval = hsv[2]; // v == maxval
float h = hsv[0], s, l = (minval+maxval) / 2;
if (minval == maxval)
s = 0; // special 'achromatic' case, hue is 0
else if (l <= 0.5)
s = (maxval - minval) / (maxval + minval);
else
s = (maxval - minval) / (2 - maxval - minval);
return color (h, s, l);
}
color rgb_to_hsl(color rgb) { // See Foley & van Dam
// First convert rgb to hsv, then to hsl
float minval = min(rgb[0], min(rgb[1], rgb[2]));
color hsv = rgb_to_hsv(rgb);
float maxval = hsv[2]; // v == maxval
float h = hsv[0], s, l = (minval + maxval) / 2;
if (minval == maxval)
s = 0; // special 'achromatic' case, hue is 0
else if (l <= 0.5)
s = (maxval - minval) / (maxval + minval);
else
s = (maxval - minval) / (2 - maxval - minval);
return color(h, s, l);
}
color r;
if (to == "rgb" || to == "RGB")
r = x;
else if (to == "hsv")
r = rgb_to_hsv (x);
else if (to == "hsl")
r = rgb_to_hsl (x);
else if (to == "YIQ")
r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
dot (vector(0.596, -0.275, -0.321), (vector)x),
dot (vector(0.212, -0.523, 0.311), (vector)x));
else if (to == "xyz")
r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
else {
error ("Unknown color space \"%s\"", to);
r = x;
}
return r;
color r;
if (to == "rgb" || to == "RGB")
r = x;
else if (to == "hsv")
r = rgb_to_hsv(x);
else if (to == "hsl")
r = rgb_to_hsl(x);
else if (to == "YIQ")
r = color(dot(vector(0.299, 0.587, 0.114), (vector)x),
dot(vector(0.596, -0.275, -0.321), (vector)x),
dot(vector(0.212, -0.523, 0.311), (vector)x));
else if (to == "xyz")
r = color(dot(vector(0.412453, 0.357580, 0.180423), (vector)x),
dot(vector(0.212671, 0.715160, 0.072169), (vector)x),
dot(vector(0.019334, 0.119193, 0.950227), (vector)x));
else {
error("Unknown color space \"%s\"", to);
r = x;
}
return r;
}
color transformc (string from, string to, color x)
color transformc(string from, string to, color x)
{
color hsv_to_rgb (color c) { // Reference: Foley & van Dam
float h = c[0], s = c[1], v = c[2];
color r;
if (s < 0.0001) {
r = v;
} else {
h = 6 * (h - floor(h)); // expand to [0..6)
int hi = (int)h;
float f = h - hi;
float p = v * (1-s);
float q = v * (1-s*f);
float t = v * (1-s*(1-f));
if (hi == 0) r = color (v, t, p);
else if (hi == 1) r = color (q, v, p);
else if (hi == 2) r = color (p, v, t);
else if (hi == 3) r = color (p, q, v);
else if (hi == 4) r = color (t, p, v);
else r = color (v, p, q);
}
return r;
}
color hsv_to_rgb(color c) { // Reference: Foley & van Dam
float h = c[0], s = c[1], v = c[2];
color r;
if (s < 0.0001) {
r = v;
}
else {
h = 6 * (h - floor(h)); // expand to [0..6)
int hi = (int)h;
float f = h - hi;
float p = v * (1 - s);
float q = v * (1 - s * f);
float t = v * (1 - s * (1 - f));
if (hi == 0) r = color(v, t, p);
else if (hi == 1) r = color(q, v, p);
else if (hi == 2) r = color(p, v, t);
else if (hi == 3) r = color(p, q, v);
else if (hi == 4) r = color(t, p, v);
else r = color(v, p, q);
}
return r;
}
color hsl_to_rgb (color c) {
float h = c[0], s = c[1], l = c[2];
// Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
color r;
if (v <= 0) {
r = 0;
} else {
float min = 2 * l - v;
s = (v - min) / v;
r = hsv_to_rgb (color (h, s, v));
}
return r;
}
color hsl_to_rgb(color c) {
float h = c[0], s = c[1], l = c[2];
// Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
color r;
if (v <= 0) {
r = 0;
}
else {
float min = 2 * l - v;
s = (v - min) / v;
r = hsv_to_rgb(color(h, s, v));
}
return r;
}
color r;
if (from == "rgb" || from == "RGB")
r = x;
else if (from == "hsv")
r = hsv_to_rgb (x);
else if (from == "hsl")
r = hsl_to_rgb (x);
else if (from == "YIQ")
r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
dot (vector(1, -0.2716, -0.6469), (vector)x),
dot (vector(1, -1.1082, 1.7051), (vector)x));
else if (from == "xyz")
r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
dot (vector(-0.969256, 1.875991, 0.041556), (vector)x),
dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
else {
error ("Unknown color space \"%s\"", to);
r = x;
}
return transformc (to, r);
color r;
if (from == "rgb" || from == "RGB")
r = x;
else if (from == "hsv")
r = hsv_to_rgb(x);
else if (from == "hsl")
r = hsl_to_rgb(x);
else if (from == "YIQ")
r = color(dot(vector(1, 0.9557, 0.6199), (vector)x),
dot(vector(1, -0.2716, -0.6469), (vector)x),
dot(vector(1, -1.1082, 1.7051), (vector)x));
else if (from == "xyz")
r = color(dot(vector(3.240479, -1.537150, -0.498535), (vector)x),
dot(vector(-0.969256, 1.875991, 0.041556), (vector)x),
dot(vector(0.055648, -0.204043, 1.057311), (vector)x));
else {
error("Unknown color space \"%s\"", to);
r = x;
}
return transformc(to, r);
}
// Matrix functions
float determinant (matrix m) BUILTIN;
matrix transpose (matrix m) BUILTIN;
float determinant(matrix m) BUILTIN;
matrix transpose(matrix m) BUILTIN;
// Pattern generation
float step (float edge, float x) BUILTIN;
color step (color edge, color x) BUILTIN;
point step (point edge, point x) BUILTIN;
vector step (vector edge, vector x) BUILTIN;
normal step (normal edge, normal x) BUILTIN;
float smoothstep (float edge0, float edge1, float x) BUILTIN;
float step(float edge, float x) BUILTIN;
color step(color edge, color x) BUILTIN;
point step(point edge, point x) BUILTIN;
vector step(vector edge, vector x) BUILTIN;
normal step(normal edge, normal x) BUILTIN;
float smoothstep(float edge0, float edge1, float x) BUILTIN;
// Derivatives and area operators
@@ -408,24 +413,26 @@ float smoothstep (float edge0, float edge1, float x) BUILTIN;
// String functions
int strlen (string s) BUILTIN;
int startswith (string s, string prefix) BUILTIN;
int endswith (string s, string suffix) BUILTIN;
string substr (string s, int start, int len) BUILTIN;
string substr (string s, int start) { return substr (s, start, strlen(s)); }
int strlen(string s) BUILTIN;
int startswith(string s, string prefix) BUILTIN;
int endswith(string s, string suffix) BUILTIN;
string substr(string s, int start, int len) BUILTIN;
string substr(string s, int start) {
return substr(s, start, strlen(s));
}
// Define concat in terms of shorter concat
string concat (string a, string b, string c) {
return concat(concat(a,b), c);
string concat(string a, string b, string c) {
return concat(concat(a, b), c);
}
string concat (string a, string b, string c, string d) {
return concat(concat(a,b,c), d);
string concat(string a, string b, string c, string d) {
return concat(concat(a, b, c), d);
}
string concat (string a, string b, string c, string d, string e) {
return concat(concat(a,b,c,d), e);
string concat(string a, string b, string c, string d, string e) {
return concat(concat(a, b, c, d), e);
}
string concat (string a, string b, string c, string d, string e, string f) {
return concat(concat(a,b,c,d,e), f);
string concat(string a, string b, string c, string d, string e, string f) {
return concat(concat(a, b, c, d, e), f);
}
@@ -438,7 +445,7 @@ closure color diffuse(normal N) BUILTIN;
closure color oren_nayar(normal N, float sigma) BUILTIN;
closure color translucent(normal N) BUILTIN;
closure color reflection(normal N, float eta) BUILTIN;
closure color reflection(normal N) { return reflection (N, 0.0); }
closure color reflection(normal N) { return reflection(N, 0.0); }
closure color refraction(normal N, float eta) BUILTIN;
closure color dielectric(normal N, float eta) BUILTIN;
closure color transparent() BUILTIN;
@@ -446,7 +453,7 @@ closure color microfacet_ggx(normal N, float ag) BUILTIN;
closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
closure color microfacet_beckmann(normal N, float ab) BUILTIN;
closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN;
closure color ward(normal N, vector T,float ax, float ay) BUILTIN;
closure color ward(normal N, vector T, float ax, float ay) BUILTIN;
closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
closure color westin_backscatter(normal N, float roughness) BUILTIN;
closure color westin_sheen(normal N, float edginess) BUILTIN;
@@ -460,7 +467,7 @@ closure color holdout() BUILTIN;
closure color subsurface(float eta, float g, float mfp, float albedo) BUILTIN;
// Renderer state
int raytype (string typename) BUILTIN;
int raytype(string typename) BUILTIN;
#undef BUILTIN
#undef BUILTIN_DERIV

View File

@@ -37,7 +37,7 @@ CCL_NAMESPACE_BEGIN
/* RenderServices implementation */
#define TO_MATRIX44(m) (*(OSL::Matrix44*)&(m))
#define TO_MATRIX44(m) (*(OSL::Matrix44 *)&(m))
/* static ustrings */
ustring OSLRenderServices::u_distance("distance");
@@ -66,12 +66,12 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr
{
/* 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. */
if(xform) {
if (xform) {
KernelGlobals *kg = kernel_globals;
const ShaderData *sd = (const ShaderData*)xform;
const ShaderData *sd = (const ShaderData *)xform;
int object = sd->object;
if(object != ~0) {
if (object != ~0) {
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
tfm = transform_transpose(tfm);
result = TO_MATRIX44(tfm);
@@ -87,12 +87,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform
{
/* 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. */
if(xform) {
if (xform) {
KernelGlobals *kg = kernel_globals;
const ShaderData *sd = (const ShaderData*)xform;
const ShaderData *sd = (const ShaderData *)xform;
int object = sd->object;
if(object != ~0) {
if (object != ~0) {
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
tfm = transform_transpose(tfm);
result = TO_MATRIX44(tfm);
@@ -108,22 +108,22 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti
{
KernelGlobals *kg = kernel_globals;
if(from == u_ndc) {
if (from == u_ndc) {
Transform tfm = transform_transpose(kernel_data.cam.ndctoworld);
result = TO_MATRIX44(tfm);
return true;
}
else if(from == u_raster) {
else if (from == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
result = TO_MATRIX44(tfm);
return true;
}
else if(from == u_screen) {
else if (from == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
result = TO_MATRIX44(tfm);
return true;
}
else if(from == u_camera) {
else if (from == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
result = TO_MATRIX44(tfm);
return true;
@@ -136,22 +136,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl
{
KernelGlobals *kg = kernel_globals;
if(to == u_ndc) {
if (to == u_ndc) {
Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
result = TO_MATRIX44(tfm);
return true;
}
else if(to == u_raster) {
else if (to == u_raster) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
result = TO_MATRIX44(tfm);
return true;
}
else if(to == u_screen) {
else if (to == u_screen) {
Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
result = TO_MATRIX44(tfm);
return true;
}
else if(to == u_camera) {
else if (to == u_camera) {
Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
result = TO_MATRIX44(tfm);
return true;
@@ -161,56 +161,57 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl
}
bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives,
ustring object, TypeDesc type, ustring name,
int index, void *val)
ustring object, TypeDesc type, ustring name,
int index, void *val)
{
return false;
}
static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd,
const OSLGlobals::Attribute& attr, bool derivatives, void *val)
const OSLGlobals::Attribute& attr, bool derivatives, void *val)
{
if(attr.type == TypeDesc::TypeFloat) {
float *fval = (float*)val;
if (attr.type == TypeDesc::TypeFloat) {
float *fval = (float *)val;
fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
(derivatives)? &fval[1]: NULL, (derivatives)? &fval[2]: NULL);
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
}
else {
/* todo: this won't work when float3 has w component */
float3 *fval = (float3*)val;
float3 *fval = (float3 *)val;
fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
(derivatives)? &fval[1]: NULL, (derivatives)? &fval[2]: NULL);
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
}
return true;
}
static bool get_mesh_attribute_convert(KernelGlobals *kg, const ShaderData *sd,
const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val)
const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val)
{
if(attr.type == TypeDesc::TypeFloat) {
if (attr.type == TypeDesc::TypeFloat) {
float tmp[3];
float3 *fval = (float3*)val;
float3 *fval = (float3 *)val;
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
fval[0] = make_float3(tmp[0], tmp[0], tmp[0]);
if(derivatives) {
if (derivatives) {
fval[1] = make_float3(tmp[1], tmp[1], tmp[1]);
fval[2] = make_float3(tmp[2], tmp[2], tmp[2]);
}
return true;
}
else if(attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
{
float3 tmp[3];
float *fval = (float*)val;
float *fval = (float *)val;
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
fval[0] = average(tmp[0]);
if(derivatives) {
if (derivatives) {
fval[1] = average(tmp[1]);
fval[2] = average(tmp[2]);
}
@@ -226,29 +227,29 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat
size_t datasize = attr.value.datasize();
memcpy(val, attr.value.data(), datasize);
if(derivatives)
memset((char*)val + datasize, 0, datasize*2);
if (derivatives)
memset((char *)val + datasize, 0, datasize * 2);
}
bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name,
TypeDesc type, ustring name, void *val)
TypeDesc type, ustring name, void *val)
{
KernelGlobals *kg = kernel_globals;
const ShaderData *sd = (const ShaderData*)renderstate;
const ShaderData *sd = (const ShaderData *)renderstate;
int object = sd->object;
int tri = sd->prim;
/* lookup of attribute on another object */
if(object_name != u_empty) {
if (object_name != u_empty) {
OSLGlobals::ObjectNameMap::iterator it = kg->osl.object_name_map.find(object_name);
if(it == kg->osl.object_name_map.end())
if (it == kg->osl.object_name_map.end())
return false;
object = it->second;
tri = ~0;
}
else if(object == ~0) {
else if (object == ~0) {
/* no background attributes supported */
return false;
}
@@ -257,20 +258,23 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
OSLGlobals::AttributeMap& attribute_map = kg->osl.attribute_map[object];
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
if(it == attribute_map.end())
if (it == attribute_map.end())
return false;
/* type mistmatch? */
const OSLGlobals::Attribute& attr = it->second;
if(attr.elem != ATTR_ELEMENT_VALUE) {
if (attr.elem != ATTR_ELEMENT_VALUE) {
/* triangle and vertex attributes */
if(tri != ~0) {
if(attr.type == type || (attr.type == TypeDesc::TypeColor &&
(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal)))
if (tri != ~0) {
if (attr.type == type || (attr.type == TypeDesc::TypeColor &&
(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal)))
{
return get_mesh_attribute(kg, sd, attr, derivatives, val);
else
}
else {
return get_mesh_attribute_convert(kg, sd, attr, type, derivatives, val);
}
}
}
else {
@@ -283,7 +287,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
}
bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type,
void *renderstate, void *val)
void *renderstate, void *val)
{
return false; /* disabled by lockgeom */
}
@@ -294,7 +298,7 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst
}
void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names,
TypeDesc *attr_types, int nattrs)
TypeDesc *attr_types, int nattrs)
{
#ifdef WITH_PARTIO
m_attr_queries.push_back(AttrQuery());
@@ -308,28 +312,32 @@ void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names,
to the query. Just to prevent buffer overruns */
query.capacity = -1;
for(int i = 0; i < nattrs; ++i)
{
for (int i = 0; i < nattrs; ++i) {
query.attr_names[i] = attr_names[i];
TypeDesc element_type = attr_types[i].elementtype ();
TypeDesc element_type = attr_types[i].elementtype();
if(query.capacity < 0)
query.capacity = attr_types[i].numelements();
if (query.capacity < 0)
query.capacity = attr_types[i].numelements();
else
query.capacity = min(query.capacity, (int)attr_types[i].numelements());
query.capacity = min(query.capacity, (int)attr_types[i].numelements());
/* convert the OSL (OIIO) type to the equivalent Partio type so
we can do a fast check at query time. */
if(element_type == TypeDesc::TypeFloat)
query.attr_partio_types[i] = Partio::FLOAT;
else if(element_type == TypeDesc::TypeInt)
query.attr_partio_types[i] = Partio::INT;
else if(element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint ||
element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal)
query.attr_partio_types[i] = Partio::VECTOR;
else
return NULL; /* report some error of unknown type */
if (element_type == TypeDesc::TypeFloat) {
query.attr_partio_types[i] = Partio::FLOAT;
}
else if (element_type == TypeDesc::TypeInt) {
query.attr_partio_types[i] = Partio::INT;
}
else if (element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint ||
element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal)
{
query.attr_partio_types[i] = Partio::VECTOR;
}
else {
return NULL; /* report some error of unknown type */
}
}
/* this is valid until the end of RenderServices */
@@ -348,18 +356,18 @@ Partio::ParticlesData *OSLRenderServices::get_pointcloud(ustring filename)
#endif
int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 &center, float radius,
int max_points, void *_attr_query, void **attr_outdata)
int max_points, void *_attr_query, void **attr_outdata)
{
/* todo: this code has never been tested, and most likely does not
work. it's based on the example code in OSL */
#ifdef WITH_PARTIO
/* query Partio for this pointcloud lookup using cached attr_query */
if(!_attr_query)
if (!_attr_query)
return 0;
AttrQuery *attr_query = (AttrQuery *)_attr_query;
if(attr_query->capacity < max_points)
if (attr_query->capacity < max_points)
return 0;
/* get the pointcloud entry for the given filename */
@@ -370,13 +378,13 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 &center, flo
int nattrs = attr_query->attr_names.size();
Partio::ParticleAttribute *attr = (Partio::ParticleAttribute *)alloca(sizeof(Partio::ParticleAttribute) * nattrs);
for(int i = 0; i < nattrs; ++i) {
for (int i = 0; i < nattrs; ++i) {
/* special case attributes */
if(attr_query->attr_names[i] == u_distance || attr_query->attr_names[i] == u_index)
if (attr_query->attr_names[i] == u_distance || attr_query->attr_names[i] == u_index)
continue;
/* lookup the attribute by name*/
if(!cloud->attributeInfo(attr_query->attr_names[i].c_str(), attr[i])) {
if (!cloud->attributeInfo(attr_query->attr_names[i].c_str(), attr[i])) {
/* issue an error here and return, types don't match */
Partio::endCachedAccess(cloud);
cloud->release();
@@ -394,14 +402,14 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 &center, flo
int count = indices.size();
/* retrieve the attributes directly to user space */
for(int j = 0; j < nattrs; ++j) {
for (int j = 0; j < nattrs; ++j) {
/* special cases */
if(attr_query->attr_names[j] == u_distance) {
for(int i = 0; i < count; ++i)
if (attr_query->attr_names[j] == u_distance) {
for (int i = 0; i < count; ++i)
((float *)attr_outdata[j])[i] = sqrtf(dist2[i]);
}
else if(attr_query->attr_names[j] == u_index) {
for(int i = 0; i < count; ++i)
else if (attr_query->attr_names[j] == u_index) {
for (int i = 0; i < count; ++i)
((int *)attr_outdata[j])[i] = indices[i];
}
else {

View File

@@ -57,19 +57,19 @@ public:
bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time);
bool get_array_attribute(void *renderstate, bool derivatives,
ustring object, TypeDesc type, ustring name,
int index, void *val);
ustring object, TypeDesc type, ustring name,
int index, void *val);
bool get_attribute(void *renderstate, bool derivatives, ustring object,
TypeDesc type, ustring name, void *val);
TypeDesc type, ustring name, void *val);
bool get_userdata(bool derivatives, ustring name, TypeDesc type,
void *renderstate, void *val);
void *renderstate, void *val);
bool has_userdata(ustring name, TypeDesc type, void *renderstate);
void *get_pointcloud_attr_query(ustring *attr_names,
TypeDesc *attr_types, int nattrs);
TypeDesc *attr_types, int nattrs);
int pointcloud(ustring filename, const OSL::Vec3 &center, float radius,
int max_points, void *attr_query, void **attr_outdata);
int max_points, void *attr_query, void **attr_outdata);
private:
KernelGlobals *kernel_globals;
@@ -79,8 +79,7 @@ private:
right now it only caches the types already converted to
Partio constants. this is what get_pointcloud_attr_query
returns */
struct AttrQuery
{
struct AttrQuery {
/* names of the attributes to query */
std::vector<ustring> attr_names;
/* types as (enum Partio::ParticleAttributeType) of the

View File

@@ -37,7 +37,7 @@ tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data);
void OSLShader::thread_init(KernelGlobals *kg)
{
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData();
@@ -46,12 +46,12 @@ void OSLShader::thread_init(KernelGlobals *kg)
tls_set(kg->osl.thread_data, tdata);
((OSLRenderServices*)ssi->renderer())->thread_init(kg);
((OSLRenderServices *)ssi->renderer())->thread_init(kg);
}
void OSLShader::thread_free(KernelGlobals *kg)
{
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
@@ -62,12 +62,12 @@ void OSLShader::thread_free(KernelGlobals *kg)
/* Globals */
#define TO_VEC3(v) (*(OSL::Vec3*)&(v))
#define TO_COLOR3(v) (*(OSL::Color3*)&(v))
#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,
int path_flag, OSL::ShaderGlobals *globals)
int path_flag, OSL::ShaderGlobals *globals)
{
/* copy from shader data to shader globals */
globals->P = TO_VEC3(sd->P);
@@ -86,7 +86,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
globals->dvdy = sd->dv.dy;
globals->dPdu = TO_VEC3(sd->dPdu);
globals->dPdv = TO_VEC3(sd->dPdv);
globals->surfacearea = (sd->object == ~0)? 1.0f: object_surface_area(kg, sd->object);
globals->surfacearea = (sd->object == ~0) ? 1.0f : object_surface_area(kg, sd->object);
/* booleans */
globals->raytype = path_flag; /* todo: add our own ray types */
@@ -109,35 +109,35 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
/* Surface */
static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
/* OSL gives use a closure tree, we flatten it into arrays per
* closure type, for evaluation, sampling, etc later on. */
if(closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
if(prim) {
if (prim) {
ShaderClosure sc;
sc.prim = prim;
sc.weight = weight;
switch(prim->category()) {
switch (prim->category()) {
case ClosurePrimitive::BSDF: {
if(sd->num_closure == MAX_CLOSURE)
if (sd->num_closure == MAX_CLOSURE)
return;
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim;
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)prim;
ustring scattering = bsdf->scattering();
/* no caustics option */
if(no_glossy && scattering == OSL::Labels::GLOSSY)
if (no_glossy && scattering == OSL::Labels::GLOSSY)
return;
/* sample weight */
float albedo = bsdf->albedo(TO_VEC3(sd->I));
float sample_weight = fabsf(average(weight))*albedo;
float sample_weight = fabsf(average(weight)) * albedo;
float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight;
sc.sample_weight = sample_weight;
@@ -145,10 +145,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
sd->osl_closure.bsdf_sample_sum = sample_sum;
/* scattering flags */
if(scattering == OSL::Labels::DIFFUSE)
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
else if(scattering == OSL::Labels::GLOSSY)
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
if (scattering == OSL::Labels::DIFFUSE)
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL;
else if (scattering == OSL::Labels::GLOSSY)
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
else
sd->flag |= SD_BSDF;
@@ -157,7 +157,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
break;
}
case ClosurePrimitive::Emissive: {
if(sd->num_closure == MAX_CLOSURE)
if (sd->num_closure == MAX_CLOSURE)
return;
/* sample weight */
@@ -175,7 +175,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
break;
}
case ClosurePrimitive::Holdout:
if(sd->num_closure == MAX_CLOSURE)
if (sd->num_closure == MAX_CLOSURE)
return;
sc.sample_weight = 0.0f;
@@ -192,12 +192,12 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
}
}
}
else if(closure->type == OSL::ClosureColor::MUL) {
OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
else if (closure->type == OSL::ClosureColor::MUL) {
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight);
}
else if(closure->type == OSL::ClosureColor::ADD) {
OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
else if (closure->type == OSL::ClosureColor::ADD) {
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight);
flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight);
}
@@ -206,7 +206,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
{
/* gather pointers */
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
OSL::ShaderGlobals *globals = &tdata->globals;
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
@@ -218,14 +218,14 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
/* execute shader for this point */
int shader = sd->shader & SHADER_MASK;
if(kg->osl.surface_state[shader])
if (kg->osl.surface_state[shader])
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals);
/* flatten closure tree */
sd->num_closure = 0;
sd->randb_closure = randb;
if(globals->Ci) {
if (globals->Ci) {
bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
flatten_surface_closure_tree(sd, no_glossy, globals->Ci);
}
@@ -239,23 +239,23 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
* is only one supported closure type at the moment, which has no evaluation
* functions, so we just sum the weights */
if(closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
if(prim && prim->category() == OSL::ClosurePrimitive::Background)
if (prim && prim->category() == OSL::ClosurePrimitive::Background)
return make_float3(1.0f, 1.0f, 1.0f);
}
else if(closure->type == OSL::ClosureColor::MUL) {
OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
else if (closure->type == OSL::ClosureColor::MUL) {
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
}
else if(closure->type == OSL::ClosureColor::ADD) {
OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
else if (closure->type == OSL::ClosureColor::ADD) {
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
return flatten_background_closure_tree(add->closureA) +
flatten_background_closure_tree(add->closureB);
flatten_background_closure_tree(add->closureB);
}
return make_float3(0.0f, 0.0f, 0.0f);
@@ -264,7 +264,7 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
{
/* gather pointers */
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
OSL::ShaderGlobals *globals = &tdata->globals;
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
@@ -274,11 +274,11 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl
shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
/* execute shader for this point */
if(kg->osl.background_state)
if (kg->osl.background_state)
ctx->execute(OSL::pvt::ShadUseSurface, *kg->osl.background_state, *globals);
/* return background color immediately */
if(globals->Ci)
if (globals->Ci)
return flatten_background_closure_tree(globals->Ci);
return make_float3(0.0f, 0.0f, 0.0f);
@@ -287,23 +287,23 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl
/* Volume */
static void flatten_volume_closure_tree(ShaderData *sd,
const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
/* OSL gives use a closure tree, we flatten it into arrays per
* closure type, for evaluation, sampling, etc later on. */
if(closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
if (closure->type == OSL::ClosureColor::COMPONENT) {
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
if(prim) {
if (prim) {
ShaderClosure sc;
sc.prim = prim;
sc.weight = weight;
switch(prim->category()) {
switch (prim->category()) {
case ClosurePrimitive::Volume: {
if(sd->num_closure == MAX_CLOSURE)
if (sd->num_closure == MAX_CLOSURE)
return;
/* sample weight */
@@ -329,12 +329,12 @@ static void flatten_volume_closure_tree(ShaderData *sd,
}
}
}
else if(closure->type == OSL::ClosureColor::MUL) {
OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
else if (closure->type == OSL::ClosureColor::MUL) {
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
}
else if(closure->type == OSL::ClosureColor::ADD) {
OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
else if (closure->type == OSL::ClosureColor::ADD) {
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
flatten_volume_closure_tree(sd, add->closureA, weight);
flatten_volume_closure_tree(sd, add->closureB, weight);
}
@@ -343,7 +343,7 @@ static void flatten_volume_closure_tree(ShaderData *sd,
void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
{
/* gather pointers */
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
OSL::ShaderGlobals *globals = &tdata->globals;
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
@@ -355,7 +355,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
/* execute shader */
int shader = sd->shader & SHADER_MASK;
if(kg->osl.volume_state[shader])
if (kg->osl.volume_state[shader])
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals);
/* retrieve resulting closures */
@@ -363,7 +363,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
sd->osl_closure.num_volume = 0;
sd->osl_closure.randb = randb;
if(globals->Ci)
if (globals->Ci)
flatten_volume_closure_tree(sd, globals->Ci);
}
@@ -372,7 +372,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
{
/* gather pointers */
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
OSL::ShaderGlobals *globals = &tdata->globals;
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
@@ -384,7 +384,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
/* execute shader */
int shader = sd->shader & SHADER_MASK;
if(kg->osl.displacement_state[shader])
if (kg->osl.displacement_state[shader])
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals);
/* get back position */
@@ -393,17 +393,17 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
void OSLShader::release(KernelGlobals *kg, const ShaderData *sd)
{
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss;
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
ssi->release_context((OSL::pvt::ShadingContext*)sd->osl_ctx, tdata->thread_info);
ssi->release_context((OSL::pvt::ShadingContext *)sd->osl_ctx, tdata->thread_info);
}
/* BSDF Closure */
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;
OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure *)sc->prim;
int label = LABEL_NONE;
pdf = 0.0f;
@@ -412,27 +412,27 @@ int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float
ustring ulabel;
ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
randu, randv,
TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
pdf, TO_COLOR3(eval));
TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
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)
if (ulabel == OSL::Labels::REFLECT)
label = LABEL_REFLECT;
else if(ulabel == OSL::Labels::TRANSMIT)
else if (ulabel == OSL::Labels::TRANSMIT)
label = LABEL_TRANSMIT;
else
return LABEL_NONE; /* sampling failed */
return LABEL_NONE; /* sampling failed */
/* convert scattering to our bitflag label */
ustring uscattering = sample_bsdf->scattering();
if(uscattering == OSL::Labels::DIFFUSE)
if (uscattering == OSL::Labels::DIFFUSE)
label |= LABEL_DIFFUSE;
else if(uscattering == OSL::Labels::GLOSSY)
else if (uscattering == OSL::Labels::GLOSSY)
label |= LABEL_GLOSSY;
else if(uscattering == OSL::Labels::SINGULAR)
else if (uscattering == OSL::Labels::SINGULAR)
label |= LABEL_SINGULAR;
else
label |= LABEL_TRANSPARENT;
@@ -442,10 +442,10 @@ int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float
float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
{
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)sc->prim;
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)sc->prim;
OSL::Color3 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);
else
bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
@@ -457,7 +457,7 @@ float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const
float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
{
OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)sc->prim;
OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim;
OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
eval += TO_FLOAT3(emissive_eval);
@@ -468,9 +468,9 @@ float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
float3 OSLShader::volume_eval_phase(const ShaderData *sd, 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));
return TO_FLOAT3(volume_eval)*sc->weight;
return TO_FLOAT3(volume_eval) * sc->weight;
}
CCL_NAMESPACE_END

View File

@@ -68,15 +68,15 @@ public:
/* sample & eval */
static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
float randu, float randv,
float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
float randu, float randv,
float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
const float3& omega_in, float& pdf);
const float3& omega_in, float& pdf);
static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc,
const float3 omega_in, const float3 omega_out);
const float3 omega_in, const float3 omega_out);
/* release */
static void release(KernelGlobals *kg, const ShaderData *sd);

View File

@@ -46,88 +46,90 @@ using namespace OSL;
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() { }
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);
void setup()
{
ior(m_eta);
if (m_g >= 0.99f) m_g = 0.99f;
if (m_g <= -0.99f) m_g = -0.99f;
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;
// 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);
}
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);
}
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); }
size_t memsize() const { return sizeof(*this); }
const char *name () const { return "subsurface"; }
const char *name() const { return "subsurface"; }
void print_on (std::ostream &out) const {
out << name() << " ()";
}
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);
}
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[] = {
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) };
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)
};
CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure)