diff options
author | Mika Salmela <mika.salmela@digia.com> | 2014-07-04 09:58:12 +0300 |
---|---|---|
committer | Mika Salmela <mika.salmela@digia.com> | 2014-07-04 10:03:13 +0300 |
commit | 6e4fb232702fa128b5efa3eef5dfaff4870a9fd0 (patch) | |
tree | 315abbc95d09a558e3eb47c757c06fe66ce3c236 /src | |
parent | 6264a2ff1518d374e6150bf584f2ad3d133457dd (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')
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 |