style cleanup
This commit is contained in:
@@ -48,17 +48,17 @@ using namespace OSL;
|
|||||||
///
|
///
|
||||||
class GenericBackgroundClosure : public BackgroundClosure {
|
class GenericBackgroundClosure : public BackgroundClosure {
|
||||||
public:
|
public:
|
||||||
GenericBackgroundClosure() { }
|
GenericBackgroundClosure() {}
|
||||||
|
|
||||||
void setup() {};
|
void setup() {};
|
||||||
|
|
||||||
size_t memsize () const { return sizeof(*this); }
|
size_t memsize() const { return sizeof(*this); }
|
||||||
|
|
||||||
const char *name () const { return "background"; }
|
const char *name() const { return "background"; }
|
||||||
|
|
||||||
void print_on (std::ostream &out) const {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " ()";
|
out << name() << " ()";
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -72,27 +72,29 @@ public:
|
|||||||
///
|
///
|
||||||
class HoldoutClosure : ClosurePrimitive {
|
class HoldoutClosure : ClosurePrimitive {
|
||||||
public:
|
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 {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " ()";
|
out << name() << " ()";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ClosureParam closure_background_params[] = {
|
ClosureParam closure_background_params[] = {
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(GenericBackgroundClosure) };
|
CLOSURE_FINISH_PARAM(GenericBackgroundClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
|
CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
|
||||||
|
|
||||||
ClosureParam closure_holdout_params[] = {
|
ClosureParam closure_holdout_params[] = {
|
||||||
CLOSURE_FINISH_PARAM(HoldoutClosure) };
|
CLOSURE_FINISH_PARAM(HoldoutClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
|
CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
|
||||||
|
|
||||||
|
@@ -44,132 +44,134 @@ using namespace OSL;
|
|||||||
|
|
||||||
class AshikhminVelvetClosure : public BSDFClosure {
|
class AshikhminVelvetClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N;
|
Vec3 m_N;
|
||||||
float m_sigma;
|
float m_sigma;
|
||||||
float m_invsigma2;
|
float m_invsigma2;
|
||||||
|
|
||||||
AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) { }
|
AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) {}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
m_sigma = max(m_sigma, 0.01f);
|
m_sigma = max(m_sigma, 0.01f);
|
||||||
m_invsigma2 = 1.0f/(m_sigma * m_sigma);
|
m_invsigma2 = 1.0f / (m_sigma * m_sigma);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other;
|
const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other;
|
||||||
return m_N == comp->m_N && m_sigma == comp->m_sigma &&
|
return m_N == comp->m_N && m_sigma == comp->m_sigma &&
|
||||||
BSDFClosure::mergeable(other);
|
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
|
void print_on(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << name() << " (";
|
out << name() << " (";
|
||||||
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||||
out << m_sigma;
|
out << m_sigma;
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNO > 0 && cosNI > 0) {
|
if (cosNO > 0 && cosNI > 0) {
|
||||||
Vec3 H = omega_in + omega_out;
|
Vec3 H = omega_in + omega_out;
|
||||||
H.normalize();
|
H.normalize();
|
||||||
|
|
||||||
float cosNH = m_N.dot(H);
|
float cosNH = m_N.dot(H);
|
||||||
float cosHO = fabsf(omega_out.dot(H));
|
float cosHO = fabsf(omega_out.dot(H));
|
||||||
|
|
||||||
float cosNHdivHO = cosNH / cosHO;
|
float cosNHdivHO = cosNH / cosHO;
|
||||||
cosNHdivHO = max(cosNHdivHO, 0.00001f);
|
cosNHdivHO = max(cosNHdivHO, 0.00001f);
|
||||||
|
|
||||||
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
||||||
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
||||||
|
|
||||||
float sinNH2 = 1 - cosNH * cosNH;
|
float sinNH2 = 1 - cosNH * cosNH;
|
||||||
float sinNH4 = sinNH2 * sinNH2;
|
float sinNH4 = sinNH2 * sinNH2;
|
||||||
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
||||||
|
|
||||||
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
|
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 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;
|
pdf = 0.5f * (float) M_1_PI;
|
||||||
return Color3 (out, out, out);
|
return Color3(out, out, out);
|
||||||
}
|
}
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
// we are viewing the surface from above - send a ray out with uniform
|
// we are viewing the surface from above - send a ray out with uniform
|
||||||
// distribution over the hemisphere
|
// distribution over the hemisphere
|
||||||
sample_uniform_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
|
sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
|
||||||
if (Ng.dot(omega_in) > 0) {
|
if (Ng.dot(omega_in) > 0) {
|
||||||
Vec3 H = omega_in + omega_out;
|
Vec3 H = omega_in + omega_out;
|
||||||
H.normalize();
|
H.normalize();
|
||||||
|
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNH = m_N.dot(H);
|
float cosNH = m_N.dot(H);
|
||||||
float cosHO = fabsf(omega_out.dot(H));
|
float cosHO = fabsf(omega_out.dot(H));
|
||||||
|
|
||||||
float cosNHdivHO = cosNH / cosHO;
|
float cosNHdivHO = cosNH / cosHO;
|
||||||
cosNHdivHO = max(cosNHdivHO, 0.00001f);
|
cosNHdivHO = max(cosNHdivHO, 0.00001f);
|
||||||
|
|
||||||
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
||||||
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
||||||
|
|
||||||
float sinNH2 = 1 - cosNH * cosNH;
|
float sinNH2 = 1 - cosNH * cosNH;
|
||||||
float sinNH4 = sinNH2 * sinNH2;
|
float sinNH4 = sinNH2 * sinNH2;
|
||||||
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
||||||
|
|
||||||
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4;
|
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 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
|
// 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_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_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
|
||||||
domega_in_dx *= 125;
|
domega_in_dx *= 125;
|
||||||
domega_in_dy *= 125;
|
domega_in_dy *= 125;
|
||||||
} else
|
}
|
||||||
pdf = 0;
|
else
|
||||||
return Labels::REFLECT;
|
pdf = 0;
|
||||||
}
|
return Labels::REFLECT;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam bsdf_ashikhmin_velvet_params[] = {
|
ClosureParam bsdf_ashikhmin_velvet_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N),
|
CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (AshikhminVelvetClosure, m_sigma),
|
CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, m_sigma),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(AshikhminVelvetClosure) };
|
CLOSURE_FINISH_PARAM(AshikhminVelvetClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure)
|
CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure)
|
||||||
|
|
||||||
|
@@ -44,137 +44,141 @@ using namespace OSL;
|
|||||||
|
|
||||||
class DiffuseClosure : public BSDFClosure {
|
class DiffuseClosure : public BSDFClosure {
|
||||||
public:
|
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 {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const DiffuseClosure *comp = (const DiffuseClosure *)other;
|
const DiffuseClosure *comp = (const DiffuseClosure *)other;
|
||||||
return m_N == comp->m_N && BSDFClosure::mergeable(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
|
void print_on(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
|
out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
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;
|
float cos_pi = max(m_N.dot(omega_in), 0.0f) * (float) M_1_PI;
|
||||||
pdf = cos_pi;
|
pdf = cos_pi;
|
||||||
return Color3 (cos_pi, cos_pi, cos_pi);
|
return Color3(cos_pi, cos_pi, cos_pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
// we are viewing the surface from the right side - send a ray out with cosine
|
// we are viewing the surface from the right side - send a ray out with cosine
|
||||||
// distribution over the hemisphere
|
// distribution over the hemisphere
|
||||||
sample_cos_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
|
sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
|
||||||
if (Ng.dot(omega_in) > 0) {
|
if (Ng.dot(omega_in) > 0) {
|
||||||
eval.setValue(pdf, pdf, pdf);
|
eval.setValue(pdf, pdf, pdf);
|
||||||
// TODO: find a better approximation for the diffuse bounce
|
// 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_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_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
|
||||||
domega_in_dx *= 125;
|
domega_in_dx *= 125;
|
||||||
domega_in_dy *= 125;
|
domega_in_dy *= 125;
|
||||||
} else
|
}
|
||||||
pdf = 0;
|
else
|
||||||
return Labels::REFLECT;
|
pdf = 0;
|
||||||
}
|
return Labels::REFLECT;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TranslucentClosure : public BSDFClosure {
|
class TranslucentClosure : public BSDFClosure {
|
||||||
public:
|
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 {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const TranslucentClosure *comp = (const TranslucentClosure *)other;
|
const TranslucentClosure *comp = (const TranslucentClosure *)other;
|
||||||
return m_N == comp->m_N && BSDFClosure::mergeable(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
|
void print_on(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
|
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
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
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;
|
float cos_pi = max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI;
|
||||||
pdf = cos_pi;
|
pdf = cos_pi;
|
||||||
return Color3 (cos_pi, cos_pi, cos_pi);
|
return Color3(cos_pi, cos_pi, cos_pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
// we are viewing the surface from the right side - send a ray out with cosine
|
// we are viewing the surface from the right side - send a ray out with cosine
|
||||||
// distribution over the hemisphere
|
// distribution over the hemisphere
|
||||||
sample_cos_hemisphere (-m_N, omega_out, randu, randv, omega_in, pdf);
|
sample_cos_hemisphere(-m_N, omega_out, randu, randv, omega_in, pdf);
|
||||||
if (Ng.dot(omega_in) < 0) {
|
if (Ng.dot(omega_in) < 0) {
|
||||||
eval.setValue(pdf, pdf, pdf);
|
eval.setValue(pdf, pdf, pdf);
|
||||||
// TODO: find a better approximation for the diffuse bounce
|
// 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_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_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
|
||||||
domega_in_dx *= -125;
|
domega_in_dx *= -125;
|
||||||
domega_in_dy *= -125;
|
domega_in_dy *= -125;
|
||||||
} else
|
}
|
||||||
pdf = 0;
|
else
|
||||||
return Labels::TRANSMIT;
|
pdf = 0;
|
||||||
}
|
return Labels::TRANSMIT;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_diffuse_params[] = {
|
ClosureParam bsdf_diffuse_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM (DiffuseClosure, m_N),
|
CLOSURE_VECTOR_PARAM(DiffuseClosure, m_N),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM (DiffuseClosure) };
|
CLOSURE_FINISH_PARAM(DiffuseClosure)
|
||||||
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_translucent_params[] = {
|
ClosureParam bsdf_translucent_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM (TranslucentClosure, m_N),
|
CLOSURE_VECTOR_PARAM(TranslucentClosure, m_N),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM (TranslucentClosure) };
|
CLOSURE_FINISH_PARAM(TranslucentClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure)
|
CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure)
|
||||||
CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure)
|
CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure)
|
||||||
|
@@ -52,85 +52,85 @@ CCL_NAMESPACE_BEGIN
|
|||||||
template <int Refractive = 0>
|
template <int Refractive = 0>
|
||||||
class MicrofacetGGXClosure : public BSDFClosure {
|
class MicrofacetGGXClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N;
|
Vec3 m_N;
|
||||||
float m_ag; // width parameter (roughness)
|
float m_ag; // width parameter (roughness)
|
||||||
float m_eta; // index of refraction (for fresnel term)
|
float m_eta; // index of refraction (for fresnel term)
|
||||||
MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; }
|
MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; }
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
m_ag = clamp(m_ag, 1e-5f, 1.0f);
|
m_ag = clamp(m_ag, 1e-5f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other;
|
const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other;
|
||||||
return m_N == comp->m_N && m_ag == comp->m_ag &&
|
return m_N == comp->m_N && m_ag == comp->m_ag &&
|
||||||
m_eta == comp->m_eta && BSDFClosure::mergeable(other);
|
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 {
|
const char *name() const {
|
||||||
return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx";
|
return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx";
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_on (std::ostream &out) const {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " (";
|
out << name() << " (";
|
||||||
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||||
out << m_ag << ", ";
|
out << m_ag << ", ";
|
||||||
out << m_eta;
|
out << m_eta;
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
if (Refractive == 1) return Color3 (0, 0, 0);
|
if (Refractive == 1) return Color3(0, 0, 0);
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNI > 0 && cosNO > 0) {
|
if (cosNI > 0 && cosNO > 0) {
|
||||||
// get half vector
|
// get half vector
|
||||||
Vec3 Hr = omega_in + omega_out;
|
Vec3 Hr = omega_in + omega_out;
|
||||||
Hr.normalize();
|
Hr.normalize();
|
||||||
// eq. 20: (F*G*D)/(4*in*on)
|
// eq. 20: (F*G*D)/(4*in*on)
|
||||||
// eq. 33: first we calculate D(m) with m=Hr:
|
// eq. 33: first we calculate D(m) with m=Hr:
|
||||||
float alpha2 = m_ag * m_ag;
|
float alpha2 = m_ag * m_ag;
|
||||||
float cosThetaM = m_N.dot(Hr);
|
float cosThetaM = m_N.dot(Hr);
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||||
// eq. 34: now calculate G1(i,m) and G1(o,m)
|
// eq. 34: now calculate G1(i,m) and G1(o,m)
|
||||||
float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
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 G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||||
float G = G1o * G1i;
|
float G = G1o * G1i;
|
||||||
float out = (G * D) * 0.25f / cosNO;
|
float out = (G * D) * 0.25f / cosNO;
|
||||||
// eq. 24
|
// eq. 24
|
||||||
float pm = D * cosThetaM;
|
float pm = D * cosThetaM;
|
||||||
// convert into pdf of the sampled direction
|
// convert into pdf of the sampled direction
|
||||||
// eq. 38 - but see also:
|
// eq. 38 - but see also:
|
||||||
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||||
pdf = pm * 0.25f / Hr.dot(omega_out);
|
pdf = pm * 0.25f / Hr.dot(omega_out);
|
||||||
return Color3 (out, out, out);
|
return Color3(out, out, out);
|
||||||
}
|
}
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
if (Refractive == 0) return Color3 (0, 0, 0);
|
if (Refractive == 0) return Color3(0, 0, 0);
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNO <= 0 || cosNI >= 0)
|
if (cosNO <= 0 || cosNI >= 0)
|
||||||
return Color3 (0, 0, 0); // vectors on same side -- not possible
|
return Color3(0, 0, 0); // vectors on same side -- not possible
|
||||||
// compute half-vector of the refraction (eq. 16)
|
// compute half-vector of the refraction (eq. 16)
|
||||||
Vec3 ht = -(m_eta * omega_in + omega_out);
|
Vec3 ht = -(m_eta * omega_in + omega_out);
|
||||||
Vec3 Ht = ht; Ht.normalize();
|
Vec3 Ht = ht; Ht.normalize();
|
||||||
float cosHO = Ht.dot(omega_out);
|
float cosHO = Ht.dot(omega_out);
|
||||||
|
|
||||||
float cosHI = Ht.dot(omega_in);
|
float cosHI = Ht.dot(omega_in);
|
||||||
// eq. 33: first we calculate D(m) with m=Ht:
|
// eq. 33: first we calculate D(m) with m=Ht:
|
||||||
@@ -148,122 +148,123 @@ public:
|
|||||||
float invHt2 = 1 / ht.dot(ht);
|
float invHt2 = 1 / ht.dot(ht);
|
||||||
pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
|
pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
|
||||||
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
|
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,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
if (cosNO > 0) {
|
if (cosNO > 0) {
|
||||||
Vec3 X, Y, Z = m_N;
|
Vec3 X, Y, Z = m_N;
|
||||||
make_orthonormals(Z, X, Y);
|
make_orthonormals(Z, X, Y);
|
||||||
// generate a random microfacet normal m
|
// generate a random microfacet normal m
|
||||||
// eq. 35,36:
|
// eq. 35,36:
|
||||||
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
||||||
// and sin(atan(x)) == x/sqrt(1+x^2)
|
// and sin(atan(x)) == x/sqrt(1+x^2)
|
||||||
float alpha2 = m_ag * m_ag;
|
float alpha2 = m_ag * m_ag;
|
||||||
float tanThetaM2 = alpha2 * randu / (1 - randu);
|
float tanThetaM2 = alpha2 * randu / (1 - randu);
|
||||||
float cosThetaM = 1 / sqrtf(1 + tanThetaM2);
|
float cosThetaM = 1 / sqrtf(1 + tanThetaM2);
|
||||||
float sinThetaM = cosThetaM * sqrtf(tanThetaM2);
|
float sinThetaM = cosThetaM * sqrtf(tanThetaM2);
|
||||||
float phiM = 2 * float(M_PI) * randv;
|
float phiM = 2 * float(M_PI) * randv;
|
||||||
Vec3 m = (cosf(phiM) * sinThetaM) * X +
|
Vec3 m = (cosf(phiM) * sinThetaM) * X +
|
||||||
(sinf(phiM) * sinThetaM) * Y +
|
(sinf(phiM) * sinThetaM) * Y +
|
||||||
cosThetaM * Z;
|
cosThetaM * Z;
|
||||||
if (Refractive == 0) {
|
if (Refractive == 0) {
|
||||||
float cosMO = m.dot(omega_out);
|
float cosMO = m.dot(omega_out);
|
||||||
if (cosMO > 0) {
|
if (cosMO > 0) {
|
||||||
// eq. 39 - compute actual reflected direction
|
// eq. 39 - compute actual reflected direction
|
||||||
omega_in = 2 * cosMO * m - omega_out;
|
omega_in = 2 * cosMO * m - omega_out;
|
||||||
if (Ng.dot(omega_in) > 0) {
|
if (Ng.dot(omega_in) > 0) {
|
||||||
// microfacet normal is visible to this ray
|
// microfacet normal is visible to this ray
|
||||||
// eq. 33
|
// eq. 33
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||||
// eq. 24
|
// eq. 24
|
||||||
float pm = D * cosThetaM;
|
float pm = D * cosThetaM;
|
||||||
// convert into pdf of the sampled direction
|
// convert into pdf of the sampled direction
|
||||||
// eq. 38 - but see also:
|
// eq. 38 - but see also:
|
||||||
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||||
pdf = pm * 0.25f / cosMO;
|
pdf = pm * 0.25f / cosMO;
|
||||||
// eval BRDF*cosNI
|
// eval BRDF*cosNI
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
// eq. 34: now calculate G1(i,m) and G1(o,m)
|
// eq. 34: now calculate G1(i,m) and G1(o,m)
|
||||||
float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
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 G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||||
float G = G1o * G1i;
|
float G = G1o * G1i;
|
||||||
// eq. 20: (F*G*D)/(4*in*on)
|
// eq. 20: (F*G*D)/(4*in*on)
|
||||||
float out = (G * D) * 0.25f / cosNO;
|
float out = (G * D) * 0.25f / cosNO;
|
||||||
eval.setValue(out, out, out);
|
eval.setValue(out, out, out);
|
||||||
domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx;
|
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;
|
domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy;
|
||||||
|
|
||||||
/* disabled for now - gives texture filtering problems */
|
/* disabled for now - gives texture filtering problems */
|
||||||
#if 0
|
#if 0
|
||||||
// Since there is some blur to this reflection, make the
|
// Since there is some blur to this reflection, make the
|
||||||
// derivatives a bit bigger. In theory this varies with the
|
// derivatives a bit bigger. In theory this varies with the
|
||||||
// roughness but the exact relationship is complex and
|
// roughness but the exact relationship is complex and
|
||||||
// requires more ops than are practical.
|
// requires more ops than are practical.
|
||||||
domega_in_dx *= 10;
|
domega_in_dx *= 10;
|
||||||
domega_in_dy *= 10;
|
domega_in_dy *= 10;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// CAUTION: the i and o variables are inverted relative to the paper
|
else {
|
||||||
// eq. 39 - compute actual refractive direction
|
// CAUTION: the i and o variables are inverted relative to the paper
|
||||||
Vec3 R, dRdx, dRdy;
|
// eq. 39 - compute actual refractive direction
|
||||||
Vec3 T, dTdx, dTdy;
|
Vec3 R, dRdx, dRdy;
|
||||||
bool inside;
|
Vec3 T, dTdx, dTdy;
|
||||||
fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
|
bool inside;
|
||||||
R, dRdx, dRdy,
|
fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
|
||||||
T, dTdx, dTdy,
|
R, dRdx, dRdy,
|
||||||
inside);
|
T, dTdx, dTdy,
|
||||||
|
inside);
|
||||||
|
|
||||||
if (!inside) {
|
if (!inside) {
|
||||||
omega_in = T;
|
omega_in = T;
|
||||||
domega_in_dx = dTdx;
|
domega_in_dx = dTdx;
|
||||||
domega_in_dy = dTdy;
|
domega_in_dy = dTdy;
|
||||||
// eq. 33
|
// eq. 33
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||||
// eq. 24
|
// eq. 24
|
||||||
float pm = D * cosThetaM;
|
float pm = D * cosThetaM;
|
||||||
// eval BRDF*cosNI
|
// eval BRDF*cosNI
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
// eq. 34: now calculate G1(i,m) and G1(o,m)
|
// eq. 34: now calculate G1(i,m) and G1(o,m)
|
||||||
float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
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 G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||||
float G = G1o * G1i;
|
float G = G1o * G1i;
|
||||||
// eq. 21
|
// eq. 21
|
||||||
float cosHI = m.dot(omega_in);
|
float cosHI = m.dot(omega_in);
|
||||||
float cosHO = m.dot(omega_out);
|
float cosHO = m.dot(omega_out);
|
||||||
float Ht2 = m_eta * cosHI + cosHO;
|
float Ht2 = m_eta * cosHI + cosHO;
|
||||||
Ht2 *= Ht2;
|
Ht2 *= Ht2;
|
||||||
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
|
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
|
||||||
// eq. 38 and eq. 17
|
// eq. 38 and eq. 17
|
||||||
pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
|
pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
|
||||||
eval.setValue(out, out, out);
|
eval.setValue(out, out, out);
|
||||||
|
|
||||||
/* disabled for now - gives texture filtering problems */
|
/* disabled for now - gives texture filtering problems */
|
||||||
#if 0
|
#if 0
|
||||||
// Since there is some blur to this refraction, make the
|
// Since there is some blur to this refraction, make the
|
||||||
// derivatives a bit bigger. In theory this varies with the
|
// derivatives a bit bigger. In theory this varies with the
|
||||||
// roughness but the exact relationship is complex and
|
// roughness but the exact relationship is complex and
|
||||||
// requires more ops than are practical.
|
// requires more ops than are practical.
|
||||||
domega_in_dx *= 10;
|
domega_in_dx *= 10;
|
||||||
domega_in_dy *= 10;
|
domega_in_dy *= 10;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
|
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// microfacet model with Beckmann facet distribution
|
// microfacet model with Beckmann facet distribution
|
||||||
@@ -271,89 +272,92 @@ public:
|
|||||||
template <int Refractive = 0>
|
template <int Refractive = 0>
|
||||||
class MicrofacetBeckmannClosure : public BSDFClosure {
|
class MicrofacetBeckmannClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N;
|
Vec3 m_N;
|
||||||
float m_ab; // width parameter (roughness)
|
float m_ab; // width parameter (roughness)
|
||||||
float m_eta; // index of refraction (for fresnel term)
|
float m_eta; // index of refraction (for fresnel term)
|
||||||
MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { }
|
MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) {
|
||||||
|
}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
m_ab = clamp(m_ab, 1e-5f, 1.0f);
|
m_ab = clamp(m_ab, 1e-5f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other;
|
const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other;
|
||||||
return m_N == comp->m_N && m_ab == comp->m_ab &&
|
return m_N == comp->m_N && m_ab == comp->m_ab &&
|
||||||
m_eta == comp->m_eta && BSDFClosure::mergeable(other);
|
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 {
|
const char *name() const {
|
||||||
return Refractive ? "microfacet_beckmann_refraction"
|
return Refractive ? "microfacet_beckmann_refraction"
|
||||||
: "microfacet_beckmann";
|
: "microfacet_beckmann";
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_on (std::ostream &out) const
|
void print_on(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << name() << " (";
|
out << name() << " (";
|
||||||
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||||
out << m_ab << ", ";
|
out << m_ab << ", ";
|
||||||
out << m_eta;
|
out << m_eta;
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
if (Refractive == 1) return Color3 (0, 0, 0);
|
if (Refractive == 1) return Color3(0, 0, 0);
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNO > 0 && cosNI > 0) {
|
if (cosNO > 0 && cosNI > 0) {
|
||||||
// get half vector
|
// get half vector
|
||||||
Vec3 Hr = omega_in + omega_out;
|
Vec3 Hr = omega_in + omega_out;
|
||||||
Hr.normalize();
|
Hr.normalize();
|
||||||
// eq. 20: (F*G*D)/(4*in*on)
|
// eq. 20: (F*G*D)/(4*in*on)
|
||||||
// eq. 25: first we calculate D(m) with m=Hr:
|
// eq. 25: first we calculate D(m) with m=Hr:
|
||||||
float alpha2 = m_ab * m_ab;
|
float alpha2 = m_ab * m_ab;
|
||||||
float cosThetaM = m_N.dot(Hr);
|
float cosThetaM = m_N.dot(Hr);
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
|
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
|
||||||
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
|
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
|
||||||
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
|
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||||
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
|
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 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 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 G = G1o * G1i;
|
||||||
float out = (G * D) * 0.25f / cosNO;
|
float out = (G * D) * 0.25f / cosNO;
|
||||||
// eq. 24
|
// eq. 24
|
||||||
float pm = D * cosThetaM;
|
float pm = D * cosThetaM;
|
||||||
// convert into pdf of the sampled direction
|
// convert into pdf of the sampled direction
|
||||||
// eq. 38 - but see also:
|
// eq. 38 - but see also:
|
||||||
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||||
pdf = pm * 0.25f / Hr.dot(omega_out);
|
pdf = pm * 0.25f / Hr.dot(omega_out);
|
||||||
return Color3 (out, out, out);
|
return Color3(out, out, out);
|
||||||
}
|
}
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
if (Refractive == 0) return Color3 (0, 0, 0);
|
if (Refractive == 0) return Color3(0, 0, 0);
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNO <= 0 || cosNI >= 0)
|
if (cosNO <= 0 || cosNI >= 0)
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
// compute half-vector of the refraction (eq. 16)
|
// compute half-vector of the refraction (eq. 16)
|
||||||
Vec3 ht = -(m_eta * omega_in + omega_out);
|
Vec3 ht = -(m_eta * omega_in + omega_out);
|
||||||
Vec3 Ht = ht; Ht.normalize();
|
Vec3 Ht = ht; Ht.normalize();
|
||||||
float cosHO = Ht.dot(omega_out);
|
float cosHO = Ht.dot(omega_out);
|
||||||
|
|
||||||
float cosHI = Ht.dot(omega_in);
|
float cosHI = Ht.dot(omega_in);
|
||||||
// eq. 33: first we calculate D(m) with m=Ht:
|
// eq. 33: first we calculate D(m) with m=Ht:
|
||||||
@@ -373,156 +377,161 @@ public:
|
|||||||
float invHt2 = 1 / ht.dot(ht);
|
float invHt2 = 1 / ht.dot(ht);
|
||||||
pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
|
pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2;
|
||||||
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO;
|
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,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
if (cosNO > 0) {
|
if (cosNO > 0) {
|
||||||
Vec3 X, Y, Z = m_N;
|
Vec3 X, Y, Z = m_N;
|
||||||
make_orthonormals(Z, X, Y);
|
make_orthonormals(Z, X, Y);
|
||||||
// generate a random microfacet normal m
|
// generate a random microfacet normal m
|
||||||
// eq. 35,36:
|
// eq. 35,36:
|
||||||
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
||||||
// and sin(atan(x)) == x/sqrt(1+x^2)
|
// and sin(atan(x)) == x/sqrt(1+x^2)
|
||||||
float alpha2 = m_ab * m_ab;
|
float alpha2 = m_ab * m_ab;
|
||||||
float tanThetaM = sqrtf(-alpha2 * logf(1 - randu));
|
float tanThetaM = sqrtf(-alpha2 * logf(1 - randu));
|
||||||
float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM);
|
float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM);
|
||||||
float sinThetaM = cosThetaM * tanThetaM;
|
float sinThetaM = cosThetaM * tanThetaM;
|
||||||
float phiM = 2 * float(M_PI) * randv;
|
float phiM = 2 * float(M_PI) * randv;
|
||||||
Vec3 m = (cosf(phiM) * sinThetaM) * X +
|
Vec3 m = (cosf(phiM) * sinThetaM) * X +
|
||||||
(sinf(phiM) * sinThetaM) * Y +
|
(sinf(phiM) * sinThetaM) * Y +
|
||||||
cosThetaM * Z;
|
cosThetaM * Z;
|
||||||
if (Refractive == 0) {
|
if (Refractive == 0) {
|
||||||
float cosMO = m.dot(omega_out);
|
float cosMO = m.dot(omega_out);
|
||||||
if (cosMO > 0) {
|
if (cosMO > 0) {
|
||||||
// eq. 39 - compute actual reflected direction
|
// eq. 39 - compute actual reflected direction
|
||||||
omega_in = 2 * cosMO * m - omega_out;
|
omega_in = 2 * cosMO * m - omega_out;
|
||||||
if (Ng.dot(omega_in) > 0) {
|
if (Ng.dot(omega_in) > 0) {
|
||||||
// microfacet normal is visible to this ray
|
// microfacet normal is visible to this ray
|
||||||
// eq. 25
|
// eq. 25
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
float tanThetaM2 = tanThetaM * tanThetaM;
|
float tanThetaM2 = tanThetaM * tanThetaM;
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
|
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
|
||||||
// eq. 24
|
// eq. 24
|
||||||
float pm = D * cosThetaM;
|
float pm = D * cosThetaM;
|
||||||
// convert into pdf of the sampled direction
|
// convert into pdf of the sampled direction
|
||||||
// eq. 38 - but see also:
|
// eq. 38 - but see also:
|
||||||
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
// eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||||
pdf = pm * 0.25f / cosMO;
|
pdf = pm * 0.25f / cosMO;
|
||||||
// Eval BRDF*cosNI
|
// Eval BRDF*cosNI
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
|
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
|
||||||
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
|
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||||
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
|
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 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 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 G = G1o * G1i;
|
||||||
// eq. 20: (F*G*D)/(4*in*on)
|
// eq. 20: (F*G*D)/(4*in*on)
|
||||||
float out = (G * D) * 0.25f / cosNO;
|
float out = (G * D) * 0.25f / cosNO;
|
||||||
eval.setValue(out, out, out);
|
eval.setValue(out, out, out);
|
||||||
domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx;
|
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;
|
domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy;
|
||||||
|
|
||||||
/* disabled for now - gives texture filtering problems */
|
/* disabled for now - gives texture filtering problems */
|
||||||
#if 0
|
#if 0
|
||||||
// Since there is some blur to this reflection, make the
|
// Since there is some blur to this reflection, make the
|
||||||
// derivatives a bit bigger. In theory this varies with the
|
// derivatives a bit bigger. In theory this varies with the
|
||||||
// roughness but the exact relationship is complex and
|
// roughness but the exact relationship is complex and
|
||||||
// requires more ops than are practical.
|
// requires more ops than are practical.
|
||||||
domega_in_dx *= 10;
|
domega_in_dx *= 10;
|
||||||
domega_in_dy *= 10;
|
domega_in_dy *= 10;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// CAUTION: the i and o variables are inverted relative to the paper
|
else {
|
||||||
// eq. 39 - compute actual refractive direction
|
// CAUTION: the i and o variables are inverted relative to the paper
|
||||||
Vec3 R, dRdx, dRdy;
|
// eq. 39 - compute actual refractive direction
|
||||||
Vec3 T, dTdx, dTdy;
|
Vec3 R, dRdx, dRdy;
|
||||||
bool inside;
|
Vec3 T, dTdx, dTdy;
|
||||||
fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
|
bool inside;
|
||||||
R, dRdx, dRdy,
|
fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy,
|
||||||
T, dTdx, dTdy,
|
R, dRdx, dRdy,
|
||||||
inside);
|
T, dTdx, dTdy,
|
||||||
if (!inside) {
|
inside);
|
||||||
omega_in = T;
|
if (!inside) {
|
||||||
domega_in_dx = dTdx;
|
omega_in = T;
|
||||||
domega_in_dy = dTdy;
|
domega_in_dx = dTdx;
|
||||||
// eq. 33
|
domega_in_dy = dTdy;
|
||||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
// eq. 33
|
||||||
float tanThetaM2 = tanThetaM * tanThetaM;
|
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
float tanThetaM2 = tanThetaM * tanThetaM;
|
||||||
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
|
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||||
// eq. 24
|
float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4);
|
||||||
float pm = D * cosThetaM;
|
// eq. 24
|
||||||
// eval BRDF*cosNI
|
float pm = D * cosThetaM;
|
||||||
float cosNI = m_N.dot(omega_in);
|
// eval BRDF*cosNI
|
||||||
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
|
float cosNI = m_N.dot(omega_in);
|
||||||
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
|
// eq. 26, 27: now calculate G1(i,m) and G1(o,m)
|
||||||
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
|
float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||||
float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
|
float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||||
float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
|
float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
|
||||||
float G = G1o * G1i;
|
float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
|
||||||
// eq. 21
|
float G = G1o * G1i;
|
||||||
float cosHI = m.dot(omega_in);
|
// eq. 21
|
||||||
float cosHO = m.dot(omega_out);
|
float cosHI = m.dot(omega_in);
|
||||||
float Ht2 = m_eta * cosHI + cosHO;
|
float cosHO = m.dot(omega_out);
|
||||||
Ht2 *= Ht2;
|
float Ht2 = m_eta * cosHI + cosHO;
|
||||||
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
|
Ht2 *= Ht2;
|
||||||
// eq. 38 and eq. 17
|
float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2);
|
||||||
pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
|
// eq. 38 and eq. 17
|
||||||
eval.setValue(out, out, out);
|
pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2;
|
||||||
|
eval.setValue(out, out, out);
|
||||||
|
|
||||||
/* disabled for now - gives texture filtering problems */
|
/* disabled for now - gives texture filtering problems */
|
||||||
#if 0
|
#if 0
|
||||||
// Since there is some blur to this refraction, make the
|
// Since there is some blur to this refraction, make the
|
||||||
// derivatives a bit bigger. In theory this varies with the
|
// derivatives a bit bigger. In theory this varies with the
|
||||||
// roughness but the exact relationship is complex and
|
// roughness but the exact relationship is complex and
|
||||||
// requires more ops than are practical.
|
// requires more ops than are practical.
|
||||||
domega_in_dx *= 10;
|
domega_in_dx *= 10;
|
||||||
domega_in_dy *= 10;
|
domega_in_dy *= 10;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
|
return Refractive ? Labels::TRANSMIT : Labels::REFLECT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam bsdf_microfacet_ggx_params[] = {
|
ClosureParam bsdf_microfacet_ggx_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N),
|
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<0>, m_ag),
|
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<0>, m_ag),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>) };
|
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>)
|
||||||
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_microfacet_ggx_refraction_params[] = {
|
ClosureParam bsdf_microfacet_ggx_refraction_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N),
|
CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<1>, m_ag),
|
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_ag),
|
||||||
CLOSURE_FLOAT_PARAM (MicrofacetGGXClosure<1>, m_eta),
|
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_eta),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>) };
|
CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>)
|
||||||
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_microfacet_beckmann_params[] = {
|
ClosureParam bsdf_microfacet_beckmann_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N),
|
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<0>, m_ab),
|
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<0>, m_ab),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>) };
|
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>)
|
||||||
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_microfacet_beckmann_refraction_params[] = {
|
ClosureParam bsdf_microfacet_beckmann_refraction_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N),
|
CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<1>, m_ab),
|
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_ab),
|
||||||
CLOSURE_FLOAT_PARAM (MicrofacetBeckmannClosure<1>, m_eta),
|
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_eta),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>) };
|
CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>)
|
CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>)
|
||||||
CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>)
|
CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>)
|
||||||
|
@@ -26,13 +26,13 @@ CCL_NAMESPACE_BEGIN
|
|||||||
using namespace OSL;
|
using namespace OSL;
|
||||||
|
|
||||||
|
|
||||||
class OrenNayarClosure: public BSDFClosure {
|
class OrenNayarClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N;
|
Vec3 m_N;
|
||||||
float m_sigma;
|
float m_sigma;
|
||||||
float m_a, m_b;
|
float m_a, m_b;
|
||||||
|
|
||||||
OrenNayarClosure(): BSDFClosure(Labels::DIFFUSE) {}
|
OrenNayarClosure() : BSDFClosure(Labels::DIFFUSE) {}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
m_sigma = clamp(m_sigma, 0.0f, 1.0f);
|
m_sigma = clamp(m_sigma, 0.0f, 1.0f);
|
||||||
@@ -43,19 +43,19 @@ public:
|
|||||||
m_b = m_sigma * div;
|
m_b = m_sigma * div;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergeable(const ClosurePrimitive* other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const OrenNayarClosure* comp = static_cast<const OrenNayarClosure*>(other);
|
const OrenNayarClosure *comp = static_cast<const OrenNayarClosure *>(other);
|
||||||
return
|
return
|
||||||
m_N == comp->m_N &&
|
m_N == comp->m_N &&
|
||||||
m_sigma == comp->m_sigma &&
|
m_sigma == comp->m_sigma &&
|
||||||
BSDFClosure::mergeable(other);
|
BSDFClosure::mergeable(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t memsize() const {
|
size_t memsize() const {
|
||||||
return sizeof(*this);
|
return sizeof(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* name() const {
|
const char *name() const {
|
||||||
return "oren_nayar";
|
return "oren_nayar";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,13 +87,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ustring sample(
|
ustring sample(
|
||||||
const Vec3& Ng,
|
const Vec3& Ng,
|
||||||
const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy,
|
const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy,
|
Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy,
|
||||||
float& pdf, Color3& eval
|
float& pdf, Color3& eval
|
||||||
) const {
|
) const {
|
||||||
sample_uniform_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
|
sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
|
||||||
|
|
||||||
if (Ng.dot(omega_in) > 0.0f) {
|
if (Ng.dot(omega_in) > 0.0f) {
|
||||||
float is = get_intensity(m_N, omega_out, omega_in);
|
float is = get_intensity(m_N, omega_out, omega_in);
|
||||||
@@ -118,7 +118,7 @@ private:
|
|||||||
float nv = max(n.dot(v), 0.0f);
|
float nv = max(n.dot(v), 0.0f);
|
||||||
float t = l.dot(v) - nl * nv;
|
float t = l.dot(v) - nl * nv;
|
||||||
|
|
||||||
if(t > 0.0f) {
|
if (t > 0.0f) {
|
||||||
t /= max(nl, nv) + 1e-8f;
|
t /= max(nl, nv) + 1e-8f;
|
||||||
}
|
}
|
||||||
return nl * (m_a + m_b * t);
|
return nl * (m_a + m_b * t);
|
||||||
@@ -126,10 +126,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_oren_nayar_params[] = {
|
ClosureParam bsdf_oren_nayar_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM (OrenNayarClosure, m_N),
|
CLOSURE_VECTOR_PARAM(OrenNayarClosure, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (OrenNayarClosure, m_sigma),
|
CLOSURE_FLOAT_PARAM(OrenNayarClosure, m_sigma),
|
||||||
CLOSURE_STRING_KEYPARAM ("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM (OrenNayarClosure)
|
CLOSURE_FINISH_PARAM(OrenNayarClosure)
|
||||||
};
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure)
|
CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure)
|
||||||
|
@@ -42,65 +42,66 @@ using namespace OSL;
|
|||||||
|
|
||||||
class ReflectionClosure : public BSDFClosure {
|
class ReflectionClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N; // shading normal
|
Vec3 m_N; // shading normal
|
||||||
ReflectionClosure() : BSDFClosure(Labels::SINGULAR) { }
|
ReflectionClosure() : BSDFClosure(Labels::SINGULAR) {}
|
||||||
|
|
||||||
void setup() {};
|
void setup() {};
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const ReflectionClosure *comp = (const ReflectionClosure *)other;
|
const ReflectionClosure *comp = (const ReflectionClosure *)other;
|
||||||
return m_N == comp->m_N && BSDFClosure::mergeable(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 {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " (";
|
out << name() << " (";
|
||||||
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
|
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
// only one direction is possible
|
// only one direction is possible
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
if (cosNO > 0) {
|
if (cosNO > 0) {
|
||||||
omega_in = (2 * cosNO) * m_N - omega_out;
|
omega_in = (2 * cosNO) * m_N - omega_out;
|
||||||
if (Ng.dot(omega_in) > 0) {
|
if (Ng.dot(omega_in) > 0) {
|
||||||
domega_in_dx = 2 * m_N.dot(domega_out_dx) * m_N - domega_out_dx;
|
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_dy = 2 * m_N.dot(domega_out_dy) * m_N - domega_out_dy;
|
||||||
pdf = 1;
|
pdf = 1;
|
||||||
eval.setValue(1, 1, 1);
|
eval.setValue(1, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Labels::REFLECT;
|
return Labels::REFLECT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_reflection_params[] = {
|
ClosureParam bsdf_reflection_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N),
|
CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(ReflectionClosure) };
|
CLOSURE_FINISH_PARAM(ReflectionClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure)
|
CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure)
|
||||||
|
|
||||||
|
@@ -42,77 +42,78 @@ using namespace OSL;
|
|||||||
|
|
||||||
class RefractionClosure : public BSDFClosure {
|
class RefractionClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N; // shading normal
|
Vec3 m_N; // shading normal
|
||||||
float m_eta; // ratio of indices of refraction (inside / outside)
|
float m_eta; // ratio of indices of refraction (inside / outside)
|
||||||
RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) { }
|
RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) {}
|
||||||
|
|
||||||
void setup() {}
|
void setup() {}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const RefractionClosure *comp = (const RefractionClosure *)other;
|
const RefractionClosure *comp = (const RefractionClosure *)other;
|
||||||
return m_N == comp->m_N && m_eta == comp->m_eta &&
|
return m_N == comp->m_N && m_eta == comp->m_eta &&
|
||||||
BSDFClosure::mergeable(other);
|
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 {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " (";
|
out << name() << " (";
|
||||||
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||||
out << m_eta;
|
out << m_eta;
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
Vec3 R, dRdx, dRdy;
|
Vec3 R, dRdx, dRdy;
|
||||||
Vec3 T, dTdx, dTdy;
|
Vec3 T, dTdx, dTdy;
|
||||||
bool inside;
|
bool inside;
|
||||||
|
|
||||||
fresnel_dielectric(m_eta, m_N,
|
fresnel_dielectric(m_eta, m_N,
|
||||||
omega_out, domega_out_dx, domega_out_dy,
|
omega_out, domega_out_dx, domega_out_dy,
|
||||||
R, dRdx, dRdy,
|
R, dRdx, dRdy,
|
||||||
T, dTdx, dTdy,
|
T, dTdx, dTdy,
|
||||||
inside);
|
inside);
|
||||||
|
|
||||||
if (!inside) {
|
if (!inside) {
|
||||||
pdf = 1;
|
pdf = 1;
|
||||||
eval.setValue(1.0f, 1.0f, 1.0f);
|
eval.setValue(1.0f, 1.0f, 1.0f);
|
||||||
omega_in = T;
|
omega_in = T;
|
||||||
domega_in_dx = dTdx;
|
domega_in_dx = dTdx;
|
||||||
domega_in_dy = dTdy;
|
domega_in_dy = dTdy;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Labels::TRANSMIT;
|
return Labels::TRANSMIT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_refraction_params[] = {
|
ClosureParam bsdf_refraction_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(RefractionClosure, m_N),
|
CLOSURE_VECTOR_PARAM(RefractionClosure, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (RefractionClosure, m_eta),
|
CLOSURE_FLOAT_PARAM(RefractionClosure, m_eta),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(RefractionClosure) };
|
CLOSURE_FINISH_PARAM(RefractionClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure)
|
CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure)
|
||||||
|
|
||||||
|
@@ -42,54 +42,55 @@ using namespace OSL;
|
|||||||
|
|
||||||
class TransparentClosure : public BSDFClosure {
|
class TransparentClosure : public BSDFClosure {
|
||||||
public:
|
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 {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " ()";
|
out << name() << " ()";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
// only one direction is possible
|
// only one direction is possible
|
||||||
omega_in = -omega_out;
|
omega_in = -omega_out;
|
||||||
domega_in_dx = -domega_out_dx;
|
domega_in_dx = -domega_out_dx;
|
||||||
domega_in_dy = -domega_out_dy;
|
domega_in_dy = -domega_out_dy;
|
||||||
pdf = 1;
|
pdf = 1;
|
||||||
eval.setValue(1, 1, 1);
|
eval.setValue(1, 1, 1);
|
||||||
return Labels::TRANSMIT;
|
return Labels::TRANSMIT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam bsdf_transparent_params[] = {
|
ClosureParam bsdf_transparent_params[] = {
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(TransparentClosure) };
|
CLOSURE_FINISH_PARAM(TransparentClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure)
|
CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure)
|
||||||
|
|
||||||
|
@@ -46,175 +46,179 @@ using namespace OSL;
|
|||||||
// see http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
// see http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||||
class WardClosure : public BSDFClosure {
|
class WardClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N;
|
Vec3 m_N;
|
||||||
Vec3 m_T;
|
Vec3 m_T;
|
||||||
float m_ax, m_ay;
|
float m_ax, m_ay;
|
||||||
WardClosure() : BSDFClosure(Labels::GLOSSY) { }
|
WardClosure() : BSDFClosure(Labels::GLOSSY) {}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
m_ax = clamp(m_ax, 1e-5f, 1.0f);
|
m_ax = clamp(m_ax, 1e-5f, 1.0f);
|
||||||
m_ay = clamp(m_ay, 1e-5f, 1.0f);
|
m_ay = clamp(m_ay, 1e-5f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const WardClosure *comp = (const WardClosure *)other;
|
const WardClosure *comp = (const WardClosure *)other;
|
||||||
return m_N == comp->m_N && m_T == comp->m_T &&
|
return m_N == comp->m_N && m_T == comp->m_T &&
|
||||||
m_ax == comp->m_ax && m_ay == comp->m_ay &&
|
m_ax == comp->m_ax && m_ay == comp->m_ay &&
|
||||||
BSDFClosure::mergeable(other);
|
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 {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " ((";
|
out << name() << " ((";
|
||||||
out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), (";
|
out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), (";
|
||||||
out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), ";
|
out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), ";
|
||||||
out << m_ax << ", " << m_ay << ")";
|
out << m_ax << ", " << m_ay << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNI > 0 && cosNO > 0) {
|
if (cosNI > 0 && cosNO > 0) {
|
||||||
// get half vector and get x,y basis on the surface for anisotropy
|
// get half vector and get x,y basis on the surface for anisotropy
|
||||||
Vec3 H = omega_in + omega_out;
|
Vec3 H = omega_in + omega_out;
|
||||||
H.normalize(); // normalize needed for pdf
|
H.normalize(); // normalize needed for pdf
|
||||||
Vec3 X, Y;
|
Vec3 X, Y;
|
||||||
make_orthonormals(m_N, m_T, X, Y);
|
make_orthonormals(m_N, m_T, X, Y);
|
||||||
// eq. 4
|
// eq. 4
|
||||||
float dotx = H.dot(X) / m_ax;
|
float dotx = H.dot(X) / m_ax;
|
||||||
float doty = H.dot(Y) / m_ay;
|
float doty = H.dot(Y) / m_ay;
|
||||||
float dotn = H.dot(m_N);
|
float dotn = H.dot(m_N);
|
||||||
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
|
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
|
||||||
float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
|
float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
|
||||||
float exp_val = expf(-exp_arg);
|
float exp_val = expf(-exp_arg);
|
||||||
float out = cosNI * exp_val / denom;
|
float out = cosNI * exp_val / denom;
|
||||||
float oh = H.dot(omega_out);
|
float oh = H.dot(omega_out);
|
||||||
denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
|
denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
|
||||||
pdf = exp_val / denom;
|
pdf = exp_val / denom;
|
||||||
return Color3 (out, out, out);
|
return Color3(out, out, out);
|
||||||
}
|
}
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
if (cosNO > 0) {
|
if (cosNO > 0) {
|
||||||
// get x,y basis on the surface for anisotropy
|
// get x,y basis on the surface for anisotropy
|
||||||
Vec3 X, Y;
|
Vec3 X, Y;
|
||||||
make_orthonormals(m_N, m_T, X, Y);
|
make_orthonormals(m_N, m_T, X, Y);
|
||||||
// generate random angles for the half vector
|
// generate random angles for the half vector
|
||||||
// eq. 7 (taking care around discontinuities to keep
|
// eq. 7 (taking care around discontinuities to keep
|
||||||
// output angle in the right quadrant)
|
// output angle in the right quadrant)
|
||||||
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
||||||
// and sin(atan(x)) == x/sqrt(1+x^2)
|
// and sin(atan(x)) == x/sqrt(1+x^2)
|
||||||
float alphaRatio = m_ay / m_ax;
|
float alphaRatio = m_ay / m_ax;
|
||||||
float cosPhi, sinPhi;
|
float cosPhi, sinPhi;
|
||||||
if (randu < 0.25f) {
|
if (randu < 0.25f) {
|
||||||
float val = 4 * randu;
|
float val = 4 * randu;
|
||||||
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
||||||
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
|
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
|
||||||
sinPhi = tanPhi * cosPhi;
|
sinPhi = tanPhi * cosPhi;
|
||||||
} else if (randu < 0.5) {
|
}
|
||||||
float val = 1 - 4 * (0.5f - randu);
|
else if (randu < 0.5) {
|
||||||
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
float val = 1 - 4 * (0.5f - randu);
|
||||||
// phi = (float) M_PI - phi;
|
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
||||||
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
|
// phi = (float) M_PI - phi;
|
||||||
sinPhi = -tanPhi * cosPhi;
|
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
|
||||||
} else if (randu < 0.75f) {
|
sinPhi = -tanPhi * cosPhi;
|
||||||
float val = 4 * (randu - 0.5f);
|
}
|
||||||
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
else if (randu < 0.75f) {
|
||||||
//phi = (float) M_PI + phi;
|
float val = 4 * (randu - 0.5f);
|
||||||
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
|
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
||||||
sinPhi = tanPhi * cosPhi;
|
//phi = (float) M_PI + phi;
|
||||||
} else {
|
cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi);
|
||||||
float val = 1 - 4 * (1 - randu);
|
sinPhi = tanPhi * cosPhi;
|
||||||
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
}
|
||||||
// phi = 2 * (float) M_PI - phi;
|
else {
|
||||||
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
|
float val = 1 - 4 * (1 - randu);
|
||||||
sinPhi = -tanPhi * cosPhi;
|
float tanPhi = alphaRatio * tanf((float) M_PI_2 * val);
|
||||||
}
|
// phi = 2 * (float) M_PI - phi;
|
||||||
// eq. 6
|
cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi);
|
||||||
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
sinPhi = -tanPhi * cosPhi;
|
||||||
// and sin(atan(x)) == x/sqrt(1+x^2)
|
}
|
||||||
float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay);
|
// eq. 6
|
||||||
float tanTheta2 = -logf(1 - randv) / thetaDenom;
|
// we take advantage of cos(atan(x)) == 1/sqrt(1+x^2)
|
||||||
float cosTheta = 1 / sqrtf(1 + tanTheta2);
|
// and sin(atan(x)) == x/sqrt(1+x^2)
|
||||||
float sinTheta = cosTheta * sqrtf(tanTheta2);
|
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
|
Vec3 h; // already normalized becaused expressed from spherical coordinates
|
||||||
h.x = sinTheta * cosPhi;
|
h.x = sinTheta * cosPhi;
|
||||||
h.y = sinTheta * sinPhi;
|
h.y = sinTheta * sinPhi;
|
||||||
h.z = cosTheta;
|
h.z = cosTheta;
|
||||||
// compute terms that are easier in local space
|
// compute terms that are easier in local space
|
||||||
float dotx = h.x / m_ax;
|
float dotx = h.x / m_ax;
|
||||||
float doty = h.y / m_ay;
|
float doty = h.y / m_ay;
|
||||||
float dotn = h.z;
|
float dotn = h.z;
|
||||||
// transform to world space
|
// transform to world space
|
||||||
h = h.x * X + h.y * Y + h.z * m_N;
|
h = h.x * X + h.y * Y + h.z * m_N;
|
||||||
// generate the final sample
|
// generate the final sample
|
||||||
float oh = h.dot(omega_out);
|
float oh = h.dot(omega_out);
|
||||||
omega_in.x = 2 * oh * h.x - omega_out.x;
|
omega_in.x = 2 * oh * h.x - omega_out.x;
|
||||||
omega_in.y = 2 * oh * h.y - omega_out.y;
|
omega_in.y = 2 * oh * h.y - omega_out.y;
|
||||||
omega_in.z = 2 * oh * h.z - omega_out.z;
|
omega_in.z = 2 * oh * h.z - omega_out.z;
|
||||||
if (Ng.dot(omega_in) > 0) {
|
if (Ng.dot(omega_in) > 0) {
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNI > 0) {
|
if (cosNI > 0) {
|
||||||
// eq. 9
|
// eq. 9
|
||||||
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
|
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
|
||||||
float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
|
float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn;
|
||||||
pdf = expf(-exp_arg) / denom;
|
pdf = expf(-exp_arg) / denom;
|
||||||
// compiler will reuse expressions already computed
|
// compiler will reuse expressions already computed
|
||||||
denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
|
denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI));
|
||||||
float power = cosNI * expf(-exp_arg) / denom;
|
float power = cosNI * expf(-exp_arg) / denom;
|
||||||
eval.setValue(power, power, power);
|
eval.setValue(power, power, power);
|
||||||
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
|
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_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
|
||||||
|
|
||||||
/* disabled for now - gives texture filtering problems */
|
/* disabled for now - gives texture filtering problems */
|
||||||
#if 0
|
#if 0
|
||||||
// Since there is some blur to this reflection, make the
|
// Since there is some blur to this reflection, make the
|
||||||
// derivatives a bit bigger. In theory this varies with the
|
// derivatives a bit bigger. In theory this varies with the
|
||||||
// roughness but the exact relationship is complex and
|
// roughness but the exact relationship is complex and
|
||||||
// requires more ops than are practical.
|
// requires more ops than are practical.
|
||||||
domega_in_dx *= 10;
|
domega_in_dx *= 10;
|
||||||
domega_in_dy *= 10;
|
domega_in_dy *= 10;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Labels::REFLECT;
|
return Labels::REFLECT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam bsdf_ward_params[] = {
|
ClosureParam bsdf_ward_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(WardClosure, m_N),
|
CLOSURE_VECTOR_PARAM(WardClosure, m_N),
|
||||||
CLOSURE_VECTOR_PARAM(WardClosure, m_T),
|
CLOSURE_VECTOR_PARAM(WardClosure, m_T),
|
||||||
CLOSURE_FLOAT_PARAM (WardClosure, m_ax),
|
CLOSURE_FLOAT_PARAM(WardClosure, m_ax),
|
||||||
CLOSURE_FLOAT_PARAM (WardClosure, m_ay),
|
CLOSURE_FLOAT_PARAM(WardClosure, m_ay),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(WardClosure) };
|
CLOSURE_FINISH_PARAM(WardClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure)
|
CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure)
|
||||||
|
|
||||||
|
@@ -44,193 +44,197 @@ using namespace OSL;
|
|||||||
|
|
||||||
class WestinBackscatterClosure : public BSDFClosure {
|
class WestinBackscatterClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N;
|
Vec3 m_N;
|
||||||
float m_roughness;
|
float m_roughness;
|
||||||
float m_invroughness;
|
float m_invroughness;
|
||||||
WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) { }
|
WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) {}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
m_roughness = clamp(m_roughness, 1e-5f, 1.0f);
|
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 {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other;
|
const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other;
|
||||||
return m_N == comp->m_N && m_roughness == comp->m_roughness &&
|
return m_N == comp->m_N && m_roughness == comp->m_roughness &&
|
||||||
BSDFClosure::mergeable(other);
|
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
|
void print_on(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << name() << " (";
|
out << name() << " (";
|
||||||
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||||
out << m_roughness;
|
out << m_roughness;
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
||||||
{
|
{
|
||||||
// pdf is implicitly 0 (no indirect sampling)
|
// pdf is implicitly 0 (no indirect sampling)
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNO > 0 && cosNI > 0) {
|
if (cosNO > 0 && cosNI > 0) {
|
||||||
float cosine = omega_out.dot(omega_in);
|
float cosine = omega_out.dot(omega_in);
|
||||||
pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0;
|
pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0;
|
||||||
pdf *= 0.5f * float(M_1_PI);
|
pdf *= 0.5f * float(M_1_PI);
|
||||||
return Color3 (pdf, pdf, pdf);
|
return Color3(pdf, pdf, pdf);
|
||||||
}
|
}
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
if (cosNO > 0) {
|
if (cosNO > 0) {
|
||||||
domega_in_dx = domega_out_dx;
|
domega_in_dx = domega_out_dx;
|
||||||
domega_in_dy = domega_out_dy;
|
domega_in_dy = domega_out_dy;
|
||||||
Vec3 T, B;
|
Vec3 T, B;
|
||||||
make_orthonormals (omega_out, T, B);
|
make_orthonormals(omega_out, T, B);
|
||||||
float phi = 2 * (float) M_PI * randu;
|
float phi = 2 * (float) M_PI * randu;
|
||||||
float cosTheta = powf(randv, 1 / (m_invroughness + 1));
|
float cosTheta = powf(randv, 1 / (m_invroughness + 1));
|
||||||
float sinTheta2 = 1 - cosTheta * cosTheta;
|
float sinTheta2 = 1 - cosTheta * cosTheta;
|
||||||
float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
|
float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
|
||||||
omega_in = (cosf(phi) * sinTheta) * T +
|
omega_in = (cosf(phi) * sinTheta) * T +
|
||||||
(sinf(phi) * sinTheta) * B +
|
(sinf(phi) * sinTheta) * B +
|
||||||
( cosTheta) * omega_out;
|
(cosTheta) * omega_out;
|
||||||
if (Ng.dot(omega_in) > 0)
|
if (Ng.dot(omega_in) > 0)
|
||||||
{
|
{
|
||||||
// common terms for pdf and eval
|
// common terms for pdf and eval
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
// make sure the direction we chose is still in the right hemisphere
|
// make sure the direction we chose is still in the right hemisphere
|
||||||
if (cosNI > 0)
|
if (cosNI > 0)
|
||||||
{
|
{
|
||||||
pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness);
|
pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness);
|
||||||
pdf = (m_invroughness + 1) * pdf;
|
pdf = (m_invroughness + 1) * pdf;
|
||||||
eval.setValue(pdf, pdf, pdf);
|
eval.setValue(pdf, pdf, pdf);
|
||||||
// Since there is some blur to this reflection, make the
|
// Since there is some blur to this reflection, make the
|
||||||
// derivatives a bit bigger. In theory this varies with the
|
// derivatives a bit bigger. In theory this varies with the
|
||||||
// exponent but the exact relationship is complex and
|
// exponent but the exact relationship is complex and
|
||||||
// requires more ops than are practical.
|
// requires more ops than are practical.
|
||||||
domega_in_dx *= 10;
|
domega_in_dx *= 10;
|
||||||
domega_in_dy *= 10;
|
domega_in_dy *= 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Labels::REFLECT;
|
return Labels::REFLECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class WestinSheenClosure : public BSDFClosure {
|
class WestinSheenClosure : public BSDFClosure {
|
||||||
public:
|
public:
|
||||||
Vec3 m_N;
|
Vec3 m_N;
|
||||||
float m_edginess;
|
float m_edginess;
|
||||||
// float m_normalization;
|
// float m_normalization;
|
||||||
WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) { }
|
WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) {}
|
||||||
|
|
||||||
void setup() {};
|
void setup() {};
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const WestinSheenClosure *comp = (const WestinSheenClosure *)other;
|
const WestinSheenClosure *comp = (const WestinSheenClosure *)other;
|
||||||
return m_N == comp->m_N && m_edginess == comp->m_edginess &&
|
return m_N == comp->m_N && m_edginess == comp->m_edginess &&
|
||||||
BSDFClosure::mergeable(other);
|
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
|
void print_on(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << name() << " (";
|
out << name() << " (";
|
||||||
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||||
out << m_edginess;
|
out << m_edginess;
|
||||||
out << ")";
|
out << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float albedo (const Vec3 &omega_out) const
|
float albedo(const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
||||||
{
|
{
|
||||||
// pdf is implicitly 0 (no indirect sampling)
|
// pdf is implicitly 0 (no indirect sampling)
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float cosNI = m_N.dot(omega_in);
|
float cosNI = m_N.dot(omega_in);
|
||||||
if (cosNO > 0 && cosNI > 0) {
|
if (cosNO > 0 && cosNI > 0) {
|
||||||
float sinNO2 = 1 - cosNO * cosNO;
|
float sinNO2 = 1 - cosNO * cosNO;
|
||||||
pdf = cosNI * float(M_1_PI);
|
pdf = cosNI * float(M_1_PI);
|
||||||
float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0;
|
float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0;
|
||||||
return Color3 (westin, westin, westin);
|
return Color3(westin, westin, westin);
|
||||||
}
|
}
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const
|
||||||
{
|
{
|
||||||
return Color3 (0, 0, 0);
|
return Color3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ustring sample (const Vec3 &Ng,
|
ustring sample(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||||
float &pdf, Color3 &eval) const
|
float &pdf, Color3 &eval) const
|
||||||
{
|
{
|
||||||
// we are viewing the surface from the right side - send a ray out with cosine
|
// we are viewing the surface from the right side - send a ray out with cosine
|
||||||
// distribution over the hemisphere
|
// distribution over the hemisphere
|
||||||
sample_cos_hemisphere (m_N, omega_out, randu, randv, omega_in, pdf);
|
sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf);
|
||||||
if (Ng.dot(omega_in) > 0) {
|
if (Ng.dot(omega_in) > 0) {
|
||||||
// TODO: account for sheen when sampling
|
// TODO: account for sheen when sampling
|
||||||
float cosNO = m_N.dot(omega_out);
|
float cosNO = m_N.dot(omega_out);
|
||||||
float sinNO2 = 1 - cosNO * cosNO;
|
float sinNO2 = 1 - cosNO * cosNO;
|
||||||
float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0;
|
float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0;
|
||||||
eval.setValue(westin, westin, westin);
|
eval.setValue(westin, westin, westin);
|
||||||
// TODO: find a better approximation for the diffuse bounce
|
// 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_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_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
|
||||||
domega_in_dx *= 125;
|
domega_in_dx *= 125;
|
||||||
domega_in_dy *= 125;
|
domega_in_dy *= 125;
|
||||||
} else
|
}
|
||||||
pdf = 0;
|
else {
|
||||||
return Labels::REFLECT;
|
pdf = 0;
|
||||||
}
|
}
|
||||||
|
return Labels::REFLECT;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam bsdf_westin_backscatter_params[] = {
|
ClosureParam bsdf_westin_backscatter_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N),
|
CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (WestinBackscatterClosure, m_roughness),
|
CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, m_roughness),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(WestinBackscatterClosure) };
|
CLOSURE_FINISH_PARAM(WestinBackscatterClosure)
|
||||||
|
};
|
||||||
|
|
||||||
ClosureParam bsdf_westin_sheen_params[] = {
|
ClosureParam bsdf_westin_sheen_params[] = {
|
||||||
CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N),
|
CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N),
|
||||||
CLOSURE_FLOAT_PARAM (WestinSheenClosure, m_edginess),
|
CLOSURE_FLOAT_PARAM(WestinSheenClosure, m_edginess),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(WestinSheenClosure) };
|
CLOSURE_FINISH_PARAM(WestinSheenClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure)
|
CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure)
|
||||||
CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure)
|
CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure)
|
||||||
|
@@ -42,62 +42,63 @@ using namespace OSL;
|
|||||||
|
|
||||||
class BSSRDFCubicClosure : public BSSRDFClosure {
|
class BSSRDFCubicClosure : public BSSRDFClosure {
|
||||||
public:
|
public:
|
||||||
Color3 m_radius;
|
Color3 m_radius;
|
||||||
Color3 m_scale;
|
Color3 m_scale;
|
||||||
float m_max_radius;
|
float m_max_radius;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T pow3 (const T &x) { return x * x * x; }
|
static inline T pow3(const T &x) { return x * x * x; }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T pow5 (const T &x) { T x2 = x * x; return x2 * x2 * x; }
|
static inline T pow5(const T &x) { T x2 = x * x; return x2 * x2 * x; }
|
||||||
|
|
||||||
BSSRDFCubicClosure() { }
|
BSSRDFCubicClosure() {}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// pre-compute some terms
|
// pre-compute some terms
|
||||||
m_max_radius = 0;
|
m_max_radius = 0;
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
m_scale[i] = m_radius[i] > 0 ? 4 / pow5 (m_radius[i]) : 0;
|
m_scale[i] = m_radius[i] > 0 ? 4 / pow5(m_radius[i]) : 0;
|
||||||
m_max_radius = std::max (m_max_radius, m_radius[i]);
|
m_max_radius = std::max(m_max_radius, m_radius[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other;
|
const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other;
|
||||||
return m_radius == comp->m_radius && BSSRDFClosure::mergeable(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
|
void print_on(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), ("
|
out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), ("
|
||||||
<< m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))";
|
<< m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))";
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval (float r) const
|
Color3 eval(float r) const
|
||||||
{
|
{
|
||||||
return Color3 ((r < m_radius.x) ? pow3 (m_radius.x - r) * m_scale.x : 0,
|
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.y) ? pow3(m_radius.y - r) * m_scale.y : 0,
|
||||||
(r < m_radius.z) ? pow3 (m_radius.z - r) * m_scale.z : 0);
|
(r < m_radius.z) ? pow3(m_radius.z - r) * m_scale.z : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float max_radius() const
|
float max_radius() const
|
||||||
{
|
{
|
||||||
return m_max_radius;
|
return m_max_radius;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam closure_bssrdf_cubic_params[] = {
|
ClosureParam closure_bssrdf_cubic_params[] = {
|
||||||
CLOSURE_COLOR_PARAM (BSSRDFCubicClosure, m_radius),
|
CLOSURE_COLOR_PARAM(BSSRDFCubicClosure, m_radius),
|
||||||
CLOSURE_STRING_KEYPARAM ("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(BSSRDFCubicClosure) };
|
CLOSURE_FINISH_PARAM(BSSRDFCubicClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure)
|
CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure)
|
||||||
|
|
||||||
|
@@ -49,30 +49,31 @@ using namespace OSL;
|
|||||||
|
|
||||||
class DebugClosure : public ClosurePrimitive {
|
class DebugClosure : public ClosurePrimitive {
|
||||||
public:
|
public:
|
||||||
ustring m_tag;
|
ustring m_tag;
|
||||||
|
|
||||||
DebugClosure () : ClosurePrimitive (Debug) { }
|
DebugClosure () : ClosurePrimitive(Debug) {}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const DebugClosure *comp = (const DebugClosure *)other;
|
const DebugClosure *comp = (const DebugClosure *)other;
|
||||||
return m_tag == comp->m_tag &&
|
return m_tag == comp->m_tag &&
|
||||||
ClosurePrimitive::mergeable(other);
|
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 {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " (\"" << m_tag.c_str() << "\")";
|
out << name() << " (\"" << m_tag.c_str() << "\")";
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ClosureParam closure_debug_params[] = {
|
ClosureParam closure_debug_params[] = {
|
||||||
CLOSURE_STRING_PARAM(DebugClosure, m_tag),
|
CLOSURE_STRING_PARAM(DebugClosure, m_tag),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(DebugClosure) };
|
CLOSURE_FINISH_PARAM(DebugClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(closure_debug_prepare, DebugClosure)
|
CLOSURE_PREPARE(closure_debug_prepare, DebugClosure)
|
||||||
|
|
||||||
|
@@ -49,57 +49,58 @@ using namespace OSL;
|
|||||||
///
|
///
|
||||||
class GenericEmissiveClosure : public EmissiveClosure {
|
class GenericEmissiveClosure : public EmissiveClosure {
|
||||||
public:
|
public:
|
||||||
GenericEmissiveClosure() { }
|
GenericEmissiveClosure() { }
|
||||||
|
|
||||||
void setup() { }
|
void setup() {}
|
||||||
|
|
||||||
size_t memsize () const { return sizeof(*this); }
|
size_t memsize() const { return sizeof(*this); }
|
||||||
|
|
||||||
const char *name () const { return "emission"; }
|
const char *name() const { return "emission"; }
|
||||||
|
|
||||||
void print_on (std::ostream &out) const {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << "()";
|
out << name() << "()";
|
||||||
}
|
}
|
||||||
|
|
||||||
Color3 eval (const Vec3 &Ng, const Vec3 &omega_out) const
|
Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
float cosNO = fabsf(Ng.dot(omega_out));
|
float cosNO = fabsf(Ng.dot(omega_out));
|
||||||
float res = cosNO > 0 ? 1.0f: 0.0f;
|
float res = cosNO > 0 ? 1.0f : 0.0f;
|
||||||
return Color3(res, res, res);
|
return Color3(res, res, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sample (const Vec3 &Ng, float randu, float randv,
|
void sample(const Vec3 &Ng, float randu, float randv,
|
||||||
Vec3 &omega_out, float &pdf) const
|
Vec3 &omega_out, float &pdf) const
|
||||||
{
|
{
|
||||||
// We don't do anything sophisticated here for the step
|
// We don't do anything sophisticated here for the step
|
||||||
// We just sample the whole cone uniformly to the cosine
|
// We just sample the whole cone uniformly to the cosine
|
||||||
Vec3 T, B;
|
Vec3 T, B;
|
||||||
make_orthonormals(Ng, T, B);
|
make_orthonormals(Ng, T, B);
|
||||||
float phi = 2 * (float) M_PI * randu;
|
float phi = 2 * (float) M_PI * randu;
|
||||||
float cosTheta = sqrtf(1.0f - 1.0f * randv);
|
float cosTheta = sqrtf(1.0f - 1.0f * randv);
|
||||||
float sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
|
float sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
|
||||||
omega_out = (cosf(phi) * sinTheta) * T +
|
omega_out = (cosf(phi) * sinTheta) * T +
|
||||||
(sinf(phi) * sinTheta) * B +
|
(sinf(phi) * sinTheta) * B +
|
||||||
cosTheta * Ng;
|
cosTheta * Ng;
|
||||||
pdf = 1.0f / float(M_PI);
|
pdf = 1.0f / float(M_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the probability distribution function in the direction omega_out,
|
/// Return the probability distribution function in the direction omega_out,
|
||||||
/// given the parameters and the light's surface normal. This MUST match
|
/// given the parameters and the light's surface normal. This MUST match
|
||||||
/// the PDF computed by sample().
|
/// the PDF computed by sample().
|
||||||
float pdf (const Vec3 &Ng,
|
float pdf(const Vec3 &Ng,
|
||||||
const Vec3 &omega_out) const
|
const Vec3 &omega_out) const
|
||||||
{
|
{
|
||||||
float cosNO = Ng.dot(omega_out);
|
float cosNO = Ng.dot(omega_out);
|
||||||
return cosNO > 0 ? 1.0f: 0.0f;
|
return cosNO > 0 ? 1.0f : 0.0f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam closure_emission_params[] = {
|
ClosureParam closure_emission_params[] = {
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(GenericEmissiveClosure) };
|
CLOSURE_FINISH_PARAM(GenericEmissiveClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
|
CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
|
||||||
|
|
||||||
|
@@ -18,18 +18,18 @@
|
|||||||
|
|
||||||
float color_srgb_to_scene_linear(float c)
|
float color_srgb_to_scene_linear(float c)
|
||||||
{
|
{
|
||||||
if(c < 0.04045)
|
if (c < 0.04045)
|
||||||
return (c < 0.0)? 0.0: c * (1.0/12.92);
|
return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
|
||||||
else
|
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)
|
float color_scene_linear_to_srgb(float c)
|
||||||
{
|
{
|
||||||
if(c < 0.0031308)
|
if (c < 0.0031308)
|
||||||
return (c < 0.0)? 0.0: c * 12.92;
|
return (c < 0.0) ? 0.0 : c * 12.92;
|
||||||
else
|
else
|
||||||
return 1.055 * pow(c, 1.0/2.4) - 0.055;
|
return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
|
||||||
}
|
}
|
||||||
|
|
||||||
color color_srgb_to_scene_linear(color c)
|
color color_srgb_to_scene_linear(color c)
|
||||||
@@ -61,27 +61,27 @@ color rgb_to_hsv(color rgb)
|
|||||||
|
|
||||||
v = cmax;
|
v = cmax;
|
||||||
|
|
||||||
if(cmax != 0.0) {
|
if (cmax != 0.0) {
|
||||||
s = cdelta/cmax;
|
s = cdelta / cmax;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
s = 0.0;
|
s = 0.0;
|
||||||
h = 0.0;
|
h = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s == 0.0) {
|
if (s == 0.0) {
|
||||||
h = 0.0;
|
h = 0.0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c = (color(cmax, cmax, cmax) - rgb)/cdelta;
|
c = (color(cmax, cmax, cmax) - rgb) / cdelta;
|
||||||
|
|
||||||
if(rgb[0] == cmax) h = c[2] - c[1];
|
if (rgb[0] == cmax) h = c[2] - c[1];
|
||||||
else if(rgb[1] == cmax) h = 2.0 + c[0] - c[2];
|
else if (rgb[1] == cmax) h = 2.0 + c[0] - c[2];
|
||||||
else h = 4.0 + c[1] - c[0];
|
else h = 4.0 + c[1] - c[0];
|
||||||
|
|
||||||
h /= 6.0;
|
h /= 6.0;
|
||||||
|
|
||||||
if(h < 0.0)
|
if (h < 0.0)
|
||||||
h += 1.0;
|
h += 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,26 +97,26 @@ color hsv_to_rgb(color hsv)
|
|||||||
s = hsv[1];
|
s = hsv[1];
|
||||||
v = hsv[2];
|
v = hsv[2];
|
||||||
|
|
||||||
if(s==0.0) {
|
if (s == 0.0) {
|
||||||
rgb = color(v, v, v);
|
rgb = color(v, v, v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(h==1.0)
|
if (h == 1.0)
|
||||||
h = 0.0;
|
h = 0.0;
|
||||||
|
|
||||||
h *= 6.0;
|
h *= 6.0;
|
||||||
i = floor(h);
|
i = floor(h);
|
||||||
f = h - i;
|
f = h - i;
|
||||||
rgb = color(f, f, f);
|
rgb = color(f, f, f);
|
||||||
p = v*(1.0-s);
|
p = v * (1.0 - s);
|
||||||
q = v*(1.0-(s*f));
|
q = v * (1.0 - (s * f));
|
||||||
t = v*(1.0-(s*(1.0-f)));
|
t = v * (1.0 - (s * (1.0 - f)));
|
||||||
|
|
||||||
if(i == 0.0) rgb = color(v, t, p);
|
if (i == 0.0) rgb = color(v, t, p);
|
||||||
else if(i == 1.0) rgb = color(q, v, p);
|
else if (i == 1.0) rgb = color(q, v, p);
|
||||||
else if(i == 2.0) rgb = color(p, v, t);
|
else if (i == 2.0) rgb = color(p, v, t);
|
||||||
else if(i == 3.0) rgb = color(p, q, v);
|
else if (i == 3.0) rgb = color(p, q, v);
|
||||||
else if(i == 4.0) rgb = color(t, p, v);
|
else if (i == 4.0) rgb = color(t, p, v);
|
||||||
else rgb = color(v, p, q);
|
else rgb = color(v, p, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,11 +7,11 @@ float fresnel_dielectric(vector Incoming, normal Normal, float eta)
|
|||||||
float g = eta * eta - 1 + c * c;
|
float g = eta * eta - 1 + c * c;
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
if(g > 0) {
|
if (g > 0) {
|
||||||
g = sqrt(g);
|
g = sqrt(g);
|
||||||
float A =(g - c)/(g + c);
|
float A = (g - c) / (g + c);
|
||||||
float B =(c *(g + c)- 1)/(c *(g - c)+ 1);
|
float B = (c * (g + c) - 1) / (c * (g - c) + 1);
|
||||||
result = 0.5 * A * A *(1 + B * B);
|
result = 0.5 * A * A * (1 + B * B);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = 1.0; /* TIR (no refracted component) */
|
result = 1.0; /* TIR (no refracted component) */
|
||||||
|
@@ -20,20 +20,20 @@ float voronoi_distance(string distance_metric, vector d, float e)
|
|||||||
{
|
{
|
||||||
float result = 0.0;
|
float result = 0.0;
|
||||||
|
|
||||||
if(distance_metric == "Distance Squared")
|
if (distance_metric == "Distance Squared")
|
||||||
result = dot(d, d);
|
result = dot(d, d);
|
||||||
if(distance_metric == "Actual Distance")
|
if (distance_metric == "Actual Distance")
|
||||||
result = length(d);
|
result = length(d);
|
||||||
if(distance_metric == "Manhattan")
|
if (distance_metric == "Manhattan")
|
||||||
result = fabs(d[0]) + fabs(d[1]) + fabs(d[2]);
|
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])));
|
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]));
|
result = sqrt(fabs(d[0])) + sqrt(fabs(d[1])) + sqrt(fabs(d[1]));
|
||||||
if(distance_metric == "Minkovsky 4")
|
if (distance_metric == "Minkovsky 4")
|
||||||
result = sqrt(sqrt(dot(d*d, d*d)));
|
result = sqrt(sqrt(dot(d * d, d * d)));
|
||||||
if(distance_metric == "Minkovsky")
|
if (distance_metric == "Minkovsky")
|
||||||
result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0/e);
|
result = pow(pow(fabs(d[0]), e) + pow(fabs(d[1]), e) + pow(fabs(d[2]), e), 1.0 / e);
|
||||||
|
|
||||||
return result;
|
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[2] = 1e10;
|
||||||
da[3] = 1e10;
|
da[3] = 1e10;
|
||||||
|
|
||||||
for(xx = xi-1; xx <= xi+1; xx++) {
|
for (xx = xi - 1; xx <= xi + 1; xx++) {
|
||||||
for(yy = yi-1; yy <= yi+1; yy++) {
|
for (yy = yi - 1; yy <= yi + 1; yy++) {
|
||||||
for(zz = zi-1; zz <= zi+1; zz++) {
|
for (zz = zi - 1; zz <= zi + 1; zz++) {
|
||||||
point ip = point(xx, yy, zz);
|
point ip = point(xx, yy, zz);
|
||||||
point vp = (point)cellnoise_color(ip);
|
point vp = (point)cellnoise_color(ip);
|
||||||
point pd = p - (vp + 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);
|
vp += point(xx, yy, zz);
|
||||||
|
|
||||||
if(d < da[0]) {
|
if (d < da[0]) {
|
||||||
da[3] = da[2];
|
da[3] = da[2];
|
||||||
da[2] = da[1];
|
da[2] = da[1];
|
||||||
da[1] = da[0];
|
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[1] = pa[0];
|
||||||
pa[0] = vp;
|
pa[0] = vp;
|
||||||
}
|
}
|
||||||
else if(d < da[1]) {
|
else if (d < da[1]) {
|
||||||
da[3] = da[2];
|
da[3] = da[2];
|
||||||
da[2] = da[1];
|
da[2] = da[1];
|
||||||
da[1] = d;
|
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[2] = pa[1];
|
||||||
pa[1] = vp;
|
pa[1] = vp;
|
||||||
}
|
}
|
||||||
else if(d < da[2]) {
|
else if (d < da[2]) {
|
||||||
da[3] = da[2];
|
da[3] = da[2];
|
||||||
da[2] = d;
|
da[2] = d;
|
||||||
|
|
||||||
pa[3] = pa[2];
|
pa[3] = pa[2];
|
||||||
pa[2] = vp;
|
pa[2] = vp;
|
||||||
}
|
}
|
||||||
else if(d < da[3]) {
|
else if (d < da[3]) {
|
||||||
da[3] = d;
|
da[3] = d;
|
||||||
pa[3] = vp;
|
pa[3] = vp;
|
||||||
}
|
}
|
||||||
@@ -138,16 +138,16 @@ float voronoi_F1F2(point p) { return voronoi_FnFn(p, 0, 1); }
|
|||||||
float voronoi_Cr(point p)
|
float voronoi_Cr(point p)
|
||||||
{
|
{
|
||||||
/* crackle type pattern, just a scale/clamp of F2-F1 */
|
/* crackle type pattern, just a scale/clamp of F2-F1 */
|
||||||
float t = 10.0*voronoi_F1F2(p);
|
float t = 10.0 * voronoi_F1F2(p);
|
||||||
return (t > 1.0)? 1.0: t;
|
return (t > 1.0) ? 1.0 : t;
|
||||||
}
|
}
|
||||||
|
|
||||||
float voronoi_F1S(point p) { return 2.0*voronoi_F1(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_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_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_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_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_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; }
|
||||||
|
|
||||||
/* Noise Bases */
|
/* Noise Bases */
|
||||||
|
|
||||||
@@ -155,21 +155,21 @@ float noise_basis(point p, string basis)
|
|||||||
{
|
{
|
||||||
float result = 0.0;
|
float result = 0.0;
|
||||||
|
|
||||||
if(basis == "Perlin")
|
if (basis == "Perlin")
|
||||||
result = noise(p);
|
result = noise(p);
|
||||||
if(basis == "Voronoi F1")
|
if (basis == "Voronoi F1")
|
||||||
result = voronoi_F1S(p);
|
result = voronoi_F1S(p);
|
||||||
if(basis == "Voronoi F2")
|
if (basis == "Voronoi F2")
|
||||||
result = voronoi_F2S(p);
|
result = voronoi_F2S(p);
|
||||||
if(basis == "Voronoi F3")
|
if (basis == "Voronoi F3")
|
||||||
result = voronoi_F3S(p);
|
result = voronoi_F3S(p);
|
||||||
if(basis == "Voronoi F4")
|
if (basis == "Voronoi F4")
|
||||||
result = voronoi_F4S(p);
|
result = voronoi_F4S(p);
|
||||||
if(basis == "Voronoi F2-F1")
|
if (basis == "Voronoi F2-F1")
|
||||||
result = voronoi_F1F2S(p);
|
result = voronoi_F1F2S(p);
|
||||||
if(basis == "Voronoi Crackle")
|
if (basis == "Voronoi Crackle")
|
||||||
result = voronoi_CrS(p);
|
result = voronoi_CrS(p);
|
||||||
if(basis == "Cell Noise")
|
if (basis == "Cell Noise")
|
||||||
result = cellnoise(p);
|
result = cellnoise(p);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -180,7 +180,7 @@ float noise_basis(point p, string basis)
|
|||||||
float noise_basis_hard(point p, string basis, int hard)
|
float noise_basis_hard(point p, string basis, int hard)
|
||||||
{
|
{
|
||||||
float t = noise_basis(p, basis);
|
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 */
|
/* Waves */
|
||||||
@@ -189,22 +189,22 @@ float noise_wave(string wave, float a)
|
|||||||
{
|
{
|
||||||
float result = 0.0;
|
float result = 0.0;
|
||||||
|
|
||||||
if(wave == "Sine") {
|
if (wave == "Sine") {
|
||||||
result = 0.5 + 0.5*sin(a);
|
result = 0.5 + 0.5 * sin(a);
|
||||||
}
|
}
|
||||||
else if(wave == "Saw") {
|
else if (wave == "Saw") {
|
||||||
float b = 2*M_PI;
|
float b = 2 * M_PI;
|
||||||
int n = (int)(a / b);
|
int n = (int)(a / b);
|
||||||
a -= n*b;
|
a -= n * b;
|
||||||
if(a < 0) a += b;
|
if (a < 0) a += b;
|
||||||
|
|
||||||
result = a / b;
|
result = a / b;
|
||||||
}
|
}
|
||||||
else if(wave == "Tri") {
|
else if (wave == "Tri") {
|
||||||
float b = 2*M_PI;
|
float b = 2 * M_PI;
|
||||||
float rmax = 1.0;
|
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;
|
return result;
|
||||||
@@ -219,18 +219,18 @@ float noise_turbulence(point p, string basis, int octaves, int hard)
|
|||||||
float sum = 0.0;
|
float sum = 0.0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 0; i <= octaves; i++) {
|
for (i = 0; i <= octaves; i++) {
|
||||||
float t = noise_basis(fscale*p, basis);
|
float t = noise_basis(fscale * p, basis);
|
||||||
|
|
||||||
if(hard)
|
if (hard)
|
||||||
t = fabs(2.0*t - 1.0);
|
t = fabs(2.0 * t - 1.0);
|
||||||
|
|
||||||
sum += t*amp;
|
sum += t * amp;
|
||||||
amp *= 0.5;
|
amp *= 0.5;
|
||||||
fscale *= 2.0;
|
fscale *= 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sum *= ((float)(1 << octaves)/(float)((1 << (octaves+1)) - 1));
|
sum *= ((float)(1 << octaves) / (float)((1 << (octaves + 1)) - 1));
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
@@ -241,8 +241,8 @@ float nonzero(float f, float eps)
|
|||||||
{
|
{
|
||||||
float r;
|
float r;
|
||||||
|
|
||||||
if(abs(f) < eps)
|
if (abs(f) < eps)
|
||||||
r = sign(f)*eps;
|
r = sign(f) * eps;
|
||||||
else
|
else
|
||||||
r = f;
|
r = f;
|
||||||
|
|
||||||
|
@@ -163,241 +163,246 @@ vector normalize (vector v) BUILTIN;
|
|||||||
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
|
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
|
||||||
vector faceforward (vector N, vector I) BUILTIN;
|
vector faceforward (vector N, vector I) BUILTIN;
|
||||||
vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; }
|
vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; }
|
||||||
vector refract (vector I, vector N, float eta) {
|
vector refract(vector I, vector N, float eta) {
|
||||||
float IdotN = dot (I, N);
|
float IdotN = dot(I, N);
|
||||||
float k = 1 - eta*eta * (1 - IdotN*IdotN);
|
float k = 1 - eta * eta * (1 - IdotN * IdotN);
|
||||||
return (k < 0) ? vector(0,0,0) : (eta*I - N * (eta*IdotN + sqrt(k)));
|
return (k < 0) ? vector(0, 0, 0) : (eta * I - N * (eta * IdotN + sqrt(k)));
|
||||||
}
|
}
|
||||||
void fresnel (vector I, normal N, float eta,
|
void fresnel(vector I, normal N, float eta,
|
||||||
output float Kr, output float Kt,
|
output float Kr, output float Kt,
|
||||||
output vector R, output vector T)
|
output vector R, output vector T)
|
||||||
{
|
{
|
||||||
float sqr(float x) { return x*x; }
|
float sqr(float x) {
|
||||||
float c = dot(I, N);
|
return x * x;
|
||||||
if (c < 0)
|
}
|
||||||
c = -c;
|
float c = dot(I, N);
|
||||||
R = reflect(I, N);
|
if (c < 0)
|
||||||
float g = 1.0 / sqr(eta) - 1.0 + c * c;
|
c = -c;
|
||||||
if (g >= 0.0) {
|
R = reflect(I, N);
|
||||||
g = sqrt (g);
|
float g = 1.0 / sqr(eta) - 1.0 + c * c;
|
||||||
float beta = g - c;
|
if (g >= 0.0) {
|
||||||
float F = (c * (g+c) - 1.0) / (c * beta + 1.0);
|
g = sqrt(g);
|
||||||
F = 0.5 * (1.0 + sqr(F));
|
float beta = g - c;
|
||||||
F *= sqr (beta / (g+c));
|
float F = (c * (g + c) - 1.0) / (c * beta + 1.0);
|
||||||
Kr = F;
|
F = 0.5 * (1.0 + sqr(F));
|
||||||
Kt = (1.0 - Kr) * eta*eta;
|
F *= sqr(beta / (g + c));
|
||||||
// OPT: the following recomputes some of the above values, but it
|
Kr = F;
|
||||||
// gives us the same result as if the shader-writer called refract()
|
Kt = (1.0 - Kr) * eta * eta;
|
||||||
T = refract(I, N, eta);
|
// OPT: the following recomputes some of the above values, but it
|
||||||
} else {
|
// gives us the same result as if the shader-writer called refract()
|
||||||
// total internal reflection
|
T = refract(I, N, eta);
|
||||||
Kr = 1.0;
|
}
|
||||||
Kt = 0.0;
|
else {
|
||||||
T = vector (0,0,0);
|
// total internal reflection
|
||||||
}
|
Kr = 1.0;
|
||||||
|
Kt = 0.0;
|
||||||
|
T = vector(0, 0, 0);
|
||||||
|
}
|
||||||
#undef sqr
|
#undef sqr
|
||||||
}
|
}
|
||||||
|
|
||||||
void fresnel (vector I, normal N, float eta,
|
void fresnel(vector I, normal N, float eta,
|
||||||
output float Kr, output float Kt)
|
output float Kr, output float Kt)
|
||||||
{
|
{
|
||||||
vector R, T;
|
vector R, T;
|
||||||
fresnel(I, N, eta, Kr, Kt, 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;
|
normal transform(matrix Mto, normal p) BUILTIN;
|
||||||
vector transform (matrix Mto, vector p) BUILTIN;
|
vector transform(matrix Mto, vector p) BUILTIN;
|
||||||
point transform (matrix Mto, point p) BUILTIN;
|
point transform(matrix Mto, point p) BUILTIN;
|
||||||
|
|
||||||
// Implementation of transform-with-named-space in terms of matrices:
|
// 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 tounits, float x) BUILTIN;
|
||||||
float transformu (string fromunits, string tounits, float x) BUILTIN;
|
float transformu(string fromunits, string tounits, float x) BUILTIN;
|
||||||
|
|
||||||
|
|
||||||
// Color functions
|
// Color functions
|
||||||
|
|
||||||
float luminance (color c) {
|
float luminance(color c) {
|
||||||
return dot ((vector)c, vector(0.2126, 0.7152, 0.0722));
|
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
|
color rgb_to_hsv(color rgb) { // See Foley & van Dam
|
||||||
float r = rgb[0], g = rgb[1], b = rgb[2];
|
float r = rgb[0], g = rgb[1], b = rgb[2];
|
||||||
float mincomp = min (r, min (g, b));
|
float mincomp = min(r, min(g, b));
|
||||||
float maxcomp = max (r, max (g, b));
|
float maxcomp = max(r, max(g, b));
|
||||||
float delta = maxcomp - mincomp; // chroma
|
float delta = maxcomp - mincomp; // chroma
|
||||||
float h, s, v;
|
float h, s, v;
|
||||||
v = maxcomp;
|
v = maxcomp;
|
||||||
if (maxcomp > 0)
|
if (maxcomp > 0)
|
||||||
s = delta / maxcomp;
|
s = delta / maxcomp;
|
||||||
else s = 0;
|
else s = 0;
|
||||||
if (s <= 0)
|
if (s <= 0)
|
||||||
h = 0;
|
h = 0;
|
||||||
else {
|
else {
|
||||||
if (r >= maxcomp) h = (g-b) / delta;
|
if (r >= maxcomp) h = (g - b) / delta;
|
||||||
else if (g >= maxcomp) h = 2 + (b-r) / delta;
|
else if (g >= maxcomp) h = 2 + (b - r) / delta;
|
||||||
else h = 4 + (r-g) / delta;
|
else h = 4 + (r - g) / delta;
|
||||||
h /= 6;
|
h /= 6;
|
||||||
if (h < 0)
|
if (h < 0)
|
||||||
h += 1;
|
h += 1;
|
||||||
}
|
}
|
||||||
return color (h, s, v);
|
return color(h, s, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
color rgb_to_hsl (color rgb) { // See Foley & van Dam
|
color rgb_to_hsl(color rgb) { // See Foley & van Dam
|
||||||
// First convert rgb to hsv, then to hsl
|
// First convert rgb to hsv, then to hsl
|
||||||
float minval = min (rgb[0], min (rgb[1], rgb[2]));
|
float minval = min(rgb[0], min(rgb[1], rgb[2]));
|
||||||
color hsv = rgb_to_hsv (rgb);
|
color hsv = rgb_to_hsv(rgb);
|
||||||
float maxval = hsv[2]; // v == maxval
|
float maxval = hsv[2]; // v == maxval
|
||||||
float h = hsv[0], s, l = (minval+maxval) / 2;
|
float h = hsv[0], s, l = (minval + maxval) / 2;
|
||||||
if (minval == maxval)
|
if (minval == maxval)
|
||||||
s = 0; // special 'achromatic' case, hue is 0
|
s = 0; // special 'achromatic' case, hue is 0
|
||||||
else if (l <= 0.5)
|
else if (l <= 0.5)
|
||||||
s = (maxval - minval) / (maxval + minval);
|
s = (maxval - minval) / (maxval + minval);
|
||||||
else
|
else
|
||||||
s = (maxval - minval) / (2 - maxval - minval);
|
s = (maxval - minval) / (2 - maxval - minval);
|
||||||
return color (h, s, l);
|
return color(h, s, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
color r;
|
color r;
|
||||||
if (to == "rgb" || to == "RGB")
|
if (to == "rgb" || to == "RGB")
|
||||||
r = x;
|
r = x;
|
||||||
else if (to == "hsv")
|
else if (to == "hsv")
|
||||||
r = rgb_to_hsv (x);
|
r = rgb_to_hsv(x);
|
||||||
else if (to == "hsl")
|
else if (to == "hsl")
|
||||||
r = rgb_to_hsl (x);
|
r = rgb_to_hsl(x);
|
||||||
else if (to == "YIQ")
|
else if (to == "YIQ")
|
||||||
r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
|
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.596, -0.275, -0.321), (vector)x),
|
||||||
dot (vector(0.212, -0.523, 0.311), (vector)x));
|
dot(vector(0.212, -0.523, 0.311), (vector)x));
|
||||||
else if (to == "xyz")
|
else if (to == "xyz")
|
||||||
r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
|
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.212671, 0.715160, 0.072169), (vector)x),
|
||||||
dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
|
dot(vector(0.019334, 0.119193, 0.950227), (vector)x));
|
||||||
else {
|
else {
|
||||||
error ("Unknown color space \"%s\"", to);
|
error("Unknown color space \"%s\"", to);
|
||||||
r = x;
|
r = x;
|
||||||
}
|
}
|
||||||
return r;
|
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
|
color hsv_to_rgb(color c) { // Reference: Foley & van Dam
|
||||||
float h = c[0], s = c[1], v = c[2];
|
float h = c[0], s = c[1], v = c[2];
|
||||||
color r;
|
color r;
|
||||||
if (s < 0.0001) {
|
if (s < 0.0001) {
|
||||||
r = v;
|
r = v;
|
||||||
} else {
|
}
|
||||||
h = 6 * (h - floor(h)); // expand to [0..6)
|
else {
|
||||||
int hi = (int)h;
|
h = 6 * (h - floor(h)); // expand to [0..6)
|
||||||
float f = h - hi;
|
int hi = (int)h;
|
||||||
float p = v * (1-s);
|
float f = h - hi;
|
||||||
float q = v * (1-s*f);
|
float p = v * (1 - s);
|
||||||
float t = v * (1-s*(1-f));
|
float q = v * (1 - s * f);
|
||||||
if (hi == 0) r = color (v, t, p);
|
float t = v * (1 - s * (1 - f));
|
||||||
else if (hi == 1) r = color (q, v, p);
|
if (hi == 0) r = color(v, t, p);
|
||||||
else if (hi == 2) r = color (p, v, t);
|
else if (hi == 1) r = color(q, v, p);
|
||||||
else if (hi == 3) r = color (p, q, v);
|
else if (hi == 2) r = color(p, v, t);
|
||||||
else if (hi == 4) r = color (t, p, v);
|
else if (hi == 3) r = color(p, q, v);
|
||||||
else r = color (v, p, q);
|
else if (hi == 4) r = color(t, p, v);
|
||||||
}
|
else r = color(v, p, q);
|
||||||
return r;
|
}
|
||||||
}
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
color hsl_to_rgb (color c) {
|
color hsl_to_rgb(color c) {
|
||||||
float h = c[0], s = c[1], l = c[2];
|
float h = c[0], s = c[1], l = c[2];
|
||||||
// Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
|
// Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
|
||||||
float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
|
float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
|
||||||
color r;
|
color r;
|
||||||
if (v <= 0) {
|
if (v <= 0) {
|
||||||
r = 0;
|
r = 0;
|
||||||
} else {
|
}
|
||||||
float min = 2 * l - v;
|
else {
|
||||||
s = (v - min) / v;
|
float min = 2 * l - v;
|
||||||
r = hsv_to_rgb (color (h, s, v));
|
s = (v - min) / v;
|
||||||
}
|
r = hsv_to_rgb(color(h, s, v));
|
||||||
return r;
|
}
|
||||||
}
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
color r;
|
color r;
|
||||||
if (from == "rgb" || from == "RGB")
|
if (from == "rgb" || from == "RGB")
|
||||||
r = x;
|
r = x;
|
||||||
else if (from == "hsv")
|
else if (from == "hsv")
|
||||||
r = hsv_to_rgb (x);
|
r = hsv_to_rgb(x);
|
||||||
else if (from == "hsl")
|
else if (from == "hsl")
|
||||||
r = hsl_to_rgb (x);
|
r = hsl_to_rgb(x);
|
||||||
else if (from == "YIQ")
|
else if (from == "YIQ")
|
||||||
r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
|
r = color(dot(vector(1, 0.9557, 0.6199), (vector)x),
|
||||||
dot (vector(1, -0.2716, -0.6469), (vector)x),
|
dot(vector(1, -0.2716, -0.6469), (vector)x),
|
||||||
dot (vector(1, -1.1082, 1.7051), (vector)x));
|
dot(vector(1, -1.1082, 1.7051), (vector)x));
|
||||||
else if (from == "xyz")
|
else if (from == "xyz")
|
||||||
r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
|
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.969256, 1.875991, 0.041556), (vector)x),
|
||||||
dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
|
dot(vector(0.055648, -0.204043, 1.057311), (vector)x));
|
||||||
else {
|
else {
|
||||||
error ("Unknown color space \"%s\"", to);
|
error("Unknown color space \"%s\"", to);
|
||||||
r = x;
|
r = x;
|
||||||
}
|
}
|
||||||
return transformc (to, r);
|
return transformc(to, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Matrix functions
|
// Matrix functions
|
||||||
|
|
||||||
float determinant (matrix m) BUILTIN;
|
float determinant(matrix m) BUILTIN;
|
||||||
matrix transpose (matrix m) BUILTIN;
|
matrix transpose(matrix m) BUILTIN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Pattern generation
|
// Pattern generation
|
||||||
|
|
||||||
float step (float edge, float x) BUILTIN;
|
float step(float edge, float x) BUILTIN;
|
||||||
color step (color edge, color x) BUILTIN;
|
color step(color edge, color x) BUILTIN;
|
||||||
point step (point edge, point x) BUILTIN;
|
point step(point edge, point x) BUILTIN;
|
||||||
vector step (vector edge, vector x) BUILTIN;
|
vector step(vector edge, vector x) BUILTIN;
|
||||||
normal step (normal edge, normal x) BUILTIN;
|
normal step(normal edge, normal x) BUILTIN;
|
||||||
float smoothstep (float edge0, float edge1, float x) BUILTIN;
|
float smoothstep(float edge0, float edge1, float x) BUILTIN;
|
||||||
|
|
||||||
|
|
||||||
// Derivatives and area operators
|
// Derivatives and area operators
|
||||||
@@ -408,24 +413,26 @@ float smoothstep (float edge0, float edge1, float x) BUILTIN;
|
|||||||
|
|
||||||
// String functions
|
// String functions
|
||||||
|
|
||||||
int strlen (string s) BUILTIN;
|
int strlen(string s) BUILTIN;
|
||||||
int startswith (string s, string prefix) BUILTIN;
|
int startswith(string s, string prefix) BUILTIN;
|
||||||
int endswith (string s, string suffix) BUILTIN;
|
int endswith(string s, string suffix) BUILTIN;
|
||||||
string substr (string s, int start, int len) BUILTIN;
|
string substr(string s, int start, int len) BUILTIN;
|
||||||
string substr (string s, int start) { return substr (s, start, strlen(s)); }
|
string substr(string s, int start) {
|
||||||
|
return substr(s, start, strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
// Define concat in terms of shorter concat
|
// Define concat in terms of shorter concat
|
||||||
string concat (string a, string b, string c) {
|
string concat(string a, string b, string c) {
|
||||||
return concat(concat(a,b), c);
|
return concat(concat(a, b), c);
|
||||||
}
|
}
|
||||||
string concat (string a, string b, string c, string d) {
|
string concat(string a, string b, string c, string d) {
|
||||||
return concat(concat(a,b,c), d);
|
return concat(concat(a, b, c), d);
|
||||||
}
|
}
|
||||||
string concat (string a, string b, string c, string d, string e) {
|
string concat(string a, string b, string c, string d, string e) {
|
||||||
return concat(concat(a,b,c,d), e);
|
return concat(concat(a, b, c, d), e);
|
||||||
}
|
}
|
||||||
string concat (string a, string b, string c, string d, string e, string f) {
|
string concat(string a, string b, string c, string d, string e, string f) {
|
||||||
return concat(concat(a,b,c,d,e), 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 oren_nayar(normal N, float sigma) BUILTIN;
|
||||||
closure color translucent(normal N) BUILTIN;
|
closure color translucent(normal N) BUILTIN;
|
||||||
closure color reflection(normal N, float eta) 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 refraction(normal N, float eta) BUILTIN;
|
||||||
closure color dielectric(normal N, float eta) BUILTIN;
|
closure color dielectric(normal N, float eta) BUILTIN;
|
||||||
closure color transparent() 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_ggx_refraction(normal N, float ag, float eta) BUILTIN;
|
||||||
closure color microfacet_beckmann(normal N, float ab) BUILTIN;
|
closure color microfacet_beckmann(normal N, float ab) BUILTIN;
|
||||||
closure color microfacet_beckmann_refraction(normal N, float ab, float eta) 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 ashikhmin_velvet(normal N, float sigma) BUILTIN;
|
||||||
closure color westin_backscatter(normal N, float roughness) BUILTIN;
|
closure color westin_backscatter(normal N, float roughness) BUILTIN;
|
||||||
closure color westin_sheen(normal N, float edginess) 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;
|
closure color subsurface(float eta, float g, float mfp, float albedo) BUILTIN;
|
||||||
|
|
||||||
// Renderer state
|
// Renderer state
|
||||||
int raytype (string typename) BUILTIN;
|
int raytype(string typename) BUILTIN;
|
||||||
|
|
||||||
#undef BUILTIN
|
#undef BUILTIN
|
||||||
#undef BUILTIN_DERIV
|
#undef BUILTIN_DERIV
|
||||||
|
@@ -37,7 +37,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
/* RenderServices implementation */
|
/* RenderServices implementation */
|
||||||
|
|
||||||
#define TO_MATRIX44(m) (*(OSL::Matrix44*)&(m))
|
#define TO_MATRIX44(m) (*(OSL::Matrix44 *)&(m))
|
||||||
|
|
||||||
/* static ustrings */
|
/* static ustrings */
|
||||||
ustring OSLRenderServices::u_distance("distance");
|
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
|
/* this is only used for shader and object space, we don't really have
|
||||||
a concept of shader space, so we just use object space for both. */
|
a concept of shader space, so we just use object space for both. */
|
||||||
if(xform) {
|
if (xform) {
|
||||||
KernelGlobals *kg = kernel_globals;
|
KernelGlobals *kg = kernel_globals;
|
||||||
const ShaderData *sd = (const ShaderData*)xform;
|
const ShaderData *sd = (const ShaderData *)xform;
|
||||||
int object = sd->object;
|
int object = sd->object;
|
||||||
|
|
||||||
if(object != ~0) {
|
if (object != ~0) {
|
||||||
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
|
Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
|
||||||
tfm = transform_transpose(tfm);
|
tfm = transform_transpose(tfm);
|
||||||
result = TO_MATRIX44(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
|
/* this is only used for shader and object space, we don't really have
|
||||||
a concept of shader space, so we just use object space for both. */
|
a concept of shader space, so we just use object space for both. */
|
||||||
if(xform) {
|
if (xform) {
|
||||||
KernelGlobals *kg = kernel_globals;
|
KernelGlobals *kg = kernel_globals;
|
||||||
const ShaderData *sd = (const ShaderData*)xform;
|
const ShaderData *sd = (const ShaderData *)xform;
|
||||||
int object = sd->object;
|
int object = sd->object;
|
||||||
|
|
||||||
if(object != ~0) {
|
if (object != ~0) {
|
||||||
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
|
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
|
||||||
tfm = transform_transpose(tfm);
|
tfm = transform_transpose(tfm);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
@@ -108,22 +108,22 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti
|
|||||||
{
|
{
|
||||||
KernelGlobals *kg = kernel_globals;
|
KernelGlobals *kg = kernel_globals;
|
||||||
|
|
||||||
if(from == u_ndc) {
|
if (from == u_ndc) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.ndctoworld);
|
Transform tfm = transform_transpose(kernel_data.cam.ndctoworld);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(from == u_raster) {
|
else if (from == u_raster) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
|
Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(from == u_screen) {
|
else if (from == u_screen) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
|
Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(from == u_camera) {
|
else if (from == u_camera) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
|
Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
return true;
|
||||||
@@ -136,22 +136,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl
|
|||||||
{
|
{
|
||||||
KernelGlobals *kg = kernel_globals;
|
KernelGlobals *kg = kernel_globals;
|
||||||
|
|
||||||
if(to == u_ndc) {
|
if (to == u_ndc) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
|
Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(to == u_raster) {
|
else if (to == u_raster) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
|
Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(to == u_screen) {
|
else if (to == u_screen) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
|
Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(to == u_camera) {
|
else if (to == u_camera) {
|
||||||
Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
|
Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
|
||||||
result = TO_MATRIX44(tfm);
|
result = TO_MATRIX44(tfm);
|
||||||
return true;
|
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,
|
bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives,
|
||||||
ustring object, TypeDesc type, ustring name,
|
ustring object, TypeDesc type, ustring name,
|
||||||
int index, void *val)
|
int index, void *val)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd,
|
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) {
|
if (attr.type == TypeDesc::TypeFloat) {
|
||||||
float *fval = (float*)val;
|
float *fval = (float *)val;
|
||||||
fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
|
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 {
|
else {
|
||||||
/* todo: this won't work when float3 has w component */
|
/* 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,
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_mesh_attribute_convert(KernelGlobals *kg, const ShaderData *sd,
|
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];
|
float tmp[3];
|
||||||
float3 *fval = (float3*)val;
|
float3 *fval = (float3 *)val;
|
||||||
|
|
||||||
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
|
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
|
||||||
|
|
||||||
fval[0] = make_float3(tmp[0], tmp[0], tmp[0]);
|
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[1] = make_float3(tmp[1], tmp[1], tmp[1]);
|
||||||
fval[2] = make_float3(tmp[2], tmp[2], tmp[2]);
|
fval[2] = make_float3(tmp[2], tmp[2], tmp[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
|
else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
|
||||||
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
|
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
|
||||||
|
{
|
||||||
float3 tmp[3];
|
float3 tmp[3];
|
||||||
float *fval = (float*)val;
|
float *fval = (float *)val;
|
||||||
|
|
||||||
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
|
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
|
||||||
|
|
||||||
fval[0] = average(tmp[0]);
|
fval[0] = average(tmp[0]);
|
||||||
if(derivatives) {
|
if (derivatives) {
|
||||||
fval[1] = average(tmp[1]);
|
fval[1] = average(tmp[1]);
|
||||||
fval[2] = average(tmp[2]);
|
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();
|
size_t datasize = attr.value.datasize();
|
||||||
|
|
||||||
memcpy(val, attr.value.data(), datasize);
|
memcpy(val, attr.value.data(), datasize);
|
||||||
if(derivatives)
|
if (derivatives)
|
||||||
memset((char*)val + datasize, 0, datasize*2);
|
memset((char *)val + datasize, 0, datasize * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name,
|
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;
|
KernelGlobals *kg = kernel_globals;
|
||||||
const ShaderData *sd = (const ShaderData*)renderstate;
|
const ShaderData *sd = (const ShaderData *)renderstate;
|
||||||
int object = sd->object;
|
int object = sd->object;
|
||||||
int tri = sd->prim;
|
int tri = sd->prim;
|
||||||
|
|
||||||
/* lookup of attribute on another object */
|
/* 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);
|
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;
|
return false;
|
||||||
|
|
||||||
object = it->second;
|
object = it->second;
|
||||||
tri = ~0;
|
tri = ~0;
|
||||||
}
|
}
|
||||||
else if(object == ~0) {
|
else if (object == ~0) {
|
||||||
/* no background attributes supported */
|
/* no background attributes supported */
|
||||||
return false;
|
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& attribute_map = kg->osl.attribute_map[object];
|
||||||
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
|
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
|
||||||
|
|
||||||
if(it == attribute_map.end())
|
if (it == attribute_map.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* type mistmatch? */
|
/* type mistmatch? */
|
||||||
const OSLGlobals::Attribute& attr = it->second;
|
const OSLGlobals::Attribute& attr = it->second;
|
||||||
|
|
||||||
if(attr.elem != ATTR_ELEMENT_VALUE) {
|
if (attr.elem != ATTR_ELEMENT_VALUE) {
|
||||||
/* triangle and vertex attributes */
|
/* triangle and vertex attributes */
|
||||||
if(tri != ~0) {
|
if (tri != ~0) {
|
||||||
if(attr.type == type || (attr.type == TypeDesc::TypeColor &&
|
if (attr.type == type || (attr.type == TypeDesc::TypeColor &&
|
||||||
(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal)))
|
(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal)))
|
||||||
|
{
|
||||||
return get_mesh_attribute(kg, sd, attr, derivatives, val);
|
return get_mesh_attribute(kg, sd, attr, derivatives, val);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return get_mesh_attribute_convert(kg, sd, attr, type, derivatives, val);
|
return get_mesh_attribute_convert(kg, sd, attr, type, derivatives, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -283,7 +287,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type,
|
bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type,
|
||||||
void *renderstate, void *val)
|
void *renderstate, void *val)
|
||||||
{
|
{
|
||||||
return false; /* disabled by lockgeom */
|
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,
|
void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names,
|
||||||
TypeDesc *attr_types, int nattrs)
|
TypeDesc *attr_types, int nattrs)
|
||||||
{
|
{
|
||||||
#ifdef WITH_PARTIO
|
#ifdef WITH_PARTIO
|
||||||
m_attr_queries.push_back(AttrQuery());
|
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 */
|
to the query. Just to prevent buffer overruns */
|
||||||
query.capacity = -1;
|
query.capacity = -1;
|
||||||
|
|
||||||
for(int i = 0; i < nattrs; ++i)
|
for (int i = 0; i < nattrs; ++i) {
|
||||||
{
|
|
||||||
query.attr_names[i] = attr_names[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)
|
if (query.capacity < 0)
|
||||||
query.capacity = attr_types[i].numelements();
|
query.capacity = attr_types[i].numelements();
|
||||||
else
|
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
|
/* convert the OSL (OIIO) type to the equivalent Partio type so
|
||||||
we can do a fast check at query time. */
|
we can do a fast check at query time. */
|
||||||
if(element_type == TypeDesc::TypeFloat)
|
if (element_type == TypeDesc::TypeFloat) {
|
||||||
query.attr_partio_types[i] = Partio::FLOAT;
|
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::TypeInt) {
|
||||||
else if(element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint ||
|
query.attr_partio_types[i] = Partio::INT;
|
||||||
element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal)
|
}
|
||||||
query.attr_partio_types[i] = Partio::VECTOR;
|
else if (element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint ||
|
||||||
else
|
element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal)
|
||||||
return NULL; /* report some error of unknown type */
|
{
|
||||||
|
query.attr_partio_types[i] = Partio::VECTOR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return NULL; /* report some error of unknown type */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is valid until the end of RenderServices */
|
/* this is valid until the end of RenderServices */
|
||||||
@@ -348,18 +356,18 @@ Partio::ParticlesData *OSLRenderServices::get_pointcloud(ustring filename)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius,
|
int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, 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
|
/* todo: this code has never been tested, and most likely does not
|
||||||
work. it's based on the example code in OSL */
|
work. it's based on the example code in OSL */
|
||||||
|
|
||||||
#ifdef WITH_PARTIO
|
#ifdef WITH_PARTIO
|
||||||
/* query Partio for this pointcloud lookup using cached attr_query */
|
/* query Partio for this pointcloud lookup using cached attr_query */
|
||||||
if(!_attr_query)
|
if (!_attr_query)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
AttrQuery *attr_query = (AttrQuery *)_attr_query;
|
AttrQuery *attr_query = (AttrQuery *)_attr_query;
|
||||||
if(attr_query->capacity < max_points)
|
if (attr_query->capacity < max_points)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* get the pointcloud entry for the given filename */
|
/* get the pointcloud entry for the given filename */
|
||||||
@@ -370,13 +378,13 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, flo
|
|||||||
int nattrs = attr_query->attr_names.size();
|
int nattrs = attr_query->attr_names.size();
|
||||||
Partio::ParticleAttribute *attr = (Partio::ParticleAttribute *)alloca(sizeof(Partio::ParticleAttribute) * nattrs);
|
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 */
|
/* 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;
|
continue;
|
||||||
|
|
||||||
/* lookup the attribute by name*/
|
/* 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 */
|
/* issue an error here and return, types don't match */
|
||||||
Partio::endCachedAccess(cloud);
|
Partio::endCachedAccess(cloud);
|
||||||
cloud->release();
|
cloud->release();
|
||||||
@@ -394,14 +402,14 @@ int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, flo
|
|||||||
int count = indices.size();
|
int count = indices.size();
|
||||||
|
|
||||||
/* retrieve the attributes directly to user space */
|
/* retrieve the attributes directly to user space */
|
||||||
for(int j = 0; j < nattrs; ++j) {
|
for (int j = 0; j < nattrs; ++j) {
|
||||||
/* special cases */
|
/* special cases */
|
||||||
if(attr_query->attr_names[j] == u_distance) {
|
if (attr_query->attr_names[j] == u_distance) {
|
||||||
for(int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
((float *)attr_outdata[j])[i] = sqrtf(dist2[i]);
|
((float *)attr_outdata[j])[i] = sqrtf(dist2[i]);
|
||||||
}
|
}
|
||||||
else if(attr_query->attr_names[j] == u_index) {
|
else if (attr_query->attr_names[j] == u_index) {
|
||||||
for(int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
((int *)attr_outdata[j])[i] = indices[i];
|
((int *)attr_outdata[j])[i] = indices[i];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -57,19 +57,19 @@ public:
|
|||||||
bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time);
|
bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time);
|
||||||
|
|
||||||
bool get_array_attribute(void *renderstate, bool derivatives,
|
bool get_array_attribute(void *renderstate, bool derivatives,
|
||||||
ustring object, TypeDesc type, ustring name,
|
ustring object, TypeDesc type, ustring name,
|
||||||
int index, void *val);
|
int index, void *val);
|
||||||
bool get_attribute(void *renderstate, bool derivatives, ustring object,
|
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,
|
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);
|
bool has_userdata(ustring name, TypeDesc type, void *renderstate);
|
||||||
|
|
||||||
void *get_pointcloud_attr_query(ustring *attr_names,
|
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 ¢er, float radius,
|
int pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius,
|
||||||
int max_points, void *attr_query, void **attr_outdata);
|
int max_points, void *attr_query, void **attr_outdata);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KernelGlobals *kernel_globals;
|
KernelGlobals *kernel_globals;
|
||||||
@@ -79,8 +79,7 @@ private:
|
|||||||
right now it only caches the types already converted to
|
right now it only caches the types already converted to
|
||||||
Partio constants. this is what get_pointcloud_attr_query
|
Partio constants. this is what get_pointcloud_attr_query
|
||||||
returns */
|
returns */
|
||||||
struct AttrQuery
|
struct AttrQuery {
|
||||||
{
|
|
||||||
/* names of the attributes to query */
|
/* names of the attributes to query */
|
||||||
std::vector<ustring> attr_names;
|
std::vector<ustring> attr_names;
|
||||||
/* types as (enum Partio::ParticleAttributeType) of the
|
/* types as (enum Partio::ParticleAttributeType) of the
|
||||||
|
@@ -37,7 +37,7 @@ tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data);
|
|||||||
|
|
||||||
void OSLShader::thread_init(KernelGlobals *kg)
|
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();
|
OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData();
|
||||||
|
|
||||||
@@ -46,12 +46,12 @@ void OSLShader::thread_init(KernelGlobals *kg)
|
|||||||
|
|
||||||
tls_set(kg->osl.thread_data, tdata);
|
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)
|
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);
|
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||||
|
|
||||||
@@ -62,12 +62,12 @@ void OSLShader::thread_free(KernelGlobals *kg)
|
|||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
|
|
||||||
#define TO_VEC3(v) (*(OSL::Vec3*)&(v))
|
#define TO_VEC3(v) (*(OSL::Vec3 *)&(v))
|
||||||
#define TO_COLOR3(v) (*(OSL::Color3*)&(v))
|
#define TO_COLOR3(v) (*(OSL::Color3 *)&(v))
|
||||||
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
|
#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
|
||||||
|
|
||||||
static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
|
static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
|
||||||
int path_flag, OSL::ShaderGlobals *globals)
|
int path_flag, OSL::ShaderGlobals *globals)
|
||||||
{
|
{
|
||||||
/* copy from shader data to shader globals */
|
/* copy from shader data to shader globals */
|
||||||
globals->P = TO_VEC3(sd->P);
|
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->dvdy = sd->dv.dy;
|
||||||
globals->dPdu = TO_VEC3(sd->dPdu);
|
globals->dPdu = TO_VEC3(sd->dPdu);
|
||||||
globals->dPdv = TO_VEC3(sd->dPdv);
|
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 */
|
/* booleans */
|
||||||
globals->raytype = path_flag; /* todo: add our own ray types */
|
globals->raytype = path_flag; /* todo: add our own ray types */
|
||||||
@@ -109,35 +109,35 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
|
|||||||
/* Surface */
|
/* Surface */
|
||||||
|
|
||||||
static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
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
|
/* OSL gives use a closure tree, we flatten it into arrays per
|
||||||
* closure type, for evaluation, sampling, etc later on. */
|
* closure type, for evaluation, sampling, etc later on. */
|
||||||
|
|
||||||
if(closure->type == OSL::ClosureColor::COMPONENT) {
|
if (closure->type == OSL::ClosureColor::COMPONENT) {
|
||||||
OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
|
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
|
||||||
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
|
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
|
||||||
|
|
||||||
if(prim) {
|
if (prim) {
|
||||||
ShaderClosure sc;
|
ShaderClosure sc;
|
||||||
sc.prim = prim;
|
sc.prim = prim;
|
||||||
sc.weight = weight;
|
sc.weight = weight;
|
||||||
|
|
||||||
switch(prim->category()) {
|
switch (prim->category()) {
|
||||||
case ClosurePrimitive::BSDF: {
|
case ClosurePrimitive::BSDF: {
|
||||||
if(sd->num_closure == MAX_CLOSURE)
|
if (sd->num_closure == MAX_CLOSURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim;
|
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)prim;
|
||||||
ustring scattering = bsdf->scattering();
|
ustring scattering = bsdf->scattering();
|
||||||
|
|
||||||
/* no caustics option */
|
/* no caustics option */
|
||||||
if(no_glossy && scattering == OSL::Labels::GLOSSY)
|
if (no_glossy && scattering == OSL::Labels::GLOSSY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* sample weight */
|
/* sample weight */
|
||||||
float albedo = bsdf->albedo(TO_VEC3(sd->I));
|
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;
|
float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight;
|
||||||
|
|
||||||
sc.sample_weight = 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;
|
sd->osl_closure.bsdf_sample_sum = sample_sum;
|
||||||
|
|
||||||
/* scattering flags */
|
/* scattering flags */
|
||||||
if(scattering == OSL::Labels::DIFFUSE)
|
if (scattering == OSL::Labels::DIFFUSE)
|
||||||
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
|
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||||
else if(scattering == OSL::Labels::GLOSSY)
|
else if (scattering == OSL::Labels::GLOSSY)
|
||||||
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
|
sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
|
||||||
else
|
else
|
||||||
sd->flag |= SD_BSDF;
|
sd->flag |= SD_BSDF;
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ClosurePrimitive::Emissive: {
|
case ClosurePrimitive::Emissive: {
|
||||||
if(sd->num_closure == MAX_CLOSURE)
|
if (sd->num_closure == MAX_CLOSURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* sample weight */
|
/* sample weight */
|
||||||
@@ -175,7 +175,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ClosurePrimitive::Holdout:
|
case ClosurePrimitive::Holdout:
|
||||||
if(sd->num_closure == MAX_CLOSURE)
|
if (sd->num_closure == MAX_CLOSURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sc.sample_weight = 0.0f;
|
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) {
|
else if (closure->type == OSL::ClosureColor::MUL) {
|
||||||
OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
|
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
|
||||||
flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight);
|
flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight);
|
||||||
}
|
}
|
||||||
else if(closure->type == OSL::ClosureColor::ADD) {
|
else if (closure->type == OSL::ClosureColor::ADD) {
|
||||||
OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
|
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
|
||||||
flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight);
|
flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight);
|
||||||
flatten_surface_closure_tree(sd, no_glossy, add->closureB, 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)
|
void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
|
||||||
{
|
{
|
||||||
/* gather pointers */
|
/* 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);
|
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
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 */
|
/* execute shader for this point */
|
||||||
int shader = sd->shader & SHADER_MASK;
|
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);
|
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals);
|
||||||
|
|
||||||
/* flatten closure tree */
|
/* flatten closure tree */
|
||||||
sd->num_closure = 0;
|
sd->num_closure = 0;
|
||||||
sd->randb_closure = randb;
|
sd->randb_closure = randb;
|
||||||
|
|
||||||
if(globals->Ci) {
|
if (globals->Ci) {
|
||||||
bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
|
bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
|
||||||
flatten_surface_closure_tree(sd, no_glossy, globals->Ci);
|
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
|
* is only one supported closure type at the moment, which has no evaluation
|
||||||
* functions, so we just sum the weights */
|
* functions, so we just sum the weights */
|
||||||
|
|
||||||
if(closure->type == OSL::ClosureColor::COMPONENT) {
|
if (closure->type == OSL::ClosureColor::COMPONENT) {
|
||||||
OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
|
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
|
||||||
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
|
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);
|
return make_float3(1.0f, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
else if(closure->type == OSL::ClosureColor::MUL) {
|
else if (closure->type == OSL::ClosureColor::MUL) {
|
||||||
OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
|
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
|
||||||
|
|
||||||
return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
|
return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
|
||||||
}
|
}
|
||||||
else if(closure->type == OSL::ClosureColor::ADD) {
|
else if (closure->type == OSL::ClosureColor::ADD) {
|
||||||
OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
|
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
|
||||||
|
|
||||||
return flatten_background_closure_tree(add->closureA) +
|
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);
|
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)
|
float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
|
||||||
{
|
{
|
||||||
/* gather pointers */
|
/* 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);
|
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
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);
|
shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
|
||||||
|
|
||||||
/* execute shader for this point */
|
/* 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);
|
ctx->execute(OSL::pvt::ShadUseSurface, *kg->osl.background_state, *globals);
|
||||||
|
|
||||||
/* return background color immediately */
|
/* return background color immediately */
|
||||||
if(globals->Ci)
|
if (globals->Ci)
|
||||||
return flatten_background_closure_tree(globals->Ci);
|
return flatten_background_closure_tree(globals->Ci);
|
||||||
|
|
||||||
return make_float3(0.0f, 0.0f, 0.0f);
|
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 */
|
/* Volume */
|
||||||
|
|
||||||
static void flatten_volume_closure_tree(ShaderData *sd,
|
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
|
/* OSL gives use a closure tree, we flatten it into arrays per
|
||||||
* closure type, for evaluation, sampling, etc later on. */
|
* closure type, for evaluation, sampling, etc later on. */
|
||||||
|
|
||||||
if(closure->type == OSL::ClosureColor::COMPONENT) {
|
if (closure->type == OSL::ClosureColor::COMPONENT) {
|
||||||
OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure;
|
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
|
||||||
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
|
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
|
||||||
|
|
||||||
if(prim) {
|
if (prim) {
|
||||||
ShaderClosure sc;
|
ShaderClosure sc;
|
||||||
sc.prim = prim;
|
sc.prim = prim;
|
||||||
sc.weight = weight;
|
sc.weight = weight;
|
||||||
|
|
||||||
switch(prim->category()) {
|
switch (prim->category()) {
|
||||||
case ClosurePrimitive::Volume: {
|
case ClosurePrimitive::Volume: {
|
||||||
if(sd->num_closure == MAX_CLOSURE)
|
if (sd->num_closure == MAX_CLOSURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* sample weight */
|
/* sample weight */
|
||||||
@@ -329,12 +329,12 @@ static void flatten_volume_closure_tree(ShaderData *sd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(closure->type == OSL::ClosureColor::MUL) {
|
else if (closure->type == OSL::ClosureColor::MUL) {
|
||||||
OSL::ClosureMul *mul = (OSL::ClosureMul*)closure;
|
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
|
||||||
flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
|
flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
|
||||||
}
|
}
|
||||||
else if(closure->type == OSL::ClosureColor::ADD) {
|
else if (closure->type == OSL::ClosureColor::ADD) {
|
||||||
OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure;
|
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
|
||||||
flatten_volume_closure_tree(sd, add->closureA, weight);
|
flatten_volume_closure_tree(sd, add->closureA, weight);
|
||||||
flatten_volume_closure_tree(sd, add->closureB, 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)
|
void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
|
||||||
{
|
{
|
||||||
/* gather pointers */
|
/* 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);
|
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
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 */
|
/* execute shader */
|
||||||
int shader = sd->shader & SHADER_MASK;
|
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);
|
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals);
|
||||||
|
|
||||||
/* retrieve resulting closures */
|
/* 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.num_volume = 0;
|
||||||
sd->osl_closure.randb = randb;
|
sd->osl_closure.randb = randb;
|
||||||
|
|
||||||
if(globals->Ci)
|
if (globals->Ci)
|
||||||
flatten_volume_closure_tree(sd, 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)
|
void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
|
||||||
{
|
{
|
||||||
/* gather pointers */
|
/* 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);
|
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
||||||
@@ -384,7 +384,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
|
|||||||
/* execute shader */
|
/* execute shader */
|
||||||
int shader = sd->shader & SHADER_MASK;
|
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);
|
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals);
|
||||||
|
|
||||||
/* get back position */
|
/* get back position */
|
||||||
@@ -393,17 +393,17 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
|
|||||||
|
|
||||||
void OSLShader::release(KernelGlobals *kg, const 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);
|
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 */
|
/* 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)
|
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;
|
int label = LABEL_NONE;
|
||||||
|
|
||||||
pdf = 0.0f;
|
pdf = 0.0f;
|
||||||
@@ -412,27 +412,27 @@ int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float
|
|||||||
ustring ulabel;
|
ustring ulabel;
|
||||||
|
|
||||||
ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
|
ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
|
||||||
TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
|
TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
|
||||||
randu, randv,
|
randu, randv,
|
||||||
TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
|
TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
|
||||||
pdf, TO_COLOR3(eval));
|
pdf, TO_COLOR3(eval));
|
||||||
|
|
||||||
/* convert OSL label */
|
/* convert OSL label */
|
||||||
if(ulabel == OSL::Labels::REFLECT)
|
if (ulabel == OSL::Labels::REFLECT)
|
||||||
label = LABEL_REFLECT;
|
label = LABEL_REFLECT;
|
||||||
else if(ulabel == OSL::Labels::TRANSMIT)
|
else if (ulabel == OSL::Labels::TRANSMIT)
|
||||||
label = LABEL_TRANSMIT;
|
label = LABEL_TRANSMIT;
|
||||||
else
|
else
|
||||||
return LABEL_NONE; /* sampling failed */
|
return LABEL_NONE; /* sampling failed */
|
||||||
|
|
||||||
/* convert scattering to our bitflag label */
|
/* convert scattering to our bitflag label */
|
||||||
ustring uscattering = sample_bsdf->scattering();
|
ustring uscattering = sample_bsdf->scattering();
|
||||||
|
|
||||||
if(uscattering == OSL::Labels::DIFFUSE)
|
if (uscattering == OSL::Labels::DIFFUSE)
|
||||||
label |= LABEL_DIFFUSE;
|
label |= LABEL_DIFFUSE;
|
||||||
else if(uscattering == OSL::Labels::GLOSSY)
|
else if (uscattering == OSL::Labels::GLOSSY)
|
||||||
label |= LABEL_GLOSSY;
|
label |= LABEL_GLOSSY;
|
||||||
else if(uscattering == OSL::Labels::SINGULAR)
|
else if (uscattering == OSL::Labels::SINGULAR)
|
||||||
label |= LABEL_SINGULAR;
|
label |= LABEL_SINGULAR;
|
||||||
else
|
else
|
||||||
label |= LABEL_TRANSPARENT;
|
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)
|
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;
|
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);
|
bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
|
||||||
else
|
else
|
||||||
bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
|
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)
|
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));
|
OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
|
||||||
eval += TO_FLOAT3(emissive_eval);
|
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)
|
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));
|
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
|
CCL_NAMESPACE_END
|
||||||
|
@@ -68,15 +68,15 @@ public:
|
|||||||
|
|
||||||
/* sample & eval */
|
/* sample & eval */
|
||||||
static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
|
static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
|
||||||
float randu, float randv,
|
float randu, float randv,
|
||||||
float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
|
float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
|
||||||
static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
|
static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
|
||||||
const float3& omega_in, float& pdf);
|
const float3& omega_in, float& pdf);
|
||||||
|
|
||||||
static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
|
static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
|
||||||
|
|
||||||
static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc,
|
static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc,
|
||||||
const float3 omega_in, const float3 omega_out);
|
const float3 omega_in, const float3 omega_out);
|
||||||
|
|
||||||
/* release */
|
/* release */
|
||||||
static void release(KernelGlobals *kg, const ShaderData *sd);
|
static void release(KernelGlobals *kg, const ShaderData *sd);
|
||||||
|
@@ -46,88 +46,90 @@ using namespace OSL;
|
|||||||
|
|
||||||
class SubsurfaceClosure : public VolumeClosure {
|
class SubsurfaceClosure : public VolumeClosure {
|
||||||
public:
|
public:
|
||||||
float m_g;
|
float m_g;
|
||||||
float m_eta;
|
float m_eta;
|
||||||
Color3 m_mfp, m_albedo;
|
Color3 m_mfp, m_albedo;
|
||||||
static float root_find_Rd(const float Rd0, const float A) {
|
static float root_find_Rd(const float Rd0, const float A) {
|
||||||
// quick exit for trivial cases
|
// quick exit for trivial cases
|
||||||
if (Rd0 <= 0) return 0;
|
if (Rd0 <= 0) return 0;
|
||||||
const float A43 = A * 4.0f / 3.0f;
|
const float A43 = A * 4.0f / 3.0f;
|
||||||
// Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection
|
// Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection
|
||||||
// method can be used because this function is monotonicaly increasing.
|
// method can be used because this function is monotonicaly increasing.
|
||||||
float lo = 0, hi = 1;
|
float lo = 0, hi = 1;
|
||||||
for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient
|
for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient
|
||||||
// eval function at midpoint
|
// eval function at midpoint
|
||||||
float alpha = 0.5f * (lo + hi);
|
float alpha = 0.5f * (lo + hi);
|
||||||
float a1 = sqrtf(3 * (1 - alpha));
|
float a1 = sqrtf(3 * (1 - alpha));
|
||||||
float e1 = expf(-a1);
|
float e1 = expf(-a1);
|
||||||
float e2 = expf(-A43 * a1);
|
float e2 = expf(-A43 * a1);
|
||||||
float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0;
|
float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0;
|
||||||
if (fabsf(Rd) < 1e-6f)
|
if (fabsf(Rd) < 1e-6f)
|
||||||
return alpha; // close enough
|
return alpha; // close enough
|
||||||
else if (Rd > 0)
|
else if (Rd > 0)
|
||||||
hi = alpha; // root is on left side
|
hi = alpha; // root is on left side
|
||||||
else
|
else
|
||||||
lo = alpha; // root is on right side
|
lo = alpha; // root is on right side
|
||||||
}
|
}
|
||||||
// didn't quite converge, pick result in the middle of remaining interval
|
// didn't quite converge, pick result in the middle of remaining interval
|
||||||
return 0.5f * (lo + hi);
|
return 0.5f * (lo + hi);
|
||||||
}
|
}
|
||||||
SubsurfaceClosure() { }
|
SubsurfaceClosure() {
|
||||||
|
}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
ior(m_eta);
|
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
|
// eq.10
|
||||||
float inv_eta = 1 / m_eta;
|
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 Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta;
|
||||||
float A = (1 + Fdr) / (1 - Fdr);
|
float A = (1 + Fdr) / (1 - Fdr);
|
||||||
// compute sigma_s, sigma_a (eq.16)
|
// compute sigma_s, sigma_a (eq.16)
|
||||||
Color3 alpha_prime = Color3 (root_find_Rd(m_albedo[0], A),
|
Color3 alpha_prime = Color3(root_find_Rd(m_albedo[0], A),
|
||||||
root_find_Rd(m_albedo[1], A),
|
root_find_Rd(m_albedo[1], A),
|
||||||
root_find_Rd(m_albedo[2], 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,
|
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.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);
|
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;
|
Color3 sigma_s_prime = alpha_prime * sigma_t_prime;
|
||||||
|
|
||||||
sigma_s((1.0f / (1 - m_g)) * sigma_s_prime);
|
sigma_s((1.0f / (1 - m_g)) * sigma_s_prime);
|
||||||
sigma_a(sigma_t_prime - sigma_s_prime);
|
sigma_a(sigma_t_prime - sigma_s_prime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mergeable (const ClosurePrimitive *other) const {
|
bool mergeable(const ClosurePrimitive *other) const {
|
||||||
const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other;
|
const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other;
|
||||||
return m_g == comp->m_g && VolumeClosure::mergeable(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 {
|
void print_on(std::ostream &out) const {
|
||||||
out << name() << " ()";
|
out << name() << " ()";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const {
|
virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const {
|
||||||
float costheta = omega_in.dot(omega_out);
|
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));
|
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);
|
return Color3(ph, ph, ph);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ClosureParam closure_subsurface_params[] = {
|
ClosureParam closure_subsurface_params[] = {
|
||||||
CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_eta),
|
CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_eta),
|
||||||
CLOSURE_FLOAT_PARAM (SubsurfaceClosure, m_g),
|
CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_g),
|
||||||
CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_mfp),
|
CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_mfp),
|
||||||
CLOSURE_COLOR_PARAM (SubsurfaceClosure, m_albedo),
|
CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_albedo),
|
||||||
CLOSURE_STRING_KEYPARAM("label"),
|
CLOSURE_STRING_KEYPARAM("label"),
|
||||||
CLOSURE_FINISH_PARAM(SubsurfaceClosure) };
|
CLOSURE_FINISH_PARAM(SubsurfaceClosure)
|
||||||
|
};
|
||||||
|
|
||||||
CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure)
|
CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user