summaryrefslogtreecommitdiffstats
path: root/src
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 /src
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>
Diffstat (limited to 'src')
-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
13 files changed, 247 insertions, 50 deletions
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);