summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMika Salmela <mika.salmela@digia.com>2014-07-04 09:58:12 +0300
committerMika Salmela <mika.salmela@digia.com>2014-07-04 10:03:13 +0300
commit6e4fb232702fa128b5efa3eef5dfaff4870a9fd0 (patch)
tree315abbc95d09a558e3eb47c757c06fe66ce3c236 /src
parent6264a2ff1518d374e6150bf584f2ad3d133457dd (diff)
Texture to surface
API for setting a texture to surface. Task-number: QTRD-3232 Change-Id: Icd9de61882b54b9c1fc84a742e49980926ca681d Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/datavisualization/data/qsurface3dseries.cpp55
-rw-r--r--src/datavisualization/data/qsurface3dseries.h9
-rw-r--r--src/datavisualization/data/qsurface3dseries_p.h3
-rw-r--r--src/datavisualization/engine/engine.qrc2
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp4
-rw-r--r--src/datavisualization/engine/shaders/surfaceFlat.vert3
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowFlat.vert3
-rw-r--r--src/datavisualization/engine/shaders/surfaceTexturedFlat.frag39
-rw-r--r--src/datavisualization/engine/shaders/surfaceTexturedShadowFlat.frag72
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp19
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h7
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp112
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h3
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache.cpp7
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache_p.h3
-rw-r--r--src/datavisualization/utils/abstractobjecthelper_p.h2
-rw-r--r--src/datavisualization/utils/surfaceobject.cpp87
-rw-r--r--src/datavisualization/utils/surfaceobject_p.h6
18 files changed, 407 insertions, 29 deletions
diff --git a/src/datavisualization/data/qsurface3dseries.cpp b/src/datavisualization/data/qsurface3dseries.cpp
index 1107d721..bcfc4042 100644
--- a/src/datavisualization/data/qsurface3dseries.cpp
+++ b/src/datavisualization/data/qsurface3dseries.cpp
@@ -300,6 +300,54 @@ QSurface3DSeries::DrawFlags QSurface3DSeries::drawMode() const
}
/*!
+ * Set the \a texture as a QImage for the surface. To clear the texture, set empty
+ * QImage as texture.
+ */
+void QSurface3DSeries::setTexture(const QImage &texture)
+{
+ if (dptr()->m_texture != texture) {
+ dptr()->setTexture(texture);
+
+ emit textureChanged(texture);
+ dptr()->m_textureFile.clear();
+ }
+}
+
+QImage QSurface3DSeries::texture() const
+{
+ return dptrc()->m_texture;
+}
+
+/*! \property QSurface3DSeries::textureFile
+ *
+ * Holds the texture file name for the surface texture. To clear the texture, set empty
+ * file name.
+ */
+void QSurface3DSeries::setTextureFile(const QString &filename)
+{
+ if (dptr()->m_textureFile != filename) {
+ if (filename.isEmpty()) {
+ setTexture(QImage());
+ } else {
+ QImage image(filename);
+ if (image.isNull()) {
+ qWarning() << "Warning: Tried to set invalid image file as surface texture.";
+ return;
+ }
+ setTexture(image);
+ }
+
+ dptr()->m_textureFile = filename;
+ emit textureFileChanged(filename);
+ }
+}
+
+QString QSurface3DSeries::textureFile() const
+{
+ return dptrc()->m_textureFile;
+}
+
+/*!
* \internal
*/
QSurface3DSeriesPrivate *QSurface3DSeries::dptr()
@@ -445,4 +493,11 @@ void QSurface3DSeriesPrivate::setDrawMode(QSurface3DSeries::DrawFlags mode)
}
}
+void QSurface3DSeriesPrivate::setTexture(const QImage &texture)
+{
+ m_texture = texture;
+ if (static_cast<Surface3DController *>(m_controller))
+ static_cast<Surface3DController *>(m_controller)->updateSurfaceTexture(qptr());
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/data/qsurface3dseries.h b/src/datavisualization/data/qsurface3dseries.h
index 64df7202..7051e583 100644
--- a/src/datavisualization/data/qsurface3dseries.h
+++ b/src/datavisualization/data/qsurface3dseries.h
@@ -35,6 +35,8 @@ class QT_DATAVISUALIZATION_EXPORT QSurface3DSeries : public QAbstract3DSeries
Q_PROPERTY(bool flatShadingEnabled READ isFlatShadingEnabled WRITE setFlatShadingEnabled NOTIFY flatShadingEnabledChanged)
Q_PROPERTY(bool flatShadingSupported READ isFlatShadingSupported NOTIFY flatShadingSupportedChanged)
Q_PROPERTY(DrawFlags drawMode READ drawMode WRITE setDrawMode NOTIFY drawModeChanged)
+ Q_PROPERTY(QImage texture READ texture WRITE setTexture NOTIFY textureChanged)
+ Q_PROPERTY(QString textureFile READ textureFile WRITE setTextureFile NOTIFY textureFileChanged)
public:
enum DrawFlag {
@@ -63,12 +65,19 @@ public:
bool isFlatShadingSupported() const;
+ void setTexture(const QImage &texture);
+ QImage texture() const;
+ void setTextureFile(const QString &filename);
+ QString textureFile() const;
+
signals:
void dataProxyChanged(QSurfaceDataProxy *proxy);
void selectedPointChanged(const QPoint &position);
void flatShadingEnabledChanged(bool enable);
void flatShadingSupportedChanged(bool enable);
void drawModeChanged(QSurface3DSeries::DrawFlags mode);
+ void textureChanged(const QImage &image);
+ void textureFileChanged(const QString &filename);
protected:
explicit QSurface3DSeries(QSurface3DSeriesPrivate *d, QObject *parent = 0);
diff --git a/src/datavisualization/data/qsurface3dseries_p.h b/src/datavisualization/data/qsurface3dseries_p.h
index d4cc2820..270a3ad1 100644
--- a/src/datavisualization/data/qsurface3dseries_p.h
+++ b/src/datavisualization/data/qsurface3dseries_p.h
@@ -48,6 +48,7 @@ public:
void setSelectedPoint(const QPoint &position);
void setFlatShadingEnabled(bool enabled);
void setDrawMode(QSurface3DSeries::DrawFlags mode);
+ void setTexture(const QImage &texture);
private:
QSurface3DSeries *qptr();
@@ -55,6 +56,8 @@ private:
QPoint m_selectedPoint;
bool m_flatShadingEnabled;
QSurface3DSeries::DrawFlags m_drawMode;
+ QImage m_texture;
+ QString m_textureFile;
private:
friend class QSurface3DSeries;
diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc
index 673b6ee0..f788b5df 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -57,5 +57,7 @@
<file alias="fragmentTexture">shaders/texture.frag</file>
<file alias="fragmentTextureES2">shaders/texture_ES2.frag</file>
<file alias="vertexTexture">shaders/texture.vert</file>
+ <file alias="fragmentTexturedSurfaceShadowFlat">shaders/surfaceTexturedShadowFlat.frag</file>
+ <file alias="fragmentSurfaceTexturedFlat">shaders/surfaceTexturedFlat.frag</file>
</qresource>
</RCC>
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index 65719b15..5f8eede9 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -2062,10 +2062,10 @@ void Scatter3DRenderer::calculateSceneScalingFactors()
m_axisCacheX.setScale(m_scaleX * 2.0f);
m_axisCacheY.setScale(m_scaleY * 2.0f);
- m_axisCacheZ.setScale(m_scaleZ * 2.0f);
+ m_axisCacheZ.setScale(-m_scaleZ * 2.0f);
m_axisCacheX.setTranslate(-m_scaleX);
m_axisCacheY.setTranslate(-m_scaleY);
- m_axisCacheZ.setTranslate(-m_scaleZ);
+ m_axisCacheZ.setTranslate(m_scaleZ);
}
void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
diff --git a/src/datavisualization/engine/shaders/surfaceFlat.vert b/src/datavisualization/engine/shaders/surfaceFlat.vert
index 102bea78..0f953f4c 100644
--- a/src/datavisualization/engine/shaders/surfaceFlat.vert
+++ b/src/datavisualization/engine/shaders/surfaceFlat.vert
@@ -4,6 +4,7 @@
attribute highp vec3 vertexPosition_mdl;
attribute highp vec3 vertexNormal_mdl;
+attribute highp vec2 vertexUV;
uniform highp mat4 MVP;
uniform highp mat4 V;
@@ -11,6 +12,7 @@ uniform highp mat4 M;
uniform highp mat4 itM;
uniform highp vec3 lightPosition_wrld;
+varying highp vec2 UV;
varying highp vec3 position_wrld;
flat varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -26,4 +28,5 @@ void main() {
vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz;
lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ UV = vertexUV;
}
diff --git a/src/datavisualization/engine/shaders/surfaceShadowFlat.vert b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
index 8da7b196..d80e062e 100644
--- a/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
+++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
@@ -4,6 +4,7 @@
attribute highp vec3 vertexPosition_mdl;
attribute highp vec3 vertexNormal_mdl;
+attribute highp vec2 vertexUV;
uniform highp mat4 MVP;
uniform highp mat4 V;
@@ -12,6 +13,7 @@ uniform highp mat4 itM;
uniform highp mat4 depthMVP;
uniform highp vec3 lightPosition_wrld;
+varying highp vec2 UV;
varying highp vec3 position_wrld;
flat varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -34,4 +36,5 @@ void main() {
vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz;
lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ UV = vertexUV;
}
diff --git a/src/datavisualization/engine/shaders/surfaceTexturedFlat.frag b/src/datavisualization/engine/shaders/surfaceTexturedFlat.frag
new file mode 100644
index 00000000..7c654e0c
--- /dev/null
+++ b/src/datavisualization/engine/shaders/surfaceTexturedFlat.frag
@@ -0,0 +1,39 @@
+#version 120
+
+#extension GL_EXT_gpu_shader4 : require
+
+varying highp vec3 coords_mdl;
+varying highp vec3 position_wrld;
+flat varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+varying highp vec2 UV;
+
+uniform sampler2D textureSampler;
+uniform highp vec3 lightPosition_wrld;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp vec4 lightColor;
+
+void main() {
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).xyz;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
+
+ highp float distance = length(lightPosition_wrld - position_wrld);
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
+
+ gl_FragColor.rgb =
+ materialAmbientColor +
+ materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance +
+ materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance;
+ gl_FragColor.a = 1.0;
+}
+
diff --git a/src/datavisualization/engine/shaders/surfaceTexturedShadowFlat.frag b/src/datavisualization/engine/shaders/surfaceTexturedShadowFlat.frag
new file mode 100644
index 00000000..421fe342
--- /dev/null
+++ b/src/datavisualization/engine/shaders/surfaceTexturedShadowFlat.frag
@@ -0,0 +1,72 @@
+#version 120
+
+#extension GL_EXT_gpu_shader4 : require
+
+varying highp vec3 coords_mdl;
+varying highp vec3 position_wrld;
+flat varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+varying highp vec2 UV;
+
+uniform highp sampler2DShadow shadowMap;
+uniform sampler2D textureSampler;
+varying highp vec4 shadowCoord;
+uniform highp vec3 lightPosition_wrld;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp float shadowQuality;
+uniform highp vec4 lightColor;
+
+highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
+ vec2(0.94558609, -0.76890725),
+ vec2(-0.094184101, -0.92938870),
+ vec2(0.34495938, 0.29387760),
+ vec2(-0.91588581, 0.45771432),
+ vec2(-0.81544232, -0.87912464),
+ vec2(-0.38277543, 0.27676845),
+ vec2(0.97484398, 0.75648379),
+ vec2(0.44323325, -0.97511554),
+ vec2(0.53742981, -0.47373420),
+ vec2(-0.26496911, -0.41893023),
+ vec2(0.79197514, 0.19090188),
+ vec2(-0.24188840, 0.99706507),
+ vec2(-0.81409955, 0.91437590),
+ vec2(0.19984126, 0.78641367),
+ vec2(0.14383161, -0.14100790));
+
+void main() {
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).xyz;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
+
+ highp float bias = 0.005 * tan(acos(cosTheta));
+ bias = clamp(bias, 0.0, 0.01);
+
+ vec4 shadCoords = shadowCoord;
+ shadCoords.z -= bias;
+
+ highp float visibility = 0.6;
+ for (int i = 0; i < 15; i++) {
+ vec4 shadCoordsPD = shadCoords;
+ shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality;
+ shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality;
+ visibility += 0.025 * shadow2DProj(shadowMap, shadCoordsPD).r;
+ }
+
+ gl_FragColor.rgb =
+ (materialAmbientColor +
+ materialDiffuseColor * lightStrength * cosTheta +
+ materialSpecularColor * lightStrength * pow(cosAlpha, 10));
+ gl_FragColor.a = 1.0;
+ gl_FragColor.rgb = visibility * clamp(gl_FragColor.rgb, 0.0, 1.0);
+}
+
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index 5293cb0c..a6c086da 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -85,6 +85,12 @@ void Surface3DController::synchDataToRenderer()
m_renderer->updateFlipHorizontalGrid(m_flipHorizontalGrid);
m_changeTracker.flipHorizontalGridChanged = false;
}
+
+ if (m_changeTracker.surfaceTextureChanged) {
+ m_renderer->updateSurfaceTextures(m_changedTextures);
+ m_changeTracker.surfaceTextureChanged = false;
+ m_changedTextures.clear();
+ }
}
void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(
@@ -146,6 +152,9 @@ void Surface3DController::addSeries(QAbstract3DSeries *series)
QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
if (surfaceSeries->selectedPoint() != invalidSelectionPosition())
setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries, false);
+
+ if (!surfaceSeries->texture().isNull())
+ updateSurfaceTexture(surfaceSeries);
}
void Surface3DController::removeSeries(QAbstract3DSeries *series)
@@ -450,6 +459,16 @@ void Surface3DController::handleRowsRemoved(int startIndex, int count)
emitNeedRender();
}
+void Surface3DController::updateSurfaceTexture(QSurface3DSeries *series)
+{
+ m_changeTracker.surfaceTextureChanged = true;
+
+ if (!m_changedTextures.contains(series))
+ m_changedTextures.append(series);
+
+ emitNeedRender();
+}
+
void Surface3DController::adjustAxisRanges()
{
QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX);
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index 653f41c3..8bcdea91 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -42,12 +42,14 @@ struct Surface3DChangeBitField {
bool rowsChanged : 1;
bool itemChanged : 1;
bool flipHorizontalGridChanged : 1;
+ bool surfaceTextureChanged : 1;
Surface3DChangeBitField() :
selectedPointChanged(true),
rowsChanged(false),
itemChanged(false),
- flipHorizontalGridChanged(true)
+ flipHorizontalGridChanged(true),
+ surfaceTextureChanged(true)
{
}
};
@@ -76,6 +78,7 @@ private:
QVector<ChangeItem> m_changedItems;
QVector<ChangeRow> m_changedRows;
bool m_flipHorizontalGrid;
+ QVector<QSurface3DSeries *> m_changedTextures;
public:
explicit Surface3DController(QRect rect, Q3DScene *scene = 0);
@@ -107,6 +110,8 @@ public:
void setFlipHorizontalGrid(bool flip);
bool flipHorizontalGrid() const;
+ void updateSurfaceTexture(QSurface3DSeries *series);
+
public slots:
void handleArrayReset();
void handleRowsAdded(int startIndex, int count);
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index f5f05498..a30239f7 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -43,6 +43,8 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_backgroundShader(0),
m_surfaceFlatShader(0),
m_surfaceSmoothShader(0),
+ m_surfaceTexturedSmoothShader(0),
+ m_surfaceTexturedFlatShader(0),
m_surfaceGridShader(0),
m_surfaceSliceFlatShader(0),
m_surfaceSliceSmoothShader(0),
@@ -104,6 +106,8 @@ Surface3DRenderer::~Surface3DRenderer()
delete m_selectionShader;
delete m_surfaceFlatShader;
delete m_surfaceSmoothShader;
+ delete m_surfaceTexturedSmoothShader;
+ delete m_surfaceTexturedFlatShader;
delete m_surfaceGridShader;
delete m_surfaceSliceFlatShader;
delete m_surfaceSliceSmoothShader;
@@ -257,6 +261,33 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis
}
}
+void Surface3DRenderer::updateSurfaceTextures(QVector<QSurface3DSeries *> seriesList)
+{
+ foreach (QSurface3DSeries *series, seriesList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(m_renderCacheList.value(series));
+ if (cache) {
+ GLuint oldTexture = cache->surfaceTexture();
+ m_textureHelper->deleteTexture(&oldTexture);
+ cache->setSurfaceTexture(0);
+
+ const QSurface3DSeries *currentSeries = cache->series();
+ QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
+ const QSurfaceDataArray &array = *dataProxy->array();
+
+ if (!series->texture().isNull()) {
+ cache->setSurfaceTexture(m_textureHelper->create2DTexture(
+ series->texture(), true, true, true));
+
+ if (cache->isFlatShadingEnabled())
+ cache->surfaceObject()->coarseUVs(array, cache->dataArray());
+ else
+ cache->surfaceObject()->smoothUVs(array, cache->dataArray());
+ }
+ }
+ }
+}
+
SeriesRenderCache *Surface3DRenderer::createNewCache(QAbstract3DSeries *series)
{
m_selectionTexturesDirty = true;
@@ -1191,6 +1222,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glCullFace(GL_BACK);
}
#endif
+
// Draw selection buffer
if (!m_cachedIsSlicingActivated && (!m_renderCacheList.isEmpty()
|| !m_customRenderCache.isEmpty())
@@ -1220,6 +1252,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
MVPMatrix = projectionViewMatrix * modelMatrix;
m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
+ cache->surfaceObject()->activateSurfaceTexture(false);
+
m_drawer->drawObject(m_selectionShader, cache->surfaceObject(),
cache->selectionTexture());
}
@@ -1285,8 +1319,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
if (cache->surfaceVisible()) {
ShaderHelper *shader = m_surfaceFlatShader;
- if (!cache->isFlatShadingEnabled())
+ if (cache->surfaceTexture())
+ shader = m_surfaceTexturedFlatShader;
+ if (!cache->isFlatShadingEnabled()) {
shader = m_surfaceSmoothShader;
+ if (cache->surfaceTexture())
+ shader = m_surfaceTexturedSmoothShader;
+ }
shader->bind();
// Set shader bindings
@@ -1300,23 +1339,30 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_cachedTheme->ambientLightStrength());
shader->setUniformValue(shader->lightColor(), lightColor);
- GLuint gradientTexture;
- if (cache->colorStyle() == Q3DTheme::ColorStyleUniform) {
- gradientTexture = cache->baseUniformTexture();
- shader->setUniformValue(shader->gradientMin(), 0.0f);
- shader->setUniformValue(shader->gradientHeight(), 0.0f);
+ // Set the surface texturing
+ cache->surfaceObject()->activateSurfaceTexture(false);
+ GLuint texture;
+ if (cache->surfaceTexture()) {
+ texture = cache->surfaceTexture();
+ cache->surfaceObject()->activateSurfaceTexture(true);
} else {
- gradientTexture = cache->baseGradientTexture();
- if (cache->colorStyle() == Q3DTheme::ColorStyleObjectGradient) {
- float objMin = cache->surfaceObject()->minYValue();
- float objMax = cache->surfaceObject()->maxYValue();
- float objRange = objMax - objMin;
- shader->setUniformValue(shader->gradientMin(), -(objMin / objRange));
- shader->setUniformValue(shader->gradientHeight(), 1.0f / objRange);
+ if (cache->colorStyle() == Q3DTheme::ColorStyleUniform) {
+ texture = cache->baseUniformTexture();
+ shader->setUniformValue(shader->gradientMin(), 0.0f);
+ shader->setUniformValue(shader->gradientHeight(), 0.0f);
} else {
- shader->setUniformValue(shader->gradientMin(), 0.5f);
- shader->setUniformValue(shader->gradientHeight(),
- 1.0f / (m_scaleY * 2.0f));
+ texture = cache->baseGradientTexture();
+ if (cache->colorStyle() == Q3DTheme::ColorStyleObjectGradient) {
+ float objMin = cache->surfaceObject()->minYValue();
+ float objMax = cache->surfaceObject()->maxYValue();
+ float objRange = objMax - objMin;
+ shader->setUniformValue(shader->gradientMin(), -(objMin / objRange));
+ shader->setUniformValue(shader->gradientHeight(), 1.0f / objRange);
+ } else {
+ shader->setUniformValue(shader->gradientMin(), 0.5f);
+ shader->setUniformValue(shader->gradientHeight(),
+ 1.0f / (m_scaleY * 2.0f));
+ }
}
}
@@ -1329,7 +1375,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
shader->setUniformValue(shader->lightS(), adjustedLightStrength);
// Draw the objects
- m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture,
+ m_drawer->drawObject(shader, cache->surfaceObject(), texture,
m_depthModelTexture);
} else
#endif
@@ -1339,7 +1385,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_cachedTheme->lightStrength());
// Draw the objects
- m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture);
+ m_drawer->drawObject(shader, cache->surfaceObject(), texture);
}
}
}
@@ -2448,10 +2494,10 @@ void Surface3DRenderer::calculateSceneScalingFactors()
m_axisCacheX.setScale(m_scaleX * 2.0f);
m_axisCacheY.setScale(m_scaleY * 2.0f);
- m_axisCacheZ.setScale(m_scaleZ * 2.0f);
+ m_axisCacheZ.setScale(-m_scaleZ * 2.0f);
m_axisCacheX.setTranslate(-m_scaleX);
m_axisCacheY.setTranslate(-m_scaleY);
- m_axisCacheZ.setTranslate(-m_scaleZ);
+ m_axisCacheZ.setTranslate(m_scaleZ);
}
void Surface3DRenderer::checkFlatSupport(SurfaceSeriesRenderCache *cache)
@@ -2470,11 +2516,19 @@ void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dime
QSurfaceDataArray &dataArray = cache->dataArray();
const QRect &sampleSpace = cache->sampleSpace();
+ const QSurface3DSeries *currentSeries = cache->series();
+ QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
+ const QSurfaceDataArray &array = *dataProxy->array();
+
if (cache->isFlatShadingEnabled()) {
cache->surfaceObject()->setUpData(dataArray, sampleSpace, dimensionChanged, m_polarGraph);
+ if (cache->surfaceTexture())
+ cache->surfaceObject()->coarseUVs(array, dataArray);
} else {
cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, dimensionChanged,
m_polarGraph);
+ if (cache->surfaceTexture())
+ cache->surfaceObject()->smoothUVs(array, dataArray);
}
}
@@ -2736,6 +2790,10 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
delete m_surfaceFlatShader;
if (m_surfaceSmoothShader)
delete m_surfaceSmoothShader;
+ if (m_surfaceTexturedSmoothShader)
+ delete m_surfaceTexturedSmoothShader;
+ if (m_surfaceTexturedFlatShader)
+ delete m_surfaceTexturedFlatShader;
if (m_surfaceSliceFlatShader)
delete m_surfaceSliceFlatShader;
if (m_surfaceSliceSmoothShader)
@@ -2745,9 +2803,13 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex"));
+ m_surfaceTexturedSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadow"));
} else {
m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurface"));
+ m_surfaceTexturedSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexTexture"),
+ QStringLiteral(":/shaders/fragmentTexture"));
}
m_surfaceSliceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurface"));
@@ -2755,9 +2817,13 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
QStringLiteral(":/shaders/fragmentSurfaceShadowFlat"));
+ m_surfaceTexturedFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
+ QStringLiteral(":/shaders/fragmentTexturedSurfaceShadowFlat"));
} else {
m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ m_surfaceTexturedFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceTexturedFlat"));
}
m_surfaceSliceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
@@ -2770,6 +2836,10 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
QStringLiteral(":/shaders/fragmentSurfaceES2"));
m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurfaceES2"));
+ m_surfaceTexturedSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexTexture"),
+ QStringLiteral(":/shaders/fragmentTextureES2"));
+ m_surfaceTexturedFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexTexture"),
+ QStringLiteral(":/shaders/fragmentTextureES2"));
m_surfaceSliceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurfaceES2"));
m_surfaceSliceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
@@ -2777,9 +2847,11 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
#endif
m_surfaceSmoothShader->initialize();
m_surfaceSliceSmoothShader->initialize();
+ m_surfaceTexturedSmoothShader->initialize();
if (m_flatSupported) {
m_surfaceFlatShader->initialize();
m_surfaceSliceFlatShader->initialize();
+ m_surfaceTexturedFlatShader->initialize();
}
}
diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h
index cb9c49c3..c276c1f9 100644
--- a/src/datavisualization/engine/surface3drenderer_p.h
+++ b/src/datavisualization/engine/surface3drenderer_p.h
@@ -51,6 +51,8 @@ private:
ShaderHelper *m_backgroundShader;
ShaderHelper *m_surfaceFlatShader;
ShaderHelper *m_surfaceSmoothShader;
+ ShaderHelper *m_surfaceTexturedSmoothShader;
+ ShaderHelper *m_surfaceTexturedFlatShader;
ShaderHelper *m_surfaceGridShader;
ShaderHelper *m_surfaceSliceFlatShader;
ShaderHelper *m_surfaceSliceSmoothShader;
@@ -87,6 +89,7 @@ public:
void updateData();
void updateSeries(const QList<QAbstract3DSeries *> &seriesList);
+ void updateSurfaceTextures(QVector<QSurface3DSeries *> seriesList);
SeriesRenderCache *createNewCache(QAbstract3DSeries *series);
void cleanCache(SeriesRenderCache *cache);
void updateSelectionMode(QAbstract3DGraph::SelectionFlags mode);
diff --git a/src/datavisualization/engine/surfaceseriesrendercache.cpp b/src/datavisualization/engine/surfaceseriesrendercache.cpp
index 1cce5288..f1ad752a 100644
--- a/src/datavisualization/engine/surfaceseriesrendercache.cpp
+++ b/src/datavisualization/engine/surfaceseriesrendercache.cpp
@@ -39,7 +39,8 @@ SurfaceSeriesRenderCache::SurfaceSeriesRenderCache(QAbstract3DSeries *series,
m_sliceSelectionPointer(0),
m_mainSelectionPointer(0),
m_slicePointerActive(false),
- m_mainPointerActive(false)
+ m_mainPointerActive(false),
+ m_surfaceTexture(0)
{
}
@@ -62,8 +63,10 @@ void SurfaceSeriesRenderCache::populate(bool newSeries)
void SurfaceSeriesRenderCache::cleanup(TextureHelper *texHelper)
{
- if (QOpenGLContext::currentContext())
+ if (QOpenGLContext::currentContext()) {
texHelper->deleteTexture(&m_selectionTexture);
+ texHelper->deleteTexture(&m_surfaceTexture);
+ }
delete m_surfaceObj;
delete m_sliceSurfaceObj;
diff --git a/src/datavisualization/engine/surfaceseriesrendercache_p.h b/src/datavisualization/engine/surfaceseriesrendercache_p.h
index b6254a75..4d04149f 100644
--- a/src/datavisualization/engine/surfaceseriesrendercache_p.h
+++ b/src/datavisualization/engine/surfaceseriesrendercache_p.h
@@ -85,6 +85,8 @@ public:
inline bool slicePointerActive() const { return m_slicePointerActive; }
inline void setMainPointerActivity(bool activity) { m_mainPointerActive = activity; }
inline bool mainPointerActive() const { return m_mainPointerActive; }
+ inline void setSurfaceTexture(GLuint texture) { m_surfaceTexture = texture; }
+ inline GLuint surfaceTexture() const { return m_surfaceTexture; }
protected:
bool m_surfaceVisible;
@@ -105,6 +107,7 @@ protected:
SelectionPointer *m_mainSelectionPointer;
bool m_slicePointerActive;
bool m_mainPointerActive;
+ GLuint m_surfaceTexture;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/utils/abstractobjecthelper_p.h b/src/datavisualization/utils/abstractobjecthelper_p.h
index c1618909..b12bc474 100644
--- a/src/datavisualization/utils/abstractobjecthelper_p.h
+++ b/src/datavisualization/utils/abstractobjecthelper_p.h
@@ -42,7 +42,7 @@ public:
GLuint vertexBuf();
GLuint normalBuf();
- GLuint uvBuf();
+ virtual GLuint uvBuf();
GLuint elementBuf();
GLuint indexCount();
GLuint indicesType();
diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp
index a98f2f2a..f8dae6f4 100644
--- a/src/datavisualization/utils/surfaceobject.cpp
+++ b/src/datavisualization/utils/surfaceobject.cpp
@@ -31,8 +31,8 @@ SurfaceObject::SurfaceObject(Surface3DRenderer *renderer)
m_axisCacheX(renderer->m_axisCacheX),
m_axisCacheY(renderer->m_axisCacheY),
m_axisCacheZ(renderer->m_axisCacheZ),
- m_renderer(renderer)
-
+ m_renderer(renderer),
+ m_returnTextureBuffer(false)
{
m_indicesType = GL_UNSIGNED_INT;
initializeOpenGLFunctions();
@@ -41,12 +41,15 @@ SurfaceObject::SurfaceObject(Surface3DRenderer *renderer)
glGenBuffers(1, &m_uvbuffer);
glGenBuffers(1, &m_elementbuffer);
glGenBuffers(1, &m_gridElementbuffer);
+ glGenBuffers(1, &m_uvTextureBuffer);
}
SurfaceObject::~SurfaceObject()
{
- if (QOpenGLContext::currentContext())
+ if (QOpenGLContext::currentContext()) {
glDeleteBuffers(1, &m_gridElementbuffer);
+ glDeleteBuffers(1, &m_uvTextureBuffer);
+ }
}
void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space,
@@ -135,6 +138,37 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR
createBuffers(m_vertices, uvs, m_normals, 0, changeGeometry);
}
+void SurfaceObject::smoothUVs(const QSurfaceDataArray &dataArray,
+ const QSurfaceDataArray &modelArray)
+{
+ int columns = dataArray.at(0)->size();
+ int rows = dataArray.size();
+ float xRangeNormalizer = dataArray.at(0)->at(columns - 1).x() - dataArray.at(0)->at(0).x();
+ float zRangeNormalizer = dataArray.at(rows - 1)->at(0).z() - dataArray.at(0)->at(0).z();
+ float xMin = dataArray.at(0)->at(0).x();
+ float zMin = dataArray.at(0)->at(0).z();
+
+ QVector<QVector2D> uvs;
+ uvs.resize(m_rows * m_columns);
+ int index = 0;
+ for (int i = 0; i < m_rows; i++) {
+ float y = (modelArray.at(i)->at(0).z() - zMin) / zRangeNormalizer;
+ const QSurfaceDataRow &p = *modelArray.at(i);
+ for (int j = 0; j < m_columns; j++) {
+ float x = (p.at(j).x() - xMin) / xRangeNormalizer;
+ uvs[index] = QVector2D(x, y);
+ index++;
+ }
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvTextureBuffer);
+ glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D),
+ &uvs.at(0), GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_returnTextureBuffer = true;
+}
+
void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar)
{
// Update vertices
@@ -426,6 +460,42 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s
delete[] indices;
}
+void SurfaceObject::coarseUVs(const QSurfaceDataArray &dataArray,
+ const QSurfaceDataArray &modelArray)
+{
+ int columns = dataArray.at(0)->size();
+ int rows = dataArray.size();
+ float xRangeNormalizer = dataArray.at(0)->at(columns - 1).x() - dataArray.at(0)->at(0).x();
+ float zRangeNormalizer = dataArray.at(rows - 1)->at(0).z() - dataArray.at(0)->at(0).z();
+ float xMin = dataArray.at(0)->at(0).x();
+ float zMin = dataArray.at(0)->at(0).z();
+
+ QVector<QVector2D> uvs;
+ uvs.resize(m_rows * m_columns * 2);
+ int index = 0;
+ int colLimit = m_columns - 1;
+ for (int i = 0; i < m_rows; i++) {
+ float y = (modelArray.at(i)->at(0).z() - zMin) / zRangeNormalizer;
+ const QSurfaceDataRow &p = *modelArray.at(i);
+ for (int j = 0; j < m_columns; j++) {
+ float x = (p.at(j).x() - xMin) / xRangeNormalizer;
+ uvs[index] = QVector2D(x, y);
+ index++;
+ if (j > 0 && j < colLimit) {
+ uvs[index] = uvs[index - 1];
+ index++;
+ }
+ }
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_uvTextureBuffer);
+ glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D),
+ &uvs.at(0), GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_returnTextureBuffer = true;
+}
+
void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar)
{
int colLimit = m_columns - 1;
@@ -684,6 +754,17 @@ GLuint SurfaceObject::gridElementBuf()
return m_gridElementbuffer;
}
+GLuint SurfaceObject::uvBuf()
+{
+ if (!m_meshDataLoaded)
+ qFatal("No loaded object");
+
+ if (m_returnTextureBuffer)
+ return m_uvTextureBuffer;
+ else
+ return m_uvbuffer;
+}
+
GLuint SurfaceObject::gridIndexCount()
{
return m_gridIndexCount;
diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h
index b3ba80e9..3266c626 100644
--- a/src/datavisualization/utils/surfaceobject_p.h
+++ b/src/datavisualization/utils/surfaceobject_p.h
@@ -57,6 +57,8 @@ public:
bool changeGeometry, bool polar, bool flipXZ = false);
void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space,
bool changeGeometry, bool polar, bool flipXZ = false);
+ void smoothUVs(const QSurfaceDataArray &dataArray, const QSurfaceDataArray &modelArray);
+ void coarseUVs(const QSurfaceDataArray &dataArray, const QSurfaceDataArray &modelArray);
void updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar);
void updateSmoothRow(const QSurfaceDataArray &dataArray, int startRow, bool polar);
void updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column, bool polar);
@@ -67,11 +69,13 @@ public:
void createCoarseGridlineIndices(int x, int y, int endX, int endY);
void uploadBuffers();
GLuint gridElementBuf();
+ GLuint uvBuf();
GLuint gridIndexCount();
QVector3D vertexAt(int column, int row);
void clear();
float minYValue() const { return m_minY; }
float maxYValue() const { return m_maxY; }
+ inline void activateSurfaceTexture(bool value) { m_returnTextureBuffer = value; }
private:
QVector3D normal(const QVector3D &a, const QVector3D &b, const QVector3D &c, bool flipNormal);
@@ -97,6 +101,8 @@ private:
Surface3DRenderer *m_renderer;
float m_minY;
float m_maxY;
+ GLuint m_uvTextureBuffer;
+ bool m_returnTextureBuffer;
};
QT_END_NAMESPACE_DATAVISUALIZATION