various shader-related improvements
parent
6013021a56
commit
4871d6793a
|
@ -2,13 +2,6 @@
|
||||||
to be tested for consistency. This is done
|
to be tested for consistency. This is done
|
||||||
using the testcase 'test_chisquare' -->
|
using the testcase 'test_chisquare' -->
|
||||||
<scene>
|
<scene>
|
||||||
<!-- Test the rough plastic model with the
|
|
||||||
Beckmann microfacet distribution -->
|
|
||||||
<bsdf type="roughplastic">
|
|
||||||
<string name="distribution" value="beckmann"/>
|
|
||||||
<float name="alpha" value=".7"/>
|
|
||||||
</bsdf>
|
|
||||||
|
|
||||||
<!-- Test the smooth diffuse model -->
|
<!-- Test the smooth diffuse model -->
|
||||||
<bsdf type="diffuse"/>
|
<bsdf type="diffuse"/>
|
||||||
|
|
||||||
|
@ -40,9 +33,6 @@
|
||||||
<string name="extIOR" value="air"/>
|
<string name="extIOR" value="air"/>
|
||||||
</bsdf>
|
</bsdf>
|
||||||
|
|
||||||
<!-- Test the smooth plastic model -->
|
|
||||||
<bsdf type="plastic"/>
|
|
||||||
|
|
||||||
<!-- Test a mixture of degenerate materials -->
|
<!-- Test a mixture of degenerate materials -->
|
||||||
<bsdf type="mixture">
|
<bsdf type="mixture">
|
||||||
<string name="weights" value=".8 .2"/>
|
<string name="weights" value=".8 .2"/>
|
||||||
|
@ -110,4 +100,14 @@
|
||||||
<float name="alphaU" value="0.1"/>
|
<float name="alphaU" value="0.1"/>
|
||||||
<float name="alphaV" value="0.3"/>
|
<float name="alphaV" value="0.3"/>
|
||||||
</bsdf>
|
</bsdf>
|
||||||
|
|
||||||
|
<!-- Test the smooth plastic model -->
|
||||||
|
<bsdf type="plastic"/>
|
||||||
|
|
||||||
|
<!-- Test the rough plastic model with the
|
||||||
|
Beckmann microfacet distribution -->
|
||||||
|
<bsdf type="roughplastic">
|
||||||
|
<string name="distribution" value="beckmann"/>
|
||||||
|
<float name="alpha" value=".7"/>
|
||||||
|
</bsdf>
|
||||||
</scene>
|
</scene>
|
||||||
|
|
|
@ -441,13 +441,13 @@ extern MTS_EXPORT_CORE Float fresnelDielectric(Float cosThetaI,
|
||||||
*
|
*
|
||||||
* \param cosThetaI
|
* \param cosThetaI
|
||||||
* Cosine of the angle between the normal and the incident ray
|
* Cosine of the angle between the normal and the incident ray
|
||||||
* \param etaExt
|
* \param extIOR
|
||||||
* Refraction coefficient outside of the material
|
* Refraction coefficient outside of the material
|
||||||
* \param etaInt
|
* \param intIOR
|
||||||
* Refraction coefficient inside the material
|
* Refraction coefficient inside the material
|
||||||
*/
|
*/
|
||||||
extern MTS_EXPORT_CORE Float fresnel(Float cosThetaI, Float etaExt,
|
extern MTS_EXPORT_CORE Float fresnel(Float cosThetaI, Float extIOR,
|
||||||
Float etaInt);
|
Float intIOR);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the unpolarized fresnel reflection coefficient on
|
* Calculates the unpolarized fresnel reflection coefficient on
|
||||||
|
|
|
@ -349,9 +349,8 @@ public:
|
||||||
<< " abs(2 * nDotM * cosTheta(wi) / dot(wi, m))));" << endl
|
<< " abs(2 * nDotM * cosTheta(wi) / dot(wi, m))));" << endl
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "vec3 " << evalName << "_schlick(vec3 wi) {" << endl
|
<< "vec3 " << evalName << "_schlick(float ct) {" << endl
|
||||||
<< " float ct = cosTheta(wi), ctSqr = ct*ct," << endl
|
<< " float ctSqr = ct*ct, ct5 = ctSqr*ctSqr*ct;" << endl
|
||||||
<< " ct5 = ctSqr*ctSqr*ct;" << endl
|
|
||||||
<< " return " << evalName << "_R0 + (vec3(1.0) - " << evalName << "_R0) * ct5;" << endl
|
<< " return " << evalName << "_R0 + (vec3(1.0) - " << evalName << "_R0) * ct5;" << endl
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
|
@ -362,8 +361,8 @@ public:
|
||||||
<< " vec3 reflectance = " << depNames[0] << "(uv);" << endl
|
<< " vec3 reflectance = " << depNames[0] << "(uv);" << endl
|
||||||
<< " float D = " << evalName << "_D(H, " << m_alpha << ")" << ";" << endl
|
<< " float D = " << evalName << "_D(H, " << m_alpha << ")" << ";" << endl
|
||||||
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
||||||
<< " vec3 Fr = " << evalName << "_schlick(wi);" << endl
|
<< " vec3 F = " << evalName << "_schlick(1-dot(wi, H));" << endl
|
||||||
<< " return reflectance * Fr * (D * G / (4*cosTheta(wi)));" << endl
|
<< " return reflectance * F * (D * G / (4*cosTheta(wi)));" << endl
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
|
|
|
@ -37,7 +37,8 @@ MTS_NAMESPACE_BEGIN
|
||||||
*
|
*
|
||||||
* \renderings{
|
* \renderings{
|
||||||
* \rendering{A rendering with the default parameters}{bsdf_plastic_default}
|
* \rendering{A rendering with the default parameters}{bsdf_plastic_default}
|
||||||
* \rendering{A rendering with custom parameters (\lstref{plastic-shiny})}{bsdf_plastic_shiny}
|
* \rendering{A rendering with custom parameters (\lstref{plastic-shiny})}
|
||||||
|
* {bsdf_plastic_shiny}
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* This plugin describes a perfectly smooth plastic-like dielectric material
|
* This plugin describes a perfectly smooth plastic-like dielectric material
|
||||||
|
@ -90,10 +91,15 @@ public:
|
||||||
m_usesRayDifferentials =
|
m_usesRayDifferentials =
|
||||||
m_specularReflectance->usesRayDifferentials() ||
|
m_specularReflectance->usesRayDifferentials() ||
|
||||||
m_diffuseReflectance->usesRayDifferentials();
|
m_diffuseReflectance->usesRayDifferentials();
|
||||||
|
configure();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SmoothPlastic() { }
|
virtual ~SmoothPlastic() { }
|
||||||
|
|
||||||
|
Spectrum getDiffuseReflectance(const Intersection &its) const {
|
||||||
|
return m_diffuseReflectance->getValue(its);
|
||||||
|
}
|
||||||
|
|
||||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
BSDF::serialize(stream, manager);
|
BSDF::serialize(stream, manager);
|
||||||
|
|
||||||
|
@ -123,6 +129,13 @@ public:
|
||||||
m_specularReflectance, "specularReflectance", 1.0f);
|
m_specularReflectance, "specularReflectance", 1.0f);
|
||||||
m_diffuseReflectance = ensureEnergyConservation(
|
m_diffuseReflectance = ensureEnergyConservation(
|
||||||
m_diffuseReflectance, "diffuseReflectance", 1.0f);
|
m_diffuseReflectance, "diffuseReflectance", 1.0f);
|
||||||
|
|
||||||
|
/* Compute weights that further steer samples towards
|
||||||
|
the specular or diffuse components */
|
||||||
|
Float dAvg = m_diffuseReflectance->getAverage().getLuminance(),
|
||||||
|
sAvg = m_specularReflectance->getAverage().getLuminance();
|
||||||
|
m_specularSamplingWeight = sAvg / (dAvg + sAvg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reflection in local coordinates
|
/// Reflection in local coordinates
|
||||||
|
@ -165,17 +178,22 @@ public:
|
||||||
if (Frame::cosTheta(bRec.wo) <= 0 || Frame::cosTheta(bRec.wi) <= 0)
|
if (Frame::cosTheta(bRec.wo) <= 0 || Frame::cosTheta(bRec.wi) <= 0)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
|
Float probSpecular = 1.0f;
|
||||||
|
if (sampleSpecular && sampleDiffuse) {
|
||||||
|
probSpecular = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
|
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
||||||
|
(probSpecular*m_specularSamplingWeight +
|
||||||
|
(1-probSpecular) * (1-m_specularSamplingWeight));
|
||||||
|
}
|
||||||
|
|
||||||
if (measure == EDiscrete && sampleSpecular) {
|
if (measure == EDiscrete && sampleSpecular) {
|
||||||
/* Check if the provided direction pair matches an ideal
|
/* Check if the provided direction pair matches an ideal
|
||||||
specular reflection; tolerate some roundoff errors */
|
specular reflection; tolerate some roundoff errors */
|
||||||
bool reflection = std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) < Epsilon;
|
if (std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) < Epsilon)
|
||||||
if (reflection)
|
return sampleDiffuse ? probSpecular : 1.0f;
|
||||||
return sampleDiffuse ?
|
|
||||||
fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR) : 1.0f;
|
|
||||||
} else if (measure == ESolidAngle && sampleDiffuse) {
|
} else if (measure == ESolidAngle && sampleDiffuse) {
|
||||||
return Frame::cosTheta(bRec.wo) * INV_PI *
|
return Frame::cosTheta(bRec.wo) * INV_PI *
|
||||||
(sampleSpecular ? (1 - fresnel(Frame::cosTheta(bRec.wi),
|
(sampleSpecular ? (1 - probSpecular) : 1.0f);
|
||||||
m_extIOR, m_intIOR)) : 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
@ -192,23 +210,29 @@ public:
|
||||||
|
|
||||||
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
|
|
||||||
|
Float probSpecular = (Fr*m_specularSamplingWeight) /
|
||||||
|
(Fr*m_specularSamplingWeight +
|
||||||
|
(1-Fr) * (1-m_specularSamplingWeight));
|
||||||
|
|
||||||
if (sampleDiffuse && sampleSpecular) {
|
if (sampleDiffuse && sampleSpecular) {
|
||||||
/* Importance sample wrt. the Fresnel reflectance */
|
/* Importance sample wrt. the Fresnel reflectance */
|
||||||
if (sample.x <= Fr) {
|
if (sample.x <= probSpecular) {
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
bRec.sampledType = EDeltaReflection;
|
bRec.sampledType = EDeltaReflection;
|
||||||
bRec.wo = reflect(bRec.wi);
|
bRec.wo = reflect(bRec.wi);
|
||||||
|
|
||||||
return m_specularReflectance->getValue(bRec.its);
|
return m_specularReflectance->getValue(bRec.its) *
|
||||||
|
Fr / probSpecular;
|
||||||
} else {
|
} else {
|
||||||
bRec.sampledComponent = 1;
|
bRec.sampledComponent = 1;
|
||||||
bRec.sampledType = EDiffuseReflection;
|
bRec.sampledType = EDiffuseReflection;
|
||||||
bRec.wo = squareToHemispherePSA(Point2(
|
bRec.wo = squareToHemispherePSA(Point2(
|
||||||
(sample.x - Fr) / (1 - Fr),
|
(sample.x - probSpecular) / (1 - probSpecular),
|
||||||
sample.y
|
sample.y
|
||||||
));
|
));
|
||||||
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its);
|
return m_diffuseReflectance->getValue(bRec.its) *
|
||||||
|
(1-Fr) / (1-probSpecular);
|
||||||
}
|
}
|
||||||
} else if (sampleSpecular) {
|
} else if (sampleSpecular) {
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
|
@ -223,7 +247,7 @@ public:
|
||||||
return Spectrum(0.0f);
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
bRec.wo = squareToHemispherePSA(sample);
|
bRec.wo = squareToHemispherePSA(sample);
|
||||||
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its) * (1-Fr);
|
return m_diffuseReflectance->getValue(bRec.its) * (1-Fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,15 +262,18 @@ public:
|
||||||
return Spectrum(0.0f);
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
|
Float probSpecular = (Fr*m_specularSamplingWeight) /
|
||||||
|
(Fr*m_specularSamplingWeight +
|
||||||
|
(1-Fr) * (1-m_specularSamplingWeight));
|
||||||
|
|
||||||
if (sampleDiffuse && sampleSpecular) {
|
if (sampleDiffuse && sampleSpecular) {
|
||||||
/* Importance sample wrt. the Fresnel reflectance */
|
/* Importance sample wrt. the Fresnel reflectance */
|
||||||
if (sample.x <= Fr) {
|
if (sample.x <= probSpecular) {
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
bRec.sampledType = EDeltaReflection;
|
bRec.sampledType = EDeltaReflection;
|
||||||
bRec.wo = reflect(bRec.wi);
|
bRec.wo = reflect(bRec.wi);
|
||||||
|
|
||||||
pdf = Fr;
|
pdf = probSpecular;
|
||||||
return m_specularReflectance->getValue(bRec.its) * Fr;
|
return m_specularReflectance->getValue(bRec.its) * Fr;
|
||||||
} else {
|
} else {
|
||||||
bRec.sampledComponent = 1;
|
bRec.sampledComponent = 1;
|
||||||
|
@ -256,7 +283,7 @@ public:
|
||||||
sample.y
|
sample.y
|
||||||
));
|
));
|
||||||
|
|
||||||
pdf = (1-Fr) * Frame::cosTheta(bRec.wo) * INV_PI;
|
pdf = (1-probSpecular) * Frame::cosTheta(bRec.wo) * INV_PI;
|
||||||
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its)
|
return m_diffuseReflectance->getValue(bRec.its)
|
||||||
* (INV_PI * Frame::cosTheta(bRec.wo) * (1-Fr));
|
* (INV_PI * Frame::cosTheta(bRec.wo) * (1-Fr));
|
||||||
|
@ -283,14 +310,18 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shader *createShader(Renderer *renderer) const;
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "SmoothPlastic[" << endl
|
oss << "SmoothPlastic[" << endl
|
||||||
<< " name = \"" << getName() << "\"," << endl
|
<< " name = \"" << getName() << "\"," << endl
|
||||||
<< " intIOR = " << m_intIOR << "," << endl
|
|
||||||
<< " extIOR = " << m_extIOR << "," << endl
|
|
||||||
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
|
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
|
||||||
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << endl
|
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl
|
||||||
|
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
|
||||||
|
<< " diffuseSamplingWeight = " << (1-m_specularSamplingWeight) << "," << endl
|
||||||
|
<< " intIOR = " << m_intIOR << "," << endl
|
||||||
|
<< " extIOR = " << m_extIOR << endl
|
||||||
<< "]";
|
<< "]";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
@ -300,8 +331,119 @@ private:
|
||||||
Float m_intIOR, m_extIOR;
|
Float m_intIOR, m_extIOR;
|
||||||
ref<Texture> m_diffuseReflectance;
|
ref<Texture> m_diffuseReflectance;
|
||||||
ref<Texture> m_specularReflectance;
|
ref<Texture> m_specularReflectance;
|
||||||
|
Float m_specularSamplingWeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smooth plastic shader -- it is really hopeless to visualize
|
||||||
|
* this material in the VPL renderer, so let's try to do at least
|
||||||
|
* something that suggests the presence of a specularly-reflecting
|
||||||
|
* dielectric coating.
|
||||||
|
*/
|
||||||
|
class SmoothPlasticShader : public Shader {
|
||||||
|
public:
|
||||||
|
SmoothPlasticShader(Renderer *renderer, const Texture *specularReflectance,
|
||||||
|
const Texture *diffuseReflectance, Float extIOR,
|
||||||
|
Float intIOR) : Shader(renderer, EBSDFShader),
|
||||||
|
m_specularReflectance(specularReflectance),
|
||||||
|
m_diffuseReflectance(diffuseReflectance),
|
||||||
|
m_extIOR(extIOR), m_intIOR(intIOR) {
|
||||||
|
m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get());
|
||||||
|
m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get());
|
||||||
|
m_alpha = 0.4f;
|
||||||
|
m_R0 = fresnel(1.0f, m_extIOR, m_intIOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isComplete() const {
|
||||||
|
return m_specularReflectanceShader.get() != NULL &&
|
||||||
|
m_diffuseReflectanceShader.get() != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void putDependencies(std::vector<Shader *> &deps) {
|
||||||
|
deps.push_back(m_specularReflectanceShader.get());
|
||||||
|
deps.push_back(m_diffuseReflectanceShader.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(Renderer *renderer) {
|
||||||
|
renderer->unregisterShaderForResource(m_specularReflectance.get());
|
||||||
|
renderer->unregisterShaderForResource(m_diffuseReflectance.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
||||||
|
parameterIDs.push_back(program->getParameterID(evalName + "_alpha", false));
|
||||||
|
parameterIDs.push_back(program->getParameterID(evalName + "_R0", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
||||||
|
program->setParameter(parameterIDs[0], m_alpha);
|
||||||
|
program->setParameter(parameterIDs[1], m_R0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateCode(std::ostringstream &oss,
|
||||||
|
const std::string &evalName,
|
||||||
|
const std::vector<std::string> &depNames) const {
|
||||||
|
oss << "uniform float " << evalName << "_alpha;" << endl
|
||||||
|
<< "uniform float " << evalName << "_R0;" << endl
|
||||||
|
<< endl
|
||||||
|
<< "float " << evalName << "_D(vec3 m) {" << endl
|
||||||
|
<< " float ct = cosTheta(m);" << endl
|
||||||
|
<< " if (cosTheta(m) <= 0.0)" << endl
|
||||||
|
<< " return 0.0;" << endl
|
||||||
|
<< " float ex = tanTheta(m) / " << evalName << "_alpha;" << endl
|
||||||
|
<< " return exp(-(ex*ex)) / (pi * " << evalName << "_alpha" << endl
|
||||||
|
<< " * " << evalName << "_alpha * pow(cosTheta(m), 4.0));" << endl
|
||||||
|
<< "}" << endl
|
||||||
|
<< endl
|
||||||
|
<< "float " << evalName << "_G(vec3 m, vec3 wi, vec3 wo) {" << endl
|
||||||
|
<< " if ((dot(wi, m) * cosTheta(wi)) <= 0 || " << endl
|
||||||
|
<< " (dot(wo, m) * cosTheta(wo)) <= 0)" << endl
|
||||||
|
<< " return 0.0;" << endl
|
||||||
|
<< " float nDotM = cosTheta(m);" << endl
|
||||||
|
<< " return min(1.0, min(" << endl
|
||||||
|
<< " abs(2 * nDotM * cosTheta(wo) / dot(wo, m))," << endl
|
||||||
|
<< " abs(2 * nDotM * cosTheta(wi) / dot(wi, m))));" << endl
|
||||||
|
<< "}" << endl
|
||||||
|
<< endl
|
||||||
|
<< endl
|
||||||
|
<< "float " << evalName << "_schlick(float ct) {" << endl
|
||||||
|
<< " float ctSqr = ct*ct, ct5 = ctSqr*ctSqr*ct;" << endl
|
||||||
|
<< " return " << evalName << "_R0 + (1.0 - " << evalName << "_R0) * ct5;" << endl
|
||||||
|
<< "}" << endl
|
||||||
|
<< endl
|
||||||
|
<< "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
|
<< " if (cosTheta(wi) <= 0 || cosTheta(wo) <= 0)" << endl
|
||||||
|
<< " return vec3(0.0);" << endl
|
||||||
|
<< " vec3 H = normalize(wi + wo);" << endl
|
||||||
|
<< " vec3 specRef = " << depNames[0] << "(uv);" << endl
|
||||||
|
<< " vec3 diffuseRef = " << depNames[1] << "(uv);" << endl
|
||||||
|
<< " float D = " << evalName << "_D(H)" << ";" << endl
|
||||||
|
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
||||||
|
<< " float F = " << evalName << "_schlick(1-dot(wi, H));" << endl
|
||||||
|
<< " return specRef * (F * D * G / (4*cosTheta(wi))) + " << endl
|
||||||
|
<< " diffuseRef * ((1-F) * cosTheta(wo) * 0.31831);" << endl
|
||||||
|
<< "}" << endl
|
||||||
|
<< endl
|
||||||
|
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
|
<< " vec3 diffuseRef = " << depNames[1] << "(uv);" << endl
|
||||||
|
<< " return diffuseRef * 0.31831 * cosTheta(wo);"<< endl
|
||||||
|
<< "}" << endl;
|
||||||
|
}
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
private:
|
||||||
|
ref<const Texture> m_specularReflectance;
|
||||||
|
ref<const Texture> m_diffuseReflectance;
|
||||||
|
ref<Shader> m_specularReflectanceShader;
|
||||||
|
ref<Shader> m_diffuseReflectanceShader;
|
||||||
|
Float m_alpha, m_extIOR, m_intIOR, m_R0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Shader *SmoothPlastic::createShader(Renderer *renderer) const {
|
||||||
|
return new SmoothPlasticShader(renderer,
|
||||||
|
m_specularReflectance.get(), m_diffuseReflectance.get(), m_extIOR, m_intIOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTS_IMPLEMENT_CLASS(SmoothPlasticShader, false, Shader)
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(SmoothPlastic, false, BSDF)
|
MTS_IMPLEMENT_CLASS_S(SmoothPlastic, false, BSDF)
|
||||||
MTS_EXPORT_PLUGIN(SmoothPlastic, "Smooth plastic BSDF");
|
MTS_EXPORT_PLUGIN(SmoothPlastic, "Smooth plastic BSDF");
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -479,9 +479,8 @@ public:
|
||||||
<< " abs(2 * nDotM * cosTheta(wi) / dot(wi, m))));" << endl
|
<< " abs(2 * nDotM * cosTheta(wi) / dot(wi, m))));" << endl
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "vec3 " << evalName << "_schlick(vec3 wi) {" << endl
|
<< "vec3 " << evalName << "_schlick(float ct) {" << endl
|
||||||
<< " float ct = cosTheta(wi), ctSqr = ct*ct," << endl
|
<< " float ctSqr = ct*ct, ct5 = ctSqr*ctSqr*ct;" << endl
|
||||||
<< " ct5 = ctSqr*ctSqr*ct;" << endl
|
|
||||||
<< " return " << evalName << "_R0 + (vec3(1.0) - " << evalName << "_R0) * ct5;" << endl
|
<< " return " << evalName << "_R0 + (vec3(1.0) - " << evalName << "_R0) * ct5;" << endl
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
|
@ -494,8 +493,8 @@ public:
|
||||||
<< " float alphaV = max(0.2, " << depNames[2] << "(uv).r);" << endl
|
<< " float alphaV = max(0.2, " << depNames[2] << "(uv).r);" << endl
|
||||||
<< " float D = " << evalName << "_D(H, alphaU, alphaV)" << ";" << endl
|
<< " float D = " << evalName << "_D(H, alphaU, alphaV)" << ";" << endl
|
||||||
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
||||||
<< " vec3 Fr = " << evalName << "_schlick(wi);" << endl
|
<< " vec3 F = " << evalName << "_schlick(1-dot(wi, H));" << endl
|
||||||
<< " return reflectance * Fr * (D * G / (4*cosTheta(wi)));" << endl
|
<< " return reflectance * F * (D * G / (4*cosTheta(wi)));" << endl
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
|
|
|
@ -116,6 +116,10 @@ public:
|
||||||
m_reflectance = ensureEnergyConservation(m_reflectance, "reflectance", 1.0f);
|
m_reflectance = ensureEnergyConservation(m_reflectance, "reflectance", 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spectrum getDiffuseReflectance(const Intersection &its) const {
|
||||||
|
return m_reflectance->getValue(its);
|
||||||
|
}
|
||||||
|
|
||||||
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
if (!(bRec.typeMask & EGlossyReflection) || measure != ESolidAngle
|
if (!(bRec.typeMask & EGlossyReflection) || measure != ESolidAngle
|
||||||
|| Frame::cosTheta(bRec.wi) <= 0
|
|| Frame::cosTheta(bRec.wi) <= 0
|
||||||
|
@ -310,7 +314,7 @@ public:
|
||||||
const std::string &evalName,
|
const std::string &evalName,
|
||||||
const std::vector<std::string> &depNames) const {
|
const std::vector<std::string> &depNames) const {
|
||||||
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
<< " if (cosTheta(wi) < 0.0 || cosTheta(wo) < 0.0)" << endl
|
<< " if (cosTheta(wi) <= 0.0 || cosTheta(wo) <= 0.0)" << endl
|
||||||
<< " return vec3(0.0);" << endl
|
<< " return vec3(0.0);" << endl
|
||||||
<< " float sigma = " << depNames[1] << "(uv)[0] * 0.70711;" << endl
|
<< " float sigma = " << depNames[1] << "(uv)[0] * 0.70711;" << endl
|
||||||
<< " float sigma2 = sigma * sigma;" << endl
|
<< " float sigma2 = sigma * sigma;" << endl
|
||||||
|
@ -330,7 +334,7 @@ public:
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
<< " if (cosTheta(wi) < 0.0 || cosTheta(wo) < 0.0)" << endl
|
<< " if (cosTheta(wi) <= 0.0 || cosTheta(wo) <= 0.0)" << endl
|
||||||
<< " return vec3(0.0);" << endl
|
<< " return vec3(0.0);" << endl
|
||||||
<< " return " << depNames[0] << "(uv) * 0.31831 * cosTheta(wo);" << endl
|
<< " return " << depNames[0] << "(uv) * 0.31831 * cosTheta(wo);" << endl
|
||||||
<< "}" << endl;
|
<< "}" << endl;
|
||||||
|
|
|
@ -144,6 +144,10 @@ public:
|
||||||
|
|
||||||
virtual ~RoughPlastic() { }
|
virtual ~RoughPlastic() { }
|
||||||
|
|
||||||
|
Spectrum getDiffuseReflectance(const Intersection &its) const {
|
||||||
|
return m_diffuseReflectance->getValue(its);
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper function: reflect \c wi with respect to a given surface normal
|
/// Helper function: reflect \c wi with respect to a given surface normal
|
||||||
inline Vector reflect(const Vector &wi, const Normal &m) const {
|
inline Vector reflect(const Vector &wi, const Normal &m) const {
|
||||||
return 2 * dot(wi, m) * Vector(m) - wi;
|
return 2 * dot(wi, m) * Vector(m) - wi;
|
||||||
|
@ -246,7 +250,6 @@ public:
|
||||||
if (Frame::cosTheta(bRec.wi) <= 0 || (!sampleSpecular && !sampleDiffuse))
|
if (Frame::cosTheta(bRec.wi) <= 0 || (!sampleSpecular && !sampleDiffuse))
|
||||||
return Spectrum(0.0f);
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
|
||||||
bool choseSpecular = sampleSpecular;
|
bool choseSpecular = sampleSpecular;
|
||||||
Point2 sample(_sample);
|
Point2 sample(_sample);
|
||||||
|
|
||||||
|
@ -284,7 +287,6 @@ public:
|
||||||
bRec.sampledComponent = 1;
|
bRec.sampledComponent = 1;
|
||||||
bRec.sampledType = EDiffuseReflection;
|
bRec.sampledType = EDiffuseReflection;
|
||||||
bRec.wo = squareToHemispherePSA(sample);
|
bRec.wo = squareToHemispherePSA(sample);
|
||||||
m = normalize(bRec.wo+bRec.wi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Guard against numerical imprecisions */
|
/* Guard against numerical imprecisions */
|
||||||
|
@ -358,32 +360,116 @@ private:
|
||||||
Float m_specularSamplingWeight;
|
Float m_specularSamplingWeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Fake plastic shader -- it is really hopeless to visualize
|
/**
|
||||||
this material in the VPL renderer, so let's try to do at least
|
* GLSL port of the rough plastic shader. This version is much more
|
||||||
something that suggests the presence of a translucent boundary */
|
* approximate -- it only supports the Beckmann distribution,
|
||||||
|
* does everything in RGB, uses a cheaper shadowing-masking term, and
|
||||||
|
* it also makes use of the Schlick approximation to the Fresnel
|
||||||
|
* reflectance of dielectrics. When the roughness is lower than
|
||||||
|
* \alpha < 0.2, the shader clamps it to 0.2 so that it will still perform
|
||||||
|
* reasonably well in a VPL-based preview.
|
||||||
|
*/
|
||||||
class RoughPlasticShader : public Shader {
|
class RoughPlasticShader : public Shader {
|
||||||
public:
|
public:
|
||||||
RoughPlasticShader(Renderer *renderer) :
|
RoughPlasticShader(Renderer *renderer, const Texture *specularReflectance,
|
||||||
Shader(renderer, EBSDFShader) {
|
const Texture *diffuseReflectance, Float alpha, Float extIOR,
|
||||||
m_flags = ETransparent;
|
Float intIOR) : Shader(renderer, EBSDFShader),
|
||||||
|
m_specularReflectance(specularReflectance),
|
||||||
|
m_diffuseReflectance(diffuseReflectance),
|
||||||
|
m_alpha(alpha), m_extIOR(extIOR), m_intIOR(intIOR) {
|
||||||
|
m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get());
|
||||||
|
m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get());
|
||||||
|
m_alpha = std::max(m_alpha, (Float) 0.2f);
|
||||||
|
m_R0 = fresnel(1.0f, m_extIOR, m_intIOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isComplete() const {
|
||||||
|
return m_specularReflectanceShader.get() != NULL &&
|
||||||
|
m_diffuseReflectanceShader.get() != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void putDependencies(std::vector<Shader *> &deps) {
|
||||||
|
deps.push_back(m_specularReflectanceShader.get());
|
||||||
|
deps.push_back(m_diffuseReflectanceShader.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(Renderer *renderer) {
|
||||||
|
renderer->unregisterShaderForResource(m_specularReflectance.get());
|
||||||
|
renderer->unregisterShaderForResource(m_diffuseReflectance.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
||||||
|
parameterIDs.push_back(program->getParameterID(evalName + "_alpha", false));
|
||||||
|
parameterIDs.push_back(program->getParameterID(evalName + "_R0", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
||||||
|
program->setParameter(parameterIDs[0], m_alpha);
|
||||||
|
program->setParameter(parameterIDs[1], m_R0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generateCode(std::ostringstream &oss,
|
void generateCode(std::ostringstream &oss,
|
||||||
const std::string &evalName,
|
const std::string &evalName,
|
||||||
const std::vector<std::string> &depNames) const {
|
const std::vector<std::string> &depNames) const {
|
||||||
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
oss << "uniform float " << evalName << "_alpha;" << endl
|
||||||
<< " return vec3(0.08);" << endl
|
<< "uniform float " << evalName << "_R0;" << endl
|
||||||
|
<< endl
|
||||||
|
<< "float " << evalName << "_D(vec3 m) {" << endl
|
||||||
|
<< " float ct = cosTheta(m);" << endl
|
||||||
|
<< " if (cosTheta(m) <= 0.0)" << endl
|
||||||
|
<< " return 0.0;" << endl
|
||||||
|
<< " float ex = tanTheta(m) / " << evalName << "_alpha;" << endl
|
||||||
|
<< " return exp(-(ex*ex)) / (pi * " << evalName << "_alpha" << endl
|
||||||
|
<< " * " << evalName << "_alpha * pow(cosTheta(m), 4.0));" << endl
|
||||||
|
<< "}" << endl
|
||||||
|
<< endl
|
||||||
|
<< "float " << evalName << "_G(vec3 m, vec3 wi, vec3 wo) {" << endl
|
||||||
|
<< " if ((dot(wi, m) * cosTheta(wi)) <= 0 || " << endl
|
||||||
|
<< " (dot(wo, m) * cosTheta(wo)) <= 0)" << endl
|
||||||
|
<< " return 0.0;" << endl
|
||||||
|
<< " float nDotM = cosTheta(m);" << endl
|
||||||
|
<< " return min(1.0, min(" << endl
|
||||||
|
<< " abs(2 * nDotM * cosTheta(wo) / dot(wo, m))," << endl
|
||||||
|
<< " abs(2 * nDotM * cosTheta(wi) / dot(wi, m))));" << endl
|
||||||
|
<< "}" << endl
|
||||||
|
<< endl
|
||||||
|
<< endl
|
||||||
|
<< "float " << evalName << "_schlick(float ct) {" << endl
|
||||||
|
<< " float ctSqr = ct*ct, ct5 = ctSqr*ctSqr*ct;" << endl
|
||||||
|
<< " return " << evalName << "_R0 + (1.0 - " << evalName << "_R0) * ct5;" << endl
|
||||||
|
<< "}" << endl
|
||||||
|
<< endl
|
||||||
|
<< "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
|
<< " if (cosTheta(wi) <= 0 || cosTheta(wo) <= 0)" << endl
|
||||||
|
<< " return vec3(0.0);" << endl
|
||||||
|
<< " vec3 H = normalize(wi + wo);" << endl
|
||||||
|
<< " vec3 specRef = " << depNames[0] << "(uv);" << endl
|
||||||
|
<< " vec3 diffuseRef = " << depNames[1] << "(uv);" << endl
|
||||||
|
<< " float D = " << evalName << "_D(H)" << ";" << endl
|
||||||
|
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
||||||
|
<< " float F = " << evalName << "_schlick(1-dot(wi, H));" << endl
|
||||||
|
<< " return specRef * (F * D * G / (4*cosTheta(wi))) + " << endl
|
||||||
|
<< " diffuseRef * ((1-F) * cosTheta(wo) * 0.31831);" << endl
|
||||||
<< "}" << endl
|
<< "}" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
<< " return " << evalName << "(uv, wi, wo);" << endl
|
<< " vec3 diffuseRef = " << depNames[1] << "(uv);" << endl
|
||||||
|
<< " return diffuseRef * 0.31831 * cosTheta(wo);"<< endl
|
||||||
<< "}" << endl;
|
<< "}" << endl;
|
||||||
}
|
}
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
|
private:
|
||||||
|
ref<const Texture> m_specularReflectance;
|
||||||
|
ref<const Texture> m_diffuseReflectance;
|
||||||
|
ref<Shader> m_specularReflectanceShader;
|
||||||
|
ref<Shader> m_diffuseReflectanceShader;
|
||||||
|
Float m_alpha, m_extIOR, m_intIOR, m_R0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader *RoughPlastic::createShader(Renderer *renderer) const {
|
Shader *RoughPlastic::createShader(Renderer *renderer) const {
|
||||||
return new RoughPlasticShader(renderer);
|
return new RoughPlasticShader(renderer,
|
||||||
|
m_specularReflectance.get(), m_diffuseReflectance.get(),
|
||||||
|
m_alpha, m_extIOR, m_intIOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS(RoughPlasticShader, false, Shader)
|
MTS_IMPLEMENT_CLASS(RoughPlasticShader, false, Shader)
|
||||||
|
|
|
@ -701,8 +701,8 @@ Spectrum fresnelConductor(Float cosThetaI, const Spectrum &eta, const Spectrum &
|
||||||
return (rParl2 + rPerp2) / 2.0f;
|
return (rParl2 + rPerp2) / 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Float fresnel(Float cosThetaI, Float etaExt, Float etaInt) {
|
Float fresnel(Float cosThetaI, Float extIOR, Float intIOR) {
|
||||||
Float etaI = etaExt, etaT = etaInt;
|
Float etaI = extIOR, etaT = intIOR;
|
||||||
|
|
||||||
/* Swap the indices of refraction if the interaction starts
|
/* Swap the indices of refraction if the interaction starts
|
||||||
at the inside of the object */
|
at the inside of the object */
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_value"));
|
parameterIDs.push_back(program->getParameterID(evalName + "_value", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
||||||
|
@ -87,7 +87,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_value"));
|
parameterIDs.push_back(program->getParameterID(evalName + "_value", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
||||||
|
|
|
@ -492,6 +492,7 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
|
||||||
<< "float tanTheta(vec3 v) { return sinTheta(v)/cosTheta(v); }" << endl
|
<< "float tanTheta(vec3 v) { return sinTheta(v)/cosTheta(v); }" << endl
|
||||||
<< "float sinPhi(vec3 v) { return v.y/sinTheta(v); }" << endl
|
<< "float sinPhi(vec3 v) { return v.y/sinTheta(v); }" << endl
|
||||||
<< "float cosPhi(vec3 v) { return v.x/sinTheta(v); }" << endl
|
<< "float cosPhi(vec3 v) { return v.x/sinTheta(v); }" << endl
|
||||||
|
<< "const float pi = 3.141592653589;" << endl
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
std::string vplEvalName, bsdfEvalName, lumEvalName;
|
std::string vplEvalName, bsdfEvalName, lumEvalName;
|
||||||
|
|
Loading…
Reference in New Issue