summaryrefslogtreecommitdiffstats
path: root/src/datavisualization
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-08-25 13:16:04 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-08-25 15:01:10 +0300
commit5a51d06ec8f0210f51e65abfde9f868ab7bfa8ef (patch)
tree2319880f2d66e5610d9d1040d886f52cada82ad8 /src/datavisualization
parentf9bb71fd11cce59d74e78202a1117c8abb3a2e44 (diff)
Add alpha multiplier to QCustom3DVolume api
Change-Id: I856c4166513f6d6f7b73fd52bc46d52ab1b8fdff Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com> Reviewed-by: Mika Salmela <mika.salmela@digia.com>
Diffstat (limited to 'src/datavisualization')
-rw-r--r--src/datavisualization/data/customrenderitem.cpp8
-rw-r--r--src/datavisualization/data/customrenderitem_p.h12
-rw-r--r--src/datavisualization/data/qcustom3dvolume.cpp251
-rw-r--r--src/datavisualization/data/qcustom3dvolume.h10
-rw-r--r--src/datavisualization/data/qcustom3dvolume_p.h10
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp10
-rw-r--r--src/datavisualization/engine/shaders/texture3d.frag14
-rw-r--r--src/datavisualization/engine/shaders/texture3dslice.frag54
-rw-r--r--src/datavisualization/utils/shaderhelper.cpp16
-rw-r--r--src/datavisualization/utils/shaderhelper_p.h4
10 files changed, 295 insertions, 94 deletions
diff --git a/src/datavisualization/data/customrenderitem.cpp b/src/datavisualization/data/customrenderitem.cpp
index 3eb68845..c316fd38 100644
--- a/src/datavisualization/data/customrenderitem.cpp
+++ b/src/datavisualization/data/customrenderitem.cpp
@@ -36,7 +36,13 @@ CustomRenderItem::CustomRenderItem()
m_textureWidth(0),
m_textureHeight(0),
m_textureDepth(0),
- m_isVolume(false)
+ m_isVolume(false),
+ m_textureFormat(QImage::Format_ARGB32),
+ m_sliceIndexX(-1),
+ m_sliceIndexY(-1),
+ m_sliceIndexZ(-1),
+ m_alphaMultiplier(1.0f),
+ m_preserveOpacity(true)
{
}
diff --git a/src/datavisualization/data/customrenderitem_p.h b/src/datavisualization/data/customrenderitem_p.h
index e21b6f39..5428ce43 100644
--- a/src/datavisualization/data/customrenderitem_p.h
+++ b/src/datavisualization/data/customrenderitem_p.h
@@ -89,9 +89,13 @@ public:
inline void setSliceIndexX(int index) { m_sliceIndexX = index; }
inline void setSliceIndexY(int index) { m_sliceIndexY = index; }
inline void setSliceIndexZ(int index) { m_sliceIndexZ = index; }
- int sliceIndexX() const { return m_sliceIndexX; }
- int sliceIndexY() const { return m_sliceIndexY; }
- int sliceIndexZ() const { return m_sliceIndexZ; }
+ inline int sliceIndexX() const { return m_sliceIndexX; }
+ inline int sliceIndexY() const { return m_sliceIndexY; }
+ inline int sliceIndexZ() const { return m_sliceIndexZ; }
+ inline void setAlphaMultiplier(float mult) { m_alphaMultiplier = mult; }
+ inline float alphaMultiplier() const { return m_alphaMultiplier; }
+ inline void setPreserveOpacity(bool enable) { m_preserveOpacity = enable; }
+ inline bool preserveOpacity() const { return m_preserveOpacity; }
private:
Q_DISABLE_COPY(CustomRenderItem)
@@ -120,6 +124,8 @@ private:
int m_sliceIndexX;
int m_sliceIndexY;
int m_sliceIndexZ;
+ float m_alphaMultiplier;
+ bool m_preserveOpacity;
};
typedef QHash<QCustom3DItem *, CustomRenderItem *> CustomRenderItemArray;
diff --git a/src/datavisualization/data/qcustom3dvolume.cpp b/src/datavisualization/data/qcustom3dvolume.cpp
index cab79ac0..c1a77dba 100644
--- a/src/datavisualization/data/qcustom3dvolume.cpp
+++ b/src/datavisualization/data/qcustom3dvolume.cpp
@@ -112,6 +112,30 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty real Custom3DVolume::alphaMultiplier
+ *
+ * The alpha value of every texel of the volume texture is multiplied with this value at
+ * the render time. This can be used to introduce uniform transparency to the volume.
+ * If preserveOpacity is \c{true}, only texels with at least some transparency to begin with are
+ * affected, and fully opaque texels are not affected.
+ * The value must not be negative.
+ * Defaults to \c{1.0}.
+ *
+ * \sa preserveOpacity
+ */
+
+/*!
+ * \qmlproperty bool Custom3DVolume::preserveOpacity
+ *
+ * If this property value is \c{true}, alphaMultiplier is only applied to texels that already have
+ * some transparency. If it is \c{false}, the multiplier is applied to the alpha value of all
+ * texels.
+ * Defaults to \c{true}.
+ *
+ * \sa alphaMultiplier
+ */
+
+/*!
* Constructs QCustom3DVolume with given \a parent.
*/
QCustom3DVolume::QCustom3DVolume(QObject *parent) :
@@ -578,84 +602,72 @@ QImage::Format QCustom3DVolume::textureFormat() const
}
/*!
- * Renders the slice specified by \a index along \a axis into an image.
- * The texture format of this object is used.
+ * \property QCustom3DVolume::alphaMultiplier
*
- * \return the rendered image of the slice, or a null image if invalid index is specified.
+ * The alpha value of every texel of the volume texture is multiplied with this value at
+ * the render time. This can be used to introduce uniform transparency to the volume.
+ * If preserveOpacity is \c{true}, only texels with at least some transparency to begin with are
+ * affected, and fully opaque texels are not affected.
+ * The value must not be negative.
+ * Defaults to \c{1.0f}.
*
- * \sa textureFormat
+ * \sa preserveOpacity, textureData
*/
-QImage QCustom3DVolume::renderSlice(Qt::Axis axis, int index)
+void QCustom3DVolume::setAlphaMultiplier(float mult)
{
- if (index < 0)
- return QImage();
-
- int x;
- int y;
- if (axis == Qt::XAxis) {
- if (index >= textureWidth())
- return QImage();
- x = textureDepth();
- y = textureHeight();
- } else if (axis == Qt::YAxis) {
- if (index >= textureHeight())
- return QImage();
- x = textureWidth();
- y = textureDepth();
+ if (mult >= 0.0f) {
+ if (dptr()->m_alphaMultiplier != mult) {
+ dptr()->m_alphaMultiplier = mult;
+ dptr()->m_dirtyBitsVolume.alphaDirty = true;
+ emit alphaMultiplierChanged(mult);
+ emit dptr()->needUpdate();
+ }
} else {
- if (index >= textureDepth())
- return QImage();
- x = textureWidth();
- y = textureHeight();
+ qWarning() << __FUNCTION__ << "Attempted to set negative multiplier.";
}
+}
- int padding = 0;
- int pixelWidth = 4;
- if (textureFormat() == QImage::Format_Indexed8) {
- padding = x % 4;
- pixelWidth = 1;
- }
- QVector<uchar> data((x + padding) * y * pixelWidth);
- int frameSize = textureDataWidth() * textureHeight();
+float QCustom3DVolume::alphaMultiplier() const
+{
+ return dptrc()->m_alphaMultiplier;
+}
- int dataIndex = 0;
- if (axis == Qt::XAxis) {
- for (int i = 0; i < y; i++) {
- const uchar *p = textureData()->constData()
- + (index * pixelWidth) + (textureDataWidth() * i);
- for (int j = 0; j < x; j++) {
- data[dataIndex++] = *p;
- for (int k = 1; k < pixelWidth; k++)
- data[dataIndex++] = *(p + k);
- p += frameSize;
- }
- }
- } else if (axis == Qt::YAxis) {
- for (int i = 0; i < y; i++) {
- const uchar *p = textureData()->constData() + (index * textureDataWidth())
- + (frameSize * i);
- for (int j = 0; j < (x * pixelWidth); j++) {
- data[dataIndex++] = *p;
- p++;
- }
- }
- } else {
- for (int i = 0; i < y; i++) {
- const uchar *p = textureData()->constData() + (index * frameSize)
- + (textureDataWidth() * i);
- for (int j = 0; j < (x * pixelWidth); j++) {
- data[dataIndex++] = *p;
- p++;
- }
- }
+/*!
+ * \property QCustom3DVolume::preserveOpacity
+ *
+ * If this property value is \c{true}, alphaMultiplier is only applied to texels that already have
+ * some transparency. If it is \c{false}, the multiplier is applied to the alpha value of all
+ * texels.
+ * Defaults to \c{true}.
+ *
+ * \sa alphaMultiplier
+ */
+void QCustom3DVolume::setPreserveOpacity(bool enable)
+{
+ if (dptr()->m_preserveOpacity != enable) {
+ dptr()->m_preserveOpacity = enable;
+ dptr()->m_dirtyBitsVolume.alphaDirty = true;
+ emit preserveOpacityChanged(enable);
+ emit dptr()->needUpdate();
}
+}
- QImage image(data.constData(), x, y, x * pixelWidth, textureFormat());
- image.bits(); // Call bits() to detach the new image from local data
- if (textureFormat() == QImage::Format_Indexed8)
- image.setColorTable(colorTable());
+bool QCustom3DVolume::preserveOpacity() const
+{
+ return dptrc()->m_preserveOpacity;
+}
- return image;
+/*!
+ * Renders the slice specified by \a index along \a axis into an image.
+ * The texture format of this object is used.
+ *
+ * \return the rendered image of the slice, or a null image if invalid index is specified.
+ *
+ * \sa textureFormat
+ */
+QImage QCustom3DVolume::renderSlice(Qt::Axis axis, int index)
+{
+ return dptr()->renderSlice(axis, index);
}
/*!
@@ -683,7 +695,9 @@ QCustom3DVolumePrivate::QCustom3DVolumePrivate(QCustom3DVolume *q) :
m_textureHeight(0),
m_textureDepth(0),
m_textureFormat(QImage::Format_ARGB32),
- m_textureData(0)
+ m_textureData(0),
+ m_alphaMultiplier(1.0f),
+ m_preserveOpacity(true)
{
m_isVolumeItem = true;
m_meshFile = QStringLiteral(":/defaultMeshes/barFull");
@@ -705,7 +719,9 @@ QCustom3DVolumePrivate::QCustom3DVolumePrivate(QCustom3DVolume *q, const QVector
m_textureDepth(textureDepth),
m_textureFormat(textureFormat),
m_colorTable(colorTable),
- m_textureData(textureData)
+ m_textureData(textureData),
+ m_alphaMultiplier(1.0f),
+ m_preserveOpacity(true)
{
m_isVolumeItem = true;
m_shadowCasting = false;
@@ -738,6 +754,103 @@ void QCustom3DVolumePrivate::resetDirtyBits()
m_dirtyBitsVolume.textureFormatDirty = false;
}
+QImage QCustom3DVolumePrivate::renderSlice(Qt::Axis axis, int index)
+{
+ if (index < 0)
+ return QImage();
+
+ int x;
+ int y;
+ if (axis == Qt::XAxis) {
+ if (index >= m_textureWidth)
+ return QImage();
+ x = m_textureDepth;
+ y = m_textureHeight;
+ } else if (axis == Qt::YAxis) {
+ if (index >= m_textureHeight)
+ return QImage();
+ x = m_textureWidth;
+ y = m_textureDepth;
+ } else {
+ if (index >= m_textureDepth)
+ return QImage();
+ x = m_textureWidth;
+ y = m_textureHeight;
+ }
+
+ int padding = 0;
+ int pixelWidth = 4;
+ int dataWidth = qptr()->textureDataWidth();
+ if (m_textureFormat == QImage::Format_Indexed8) {
+ padding = x % 4;
+ pixelWidth = 1;
+ }
+ QVector<uchar> data((x + padding) * y * pixelWidth);
+ int frameSize = qptr()->textureDataWidth() * m_textureHeight;
+
+ int dataIndex = 0;
+ if (axis == Qt::XAxis) {
+ for (int i = 0; i < y; i++) {
+ const uchar *p = m_textureData->constData()
+ + (index * pixelWidth) + (dataWidth * i);
+ for (int j = 0; j < x; j++) {
+ for (int k = 0; k < pixelWidth; k++)
+ data[dataIndex++] = *(p + k);
+ p += frameSize;
+ }
+ }
+ } else if (axis == Qt::YAxis) {
+ for (int i = 0; i < y; i++) {
+ const uchar *p = m_textureData->constData() + (index * dataWidth)
+ + (frameSize * i);
+ for (int j = 0; j < (x * pixelWidth); j++) {
+ data[dataIndex++] = *p;
+ p++;
+ }
+ }
+ } else {
+ for (int i = 0; i < y; i++) {
+ const uchar *p = m_textureData->constData() + (index * frameSize) + (dataWidth * i);
+ for (int j = 0; j < (x * pixelWidth); j++) {
+ data[dataIndex++] = *p;
+ p++;
+ }
+ }
+ }
+
+ if (m_textureFormat != QImage::Format_Indexed8 && m_alphaMultiplier != 1.0f) {
+ for (int i = pixelWidth - 1; i < data.size(); i += pixelWidth)
+ data[i] = static_cast<uchar>(multipliedAlphaValue(data.at(i)));
+ }
+
+ QImage image(data.constData(), x, y, x * pixelWidth, m_textureFormat);
+ image.bits(); // Call bits() to detach the new image from local data
+ if (m_textureFormat == QImage::Format_Indexed8) {
+ QVector<QRgb> colorTable = m_colorTable;
+ if (m_alphaMultiplier != 1.0f) {
+ for (int i = 0; i < colorTable.size(); i++) {
+ QRgb curCol = colorTable.at(i);
+ int alpha = multipliedAlphaValue(qAlpha(curCol));
+ if (alpha != qAlpha(curCol))
+ colorTable[i] = qRgba(qRed(curCol), qGreen(curCol), qBlue(curCol), alpha);
+ }
+ }
+ image.setColorTable(colorTable);
+ }
+
+ return image;
+}
+
+int QCustom3DVolumePrivate::multipliedAlphaValue(int alpha)
+{
+ int modifiedAlpha = alpha;
+ if (!m_preserveOpacity || alpha != 255) {
+ modifiedAlpha = int(m_alphaMultiplier * float(alpha));
+ modifiedAlpha = qMin(modifiedAlpha, 255);
+ }
+ return modifiedAlpha;
+}
+
QCustom3DVolume *QCustom3DVolumePrivate::qptr()
{
return static_cast<QCustom3DVolume *>(q_ptr);
diff --git a/src/datavisualization/data/qcustom3dvolume.h b/src/datavisualization/data/qcustom3dvolume.h
index 00733d17..2f95fa5d 100644
--- a/src/datavisualization/data/qcustom3dvolume.h
+++ b/src/datavisualization/data/qcustom3dvolume.h
@@ -40,7 +40,8 @@ class QT_DATAVISUALIZATION_EXPORT QCustom3DVolume : public QCustom3DItem
Q_PROPERTY(QVector<QRgb> colorTable READ colorTable WRITE setColorTable NOTIFY colorTableChanged)
Q_PROPERTY(QVector<uchar> *textureData READ textureData WRITE setTextureData NOTIFY textureDataChanged)
Q_PROPERTY(QImage::Format textureFormat READ textureFormat WRITE setTextureFormat NOTIFY textureFormatChanged)
-
+ Q_PROPERTY(float alphaMultiplier READ alphaMultiplier WRITE setAlphaMultiplier NOTIFY alphaMultiplierChanged)
+ Q_PROPERTY(bool preserveOpacity READ preserveOpacity WRITE setPreserveOpacity NOTIFY preserveOpacityChanged)
public:
explicit QCustom3DVolume(QObject *parent = 0);
@@ -80,6 +81,11 @@ public:
void setTextureFormat(QImage::Format format);
QImage::Format textureFormat() const;
+ void setAlphaMultiplier(float mult);
+ float alphaMultiplier() const;
+ void setPreserveOpacity(bool enable);
+ bool preserveOpacity() const;
+
QImage renderSlice(Qt::Axis axis, int index);
signals:
@@ -92,6 +98,8 @@ signals:
void colorTableChanged();
void textureDataChanged(QVector<uchar> *data);
void textureFormatChanged(QImage::Format format);
+ void alphaMultiplierChanged(float mult);
+ void preserveOpacityChanged(bool enabled);
protected:
QCustom3DVolumePrivate *dptr();
diff --git a/src/datavisualization/data/qcustom3dvolume_p.h b/src/datavisualization/data/qcustom3dvolume_p.h
index 69dd1eb2..b83e27fb 100644
--- a/src/datavisualization/data/qcustom3dvolume_p.h
+++ b/src/datavisualization/data/qcustom3dvolume_p.h
@@ -40,13 +40,15 @@ struct QCustomVolumeDirtyBitField {
bool colorTableDirty : 1;
bool textureDataDirty : 1;
bool textureFormatDirty : 1;
+ bool alphaDirty : 1;
QCustomVolumeDirtyBitField()
: textureDimensionsDirty(false),
sliceIndicesDirty(false),
colorTableDirty(false),
textureDataDirty(false),
- textureFormatDirty(false)
+ textureFormatDirty(false),
+ alphaDirty(false)
{
}
};
@@ -64,6 +66,7 @@ public:
virtual ~QCustom3DVolumePrivate();
void resetDirtyBits();
+ QImage renderSlice(Qt::Axis axis, int index);
QCustom3DVolume *qptr();
@@ -79,9 +82,14 @@ public:
QVector<QRgb> m_colorTable;
QVector<uchar> *m_textureData;
+ float m_alphaMultiplier;
+ bool m_preserveOpacity;
+
QCustomVolumeDirtyBitField m_dirtyBitsVolume;
private:
+ int multipliedAlphaValue(int alpha);
+
friend class QCustom3DVolume;
};
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index 8eb1d2ce..37688beb 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -967,6 +967,8 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
newItem->setSliceIndexX(volumeItem->sliceIndexX());
newItem->setSliceIndexY(volumeItem->sliceIndexY());
newItem->setSliceIndexZ(volumeItem->sliceIndexZ());
+ newItem->setAlphaMultiplier(volumeItem->alphaMultiplier());
+ newItem->setPreserveOpacity(volumeItem->preserveOpacity());
#endif
}
newItem->setScaling(scaling);
@@ -1114,6 +1116,11 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
renderItem->setSliceIndexZ(volumeItem->sliceIndexZ());
volumeItem->dptr()->m_dirtyBitsVolume.sliceIndicesDirty = false;
}
+ if (volumeItem->dptr()->m_dirtyBitsVolume.alphaDirty) {
+ renderItem->setAlphaMultiplier(volumeItem->alphaMultiplier());
+ renderItem->setPreserveOpacity(volumeItem->preserveOpacity());
+ volumeItem->dptr()->m_dirtyBitsVolume.alphaDirty = false;
+ }
#endif
}
}
@@ -1292,6 +1299,9 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
item->colorTable().constData(), 256);
}
shader->setUniformValue(shader->color8Bit(), color8Bit);
+ shader->setUniformValue(shader->alphaMultiplier(), item->alphaMultiplier());
+ shader->setUniformValue(shader->preserveOpacity(),
+ item->preserveOpacity() ? 1 : 0);
if (shader == volumeSliceShader) {
QVector3D slices((float(item->sliceIndexX()) + 0.5f)
/ float(item->textureWidth()) * 2.0 - 1.0,
diff --git a/src/datavisualization/engine/shaders/texture3d.frag b/src/datavisualization/engine/shaders/texture3d.frag
index 90876596..1192ae85 100644
--- a/src/datavisualization/engine/shaders/texture3d.frag
+++ b/src/datavisualization/engine/shaders/texture3d.frag
@@ -8,6 +8,8 @@ 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;
const highp float alphaThreshold = 0.0001;
@@ -69,7 +71,7 @@ void main() {
// Adjust alpha multiplier according to the step size to get uniform alpha effect
// regardless of the ray angle.
- highp float alphaMultiplier = stepSize / (1.0 / sampleCount);
+ highp float totalAlphaMultiplier = (stepSize / (1.0 / sampleCount)) * alphaMultiplier;
highp vec4 curColor = vec4(0, 0, 0, 0);
highp vec3 curRgb = vec3(0, 0, 0);
@@ -81,10 +83,12 @@ void main() {
if (color8Bit != 0)
curColor = colorIndex[int(curColor.r * 255.0)];
- if (curColor.a == 1.0)
+ // Unless we have explicit alpha multiplier, we want to preserve opacity anyway
+ if (curColor.a == 1.0 && (preserveOpacity != 0 || alphaMultiplier == 1.0))
curAlpha = 1.0;
else
- curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0);
+ curAlpha = clamp(curColor.a * totalAlphaMultiplier, 0.0, 1.0);
+
if (curAlpha > alphaThreshold) {
curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha);
destColor.rgb += curRgb;
@@ -96,6 +100,10 @@ void main() {
}
}
+ // Brighten up the final color if there is some transparency left
+ if (totalAlpha > alphaThreshold && totalAlpha < 1.0)
+ destColor *= 1.0 / totalAlpha;
+
destColor.a = totalAlpha;
gl_FragColor = clamp(destColor, 0.0, 1.0);
}
diff --git a/src/datavisualization/engine/shaders/texture3dslice.frag b/src/datavisualization/engine/shaders/texture3dslice.frag
index 8870b26d..3d4c9030 100644
--- a/src/datavisualization/engine/shaders/texture3dslice.frag
+++ b/src/datavisualization/engine/shaders/texture3dslice.frag
@@ -7,6 +7,8 @@ uniform highp vec3 cameraPositionRelativeToModel;
uniform highp vec3 volumeSliceIndices;
uniform highp vec4 colorIndex[256];
uniform highp int color8Bit;
+uniform highp float alphaMultiplier;
+uniform highp int preserveOpacity;
const highp vec3 xPlaneNormal = vec3(1.0, 0, 0);
const highp vec3 yPlaneNormal = vec3(0, 1.0, 0);
@@ -76,47 +78,67 @@ void main() {
}
highp vec4 destColor = vec4(0.0, 0.0, 0.0, 0.0);
+ highp vec4 curColor = vec4(0.0, 0.0, 0.0, 0.0);
highp float totalAlpha = 0.0;
highp vec3 curRgb = vec3(0, 0, 0);
+ highp float curAlpha = 0.0;
// Convert intersection to texture coords
if (firstD <= tFar) {
highp vec3 firstTex = rayStart + rayDir * firstD;
firstTex = 0.5 * (firstTex + 1.0);
- highp vec4 firstColor = texture3D(textureSampler, firstTex);
+ curColor = texture3D(textureSampler, firstTex);
if (color8Bit != 0)
- firstColor = colorIndex[int(firstColor.r * 255.0)];
+ curColor = colorIndex[int(curColor.r * 255.0)];
- if (firstColor.a > alphaThreshold) {
- destColor.rgb = firstColor.rgb * firstColor.a;
- totalAlpha = firstColor.a;
+ if (curColor.a > alphaThreshold) {
+ curAlpha = curColor.a;
+ if (curColor.a == 1.0 && preserveOpacity != 0)
+ curAlpha = 1.0;
+ else
+ curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0);
+ destColor.rgb = curColor.rgb * curAlpha;
+ totalAlpha = curAlpha;
}
if (secondD <= tFar && totalAlpha < 1.0) {
highp vec3 secondTex = rayStart + rayDir * secondD;
secondTex = 0.5 * (secondTex + 1.0);
- highp vec4 secondColor = texture3D(textureSampler, secondTex);
+ curColor = texture3D(textureSampler, secondTex);
if (color8Bit != 0)
- secondColor = colorIndex[int(secondColor.r * 255.0)];
- if (secondColor.a > alphaThreshold) {
- curRgb = secondColor.rgb * secondColor.a * (1.0 - totalAlpha);
+ curColor = colorIndex[int(curColor.r * 255.0)];
+ if (curColor.a > alphaThreshold) {
+ if (curColor.a == 1.0 && preserveOpacity != 0)
+ curAlpha = 1.0;
+ else
+ curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0);
+ curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha);
destColor.rgb += curRgb;
- totalAlpha += secondColor.a;
+ totalAlpha += curAlpha;
}
if (thirdD <= tFar && totalAlpha < 1.0) {
highp vec3 thirdTex = rayStart + rayDir * thirdD;
thirdTex = 0.5 * (thirdTex + 1.0);
- highp vec4 thirdColor = texture3D(textureSampler, thirdTex);
- if (color8Bit != 0)
- thirdColor = colorIndex[int(thirdColor.r * 255.0)];
- if (thirdColor.a > alphaThreshold) {
- curRgb = thirdColor.rgb * thirdColor.a * (1.0 - totalAlpha);
+ curColor = texture3D(textureSampler, thirdTex);
+ if (curColor.a > alphaThreshold) {
+ if (color8Bit != 0)
+ curColor = colorIndex[int(curColor.r * 255.0)];
+ if (curColor.a == 1.0 && preserveOpacity != 0)
+ curAlpha = 1.0;
+ else
+ curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0);
+ curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha);
destColor.rgb += curRgb;
- totalAlpha += thirdColor.a;
+ totalAlpha += curAlpha;
}
}
}
}
+
+ // Brighten up the final color if there is some transparency left
+ if (totalAlpha > alphaThreshold && totalAlpha < 1.0)
+ destColor *= 1.0 / totalAlpha;
+
destColor.a = totalAlpha;
gl_FragColor = clamp(destColor, 0.0, 1.0);
}
diff --git a/src/datavisualization/utils/shaderhelper.cpp b/src/datavisualization/utils/shaderhelper.cpp
index 3361638a..9d1ad0d9 100644
--- a/src/datavisualization/utils/shaderhelper.cpp
+++ b/src/datavisualization/utils/shaderhelper.cpp
@@ -99,6 +99,8 @@ void ShaderHelper::initialize()
m_color8BitUniform = m_program->uniformLocation("color8Bit");
m_textureDimensionsUniform = m_program->uniformLocation("textureDimensions");
m_sampleCountUniform = m_program->uniformLocation("sampleCount");
+ m_alphaMultiplierUniform = m_program->uniformLocation("alphaMultiplier");
+ m_preserveOpacityUniform = m_program->uniformLocation("preserveOpacity");
m_initialized = true;
}
@@ -308,6 +310,20 @@ GLuint ShaderHelper::sampleCount()
return m_sampleCountUniform;
}
+GLuint ShaderHelper::alphaMultiplier()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_alphaMultiplierUniform;
+}
+
+GLuint ShaderHelper::preserveOpacity()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_preserveOpacityUniform;
+}
+
GLuint ShaderHelper::posAtt()
{
if (!m_initialized)
diff --git a/src/datavisualization/utils/shaderhelper_p.h b/src/datavisualization/utils/shaderhelper_p.h
index bc7609bb..ac815447 100644
--- a/src/datavisualization/utils/shaderhelper_p.h
+++ b/src/datavisualization/utils/shaderhelper_p.h
@@ -80,6 +80,8 @@ class ShaderHelper
GLuint color8Bit();
GLuint textureDimensions();
GLuint sampleCount();
+ GLuint alphaMultiplier();
+ GLuint preserveOpacity();
GLuint posAtt();
GLuint uvAtt();
@@ -120,6 +122,8 @@ class ShaderHelper
GLuint m_color8BitUniform;
GLuint m_textureDimensionsUniform;
GLuint m_sampleCountUniform;
+ GLuint m_alphaMultiplierUniform;
+ GLuint m_preserveOpacityUniform;
GLboolean m_initialized;
};