summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-01 14:45:05 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-02 09:11:56 +0300
commit3c2d0623c74cc51d0c3b73e0b56b5f5052676ee4 (patch)
treea808859fae11c73df396768f5783c10b66d16592
parenta20806dac74415f3d8cb6679c9eae86ce074ddae (diff)
Add option to use low definition volume shader.
Low definition volume shader samples the texture at even intervals, so it will sometimes skip texels, causing flickering. Change-Id: Iee6cb0e8893498b89ce1a40f34701a53d100283e Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
-rw-r--r--examples/datavisualization/volumetric/main.cpp9
-rw-r--r--examples/datavisualization/volumetric/volumetric.cpp5
-rw-r--r--examples/datavisualization/volumetric/volumetric.h1
-rw-r--r--src/datavisualization/data/customrenderitem.cpp3
-rw-r--r--src/datavisualization/data/customrenderitem_p.h3
-rw-r--r--src/datavisualization/data/qcustom3dvolume.cpp58
-rw-r--r--src/datavisualization/data/qcustom3dvolume.h5
-rw-r--r--src/datavisualization/data/qcustom3dvolume_p.h5
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp67
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h3
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp8
-rw-r--r--src/datavisualization/engine/engine.qrc1
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp7
-rw-r--r--src/datavisualization/engine/shaders/texture3d.frag8
-rw-r--r--src/datavisualization/engine/shaders/texture3dlowdef.frag119
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp10
-rw-r--r--tests/volumetrictest/volumetrictest.cpp4
17 files changed, 265 insertions, 51 deletions
diff --git a/examples/datavisualization/volumetric/main.cpp b/examples/datavisualization/volumetric/main.cpp
index 84062969..68895b17 100644
--- a/examples/datavisualization/volumetric/main.cpp
+++ b/examples/datavisualization/volumetric/main.cpp
@@ -135,6 +135,10 @@ int main(int argc, char **argv)
preserveOpacityCheckBox->setText(QStringLiteral("Preserve opacity"));
preserveOpacityCheckBox->setChecked(true);
+ QCheckBox *useHighDefShaderCheckBox = new QCheckBox(widget);
+ useHighDefShaderCheckBox->setText(QStringLiteral("Use HD shader"));
+ useHighDefShaderCheckBox->setChecked(true);
+
vLayout->addWidget(sliceXCheckBox);
vLayout->addWidget(sliceXSlider);
vLayout->addWidget(sliceImageXLabel);
@@ -150,7 +154,8 @@ int main(int argc, char **argv)
vLayout2->addWidget(colorTableCheckBox);
vLayout2->addWidget(alphaMultiplierLabel);
vLayout2->addWidget(alphaMultiplierSlider);
- vLayout2->addWidget(preserveOpacityCheckBox, 1, Qt::AlignTop);
+ vLayout2->addWidget(preserveOpacityCheckBox);
+ vLayout2->addWidget(useHighDefShaderCheckBox, 1, Qt::AlignTop);
VolumetricModifier *modifier = new VolumetricModifier(graph);
modifier->setFpsLabel(fpsLabel);
@@ -184,6 +189,8 @@ int main(int argc, char **argv)
&VolumetricModifier::changeColorTable);
QObject::connect(preserveOpacityCheckBox, &QCheckBox::stateChanged, modifier,
&VolumetricModifier::setPreserveOpacity);
+ QObject::connect(useHighDefShaderCheckBox, &QCheckBox::stateChanged, modifier,
+ &VolumetricModifier::setUseHighDefShader);
QObject::connect(alphaMultiplierSlider, &QSlider::valueChanged, modifier,
&VolumetricModifier::adjustAlphaMultiplier);
diff --git a/examples/datavisualization/volumetric/volumetric.cpp b/examples/datavisualization/volumetric/volumetric.cpp
index 56f02dcb..1de4b1b7 100644
--- a/examples/datavisualization/volumetric/volumetric.cpp
+++ b/examples/datavisualization/volumetric/volumetric.cpp
@@ -338,6 +338,11 @@ void VolumetricModifier::setPreserveOpacity(bool enabled)
adjustSliceZ(m_sliceSliderZ->value());
}
+void VolumetricModifier::setUseHighDefShader(bool enabled)
+{
+ m_volumeItem->setUseHighDefShader(enabled);
+}
+
void VolumetricModifier::adjustAlphaMultiplier(int value)
{
float mult;
diff --git a/examples/datavisualization/volumetric/volumetric.h b/examples/datavisualization/volumetric/volumetric.h
index 497506ad..83af4b3c 100644
--- a/examples/datavisualization/volumetric/volumetric.h
+++ b/examples/datavisualization/volumetric/volumetric.h
@@ -60,6 +60,7 @@ public slots:
void setSliceSliders(QSlider *sliderX, QSlider *sliderY, QSlider *sliderZ);
void changeColorTable(int enabled);
void setPreserveOpacity(bool enabled);
+ void setUseHighDefShader(bool enabled);
void adjustAlphaMultiplier(int value);
private:
diff --git a/src/datavisualization/data/customrenderitem.cpp b/src/datavisualization/data/customrenderitem.cpp
index c316fd38..555f48b7 100644
--- a/src/datavisualization/data/customrenderitem.cpp
+++ b/src/datavisualization/data/customrenderitem.cpp
@@ -42,7 +42,8 @@ CustomRenderItem::CustomRenderItem()
m_sliceIndexY(-1),
m_sliceIndexZ(-1),
m_alphaMultiplier(1.0f),
- m_preserveOpacity(true)
+ m_preserveOpacity(true),
+ m_useHighDefShader(true)
{
}
diff --git a/src/datavisualization/data/customrenderitem_p.h b/src/datavisualization/data/customrenderitem_p.h
index 5428ce43..5024270a 100644
--- a/src/datavisualization/data/customrenderitem_p.h
+++ b/src/datavisualization/data/customrenderitem_p.h
@@ -96,6 +96,8 @@ public:
inline float alphaMultiplier() const { return m_alphaMultiplier; }
inline void setPreserveOpacity(bool enable) { m_preserveOpacity = enable; }
inline bool preserveOpacity() const { return m_preserveOpacity; }
+ inline void setUseHighDefShader(bool enable) { m_useHighDefShader = enable; }
+ inline bool useHighDefShader() const {return m_useHighDefShader; }
private:
Q_DISABLE_COPY(CustomRenderItem)
@@ -126,6 +128,7 @@ private:
int m_sliceIndexZ;
float m_alphaMultiplier;
bool m_preserveOpacity;
+ bool m_useHighDefShader;
};
typedef QHash<QCustom3DItem *, CustomRenderItem *> CustomRenderItemArray;
diff --git a/src/datavisualization/data/qcustom3dvolume.cpp b/src/datavisualization/data/qcustom3dvolume.cpp
index 503d324d..789b7718 100644
--- a/src/datavisualization/data/qcustom3dvolume.cpp
+++ b/src/datavisualization/data/qcustom3dvolume.cpp
@@ -136,6 +136,24 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty bool Custom3DVolume::useHighDefShader
+ *
+ * If this property value is \c{true}, a high definition shader is used to render the volume.
+ * If it is \c{false}, a low definition shader is used.
+ *
+ * The high definition shader guarantees that every visible texel of the volume texture is sampled
+ * when the volume is rendered.
+ * The low definition shader renders only a rough approximation of the volume contents,
+ * but at much higher frame rate. The low definition shader doesn't guarantee every texel of the
+ * volume texture is sampled, so there may be flickering if the volume contains distinct thin
+ * features.
+ *
+ * \note This value doesn't affect the level of detail when rendering the slices of the volume.
+ *
+ * Defaults to \c{true}.
+ */
+
+/*!
* Constructs QCustom3DVolume with given \a parent.
*/
QCustom3DVolume::QCustom3DVolume(QObject *parent) :
@@ -673,6 +691,40 @@ bool QCustom3DVolume::preserveOpacity() const
}
/*!
+ * \property QCustom3DVolume::useHighDefShader
+ *
+ * If this property value is \c{true}, a high definition shader is used to render the volume.
+ * If it is \c{false}, a low definition shader is used.
+ *
+ * The high definition shader guarantees that every visible texel of the volume texture is sampled
+ * when the volume is rendered.
+ * The low definition shader renders only a rough approximation of the volume contents,
+ * but at much higher frame rate. The low definition shader doesn't guarantee every texel of the
+ * volume texture is sampled, so there may be flickering if the volume contains distinct thin
+ * features.
+ *
+ * \note This value doesn't affect the level of detail when rendering the slices of the volume.
+ *
+ * Defaults to \c{true}.
+ *
+ * \sa renderSlice()
+ */
+void QCustom3DVolume::setUseHighDefShader(bool enable)
+{
+ if (dptr()->m_useHighDefShader != enable) {
+ dptr()->m_useHighDefShader = enable;
+ dptr()->m_dirtyBitsVolume.shaderDirty = true;
+ emit useHighDefShaderChanged(enable);
+ emit dptr()->needUpdate();
+ }
+}
+
+bool QCustom3DVolume::useHighDefShader() const
+{
+ return dptrc()->m_useHighDefShader;
+}
+
+/*!
* Renders the slice specified by \a index along \a axis into an image.
* The texture format of this object is used.
*
@@ -712,7 +764,8 @@ QCustom3DVolumePrivate::QCustom3DVolumePrivate(QCustom3DVolume *q) :
m_textureFormat(QImage::Format_ARGB32),
m_textureData(0),
m_alphaMultiplier(1.0f),
- m_preserveOpacity(true)
+ m_preserveOpacity(true),
+ m_useHighDefShader(true)
{
m_isVolumeItem = true;
m_meshFile = QStringLiteral(":/defaultMeshes/barFull");
@@ -736,7 +789,8 @@ QCustom3DVolumePrivate::QCustom3DVolumePrivate(QCustom3DVolume *q, const QVector
m_colorTable(colorTable),
m_textureData(textureData),
m_alphaMultiplier(1.0f),
- m_preserveOpacity(true)
+ m_preserveOpacity(true),
+ m_useHighDefShader(true)
{
m_isVolumeItem = true;
m_shadowCasting = false;
diff --git a/src/datavisualization/data/qcustom3dvolume.h b/src/datavisualization/data/qcustom3dvolume.h
index 8627eb71..23ae07d9 100644
--- a/src/datavisualization/data/qcustom3dvolume.h
+++ b/src/datavisualization/data/qcustom3dvolume.h
@@ -41,6 +41,7 @@ class QT_DATAVISUALIZATION_EXPORT QCustom3DVolume : public QCustom3DItem
Q_PROPERTY(QVector<uchar> *textureData READ textureData WRITE setTextureData NOTIFY textureDataChanged)
Q_PROPERTY(float alphaMultiplier READ alphaMultiplier WRITE setAlphaMultiplier NOTIFY alphaMultiplierChanged)
Q_PROPERTY(bool preserveOpacity READ preserveOpacity WRITE setPreserveOpacity NOTIFY preserveOpacityChanged)
+ Q_PROPERTY(bool useHighDefShader READ useHighDefShader WRITE setUseHighDefShader NOTIFY useHighDefShaderChanged)
public:
@@ -86,6 +87,9 @@ public:
void setPreserveOpacity(bool enable);
bool preserveOpacity() const;
+ void setUseHighDefShader(bool enable);
+ bool useHighDefShader() const;
+
QImage renderSlice(Qt::Axis axis, int index);
signals:
@@ -100,6 +104,7 @@ signals:
void textureFormatChanged(QImage::Format format);
void alphaMultiplierChanged(float mult);
void preserveOpacityChanged(bool enabled);
+ void useHighDefShaderChanged(bool enabled);
protected:
QCustom3DVolumePrivate *dptr();
diff --git a/src/datavisualization/data/qcustom3dvolume_p.h b/src/datavisualization/data/qcustom3dvolume_p.h
index b83e27fb..8b0b439e 100644
--- a/src/datavisualization/data/qcustom3dvolume_p.h
+++ b/src/datavisualization/data/qcustom3dvolume_p.h
@@ -41,6 +41,7 @@ struct QCustomVolumeDirtyBitField {
bool textureDataDirty : 1;
bool textureFormatDirty : 1;
bool alphaDirty : 1;
+ bool shaderDirty : 1;
QCustomVolumeDirtyBitField()
: textureDimensionsDirty(false),
@@ -48,7 +49,8 @@ struct QCustomVolumeDirtyBitField {
colorTableDirty(false),
textureDataDirty(false),
textureFormatDirty(false),
- alphaDirty(false)
+ alphaDirty(false),
+ shaderDirty(false)
{
}
};
@@ -84,6 +86,7 @@ public:
float m_alphaMultiplier;
bool m_preserveOpacity;
+ bool m_useHighDefShader;
QCustomVolumeDirtyBitField m_dirtyBitsVolume;
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index 78f4b600..f031a34c 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -60,6 +60,7 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_visibleSeriesCount(0),
m_customItemShader(0),
m_volumeTextureShader(0),
+ m_volumeTextureLowDefShader(0),
m_volumeTextureSliceShader(0),
m_useOrthoProjection(false),
m_xFlipped(false),
@@ -103,6 +104,7 @@ Abstract3DRenderer::~Abstract3DRenderer()
delete m_selectionLabelItem;
delete m_customItemShader;
delete m_volumeTextureShader;
+ delete m_volumeTextureLowDefShader;
delete m_volumeTextureSliceShader;
foreach (SeriesRenderCache *cache, m_renderCacheList) {
@@ -198,22 +200,27 @@ void Abstract3DRenderer::initGradientShaders(const QString &vertexShader,
void Abstract3DRenderer::initCustomItemShaders(const QString &vertexShader,
const QString &fragmentShader)
{
- if (m_customItemShader)
- delete m_customItemShader;
+ delete m_customItemShader;
m_customItemShader = new ShaderHelper(this, vertexShader, fragmentShader);
m_customItemShader->initialize();
}
void Abstract3DRenderer::initVolumeTextureShaders(const QString &vertexShader,
const QString &fragmentShader,
+ const QString &fragmentLowDefShader,
const QString &sliceShader)
{
- if (m_volumeTextureShader)
- delete m_volumeTextureShader;
+
+ delete m_volumeTextureShader;
m_volumeTextureShader = new ShaderHelper(this, vertexShader, fragmentShader);
m_volumeTextureShader->initialize();
- if (m_volumeTextureSliceShader)
- delete m_volumeTextureSliceShader;
+
+ delete m_volumeTextureLowDefShader;
+ m_volumeTextureLowDefShader = new ShaderHelper(this, vertexShader,
+ fragmentLowDefShader);
+ m_volumeTextureLowDefShader->initialize();
+
+ delete m_volumeTextureSliceShader;
m_volumeTextureSliceShader = new ShaderHelper(this, vertexShader, sliceShader);
m_volumeTextureSliceShader->initialize();
}
@@ -319,6 +326,7 @@ void Abstract3DRenderer::reInitShaders()
}
initVolumeTextureShaders(QStringLiteral(":/shaders/vertexTexture3D"),
QStringLiteral(":/shaders/fragmentTexture3D"),
+ QStringLiteral(":/shaders/fragmentTexture3DLowDef"),
QStringLiteral(":/shaders/fragmentTexture3DSlice"));
#else
initGradientShaders(QStringLiteral(":/shaders/vertex"),
@@ -988,6 +996,7 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
newItem->setSliceIndexZ(volumeItem->sliceIndexZ());
newItem->setAlphaMultiplier(volumeItem->alphaMultiplier());
newItem->setPreserveOpacity(volumeItem->preserveOpacity());
+ newItem->setUseHighDefShader(volumeItem->useHighDefShader());
#endif
}
newItem->setScaling(scaling);
@@ -1068,15 +1077,15 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
}
} else
#if !defined(QT_OPENGL_ES_2)
- if (!item->d_ptr->m_isVolumeItem)
+ if (!item->d_ptr->m_isVolumeItem)
#endif
- {
- renderItem->setBlendNeeded(textureImage.hasAlphaChannel());
- GLuint oldTexture = renderItem->texture();
- m_textureHelper->deleteTexture(&oldTexture);
- GLuint texture = m_textureHelper->create2DTexture(textureImage, true, true, true);
- renderItem->setTexture(texture);
- }
+ {
+ renderItem->setBlendNeeded(textureImage.hasAlphaChannel());
+ GLuint oldTexture = renderItem->texture();
+ m_textureHelper->deleteTexture(&oldTexture);
+ GLuint texture = m_textureHelper->create2DTexture(textureImage, true, true, true);
+ renderItem->setTexture(texture);
+ }
item->d_ptr->clearTextureImage();
item->d_ptr->m_dirtyBits.textureDirty = false;
}
@@ -1140,6 +1149,10 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
renderItem->setPreserveOpacity(volumeItem->preserveOpacity());
volumeItem->dptr()->m_dirtyBitsVolume.alphaDirty = false;
}
+ if (volumeItem->dptr()->m_dirtyBitsVolume.shaderDirty) {
+ renderItem->setUseHighDefShader(volumeItem->useHighDefShader());
+ volumeItem->dptr()->m_dirtyBitsVolume.shaderDirty = false;
+ }
#endif
}
}
@@ -1155,8 +1168,6 @@ void Abstract3DRenderer::updateCustomItemPositions()
void Abstract3DRenderer::drawCustomItems(RenderingState state,
ShaderHelper *regularShader,
- ShaderHelper *volumeShader,
- ShaderHelper *volumeSliceShader,
const QMatrix4x4 &viewMatrix,
const QMatrix4x4 &projectionViewMatrix,
const QMatrix4x4 &depthProjectionViewMatrix,
@@ -1254,9 +1265,11 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
if (item->sliceIndexX() >= 0
|| item->sliceIndexY() >= 0
|| item->sliceIndexZ() >= 0) {
- shader = volumeSliceShader;
+ shader = m_volumeTextureSliceShader;
+ } else if (item->useHighDefShader()) {
+ shader = m_volumeTextureShader;
} else {
- shader = volumeShader;
+ shader = m_volumeTextureLowDefShader;
}
} else {
shader = regularShader;
@@ -1309,7 +1322,7 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
shader->setUniformValue(shader->alphaMultiplier(), item->alphaMultiplier());
shader->setUniformValue(shader->preserveOpacity(),
item->preserveOpacity() ? 1 : 0);
- if (shader == volumeSliceShader) {
+ if (shader == m_volumeTextureSliceShader) {
QVector3D slices((float(item->sliceIndexX()) + 0.5f)
/ float(item->textureWidth()) * 2.0 - 1.0,
(float(item->sliceIndexY()) + 0.5f)
@@ -1323,11 +1336,21 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
QVector3D textureDimensions(1.0f / float(item->textureWidth()),
1.0f / float(item->textureHeight()),
1.0f / float(item->textureDepth()));
- shader->setUniformValue(shader->textureDimensions(), textureDimensions);
// Worst case scenario sample count
- int sampleCount = item->textureWidth() + item->textureHeight()
- + item->textureDepth();
+ int sampleCount;
+ if (shader == m_volumeTextureLowDefShader) {
+ sampleCount = qMax(item->textureWidth(),
+ qMax(item->textureDepth(), item->textureHeight()));
+ // Further improve speed with big textures by simply dropping every
+ // other sample:
+ if (sampleCount > 256)
+ sampleCount /= 2;
+ } else {
+ sampleCount = item->textureWidth() + item->textureHeight()
+ + item->textureDepth();
+ }
+ shader->setUniformValue(shader->textureDimensions(), textureDimensions);
shader->setUniformValue(shader->sampleCount(), sampleCount);
}
m_drawer->drawObject(shader, item->mesh(), 0, 0, item->texture());
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index 1e815463..83b4e1c7 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -94,6 +94,7 @@ public:
const QString &fragmentShader);
virtual void initVolumeTextureShaders(const QString &vertexShader,
const QString &fragmentShader,
+ const QString &fragmentLowDefShader,
const QString &sliceShader);
virtual void updateAxisType(QAbstract3DAxis::AxisOrientation orientation,
QAbstract3DAxis::AxisType type);
@@ -146,7 +147,6 @@ public:
QString &selectionLabel();
void drawCustomItems(RenderingState state, ShaderHelper *regularShader,
- ShaderHelper *volumeShader, ShaderHelper *volumeSliceShader,
const QMatrix4x4 &viewMatrix,
const QMatrix4x4 &projectionViewMatrix,
const QMatrix4x4 &depthProjectionViewMatrix,
@@ -243,6 +243,7 @@ protected:
ShaderHelper *m_customItemShader;
ShaderHelper *m_volumeTextureShader;
+ ShaderHelper *m_volumeTextureLowDefShader;
ShaderHelper *m_volumeTextureSliceShader;
bool m_useOrthoProjection;
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index 22bf6b87..1614b563 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -1090,8 +1090,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
}
- Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader,
- m_volumeTextureSliceShader, viewMatrix,
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
projectionViewMatrix,
depthProjectionViewMatrix, m_depthTexture,
m_shadowQualityToShader);
@@ -1179,7 +1178,6 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
glCullFace(GL_BACK);
Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader,
- m_volumeTextureShader, m_volumeTextureSliceShader,
viewMatrix,
projectionViewMatrix, depthProjectionViewMatrix,
m_depthTexture, m_shadowQualityToShader);
@@ -1234,7 +1232,6 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
startBar, stopBar, stepBar, -1.0f);
Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader,
- m_volumeTextureShader, m_volumeTextureSliceShader,
viewMatrix, projectionViewMatrix,
depthProjectionViewMatrix, m_depthTexture,
m_shadowQualityToShader, -1.0f);
@@ -1272,8 +1269,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
drawGridLines(depthProjectionViewMatrix, projectionViewMatrix, viewMatrix);
// Draw custom items
- Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, m_volumeTextureShader,
- m_volumeTextureSliceShader, viewMatrix,
+ Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix,
projectionViewMatrix, depthProjectionViewMatrix,
m_depthTexture, m_shadowQualityToShader);
diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc
index 88440bec..0936bc16 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -64,5 +64,6 @@
<file alias="fragmentTexture3DSlice">shaders/texture3dslice.frag</file>
<file alias="vertexShadowNoMatrices">shaders/shadowNoMatrices.vert</file>
<file alias="vertexNoMatrices">shaders/defaultNoMatrices.vert</file>
+ <file alias="fragmentTexture3DLowDef">shaders/texture3dlowdef.frag</file>
</qresource>
</RCC>
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index ca983dac..8c4644c6 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -575,8 +575,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
}
- Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader,
- m_volumeTextureSliceShader, viewMatrix,
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
projectionViewMatrix,
depthProjectionViewMatrix, m_depthTexture,
m_shadowQualityToShader);
@@ -681,7 +680,6 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader,
- m_volumeTextureShader, m_volumeTextureSliceShader,
viewMatrix, projectionViewMatrix,
depthProjectionViewMatrix, m_depthTexture,
m_shadowQualityToShader);
@@ -1455,8 +1453,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
}
- Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, m_volumeTextureShader,
- m_volumeTextureSliceShader, viewMatrix,
+ Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix,
projectionViewMatrix, depthProjectionViewMatrix,
m_depthTexture, m_shadowQualityToShader);
diff --git a/src/datavisualization/engine/shaders/texture3d.frag b/src/datavisualization/engine/shaders/texture3d.frag
index 6dd7f78c..460cbcc6 100644
--- a/src/datavisualization/engine/shaders/texture3d.frag
+++ b/src/datavisualization/engine/shaders/texture3d.frag
@@ -74,9 +74,8 @@ void main() {
highp vec4 destColor = vec4(0, 0, 0, 0);
highp float totalOpacity = 1.0;
- highp float nextOpacity = 1.0;
- highp float extraAlphaMultiplier = fullDist * alphaThicknesses;
+ highp float extraAlphaMultiplier = fullDist * alphaThicknesses * alphaMultiplier;
// nextEdges vector indicates the next edges of the texel boundaries along each axis that
// the ray is about to cross. The first edges are offset by a fraction of a texel to
@@ -134,11 +133,10 @@ void main() {
curLen += stepSize;
if (curColor.a >= 0.0) {
- curAlpha = alphaMultiplier * curColor.a;
- if (curAlpha >= 1.0 || (curColor.a == 1.0 && preserveOpacity == 1))
+ if (curColor.a == 1.0 && (preserveOpacity == 1 || alphaMultiplier >= 1.0))
curAlpha = 1.0;
else
- curAlpha = curAlpha * extraAlphaMultiplier * stepSize;
+ curAlpha = curColor.a * extraAlphaMultiplier * stepSize;
highp float nextOpacity = totalOpacity - curAlpha;
// If opacity goes beyond full opacity, we need to adjust current alpha according
// to the fraction of the distance the material is visible, so that we don't get
diff --git a/src/datavisualization/engine/shaders/texture3dlowdef.frag b/src/datavisualization/engine/shaders/texture3dlowdef.frag
new file mode 100644
index 00000000..72b959fc
--- /dev/null
+++ b/src/datavisualization/engine/shaders/texture3dlowdef.frag
@@ -0,0 +1,119 @@
+#version 120
+
+varying highp vec3 pos;
+
+uniform highp sampler3D textureSampler;
+uniform highp vec3 cameraPositionRelativeToModel;
+uniform highp vec4 colorIndex[256];
+uniform highp int color8Bit;
+uniform highp vec3 textureDimensions;
+uniform highp int sampleCount; // This is the maximum sample count
+uniform highp float alphaMultiplier;
+uniform highp int preserveOpacity;
+
+// Ray traveling straight through a single 'alpha thickness' applies 100% of the encountered alpha.
+// Rays traveling shorter distances apply a fraction. This is used to normalize the alpha over
+// entire volume, regardless of texture dimensions
+const highp float alphaThicknesses = 32.0;
+const highp float SQRT3 = 1.73205081;
+
+void main() {
+ highp vec3 rayDir = -(cameraPositionRelativeToModel - pos);
+ vec3 rayStart = pos;
+ // Flip Y and Z so QImage bits work directly for texture and first image is in the front
+ rayDir.yz = -rayDir.yz;
+ rayStart.yz = -rayStart.yz;
+
+ // Calculate ray intersection endpoint
+ vec3 rayStop;
+ if (rayDir.x == 0.0) {
+ rayStop.yz = rayStart.yz;
+ rayStop.x = -rayStart.x;
+ } else if (rayDir.y == 0.0) {
+ rayStop.xz = rayStart.xz;
+ rayStop.y = -rayStart.y;
+ } else if (rayDir.z == 0.0) {
+ rayStop.xy = rayStart.xy;
+ rayStop.z = -rayStart.z;
+ } else {
+ highp vec3 boxBounds = vec3(1.0, 1.0, 1.0);
+ highp vec3 invRayDir = 1.0 / rayDir;
+ if (rayDir.x < 0)
+ boxBounds.x = -1.0;
+ if (rayDir.y < 0)
+ boxBounds.y = -1.0;
+ if (rayDir.z < 0)
+ boxBounds.z = -1.0;
+ highp vec3 t = (boxBounds - rayStart) * invRayDir;
+ highp float minT = min(t.x, min(t.y, t.z));
+ rayStop = rayStart + minT * rayDir;
+ }
+
+ // Convert intersections to texture coords
+ rayStart = 0.5 * (rayStart + 1.0);
+ rayStop = 0.5 * (rayStop + 1.0);
+
+ highp vec3 ray = rayStop - rayStart;
+
+ // Avoid artifacts from divisions by zero
+ if (ray.x == 0)
+ ray.x = 0.000000001;
+ if (ray.y == 0)
+ ray.y = 0.000000001;
+ if (ray.z == 0)
+ ray.z = 0.000000001;
+
+
+ highp float fullDist = length(ray);
+ highp float stepSize = SQRT3 / sampleCount;
+ highp vec3 step = (SQRT3 * normalize(ray)) / sampleCount;
+
+ rayStart += (step * 0.001);
+
+ highp vec3 curPos = rayStart;
+ highp float curLen = 0.0;
+ highp vec4 curColor = vec4(0, 0, 0, 0);
+ highp float curAlpha = 0.0;
+ highp vec3 curRgb = vec3(0, 0, 0);
+ highp vec4 destColor = vec4(0, 0, 0, 0);
+ highp float totalOpacity = 1.0;
+
+ highp float extraAlphaMultiplier = stepSize * alphaThicknesses * alphaMultiplier;
+
+ // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1
+ for (int i = 0; i < sampleCount; i++) {
+ curColor = texture3D(textureSampler, curPos);
+ if (color8Bit != 0)
+ curColor = colorIndex[int(curColor.r * 255.0)];
+
+ if (curColor.a >= 0.0) {
+ if (curColor.a == 1.0 && (preserveOpacity == 1 || alphaMultiplier >= 1.0))
+ curAlpha = 1.0;
+ else
+ curAlpha = curColor.a * extraAlphaMultiplier;
+ highp float nextOpacity = totalOpacity - curAlpha;
+ // If opacity goes beyond full opacity, we need to adjust current alpha according
+ // to the fraction of the distance the material is visible, so that we don't get
+ // box artifacts around texels.
+ if (nextOpacity < 0.0) {
+ curAlpha *= totalOpacity / curAlpha;
+ nextOpacity = 0.0;
+ }
+
+ curRgb = curColor.rgb * curAlpha * (totalOpacity + nextOpacity);
+ destColor.rgb += curRgb;
+ totalOpacity = nextOpacity;
+ }
+ curPos += step;
+ curLen += stepSize;
+ if (curLen >= fullDist || totalOpacity <= 0.0)
+ break;
+ }
+
+ // Brighten up the final color if there is some transparency left
+ if (totalOpacity >= 0.0 && totalOpacity < 1.0)
+ destColor *= (1.0 - (totalOpacity * 0.5)) / (1.0 - totalOpacity);
+
+ destColor.a = (1.0 - totalOpacity);
+ gl_FragColor = clamp(destColor, 0.0, 1.0);
+}
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 58f97b0a..ced4c789 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -1196,8 +1196,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
- Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader,
- m_volumeTextureSliceShader, viewMatrix,
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
projectionViewMatrix,
depthProjectionViewMatrix, m_depthTexture,
m_shadowQualityToShader);
@@ -1234,8 +1233,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisableVertexAttribArray(m_depthShader->posAtt());
- Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader,
- m_volumeTextureSliceShader, viewMatrix,
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
projectionViewMatrix,
depthProjectionViewMatrix, m_depthTexture,
m_shadowQualityToShader);
@@ -1292,7 +1290,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
m_surfaceGridShader->bind();
Abstract3DRenderer::drawCustomItems(RenderingSelection, m_surfaceGridShader,
- m_volumeTextureShader, m_volumeTextureSliceShader,
viewMatrix,
projectionViewMatrix, depthProjectionViewMatrix,
m_depthTexture, m_shadowQualityToShader);
@@ -1864,8 +1861,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
}
- Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, m_volumeTextureShader,
- m_volumeTextureSliceShader, viewMatrix,
+ Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix,
projectionViewMatrix, depthProjectionViewMatrix,
m_depthTexture, m_shadowQualityToShader);
diff --git a/tests/volumetrictest/volumetrictest.cpp b/tests/volumetrictest/volumetrictest.cpp
index 554373cb..9c89e761 100644
--- a/tests/volumetrictest/volumetrictest.cpp
+++ b/tests/volumetrictest/volumetrictest.cpp
@@ -51,6 +51,10 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
createAnotherVolume();
createYetAnotherVolume();
+// m_volumeItem->setUseHighDefShader(false);
+// m_volumeItem2->setUseHighDefShader(false);
+// m_volumeItem3->setUseHighDefShader(false);
+
m_plainItem = new QCustom3DItem;
QImage texture(2, 2, QImage::Format_ARGB32);
texture.fill(QColor(200, 200, 200, 130));