diff --git a/include/mitsuba/hw/vpl.h b/include/mitsuba/hw/vpl.h index 446155ca..74007676 100644 --- a/include/mitsuba/hw/vpl.h +++ b/include/mitsuba/hw/vpl.h @@ -46,6 +46,12 @@ public: /// Is shadow map generation generation performed in a single pass? inline bool isSinglePass() const { return m_singlePass; } + /// Set whether or not non-diffuse VPLs are permitted + inline void setAllowNonDiffuseVPLs(bool allowNonDiffuseVPLs) { m_allowNonDiffuseVPLs = allowNonDiffuseVPLs; } + + /// Are non-diffuse VPLs permitted? This is more realistic, but can take a long time to converge. + inline bool allowNonDiffuseVPLs() const { return m_allowNonDiffuseVPLs; } + /// Set the current shadow map resolution inline void setShadowMapResolution(int resolution) { m_shadowMapResolution = resolution; } @@ -144,7 +150,7 @@ private: bool hasLuminaire; int param_shadowMap, param_vplPos, param_camPos, param_vplPower; int param_vplN, param_vplS, param_vplT, param_vplWi, param_vplUV; - int param_nearClip, param_invClipRange, param_minDist; + int param_nearClip, param_invClipRange, param_minDist, param_allowNonDiffuseVPLs; inline VPLProgramConfiguration() { } @@ -226,7 +232,7 @@ private: ref m_shadowMap; Float m_nearClip, m_invClipRange; int m_shadowMapResolution; - bool m_singlePass; + bool m_singlePass, m_allowNonDiffuseVPLs; /* Rendering related */ std::map m_programs; diff --git a/src/libhw/vpl.cpp b/src/libhw/vpl.cpp index 5803f574..cc6ce278 100644 --- a/src/libhw/vpl.cpp +++ b/src/libhw/vpl.cpp @@ -8,7 +8,7 @@ MTS_NAMESPACE_BEGIN VPLShaderManager::VPLShaderManager(const Scene *scene, Renderer *renderer) : m_scene(scene), m_renderer(renderer), m_clamping(0.1f), m_maxClipDist(std::numeric_limits::infinity()), m_initialized(false), - m_shadowMapResolution(512), m_singlePass(false) { + m_shadowMapResolution(512), m_singlePass(false), m_allowNonDiffuseVPLs(false) { } VPLShaderManager::~VPLShaderManager() { @@ -320,6 +320,7 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, const Luminai << "uniform vec3 vplPower, vplS, vplT, vplN, vplWi;" << endl << "uniform float nearClip, invClipRange, minDist;" << endl << "uniform vec2 vplUV;" << endl + << "uniform bool allowNonDiffuseVPLs;" << endl << endl << "/* Inputs <- Vertex program */" << endl << "varying vec3 normal, tangent, lightVec, camVec;" << endl @@ -361,18 +362,20 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, const Luminai << " vec3 vplWo = -vec3(dot(vplS, nLightVec)," << endl << " dot(vplT, nLightVec)," << endl << " dot(vplN, nLightVec));" << endl - << " if (d < minDist) d = minDist;" << endl - << " gl_FragColor.rgb = " << bsdfEvalName << "(uv, wi, wo)" << endl; - + << " vec3 vplLo = vplPower;" << endl + << " if (allowNonDiffuseVPLs)" << endl + << " vplLo *= " << vplEvalName; if (vpl.type == ESurfaceVPL) - oss << " * " << vplEvalName << "(vplUV, vplWi, vplWo)" << endl; + oss << "(vplUV, vplWi, vplWo);" << endl; else - oss << " * " << vplEvalName << "_dir(vplWo)" << endl; + oss << "_dir(vplWo);" << endl; + oss << " if (d < minDist) d = minDist;" << endl + << " gl_FragColor.rgb = vplLo * " << bsdfEvalName << "(uv, wi, wo)" << endl; if (vpl.type == ESurfaceVPL || (vpl.type == ELuminaireVPL && (vpl.luminaire->getType() & Luminaire::EOnSurface))) - oss << " * vplPower * shadow * abs(cosTheta(wo) * cosTheta(vplWo)) / (d*d)"; + oss << " * (shadow * abs(cosTheta(wo) * cosTheta(vplWo)) / (d*d))"; else - oss << " * vplPower * shadow * abs(cosTheta(wo)) / (d*d)"; + oss << " * (shadow * abs(cosTheta(wo)) / (d*d))"; if (luminaire != NULL) { oss << endl; oss << " + " << lumEvalName << "_area(uv)" @@ -399,6 +402,7 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, const Luminai m_targetConfig.param_nearClip = program->getParameterID("nearClip", false); m_targetConfig.param_invClipRange = program->getParameterID("invClipRange", false); m_targetConfig.param_minDist = program->getParameterID("minDist", false); + m_targetConfig.param_allowNonDiffuseVPLs = program->getParameterID("allowNonDiffuseVPLs", false); m_current.program = program; m_current.config = m_targetConfig; m_programs[configName] = m_current; @@ -413,14 +417,19 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf, const Luminai program->setParameter(config.param_shadowMap, m_shadowMap); program->setParameter(config.param_vplPos, vpl.its.p); program->setParameter(config.param_camPos, camPos); - program->setParameter(config.param_vplPower, vpl.P); program->setParameter(config.param_vplN, vpl.its.shFrame.n); program->setParameter(config.param_vplS, vpl.its.shFrame.s); program->setParameter(config.param_vplT, vpl.its.shFrame.t); if (vpl.type == ESurfaceVPL) { program->setParameter(config.param_vplWi, vpl.its.wi); program->setParameter(config.param_vplUV, vpl.its.uv); + program->setParameter(config.param_allowNonDiffuseVPLs, m_allowNonDiffuseVPLs); } + if (!m_allowNonDiffuseVPLs && vpl.type == ESurfaceVPL) + program->setParameter(config.param_vplPower, vpl.P + * vpl.its.shape->getBSDF()->getDiffuseReflectance(vpl.its) * INV_PI); + else + program->setParameter(config.param_vplPower, vpl.P); program->setParameter(config.param_nearClip, m_nearClip); program->setParameter(config.param_invClipRange, m_invClipRange); program->setParameter(config.param_minDist, m_minDist); diff --git a/src/qtgui/common.h b/src/qtgui/common.h index 8c6b1393..010fadac 100644 --- a/src/qtgui/common.h +++ b/src/qtgui/common.h @@ -132,6 +132,7 @@ struct SceneContext { QSize windowSize, sizeIncrease; Vector2i scrollOffset; Float reinhardKey, reinhardBurn; + bool allowNonDiffuseVPLs; /* Preview state */ std::deque vpls; diff --git a/src/qtgui/glwidget.cpp b/src/qtgui/glwidget.cpp index 3d0461dd..4660cc9f 100644 --- a/src/qtgui/glwidget.cpp +++ b/src/qtgui/glwidget.cpp @@ -297,6 +297,14 @@ void GLWidget::setShadowMapResolution(int res) { } } +void GLWidget::setAllowNonDiffuseVPLs(bool value) { + if (value != m_context->allowNonDiffuseVPLs) { + m_context->allowNonDiffuseVPLs = value; + resetPreview(); + } +} + + void GLWidget::setPreviewMethod(EPreviewMethod method) { if (method != m_context->previewMethod) { m_context->previewMethod = method; diff --git a/src/qtgui/glwidget.h b/src/qtgui/glwidget.h index c282f757..67324d07 100644 --- a/src/qtgui/glwidget.h +++ b/src/qtgui/glwidget.h @@ -58,6 +58,7 @@ public slots: void setGamma(bool srgb, Float gamma); void setReinhardKey(Float value); void setReinhardBurn(Float value); + void setAllowNonDiffuseVPLs(bool value); void setExposure(Float exposure); void onException(const QString &what); void onScroll(); diff --git a/src/qtgui/mainwindow.cpp b/src/qtgui/mainwindow.cpp index e1f297de..16b7f779 100644 --- a/src/qtgui/mainwindow.cpp +++ b/src/qtgui/mainwindow.cpp @@ -927,6 +927,7 @@ void MainWindow::on_actionPreviewSettings_triggered() { connect(&d, SIGNAL(reinhardBurnChanged(Float)), ui->glView, SLOT(setReinhardBurn(Float))); connect(&d, SIGNAL(previewMethodChanged(EPreviewMethod)), ui->glView, SLOT(setPreviewMethod(EPreviewMethod))); connect(&d, SIGNAL(toneMappingMethodChanged(EToneMappingMethod)), ui->glView, SLOT(setToneMappingMethod(EToneMappingMethod))); + connect(&d, SIGNAL(allowNonDiffuseVPLsChanged(bool)), ui->glView, SLOT(setAllowNonDiffuseVPLs(bool))); d.setMaximumSize(d.minimumSize()); d.exec(); QSettings settings("mitsuba-renderer.org", "qtgui"); @@ -939,6 +940,7 @@ void MainWindow::on_actionPreviewSettings_triggered() { settings.setValue("preview_clamping", context->clamping); settings.setValue("preview_previewMethod", context->previewMethod); settings.setValue("preview_toneMappingMethod", context->toneMappingMethod); + settings.setValue("preview_allowNonDiffuseVPLs", context->allowNonDiffuseVPLs); #else if (!m_previewSettings) { m_previewSettings = new PreviewSettingsDlg(this); @@ -978,6 +980,7 @@ void MainWindow::onPreviewSettingsClose() { settings.setValue("preview_clamping", context->clamping); settings.setValue("preview_previewMethod", context->previewMethod); settings.setValue("preview_toneMappingMethod", context->toneMappingMethod); + settings.setValue("preview_allowNonDiffuseVPLs", context->allowNonDiffuseVPLs); } } @@ -1608,6 +1611,7 @@ SceneContext::SceneContext(SceneContext *ctx) { scrollOffset = ctx->scrollOffset; reinhardKey = ctx->reinhardKey; reinhardBurn = ctx->reinhardBurn; + allowNonDiffuseVPLs = ctx->allowNonDiffuseVPLs; } SceneContext::~SceneContext() { diff --git a/src/qtgui/preview.cpp b/src/qtgui/preview.cpp index 242f27e1..60978325 100644 --- a/src/qtgui/preview.cpp +++ b/src/qtgui/preview.cpp @@ -356,6 +356,7 @@ void PreviewThread::run() { m_shaderManager->setShadowMapResolution(m_context->shadowMapResolution); m_shaderManager->setClamping(m_context->clamping); m_shaderManager->setSinglePass(m_context->previewMethod == EOpenGLSinglePass); + m_shaderManager->setAllowNonDiffuseVPLs(m_context->allowNonDiffuseVPLs); if (m_timer->getMilliseconds() > 1000) { Float count = m_vplsPerSecond / (Float) m_timer->getMilliseconds() * 1000; diff --git a/src/qtgui/previewsettingsdlg.cpp b/src/qtgui/previewsettingsdlg.cpp index 57edfea6..d042f70a 100644 --- a/src/qtgui/previewsettingsdlg.cpp +++ b/src/qtgui/previewsettingsdlg.cpp @@ -56,6 +56,7 @@ PreviewSettingsDialog::PreviewSettingsDialog(QWidget *parent, SceneContext *ctx, ui->clampingSlider->setValue(clamping); ui->gammaSpinBox->setValue(ctx->gamma); ui->sRGBCheckBox->setCheckState(ctx->srgb ? Qt::Checked : Qt::Unchecked); + ui->nonDiffuseVPLBox->setCheckState(ctx->allowNonDiffuseVPLs ? Qt::Checked : Qt::Unchecked); ui->previewMethodCombo->setModel(new MethodModel(this, cap->isSupported(RendererCapabilities::EGeometryShaders))); ui->previewMethodCombo->setCurrentIndex(ctx->previewMethod); @@ -87,6 +88,7 @@ void PreviewSettingsDialog::on_resetButton_clicked() { ui->keySlider->setValue((int) ((0.18-REINHARD_MIN)/REINHARD_RANGE * 100)); ui->sRGBCheckBox->setCheckState(Qt::Checked); + ui->nonDiffuseVPLBox->setCheckState(Qt::Unchecked); } void PreviewSettingsDialog::on_keySlider_valueChanged(int value) { @@ -137,6 +139,10 @@ void PreviewSettingsDialog::on_sRGBCheckBox_stateChanged(int state) { emit gammaChanged(state == Qt::Checked, (Float) ui->gammaSpinBox->value()); } +void PreviewSettingsDialog::on_nonDiffuseVPLBox_stateChanged(int state) { + emit allowNonDiffuseVPLsChanged(state == Qt::Checked); +} + void PreviewSettingsDialog::on_previewMethodCombo_activated(int index) { bool visible = index != ERayTrace && index != ERayTraceCoherent; ui->shadowResolutionCombo->setVisible(visible); diff --git a/src/qtgui/previewsettingsdlg.h b/src/qtgui/previewsettingsdlg.h index f2d76d6e..405a876e 100644 --- a/src/qtgui/previewsettingsdlg.h +++ b/src/qtgui/previewsettingsdlg.h @@ -26,6 +26,7 @@ signals: void toneMappingMethodChanged(EToneMappingMethod method); void reinhardKeyChanged(Float key); void reinhardBurnChanged(Float burn); + void allowNonDiffuseVPLsChanged(bool); protected slots: void on_pathLengthSlider_valueChanged(int value); @@ -35,6 +36,7 @@ protected slots: void on_exposureSpinBox_valueChanged(double value); void on_gammaSpinBox_valueChanged(double value); void on_sRGBCheckBox_stateChanged(int state); + void on_nonDiffuseVPLBox_stateChanged(int state); void on_resetButton_clicked(); void on_previewMethodCombo_activated(int index); void on_toneMappingMethodCombo_activated(int index); diff --git a/src/qtgui/previewsettingsdlg.ui b/src/qtgui/previewsettingsdlg.ui index 4e6f60b8..b3365490 100644 --- a/src/qtgui/previewsettingsdlg.ui +++ b/src/qtgui/previewsettingsdlg.ui @@ -504,7 +504,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -534,7 +534,7 @@ p, li { white-space: pre-wrap; } &Other : - nonDiffuseBox + nonDiffuseVPLBox @@ -546,7 +546,7 @@ p, li { white-space: pre-wrap; } pathLengthEdit clampingSlider shadowResolutionCombo - nonDiffuseBox + nonDiffuseVPLBox toneMappingMethodCombo keySlider exposureSpinBox diff --git a/src/qtgui/sceneloader.cpp b/src/qtgui/sceneloader.cpp index 584bd76d..e82b44dd 100644 --- a/src/qtgui/sceneloader.cpp +++ b/src/qtgui/sceneloader.cpp @@ -31,6 +31,7 @@ void SceneLoader::run() { m_result->clamping = (Float) settings.value("preview_clamping", 0.1f).toDouble(); m_result->previewMethod = (EPreviewMethod) settings.value("preview_previewMethod", EOpenGL).toInt(); m_result->toneMappingMethod = (EToneMappingMethod) settings.value("preview_toneMappingMethod", EGamma).toInt(); + m_result->allowNonDiffuseVPLs = settings.value("preview_allowNonDiffuseVPLs", false).toBool(); if (endsWith(lowerCase, ".exr")) { /* This is an image, not a scene */