diff options
Diffstat (limited to 'src/datavisualization/engine')
-rw-r--r-- | src/datavisualization/engine/abstract3drenderer.cpp | 176 | ||||
-rw-r--r-- | src/datavisualization/engine/abstract3drenderer_p.h | 11 | ||||
-rw-r--r-- | src/datavisualization/engine/bars3drenderer.cpp | 15 | ||||
-rw-r--r-- | src/datavisualization/engine/drawer.cpp | 19 | ||||
-rw-r--r-- | src/datavisualization/engine/drawer_p.h | 2 | ||||
-rw-r--r-- | src/datavisualization/engine/engine.qrc | 3 | ||||
-rw-r--r-- | src/datavisualization/engine/scatter3drenderer.cpp | 19 | ||||
-rw-r--r-- | src/datavisualization/engine/shaders/default.frag | 1 | ||||
-rw-r--r-- | src/datavisualization/engine/shaders/texture3d.frag | 70 | ||||
-rw-r--r-- | src/datavisualization/engine/shaders/texture3d.vert | 12 | ||||
-rw-r--r-- | src/datavisualization/engine/shaders/texture3dslice.frag | 119 | ||||
-rw-r--r-- | src/datavisualization/engine/surface3drenderer.cpp | 23 |
12 files changed, 432 insertions, 38 deletions
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index 14cf7109..cbb90af0 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -24,6 +24,7 @@ #include "shaderhelper_p.h" #include "qcustom3ditem_p.h" #include "qcustom3dlabel_p.h" +#include "qcustom3dvolume_p.h" #include <QtCore/qmath.h> @@ -57,6 +58,8 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_selectionLabelItem(0), m_visibleSeriesCount(0), m_customItemShader(0), + m_volumeTextureShader(0), + m_volumeTextureSliceShader(0), m_useOrthoProjection(false), m_xFlipped(false), m_yFlipped(false), @@ -96,6 +99,8 @@ Abstract3DRenderer::~Abstract3DRenderer() delete m_cachedTheme; delete m_selectionLabelItem; delete m_customItemShader; + delete m_volumeTextureShader; + delete m_volumeTextureSliceShader; foreach (SeriesRenderCache *cache, m_renderCacheList) { cache->cleanup(m_textureHelper); @@ -196,6 +201,20 @@ void Abstract3DRenderer::initCustomItemShaders(const QString &vertexShader, m_customItemShader->initialize(); } +void Abstract3DRenderer::initVolumeTextureShaders(const QString &vertexShader, + const QString &fragmentShader, + const QString &sliceShader) +{ + if (m_volumeTextureShader) + delete m_volumeTextureShader; + m_volumeTextureShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_volumeTextureShader->initialize(); + if (m_volumeTextureSliceShader) + delete m_volumeTextureSliceShader; + m_volumeTextureSliceShader = new ShaderHelper(this, vertexShader, sliceShader); + m_volumeTextureSliceShader->initialize(); +} + void Abstract3DRenderer::updateTheme(Q3DTheme *theme) { // Synchronize the controller theme with renderer @@ -279,6 +298,9 @@ void Abstract3DRenderer::reInitShaders() initCustomItemShaders(QStringLiteral(":/shaders/vertexTexture"), QStringLiteral(":/shaders/fragmentTexture")); } + initVolumeTextureShaders(QStringLiteral(":/shaders/vertexTexture3D"), + QStringLiteral(":/shaders/fragmentTexture3D"), + QStringLiteral(":/shaders/fragmentTexture3DSlice")); #else initGradientShaders(QStringLiteral(":/shaders/vertex"), QStringLiteral(":/shaders/fragmentColorOnYES2")); @@ -906,6 +928,7 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item) QVector3D scaling = item->scaling(); QImage textureImage = item->d_ptr->textureImage(); bool facingCamera = false; + GLuint texture; if (item->d_ptr->m_isLabelItem) { QCustom3DLabel *labelItem = static_cast<QCustom3DLabel *>(item); float pointSize = labelItem->font().pointSizeF(); @@ -925,13 +948,39 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item) scaling.setY(scaling.y() * textureImage.height() * scaledFontSize); // Check if facing camera facingCamera = labelItem->isFacingCamera(); +#if !defined(QT_OPENGL_ES_2) + } else if (item->d_ptr->m_isVolumeItem) { + QCustom3DVolume *volumeItem = static_cast<QCustom3DVolume *>(item); + newItem->setTextureWidth(volumeItem->textureWidth()); + newItem->setTextureHeight(volumeItem->textureHeight()); + newItem->setTextureDepth(volumeItem->textureDepth()); + if (volumeItem->textureFormat() == QImage::Format_Indexed8) + newItem->setColorTable(volumeItem->colorTable()); + newItem->setTextureFormat(volumeItem->textureFormat()); + newItem->setVolume(true); + newItem->setBlendNeeded(true); + texture = m_textureHelper->create3DTexture(volumeItem->textureData(), + volumeItem->textureWidth(), + volumeItem->textureHeight(), + volumeItem->textureDepth(), + volumeItem->textureFormat()); + newItem->setSliceIndexX(volumeItem->sliceIndexX()); + newItem->setSliceIndexY(volumeItem->sliceIndexY()); + newItem->setSliceIndexZ(volumeItem->sliceIndexZ()); +#endif } newItem->setScaling(scaling); newItem->setRotation(item->rotation()); newItem->setPosition(item->position()); newItem->setPositionAbsolute(item->isPositionAbsolute()); - newItem->setBlendNeeded(textureImage.hasAlphaChannel()); - GLuint texture = m_textureHelper->create2DTexture(textureImage, true, true, true); +#if !defined(QT_OPENGL_ES_2) + // In OpenGL ES we simply draw volumes as regular custom item placeholders. + if (!item->d_ptr->m_isVolumeItem) +#endif + { + newItem->setBlendNeeded(textureImage.hasAlphaChannel()); + texture = m_textureHelper->create2DTexture(textureImage, true, true, true); + } newItem->setTexture(texture); item->d_ptr->clearTextureImage(); QVector3D translation = convertPositionToTranslation(item->position(), @@ -996,12 +1045,17 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem) m_cachedTheme->isLabelBorderEnabled()); textureImage = item->d_ptr->textureImage(); } + } else +#if !defined(QT_OPENGL_ES_2) + if (!item->d_ptr->m_isVolumeItem) +#endif + { + renderItem->setBlendNeeded(textureImage.hasAlphaChannel()); + GLuint oldTexture = renderItem->texture(); + m_textureHelper->deleteTexture(&oldTexture); + GLuint texture = m_textureHelper->create2DTexture(textureImage, true, true, true); + renderItem->setTexture(texture); } - renderItem->setBlendNeeded(textureImage.hasAlphaChannel()); - GLuint oldTexture = renderItem->texture(); - m_textureHelper->deleteTexture(&oldTexture); - GLuint texture = m_textureHelper->create2DTexture(textureImage, true, true, true); - renderItem->setTexture(texture); item->d_ptr->clearTextureImage(); item->d_ptr->m_dirtyBits.textureDirty = false; } @@ -1028,6 +1082,39 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem) renderItem->setFacingCamera(labelItem->isFacingCamera()); labelItem->dptr()->m_facingCameraDirty = false; } +#if !defined(QT_OPENGL_ES_2) + } else if (item->d_ptr->m_isVolumeItem) { + QCustom3DVolume *volumeItem = static_cast<QCustom3DVolume *>(item); + if (volumeItem->dptr()->m_dirtyBitsVolume.colorTableDirty) { + renderItem->setColorTable(volumeItem->colorTable()); + volumeItem->dptr()->m_dirtyBitsVolume.colorTableDirty = false; + } + if (volumeItem->dptr()->m_dirtyBitsVolume.textureDimensionsDirty + || volumeItem->dptr()->m_dirtyBitsVolume.textureDataDirty + || volumeItem->dptr()->m_dirtyBitsVolume.textureFormatDirty) { + GLuint oldTexture = renderItem->texture(); + m_textureHelper->deleteTexture(&oldTexture); + GLuint texture = m_textureHelper->create3DTexture(volumeItem->textureData(), + volumeItem->textureWidth(), + volumeItem->textureHeight(), + volumeItem->textureDepth(), + volumeItem->textureFormat()); + renderItem->setTexture(texture); + renderItem->setTextureWidth(volumeItem->textureWidth()); + renderItem->setTextureHeight(volumeItem->textureHeight()); + renderItem->setTextureDepth(volumeItem->textureDepth()); + renderItem->setTextureFormat(volumeItem->textureFormat()); + volumeItem->dptr()->m_dirtyBitsVolume.textureDimensionsDirty = false; + volumeItem->dptr()->m_dirtyBitsVolume.textureDataDirty = false; + volumeItem->dptr()->m_dirtyBitsVolume.textureFormatDirty = false; + } + if (volumeItem->dptr()->m_dirtyBitsVolume.sliceIndicesDirty) { + renderItem->setSliceIndexX(volumeItem->sliceIndexX()); + renderItem->setSliceIndexY(volumeItem->sliceIndexY()); + renderItem->setSliceIndexZ(volumeItem->sliceIndexZ()); + volumeItem->dptr()->m_dirtyBitsVolume.sliceIndicesDirty = false; + } +#endif } } @@ -1042,7 +1129,9 @@ void Abstract3DRenderer::updateCustomItemPositions() #ifdef USE_REFLECTIONS void Abstract3DRenderer::drawCustomItems(RenderingState state, - ShaderHelper *shader, + ShaderHelper *regularShader, + ShaderHelper *volumeShader, + ShaderHelper *volumeSliceShader, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthProjectionViewMatrix, @@ -1051,7 +1140,9 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state, GLfloat reflection) #else void Abstract3DRenderer::drawCustomItems(RenderingState state, - ShaderHelper *shader, + ShaderHelper *regularShader, + ShaderHelper *volumeShader, + ShaderHelper *volumeSliceShader, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthProjectionViewMatrix, @@ -1059,11 +1150,17 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state, GLfloat shadowQuality) #endif { +#if defined(QT_OPENGL_ES_2) + Q_UNUSED(volumeShader) + Q_UNUSED(volumeSliceShader) +#endif if (m_customRenderCache.isEmpty()) return; + ShaderHelper *shader = regularShader; + shader->bind(); + if (RenderingNormal == state) { - shader->bind(); shader->setUniformValue(shader->lightP(), m_cachedScene->activeLight()->position()); shader->setUniformValue(shader->ambientS(), m_cachedTheme->ambientLightStrength()); shader->setUniformValue(shader->lightColor(), @@ -1137,6 +1234,22 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state, if (RenderingNormal == state) { // Normal render +#if !defined(QT_OPENGL_ES_2) + ShaderHelper *prevShader = shader; + if (item->isVolume()) { + if (item->sliceIndexX() >= 0 + || item->sliceIndexY() >= 0 + || item->sliceIndexZ() >= 0) { + shader = volumeSliceShader; + } else { + shader = volumeShader; + } + } else { + shader = regularShader; + } + if (shader != prevShader) + shader->bind(); +#endif shader->setUniformValue(shader->model(), modelMatrix); shader->setUniformValue(shader->MVP(), MVPMatrix); shader->setUniformValue(shader->nModel(), itModelMatrix.inverted().transposed()); @@ -1144,14 +1257,17 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state, if (item->isBlendNeeded()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); +#if !defined(QT_OPENGL_ES_2) + if (!item->isVolume()) +#endif + glDisable(GL_CULL_FACE); } else { glDisable(GL_BLEND); glEnable(GL_CULL_FACE); } #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && !item->isVolume()) { // Set shadow shader bindings shader->setUniformValue(shader->shadowQ(), shadowQuality); shader->setUniformValue(shader->depth(), depthProjectionViewMatrix * modelMatrix); @@ -1164,8 +1280,34 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state, #endif { // Set shadowless shader bindings - shader->setUniformValue(shader->lightS(), m_cachedTheme->lightStrength()); - m_drawer->drawObject(shader, item->mesh(), item->texture()); +#if !defined(QT_OPENGL_ES_2) + if (item->isVolume()) { + // Volume shaders repurpose light position for camera position relative to item + QVector3D cameraPos = m_cachedScene->activeCamera()->position(); + cameraPos = MVPMatrix.inverted().map(cameraPos); + shader->setUniformValue(shader->cameraPositionRelativeToModel(), -cameraPos); + GLint color8Bit = (item->textureFormat() == QImage::Format_Indexed8) ? 1 : 0; + if (color8Bit) { + shader->setUniformValueArray(shader->colorIndex(), + item->colorTable().constData(), 256); + } + shader->setUniformValue(shader->color8Bit(), color8Bit); + if (shader == volumeSliceShader) { + QVector3D slices((float(item->sliceIndexX()) + 0.5f) + / float(item->textureWidth()) * 2.0 - 1.0, + (float(item->sliceIndexY()) + 0.5f) + / float(item->textureHeight()) * 2.0 - 1.0, + (float(item->sliceIndexZ()) + 0.5f) + / float(item->textureDepth()) * 2.0 - 1.0); + shader->setUniformValue(shader->volumeSliceIndices(), slices); + } + m_drawer->drawObject(shader, item->mesh(), 0, 0, item->texture()); + } else +#endif + { + shader->setUniformValue(shader->lightS(), m_cachedTheme->lightStrength()); + m_drawer->drawObject(shader, item->mesh(), item->texture()); + } } } else if (RenderingSelection == state) { // Selection render @@ -1203,6 +1345,9 @@ void Abstract3DRenderer::drawRadialGrid(ShaderHelper *shader, float yFloorLinePo const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthMatrix) { +#if defined(QT_OPENGL_ES_2) + Q_UNUSED(depthMatrix) +#endif static QVector<QQuaternion> lineRotations; if (!lineRotations.size()) { lineRotations.resize(polarGridRoundness); @@ -1264,6 +1409,9 @@ void Abstract3DRenderer::drawAngularGrid(ShaderHelper *shader, float yFloorLineP const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthMatrix) { +#if defined(QT_OPENGL_ES_2) + Q_UNUSED(depthMatrix) +#endif float halfRatio((m_polarRadius + (labelMargin / 2.0f)) / 2.0f); QVector3D gridLineScaler(gridLineWidth, gridLineWidth, halfRatio); int gridLineCount = m_axisCacheX.gridLineCount(); diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 50370954..7874a1ad 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -94,6 +94,9 @@ public: const QString &fragmentShader) = 0; virtual void initCustomItemShaders(const QString &vertexShader, const QString &fragmentShader); + virtual void initVolumeTextureShaders(const QString &vertexShader, + const QString &fragmentShader, + const QString &sliceShader); virtual void updateAxisType(QAbstract3DAxis::AxisOrientation orientation, QAbstract3DAxis::AxisType type); virtual void updateAxisTitle(QAbstract3DAxis::AxisOrientation orientation, @@ -145,13 +148,15 @@ public: QString &selectionLabel(); #ifdef USE_REFLECTIONS - void drawCustomItems(RenderingState state, ShaderHelper *shader, + void drawCustomItems(RenderingState state, ShaderHelper *regularShader, + ShaderHelper *volumeShader, ShaderHelper *volumeSliceShader, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthProjectionViewMatrix, GLuint depthTexture, GLfloat shadowQuality, GLfloat reflection = 1.0f); #else - void drawCustomItems(RenderingState state, ShaderHelper *shader, + void drawCustomItems(RenderingState state, ShaderHelper *regularShader, + ShaderHelper *volumeShader, ShaderHelper *volumeSliceShader, const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthProjectionViewMatrix, @@ -247,6 +252,8 @@ protected: int m_visibleSeriesCount; ShaderHelper *m_customItemShader; + ShaderHelper *m_volumeTextureShader; + ShaderHelper *m_volumeTextureSliceShader; bool m_useOrthoProjection; bool m_xFlipped; diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index 38fa3147..085b881e 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -1093,9 +1093,11 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } - Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix, - projectionViewMatrix, depthProjectionViewMatrix, - m_depthTexture, m_shadowQualityToShader); + Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader, + m_volumeTextureSliceShader, viewMatrix, + projectionViewMatrix, + depthProjectionViewMatrix, m_depthTexture, + m_shadowQualityToShader); // Disable drawing to depth framebuffer (= enable drawing to screen) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -1179,7 +1181,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) } } glCullFace(GL_BACK); - Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, viewMatrix, + Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, + m_volumeTextureShader, m_volumeTextureSliceShader, + viewMatrix, projectionViewMatrix, depthProjectionViewMatrix, m_depthTexture, m_shadowQualityToShader); drawLabels(true, activeCamera, viewMatrix, projectionMatrix); @@ -1267,7 +1271,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) drawGridLines(depthProjectionViewMatrix, projectionViewMatrix, viewMatrix); // Draw custom items - Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix, + Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, m_volumeTextureShader, + m_volumeTextureSliceShader, viewMatrix, projectionViewMatrix, depthProjectionViewMatrix, m_depthTexture, m_shadowQualityToShader); diff --git a/src/datavisualization/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp index b8726840..4191efc4 100644 --- a/src/datavisualization/engine/drawer.cpp +++ b/src/datavisualization/engine/drawer.cpp @@ -93,8 +93,11 @@ QFont Drawer::font() const } void Drawer::drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId, - GLuint depthTextureId) + GLuint depthTextureId, GLuint textureId3D) { +#if defined(QT_OPENGL_ES_2) + Q_UNUSED(textureId3D) +#endif if (textureId) { // Activate texture glActiveTexture(GL_TEXTURE0); @@ -108,6 +111,14 @@ void Drawer::drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLui glBindTexture(GL_TEXTURE_2D, depthTextureId); shader->setUniformValue(shader->shadow(), 1); } +#if !defined(QT_OPENGL_ES_2) + if (textureId3D) { + // Activate texture + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_3D, textureId3D); + shader->setUniformValue(shader->texture(), 2); + } +#endif // 1st attribute buffer : vertices glEnableVertexAttribArray(shader->posAtt()); @@ -139,6 +150,12 @@ void Drawer::drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLui glDisableVertexAttribArray(shader->posAtt()); // Release textures +#if !defined(QT_OPENGL_ES_2) + if (textureId3D) { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_3D, 0); + } +#endif if (depthTextureId) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/src/datavisualization/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h index ffcea315..709503dd 100644 --- a/src/datavisualization/engine/drawer_p.h +++ b/src/datavisualization/engine/drawer_p.h @@ -75,7 +75,7 @@ public: inline GLfloat scaledFontSize() const { return m_scaledFontSize; } void drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId = 0, - GLuint depthTextureId = 0); + GLuint depthTextureId = 0, GLuint textureId3D = 0); void drawSelectionObject(ShaderHelper *shader, AbstractObjectHelper *object); void drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object); void drawPoint(ShaderHelper *shader); diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc index f788b5df..936ed53f 100644 --- a/src/datavisualization/engine/engine.qrc +++ b/src/datavisualization/engine/engine.qrc @@ -59,5 +59,8 @@ <file alias="vertexTexture">shaders/texture.vert</file> <file alias="fragmentTexturedSurfaceShadowFlat">shaders/surfaceTexturedShadowFlat.frag</file> <file alias="fragmentSurfaceTexturedFlat">shaders/surfaceTexturedFlat.frag</file> + <file alias="fragmentTexture3D">shaders/texture3d.frag</file> + <file alias="vertexTexture3D">shaders/texture3d.vert</file> + <file alias="fragmentTexture3DSlice">shaders/texture3dslice.frag</file> </qresource> </RCC> diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 09225b99..13f6e02c 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -538,9 +538,11 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } } - Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix, - projectionViewMatrix, depthProjectionViewMatrix, - m_depthTexture, m_shadowQualityToShader); + Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader, + m_volumeTextureSliceShader, viewMatrix, + projectionViewMatrix, + depthProjectionViewMatrix, m_depthTexture, + m_shadowQualityToShader); // Disable drawing to framebuffer (= enable drawing to screen) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -641,9 +643,11 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } } - Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, viewMatrix, - projectionViewMatrix, depthProjectionViewMatrix, - m_depthTexture, m_shadowQualityToShader); + Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, + m_volumeTextureShader, m_volumeTextureSliceShader, + viewMatrix, projectionViewMatrix, + depthProjectionViewMatrix, m_depthTexture, + m_shadowQualityToShader); drawLabels(true, activeCamera, viewMatrix, projectionMatrix); @@ -1407,7 +1411,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } } - Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix, + Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, m_volumeTextureShader, + m_volumeTextureSliceShader, viewMatrix, projectionViewMatrix, depthProjectionViewMatrix, m_depthTexture, m_shadowQualityToShader); diff --git a/src/datavisualization/engine/shaders/default.frag b/src/datavisualization/engine/shaders/default.frag index c03b1054..0276ed95 100644 --- a/src/datavisualization/engine/shaders/default.frag +++ b/src/datavisualization/engine/shaders/default.frag @@ -33,5 +33,6 @@ void main() { materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + materialSpecularColor * lightStrength * pow(cosAlpha, 5) / distance; gl_FragColor.a = color_mdl.a; + gl_FragColor = clamp(gl_FragColor, 0.0, 1.0); } diff --git a/src/datavisualization/engine/shaders/texture3d.frag b/src/datavisualization/engine/shaders/texture3d.frag new file mode 100644 index 00000000..054b59cb --- /dev/null +++ b/src/datavisualization/engine/shaders/texture3d.frag @@ -0,0 +1,70 @@ +#version 120 + +varying highp vec3 pos; + +uniform highp sampler3D textureSampler; +uniform highp vec3 cameraPositionRelativeToModel; +uniform highp vec4 colorIndex[256]; +uniform highp int color8Bit; + +const float maxDist = sqrt(2.0); +const int sampleCount = 1024; +const float alphaThreshold = 0.001; +void main() { + // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1 + + // Find out where ray intersects the object + highp vec3 rayDir = -(cameraPositionRelativeToModel - pos); + highp vec3 invRayDir = 1.0 / rayDir; + highp vec3 minCorner = vec3(-1.0); + highp vec3 maxCorner = vec3(1.0); + highp vec3 t1 = invRayDir * (minCorner - pos); + highp vec3 t2 = invRayDir * (maxCorner - pos); + highp vec3 tmin = min(t1, t2); + highp vec3 tmax = max(t1, t2); + highp vec2 t = max(tmin.xx, tmin.yz); + t = min(tmax.xx, tmax.yz); + float tFar = min(t.x, t.y); + highp vec3 rayStart = pos; + // Flip Y and Z so QImage bits work directly for texture and first image is in the front + rayStart.yz = -rayStart.yz; + highp vec3 rayStop = pos + rayDir * tFar; + rayStop.yz = -rayStop.yz; + + // Convert intersections to texture coords + rayStart = 0.5 * (rayStart + 1.0); + rayStop = 0.5 * (rayStop + 1.0); + + highp vec3 curPos = rayStart; + highp float fullDist = distance(rayStop, rayStart); + highp float stepSize = maxDist / float(sampleCount); // TODO: Stepsize needs to be improved + highp vec3 step = normalize(rayStop - rayStart) * stepSize; + highp float totalDist = 0.0; + highp float totalAlpha = 0.0; + highp vec4 destColor = vec4(0, 0, 0, 0); + highp vec4 curColor = vec4(0, 0, 0, 0); + highp vec3 curRgb = vec3(0, 0, 0); + highp float curAlpha = 0.0; + + for (int i = 0; i < sampleCount; i++) { + curColor = texture3D(textureSampler, curPos); + if (color8Bit != 0) + curColor = colorIndex[int(curColor.r * 255.0)]; + + curAlpha = curColor.a; + if (curAlpha > alphaThreshold) { + curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha); + destColor.rgb += curRgb; + totalAlpha += curAlpha; + } + curPos += step; + totalDist += stepSize; + if (totalDist > fullDist || totalAlpha >= 1.0) { + break; + } + } + + destColor.a = totalAlpha; + gl_FragColor = clamp(destColor, 0.0, 1.0); +} + diff --git a/src/datavisualization/engine/shaders/texture3d.vert b/src/datavisualization/engine/shaders/texture3d.vert new file mode 100644 index 00000000..cad1ce06 --- /dev/null +++ b/src/datavisualization/engine/shaders/texture3d.vert @@ -0,0 +1,12 @@ +uniform highp mat4 MVP; + +attribute highp vec3 vertexPosition_mdl; +attribute highp vec2 vertexUV; +attribute highp vec3 vertexNormal_mdl; + +varying highp vec3 pos; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); + pos = vertexPosition_mdl; +} diff --git a/src/datavisualization/engine/shaders/texture3dslice.frag b/src/datavisualization/engine/shaders/texture3dslice.frag new file mode 100644 index 00000000..641b32a5 --- /dev/null +++ b/src/datavisualization/engine/shaders/texture3dslice.frag @@ -0,0 +1,119 @@ +#version 120 + +varying highp vec3 pos; + +uniform highp sampler3D textureSampler; +uniform highp vec3 cameraPositionRelativeToModel; +uniform highp vec3 volumeSliceIndices; +uniform highp vec4 colorIndex[256]; +uniform highp int color8Bit; + +const highp vec3 xPlaneNormal = vec3(1.0, 0, 0); +const highp vec3 yPlaneNormal = vec3(0, 1.0, 0); +const highp vec3 zPlaneNormal = vec3(0, 0, 1.0); + +const float alphaThreshold = 0.001; +void main() { + // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1 + + // Find out where ray intersects the slice planes + highp vec3 rayDir = -(cameraPositionRelativeToModel - pos); + highp vec3 rayStart = pos; + // Flip Y and Z so QImage bits work directly for texture and first image is in the front + rayStart.yz = -rayStart.yz; + rayDir.yz = -rayDir.yz; + highp vec3 invRayDir = 1.0 / rayDir; + highp vec3 minCorner = vec3(-1.0); + highp vec3 maxCorner = vec3(1.0); + highp vec3 t1 = invRayDir * (minCorner - rayStart); + highp vec3 t2 = invRayDir * (maxCorner - rayStart); + highp vec3 tmin = min(t1, t2); + highp vec3 tmax = max(t1, t2); + highp vec2 t = max(tmin.xx, tmin.yz); + t = min(tmax.xx, tmax.yz); + float tFar = min(t.x, t.y); + + highp vec3 xPoint = vec3(volumeSliceIndices.x, 0, 0); + highp vec3 yPoint = vec3(0, volumeSliceIndices.y, 0); + highp vec3 zPoint = vec3(0, 0, volumeSliceIndices.z); + highp float firstD = tFar + 1.0; + highp float secondD = firstD; + highp float thirdD = firstD; + if (volumeSliceIndices.x >= -1.0) { + highp float dx = dot(xPoint - rayStart, xPlaneNormal) / dot(rayDir, xPlaneNormal); + if (dx >= 0.0 && dx <= tFar) + firstD = min(dx, firstD); + } + if (volumeSliceIndices.y >= -1.0) { + highp float dy = dot(yPoint - rayStart, yPlaneNormal) / dot(rayDir, yPlaneNormal); + if (dy >= 0.0 && dy <= tFar) { + if (dy < firstD) { + secondD = firstD; + firstD = dy; + } else { + secondD = dy; + } + } + } + if (volumeSliceIndices.z >= -1.0) { + highp float dz = dot(zPoint - rayStart, zPlaneNormal) / dot(rayDir, zPlaneNormal); + if (dz >= 0.0) { + if (dz < firstD && dz <= tFar) { + thirdD = secondD; + secondD = firstD; + firstD = dz; + } else if (dz < secondD){ + thirdD = secondD; + secondD = dz; + } else { + thirdD = dz; + } + } + } + + highp vec4 destColor = vec4(0.0, 0.0, 0.0, 0.0); + highp float totalAlpha = 0.0; + highp vec3 curRgb = vec3(0, 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); + if (color8Bit != 0) + firstColor = colorIndex[int(firstColor.r * 255.0)]; + + if (firstColor.a > alphaThreshold) { + destColor.rgb = firstColor.rgb * firstColor.a; + totalAlpha = firstColor.a; + } + if (secondD <= tFar && totalAlpha < 1.0) { + highp vec3 secondTex = rayStart + rayDir * secondD; + secondTex = 0.5 * (secondTex + 1.0); + highp vec4 secondColor = 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); + destColor.rgb += curRgb; + totalAlpha += secondColor.a; + } + 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); + destColor.rgb += curRgb; + totalAlpha += thirdColor.a; + } + } + } + } + destColor.a = totalAlpha; + gl_FragColor = clamp(destColor, 0.0, 1.0); +} + diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 1607f66a..17be3278 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -1196,9 +1196,11 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); - Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix, - projectionViewMatrix, depthProjectionViewMatrix, - m_depthTexture, m_shadowQualityToShader); + Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader, + m_volumeTextureSliceShader, viewMatrix, + projectionViewMatrix, + depthProjectionViewMatrix, m_depthTexture, + m_shadowQualityToShader); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthModelTexture, 0); @@ -1232,9 +1234,11 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glDisableVertexAttribArray(m_depthShader->posAtt()); - Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix, - projectionViewMatrix, depthProjectionViewMatrix, - m_depthTexture, m_shadowQualityToShader); + Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, m_volumeTextureShader, + m_volumeTextureSliceShader, viewMatrix, + projectionViewMatrix, + depthProjectionViewMatrix, m_depthTexture, + m_shadowQualityToShader); // Disable drawing to depth framebuffer (= enable drawing to screen) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -1287,7 +1291,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } } m_surfaceGridShader->bind(); - Abstract3DRenderer::drawCustomItems(RenderingSelection, m_surfaceGridShader, viewMatrix, + Abstract3DRenderer::drawCustomItems(RenderingSelection, m_surfaceGridShader, + m_volumeTextureShader, m_volumeTextureSliceShader, + viewMatrix, projectionViewMatrix, depthProjectionViewMatrix, m_depthTexture, m_shadowQualityToShader); drawLabels(true, activeCamera, viewMatrix, projectionMatrix); @@ -1858,7 +1864,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } } - Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix, + Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, m_volumeTextureShader, + m_volumeTextureSliceShader, viewMatrix, projectionViewMatrix, depthProjectionViewMatrix, m_depthTexture, m_shadowQualityToShader); |