composite material shader, do a better job at previewing environment sources
parent
e1054035a3
commit
0d76becf5d
|
@ -264,6 +264,8 @@ public:
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shader *createShader(Renderer *renderer) const;
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
private:
|
private:
|
||||||
int m_bsdfCount;
|
int m_bsdfCount;
|
||||||
|
@ -273,6 +275,107 @@ private:
|
||||||
DiscretePDF m_pdf;
|
DiscretePDF m_pdf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ================ Hardware shader implementation ================
|
||||||
|
|
||||||
|
class CompositeShader : public Shader {
|
||||||
|
public:
|
||||||
|
CompositeShader(Renderer *renderer, const std::vector<BSDF *> &bsdfs, Float *weights)
|
||||||
|
: Shader(renderer, EBSDFShader), m_bsdfs(bsdfs), m_weights(weights), m_complete(false) {
|
||||||
|
m_bsdfShader.resize(bsdfs.size());
|
||||||
|
for (size_t i=0; i<bsdfs.size(); ++i) {
|
||||||
|
ref<Shader> shader = renderer->registerShaderForResource(bsdfs[i]);
|
||||||
|
if (shader) {
|
||||||
|
shader->incRef();
|
||||||
|
/* At least one shader has a hardware implementation */
|
||||||
|
m_complete = true;
|
||||||
|
}
|
||||||
|
m_bsdfShader[i] = shader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isComplete() const {
|
||||||
|
return m_complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(Renderer *renderer) {
|
||||||
|
for (size_t i=0; i<m_bsdfs.size(); ++i) {
|
||||||
|
renderer->unregisterShaderForResource(m_bsdfs[i]);
|
||||||
|
if (m_bsdfShader[i])
|
||||||
|
m_bsdfShader[i]->decRef();
|
||||||
|
}
|
||||||
|
m_bsdfShader.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void putDependencies(std::vector<Shader *> &deps) {
|
||||||
|
for (size_t i=0; i<m_bsdfs.size(); ++i) {
|
||||||
|
if (m_bsdfShader[i])
|
||||||
|
deps.push_back(m_bsdfShader[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateCode(std::ostringstream &oss,
|
||||||
|
const std::string &evalName,
|
||||||
|
const std::vector<std::string> &depNames) const {
|
||||||
|
Assert(m_complete);
|
||||||
|
int ctr = 0;
|
||||||
|
for (size_t i=0; i<m_bsdfs.size(); ++i) {
|
||||||
|
if (!m_bsdfShader[i])
|
||||||
|
continue;
|
||||||
|
oss << "uniform float " << evalName << "_weight_" << ctr++ << ";" << endl;
|
||||||
|
}
|
||||||
|
oss << endl;
|
||||||
|
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||||
|
<< " return ";
|
||||||
|
ctr = 0;
|
||||||
|
for (size_t i=0; i<m_bsdfs.size(); ++i) {
|
||||||
|
if (!m_bsdfShader[i])
|
||||||
|
continue;
|
||||||
|
oss << endl << " ";
|
||||||
|
if (ctr != 0)
|
||||||
|
oss << "+ ";
|
||||||
|
else
|
||||||
|
oss << " ";
|
||||||
|
oss << depNames[ctr] << "(uv, wi, wo) * "
|
||||||
|
<< evalName << "_weight_" << ctr;
|
||||||
|
ctr++;
|
||||||
|
}
|
||||||
|
oss << ";" << endl;
|
||||||
|
oss << "}" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
||||||
|
int ctr = 0;
|
||||||
|
for (size_t i=0; i<m_bsdfs.size(); ++i) {
|
||||||
|
if (!m_bsdfShader[i])
|
||||||
|
continue;
|
||||||
|
parameterIDs.push_back(
|
||||||
|
program->getParameterID(formatString("%s_weight_%i", evalName.c_str(), ctr++)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
||||||
|
int ctr = 0;
|
||||||
|
for (size_t i=0; i<m_bsdfs.size(); ++i) {
|
||||||
|
if (!m_bsdfShader[i])
|
||||||
|
continue;
|
||||||
|
program->setParameter(parameterIDs[ctr++], m_weights[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
private:
|
||||||
|
std::vector<Shader *> m_bsdfShader;
|
||||||
|
const std::vector<BSDF *> &m_bsdfs;
|
||||||
|
const Float *m_weights;
|
||||||
|
bool m_complete;
|
||||||
|
};
|
||||||
|
|
||||||
|
Shader *Composite::createShader(Renderer *renderer) const {
|
||||||
|
return new CompositeShader(renderer, m_bsdfs, m_bsdfWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTS_IMPLEMENT_CLASS(CompositeShader, false, Shader)
|
||||||
MTS_IMPLEMENT_CLASS_S(Composite, false, BSDF)
|
MTS_IMPLEMENT_CLASS_S(Composite, false, BSDF)
|
||||||
MTS_EXPORT_PLUGIN(Composite, "Composite BRDF");
|
MTS_EXPORT_PLUGIN(Composite, "Composite BRDF")
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -146,5 +146,5 @@ Shader *Lambertian::createShader(Renderer *renderer) const {
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS(LambertianShader, false, Shader)
|
MTS_IMPLEMENT_CLASS(LambertianShader, false, Shader)
|
||||||
MTS_IMPLEMENT_CLASS_S(Lambertian, false, BSDF)
|
MTS_IMPLEMENT_CLASS_S(Lambertian, false, BSDF)
|
||||||
MTS_EXPORT_PLUGIN(Lambertian, "Lambertian BRDF");
|
MTS_EXPORT_PLUGIN(Lambertian, "Lambertian BRDF")
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -67,6 +67,8 @@ Shader *Renderer::getShaderForResource(const HWResource *resource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::unregisterShaderForResource(const HWResource *resource) {
|
void Renderer::unregisterShaderForResource(const HWResource *resource) {
|
||||||
|
if (resource == NULL)
|
||||||
|
return;
|
||||||
if (m_shaders.find(resource) == m_shaders.end())
|
if (m_shaders.find(resource) == m_shaders.end())
|
||||||
return;
|
return;
|
||||||
ShaderRecord &sRec = m_shaders[resource];
|
ShaderRecord &sRec = m_shaders[resource];
|
||||||
|
|
|
@ -243,7 +243,9 @@ void Scene::initialize() {
|
||||||
if (!m_luminairePDF.isReady()) {
|
if (!m_luminairePDF.isReady()) {
|
||||||
if (m_luminaires.size() == 0) {
|
if (m_luminaires.size() == 0) {
|
||||||
Log(EWarn, "No luminaires found -- adding a constant environment source");
|
Log(EWarn, "No luminaires found -- adding a constant environment source");
|
||||||
addChild("", PluginManager::getInstance()->createObject(Luminaire::m_theClass, Properties("constant")));
|
Properties constantProps("constant");
|
||||||
|
constantProps.setSpectrum("intensity", Spectrum(0.5f));
|
||||||
|
addChild("", PluginManager::getInstance()->createObject(Luminaire::m_theClass, constantProps));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate a discrete PDF to importance sample luminaires */
|
/* Calculate a discrete PDF to importance sample luminaires */
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
void preprocess(const Scene *scene) {
|
void preprocess(const Scene *scene) {
|
||||||
/* Get the scene's bounding sphere and slightly enlarge it */
|
/* Get the scene's bounding sphere and slightly enlarge it */
|
||||||
m_bsphere = scene->getBSphere();
|
m_bsphere = scene->getBSphere();
|
||||||
m_bsphere.radius *= 2.0f;
|
m_bsphere.radius *= 1.01f;
|
||||||
m_surfaceArea = m_bsphere.radius * m_bsphere.radius * M_PI;
|
m_surfaceArea = m_bsphere.radius * m_bsphere.radius * M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ public:
|
||||||
Float radius = m_bsphere.radius;
|
Float radius = m_bsphere.radius;
|
||||||
if (eRec.type == EmissionRecord::EPreview) {
|
if (eRec.type == EmissionRecord::EPreview) {
|
||||||
/* This is more suitable for VPL-based rendering */
|
/* This is more suitable for VPL-based rendering */
|
||||||
radius *= 10;
|
radius *= 1.5;
|
||||||
}
|
}
|
||||||
Vector d = squareToSphere(sample);
|
Vector d = squareToSphere(sample);
|
||||||
eRec.sRec.p = m_bsphere.center + d * radius;
|
eRec.sRec.p = m_bsphere.center + d * radius;
|
||||||
|
@ -126,7 +126,7 @@ public:
|
||||||
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
|
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
|
||||||
Float radius = m_bsphere.radius;
|
Float radius = m_bsphere.radius;
|
||||||
if (eRec.type == EmissionRecord::EPreview)
|
if (eRec.type == EmissionRecord::EPreview)
|
||||||
radius *= 10;
|
radius *= 1.5f;
|
||||||
Point p2 = m_bsphere.center + squareToSphere(sample) * radius;
|
Point p2 = m_bsphere.center + squareToSphere(sample) * radius;
|
||||||
eRec.d = p2 - eRec.sRec.p;
|
eRec.d = p2 - eRec.sRec.p;
|
||||||
Float length = eRec.d.length();
|
Float length = eRec.d.length();
|
||||||
|
|
|
@ -195,7 +195,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
/* Preview mode, which is more suitable for VPL-based rendering: approximate
|
/* Preview mode, which is more suitable for VPL-based rendering: approximate
|
||||||
the infinitely far-away source with set of diffuse point sources */
|
the infinitely far-away source with set of diffuse point sources */
|
||||||
const Float radius = m_bsphere.radius * 10;
|
const Float radius = m_bsphere.radius * 1.5f;
|
||||||
Vector d = squareToSphere(sample);
|
Vector d = squareToSphere(sample);
|
||||||
eRec.sRec.p = m_bsphere.center + d * radius;
|
eRec.sRec.p = m_bsphere.center + d * radius;
|
||||||
eRec.sRec.n = Normal(-d);
|
eRec.sRec.n = Normal(-d);
|
||||||
|
@ -207,7 +207,7 @@ public:
|
||||||
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
|
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
|
||||||
Float radius = m_bsphere.radius;
|
Float radius = m_bsphere.radius;
|
||||||
if (eRec.type == EmissionRecord::EPreview)
|
if (eRec.type == EmissionRecord::EPreview)
|
||||||
radius *= 10;
|
radius *= 1.5f;
|
||||||
Point p2 = m_bsphere.center + squareToSphere(sample) * radius;
|
Point p2 = m_bsphere.center + squareToSphere(sample) * radius;
|
||||||
eRec.d = p2 - eRec.sRec.p;
|
eRec.d = p2 - eRec.sRec.p;
|
||||||
Float length = eRec.d.length();
|
Float length = eRec.d.length();
|
||||||
|
|
Loading…
Reference in New Issue