summaryrefslogtreecommitdiffstats
path: root/src/datavis3d
diff options
context:
space:
mode:
authorTomi Korpipää <tomi.korpipaa@digia.com>2013-05-07 09:32:14 +0300
committerTomi Korpipää <tomi.korpipaa@digia.com>2013-05-07 09:56:54 +0300
commitbec634f4141be5300ab2354d784186f9c95a8db5 (patch)
tree037a98441db507542c109dffbc249c8a60c6ae62 /src/datavis3d
parent7c29e6efc4dcb1393f90e90dc2e5e2ef242edd41 (diff)
Shadow mapping implementation draft
Does not work yet Change-Id: Ic08c6b12fa5d5aa4f76ddef82fa81eab6982dd69 Change-Id: Ic08c6b12fa5d5aa4f76ddef82fa81eab6982dd69 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavis3d')
-rw-r--r--src/datavis3d/engine/engine.qrc6
-rw-r--r--src/datavis3d/engine/q3dmaps.cpp235
-rw-r--r--src/datavis3d/engine/q3dmaps_p.h5
-rw-r--r--src/datavis3d/engine/shaders/fragmentDepthTest7
-rw-r--r--src/datavis3d/engine/shaders/fragmentShader42
-rw-r--r--src/datavis3d/engine/shaders/fragmentShaderDepth3
-rw-r--r--src/datavis3d/engine/shaders/fragmentShadow65
-rw-r--r--src/datavis3d/engine/shaders/vertexDepthTest9
-rw-r--r--src/datavis3d/engine/shaders/vertexShaderDepth8
-rw-r--r--src/datavis3d/engine/shaders/vertexShadow29
-rw-r--r--src/datavis3d/utils/shaderhelper.cpp16
-rw-r--r--src/datavis3d/utils/shaderhelper_p.h6
-rw-r--r--src/datavis3d/utils/texturehelper.cpp40
-rw-r--r--src/datavis3d/utils/texturehelper_p.h4
14 files changed, 440 insertions, 35 deletions
diff --git a/src/datavis3d/engine/engine.qrc b/src/datavis3d/engine/engine.qrc
index 94af2f13..ca260915 100644
--- a/src/datavis3d/engine/engine.qrc
+++ b/src/datavis3d/engine/engine.qrc
@@ -25,6 +25,12 @@
<file alias="vertexTexture">shaders/vertexShaderTexture</file>
<file alias="fragmentLabel">shaders/fragmentShaderLabel</file>
<file alias="vertexLabel">shaders/vertexShaderLabel</file>
+ <file alias="fragmentDepth">shaders/fragmentShaderDepth</file>
+ <file alias="vertexDepth">shaders/vertexShaderDepth</file>
+ <file alias="testDepthFrag">shaders/fragmentDepthTest</file>
+ <file alias="testDepthVert">shaders/vertexDepthTest</file>
+ <file alias="fragmentShadow">shaders/fragmentShadow</file>
+ <file alias="vertexShadow">shaders/vertexShadow</file>
</qresource>
<qresource prefix="/textures"/>
</RCC>
diff --git a/src/datavis3d/engine/q3dmaps.cpp b/src/datavis3d/engine/q3dmaps.cpp
index 57ed0913..fa9d2c38 100644
--- a/src/datavis3d/engine/q3dmaps.cpp
+++ b/src/datavis3d/engine/q3dmaps.cpp
@@ -73,6 +73,7 @@ QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE
//#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels
const GLfloat gridLineWidth = 0.005f;
+QVector3D modDefaultLightPos;
Q3DMaps::Q3DMaps()
: d_ptr(new Q3DMapsPrivate(this))
@@ -93,11 +94,17 @@ void Q3DMaps::initialize()
d_ptr->initShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragment"));
}
- d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"),
- QStringLiteral(":/shaders/fragmentTexture"));
+ d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadow"));
+// d_ptr->initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"),
+// QStringLiteral(":/shaders/fragmentTexture"));
d_ptr->initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
d_ptr->initSelectionShader();
+ d_ptr->initDepthShader();
+
+ // Init the depth buffer
+ d_ptr->initDepthBuffer();
// Init the selection buffer
d_ptr->initSelectionBuffer();
@@ -125,7 +132,7 @@ void Q3DMaps::initialize()
// Set initial camera position
// X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later
- CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 20.0f + zComp),
+ CameraHelper::setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 3.0f * zComp),
QVector3D(0.0f, 0.0f, zComp),
QVector3D(0.0f, 1.0f, 0.0f));
@@ -137,6 +144,9 @@ void Q3DMaps::initialize()
// Set initialized -flag
d_ptr->m_isInitialized = true;
+
+ // Update default light position
+ modDefaultLightPos = defaultLightPos;// * QVector3D(1.0f, 1.5f, 1.0f);
}
void Q3DMaps::render()
@@ -196,7 +206,8 @@ void Q3DMaps::drawScene()
d_ptr->m_sceneViewPort.height());
// Get light position (rotate light with camera, a bit above it (as set in defaultLightPos))
- QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos);
+ QVector3D lightPos = CameraHelper::calculateLightPosition(modDefaultLightPos);
+ //qDebug() << lightPos;
//lightPos = QVector3D(0.0f, 4.0f, zComp); // center of bars, 4.0f above - for testing
// Map adjustment direction to model matrix scaling
@@ -249,6 +260,121 @@ void Q3DMaps::drawScene()
break;
}
+ // Render scene into a depth texture for using with shadow mapping
+ // Bind depth shader
+ d_ptr->m_depthShader->bind();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, d_ptr->m_depthFrameBuffer);
+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (= far)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
+
+ // Get the depth view matrix
+ QMatrix4x4 depthViewMatrix;
+ depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -d_ptr->m_yAdjustment, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+ QMatrix4x4 depthProjectionMatrix;
+ depthProjectionMatrix.ortho(-10,10,-10,10,-10,20);
+#if 0
+ // Draw background to depth buffer
+ if (d_ptr->m_backgroundObj) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment, zComp);
+ modelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor,
+ 1.0f,
+ d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor));
+ modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
+
+ MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix);
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_backgroundObj->vertexBuf());
+ glVertexAttribPointer(d_ptr->m_depthShader->posAtt(),
+ 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_backgroundObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, d_ptr->m_backgroundObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void*)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt());
+ }
+#endif
+ // Draw bars to depth buffer
+ for (int bar = 0; bar < d_ptr->m_data->d_ptr->row().size(); bar++) {
+ QDataItem *item = d_ptr->m_data->d_ptr->getItem(bar);
+ if (!item)
+ continue;
+
+ GLfloat barHeight = item->d_ptr->value() / d_ptr->m_heightNormalizer;
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ modelMatrix.translate(item->d_ptr->translation().x(),
+ heightMultiplier * barHeight + heightScaler
+ - d_ptr->m_yAdjustment,
+ item->d_ptr->translation().z());
+ modelMatrix.scale(QVector3D(widthMultiplier * barHeight + widthScaler,
+ heightMultiplier * barHeight + heightScaler,
+ depthMultiplier * barHeight + depthScaler));
+
+ MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
+
+ d_ptr->m_depthShader->setUniformValue(d_ptr->m_depthShader->MVP(), MVPMatrix);
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(d_ptr->m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf());
+ glVertexAttribPointer(d_ptr->m_depthShader->posAtt(),
+ 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_barObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void*)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt());
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ // Release depth shader
+ d_ptr->m_depthShader->release();
+
+#if 0 // Use this if you want to see what is being drawn to the framebuffer
+ d_ptr->m_labelShader->bind();
+ glEnable(GL_TEXTURE_2D);
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 viewmatrix;
+ viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp),
+ QVector3D(0.0f, 0.0f, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+ modelMatrix.translate(0.0, 0.0, zComp);
+ QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix;
+ d_ptr->m_labelShader->setUniformValue(d_ptr->m_labelShader->MVP(), MVPMatrix);
+ d_ptr->m_drawer->drawObject(d_ptr->m_labelShader, d_ptr->m_labelObj, true,
+ d_ptr->m_depthTexture);
+ glDisable(GL_TEXTURE_2D);
+ d_ptr->m_labelShader->release();
+#endif
+#if 1
// Skip selection mode drawing if we're zoomed or have no selection mode
if (!d_ptr->m_zoomActivated && d_ptr->m_selectionMode > ModeNone) {
// Bind selection shader
@@ -432,6 +558,7 @@ void Q3DMaps::drawScene()
if (d_ptr->m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
+ QMatrix4x4 depthMVPMatrix;
modelMatrix.translate(0.0f, -d_ptr->m_yAdjustment, zComp);
modelMatrix.scale(QVector3D(d_ptr->m_areaSize.width() / d_ptr->m_scaleFactor,
@@ -440,12 +567,19 @@ void Q3DMaps::drawScene()
modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
+ depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix;
- QVector3D backgroundColor = Utils::vectorFromColor(d_ptr->m_theme->m_backgroundColor);
+ QMatrix4x4 biasMatrix(
+ 0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0,
+ 0.5, 0.5, 0.5, 1.0
+ );
+ QMatrix4x4 depthBiasMVP = biasMatrix * depthMVPMatrix;
// Set shader bindings
d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightP(),
- lightPos);
+ QVector3D(0.0f, -d_ptr->m_yAdjustment, zComp) - lightPos);
d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->view(),
viewMatrix);
d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->model(),
@@ -454,16 +588,59 @@ void Q3DMaps::drawScene()
modelMatrix.inverted().transposed());
d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->MVP(),
MVPMatrix);
- d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->color(),
- backgroundColor);
+ d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->depth(),
+ depthBiasMVP);
d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightS(),
d_ptr->m_theme->m_lightStrength / 5.0f);
d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->ambientS(),
d_ptr->m_theme->m_ambientStrength * 3.0f);
- // Draw the object
- d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, true,
- d_ptr->m_bgrTexture);
+ // TODO: Add parameter to drawObject to allow using shadow mapping
+// // Draw the object
+// d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, true,
+// d_ptr->m_bgrTexture, d_ptr->m_depthTexture);
+
+ // TODO: Done here for now
+ // Activate texture
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, d_ptr->m_bgrTexture);
+ d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->texture(), 0);
+
+ // Activate depth texture
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, d_ptr->m_depthTexture);
+ d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->shadow(), 1);
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(d_ptr->m_backgroundShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_backgroundObj->vertexBuf());
+ glVertexAttribPointer(d_ptr->m_backgroundShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // 2nd attribute buffer : normals
+ glEnableVertexAttribArray(d_ptr->m_backgroundShader->normalAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_backgroundObj->normalBuf());
+ glVertexAttribPointer(d_ptr->m_backgroundShader->normalAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // 3rd attribute buffer : UVs
+ glEnableVertexAttribArray(d_ptr->m_backgroundShader->uvAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_backgroundObj->uvBuf());
+ glVertexAttribPointer(d_ptr->m_backgroundShader->uvAtt(), 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d_ptr->m_backgroundObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, d_ptr->m_backgroundObj->indexCount(), GL_UNSIGNED_SHORT, (void*)0);
+
+ // Free buffers
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisableVertexAttribArray(d_ptr->m_backgroundShader->uvAtt());
+
+ glDisableVertexAttribArray(d_ptr->m_backgroundShader->normalAtt());
+ glDisableVertexAttribArray(d_ptr->m_backgroundShader->posAtt());
}
// Disable textures
@@ -784,6 +961,7 @@ void Q3DMaps::drawScene()
d_ptr->m_labelShader->release();
#endif
#endif
+#endif
}
void Q3DMaps::mousePressEvent(QMouseEvent *event)
@@ -885,6 +1063,9 @@ void Q3DMaps::resizeEvent(QResizeEvent *event)
// Re-init selection buffer
d_ptr->initSelectionBuffer();
+
+ // Re-init depth buffer
+ d_ptr->initDepthBuffer();
}
void Q3DMaps::setBarSpecs(const QVector3D &thickness, AdjustmentDirection direction)
@@ -1138,6 +1319,7 @@ Q3DMapsPrivate::Q3DMapsPrivate(Q3DMaps *q)
: q_ptr(q),
m_paintDevice(0),
m_barShader(0),
+ m_depthShader(0),
m_selectionShader(0),
m_backgroundShader(0),
m_labelShader(0),
@@ -1171,11 +1353,13 @@ Q3DMapsPrivate::Q3DMapsPrivate(Q3DMaps *q)
m_labelTransparency(TransparencyNone),
m_font(QFont(QStringLiteral("Arial"))),
m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)),
+ m_bgrTexture(0),
+ m_depthTexture(0),
+ m_selectionTexture(0),
+ m_depthFrameBuffer(0),
m_selectionFrameBuffer(0),
m_selectionDepthBuffer(0),
m_areaSize(QSizeF(1.0f, 1.0f)),
- m_bgrTexture(0),
- m_selectionTexture(0),
m_updateLabels(true),
m_gridEnabled(true)
{
@@ -1250,6 +1434,15 @@ void Q3DMapsPrivate::initSelectionShader()
m_selectionShader->initialize();
}
+void Q3DMapsPrivate::initDepthShader()
+{
+ if (m_depthShader)
+ delete m_depthShader;
+ m_depthShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/vertexDepth"),
+ QStringLiteral(":/shaders/fragmentDepth"));
+ m_depthShader->initialize();
+}
+
void Q3DMapsPrivate::initSelectionBuffer()
{
if (m_selectionTexture) {
@@ -1263,6 +1456,15 @@ void Q3DMapsPrivate::initSelectionBuffer()
m_selectionDepthBuffer);
}
+void Q3DMapsPrivate::initDepthBuffer()
+{
+ if (m_depthTexture) {
+ m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
+ m_textureHelper->deleteTexture(&m_depthTexture);
+ }
+ m_depthTexture = m_textureHelper->createDepthTexture(q_ptr->size(), m_depthFrameBuffer);
+}
+
void Q3DMapsPrivate::initBackgroundShaders(const QString &vertexShader,
const QString &fragmentShader)
{
@@ -1277,6 +1479,8 @@ void Q3DMapsPrivate::initLabelShaders(const QString &vertexShader, const QString
if (m_labelShader)
delete m_labelShader;
m_labelShader = new ShaderHelper(q_ptr, vertexShader, fragmentShader);
+// m_labelShader = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/testDepthVert"),
+// QStringLiteral(":/shaders/testDepthFrag"));
m_labelShader->initialize();
}
@@ -1290,7 +1494,10 @@ void Q3DMapsPrivate::calculateSceneScalingFactors(const QRect &areaRect)
{
m_areaSize = areaRect.size();
// Calculate scaling factor so that we can be sure the whole area fits to positive z space
- m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()) / zComp;
+ if (zComp > 1.0f)
+ m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()) / zComp;
+ else
+ m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height());
//qDebug() << "scaleFactor" << m_scaleFactor;
}
diff --git a/src/datavis3d/engine/q3dmaps_p.h b/src/datavis3d/engine/q3dmaps_p.h
index 6acbab79..3896bb39 100644
--- a/src/datavis3d/engine/q3dmaps_p.h
+++ b/src/datavis3d/engine/q3dmaps_p.h
@@ -104,7 +104,9 @@ public:
void initSelectionShader();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
+ void initDepthShader();
void initSelectionBuffer();
+ void initDepthBuffer();
void updateTextures();
void calculateSceneScalingFactors(const QRect &areaRect);
void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits);
@@ -116,6 +118,7 @@ public:
QOpenGLPaintDevice *m_paintDevice;
ShaderHelper *m_barShader;
+ ShaderHelper *m_depthShader;
ShaderHelper *m_selectionShader;
ShaderHelper *m_backgroundShader;
ShaderHelper *m_labelShader;
@@ -151,8 +154,10 @@ public:
Drawer *m_drawer;
QSizeF m_areaSize;
GLuint m_bgrTexture;
+ GLuint m_depthTexture;
GLuint m_selectionTexture;
//GLuint m_selectionDepthTexture;
+ GLuint m_depthFrameBuffer;
GLuint m_selectionFrameBuffer;
GLuint m_selectionDepthBuffer;
bool m_updateLabels;
diff --git a/src/datavis3d/engine/shaders/fragmentDepthTest b/src/datavis3d/engine/shaders/fragmentDepthTest
new file mode 100644
index 00000000..d6c502e1
--- /dev/null
+++ b/src/datavis3d/engine/shaders/fragmentDepthTest
@@ -0,0 +1,7 @@
+uniform sampler2D textureSampler;
+
+varying highp vec2 UV;
+
+void main() {
+ gl_FragColor = texture2D(textureSampler, UV);
+}
diff --git a/src/datavis3d/engine/shaders/fragmentShader b/src/datavis3d/engine/shaders/fragmentShader
index e8e2e223..45d8642f 100644
--- a/src/datavis3d/engine/shaders/fragmentShader
+++ b/src/datavis3d/engine/shaders/fragmentShader
@@ -4,29 +4,35 @@ varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
varying highp vec3 lightDirection_cmr;
+
uniform highp vec3 lightPosition_wrld;
uniform highp vec3 color_mdl;
uniform highp float lightStrength;
uniform highp float ambientStrength;
+
void main() {
- highp vec3 materialDiffuseColor = color_mdl;
- highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
- highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
- highp float distance = length(lightPosition_wrld - position_wrld);
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = dot(n, l);
- if (cosTheta < 0.0) { cosTheta = 0.0; }
- if (cosTheta > 1.0) { cosTheta = 1.0; }
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = dot(E, R);
- if (cosAlpha < 0.0) { cosAlpha = 0.0; }
- if (cosAlpha > 1.0) { cosAlpha = 1.0; }
- gl_FragColor.rgb = //color_mdl + color_mdl * vec3(cosTheta * cosTheta) / (distance * distance) + vec3(cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / (distance * distance);
- materialAmbientColor +
- materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
- materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance;//(distance * distance);
+ highp vec3 materialDiffuseColor = color_mdl;
+ highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
+ highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
+
+ highp float distance = length(lightPosition_wrld - position_wrld);
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = dot(n, l);
+ if (cosTheta < 0.0) { cosTheta = 0.0; }
+ if (cosTheta > 1.0) { cosTheta = 1.0; }
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = dot(E, R);
+ if (cosAlpha < 0.0) { cosAlpha = 0.0; }
+ if (cosAlpha > 1.0) { cosAlpha = 1.0; }
+
+ gl_FragColor.rgb = //color_mdl + color_mdl * vec3(cosTheta * cosTheta) / (distance * distance) + vec3(cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / (distance * distance);
+ materialAmbientColor +
+ materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
+ materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance;//(distance * distance);
gl_FragColor.a = 1.0;
}
diff --git a/src/datavis3d/engine/shaders/fragmentShaderDepth b/src/datavis3d/engine/shaders/fragmentShaderDepth
new file mode 100644
index 00000000..5cfd4b10
--- /dev/null
+++ b/src/datavis3d/engine/shaders/fragmentShaderDepth
@@ -0,0 +1,3 @@
+void main() {
+ gl_FragDepth = gl_FragCoord.z;
+}
diff --git a/src/datavis3d/engine/shaders/fragmentShadow b/src/datavis3d/engine/shaders/fragmentShadow
new file mode 100644
index 00000000..309c63fb
--- /dev/null
+++ b/src/datavis3d/engine/shaders/fragmentShadow
@@ -0,0 +1,65 @@
+varying highp vec4 shadowCoord;
+varying highp vec2 UV;
+varying highp vec3 position_wrld;
+varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp vec3 lightPosition_wrld;
+uniform sampler2D textureSampler;
+uniform sampler2DShadow shadowMap;
+
+//float random(vec3 seed, int i){
+// vec4 seed4 = vec4(seed,i);
+// float dot_product = dot(seed4, vec4(12.9898, 78.233, 45.164, 94.673));
+// return fract(sin(dot_product) * 43758.5453);
+//}
+
+void main() {
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
+ highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
+ highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = dot(n, l);
+ if (cosTheta < 0.0) { cosTheta = 0.0; }
+ if (cosTheta > 1.0) { cosTheta = 1.0; }
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = dot(E, R);
+ if (cosAlpha < 0.0) { cosAlpha = 0.0; }
+ if (cosAlpha > 1.0) { cosAlpha = 1.0; }
+
+ highp float visibility = 1.0;
+ highp float bias = 0.005;
+ //highp bias = 0.005 * tan(acos(cosTheta));
+ //if (bias < 0.0) { bias = 0.0; }
+ //if (bias > 0.01) { bias = 0.01; }
+
+ //for (int i = 0; i < 4; i++) {
+ // use either :
+ // - Always the same samples.
+ // Gives a fixed pattern in the shadow, but no noise
+ //int index = i;
+ // - A random sample, based on the pixel's screen location.
+ // No banding, but the shadow moves with the camera, which looks weird.
+ // int index = int(16.0*random(gl_FragCoord.xyy, i))%16;
+ // - A random sample, based on the pixel's position in world space.
+ // The position is rounded to the millimeter to avoid too much aliasing
+ // int index = int(16.0*random(floor(Position_worldspace.xyz*1000.0), i))%16;
+
+ // being fully in the shadow will eat up 4*0.2 = 0.8
+ // 0.2 potentially remain, which is quite dark.
+ visibility -= 0.8 * (1.0 - shadow2D(shadowMap, vec3(shadowCoord.xy, (shadowCoord.z - bias) / shadowCoord.w)).r);
+ //}
+
+ gl_FragColor.rgb =
+ materialAmbientColor +
+ visibility * materialDiffuseColor * lightStrength * cosTheta +
+ visibility * materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha);
+ gl_FragColor.a = 1.0;
+}
diff --git a/src/datavis3d/engine/shaders/vertexDepthTest b/src/datavis3d/engine/shaders/vertexDepthTest
new file mode 100644
index 00000000..d62f1aa7
--- /dev/null
+++ b/src/datavis3d/engine/shaders/vertexDepthTest
@@ -0,0 +1,9 @@
+attribute highp vec3 vertexPosition_mdl;
+
+varying highp vec2 UV;
+
+void main() {
+ gl_Position = vec4(vertexPosition_mdl, 1.0);
+ UV = (vertexPosition_mdl.xy + vec2(1.0, 1.0)) / 2.0;
+}
+
diff --git a/src/datavis3d/engine/shaders/vertexShaderDepth b/src/datavis3d/engine/shaders/vertexShaderDepth
new file mode 100644
index 00000000..69521267
--- /dev/null
+++ b/src/datavis3d/engine/shaders/vertexShaderDepth
@@ -0,0 +1,8 @@
+attribute highp vec3 vertexPosition_mdl;
+
+uniform highp mat4 MVP;
+
+void main() {
+ gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
+}
+
diff --git a/src/datavis3d/engine/shaders/vertexShadow b/src/datavis3d/engine/shaders/vertexShadow
new file mode 100644
index 00000000..04923f1a
--- /dev/null
+++ b/src/datavis3d/engine/shaders/vertexShadow
@@ -0,0 +1,29 @@
+attribute highp vec3 vertexPosition_mdl;
+attribute highp vec2 vertexUV;
+attribute highp vec3 vertexNormal_mdl;
+
+uniform highp mat4 MVP;
+uniform highp mat4 V;
+uniform highp mat4 M;
+uniform highp mat4 itM;
+uniform highp vec3 lightPosition_wrld; // this is for inverted light direction, not position (we are just reusing uniform)
+uniform highp mat4 depthBiasMVP;
+
+varying highp vec2 UV;
+varying highp vec3 position_wrld;
+varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+varying highp vec4 shadowCoord;
+
+void main() {
+ gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
+ shadowCoord = depthBiasMVP * vec4(vertexPosition_mdl, 1.0);
+ position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
+ lightDirection_cmr = (V * vec4(lightPosition_wrld, 0.0)).xyz;
+ normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; // Use modelMatrix's transposed inverse, as it's scaled
+ //normal_cmr = (V * M * vec4(vertexNormal_mdl, 0.0)).xyz; // Use modelMatrix's transposed inverse, as it's scaled
+ UV = vertexUV;
+}
diff --git a/src/datavis3d/utils/shaderhelper.cpp b/src/datavis3d/utils/shaderhelper.cpp
index 50cc564d..86b3d964 100644
--- a/src/datavis3d/utils/shaderhelper.cpp
+++ b/src/datavis3d/utils/shaderhelper.cpp
@@ -92,11 +92,13 @@ void ShaderHelper::initialize()
m_viewMatrixUniform = m_program->uniformLocation("V");
m_modelMatrixUniform = m_program->uniformLocation("M");
m_invTransModelMatrixUniform = m_program->uniformLocation("itM");
+ m_depthBiasMatrixUniform = m_program->uniformLocation("depthBiasMVP");
m_lightPositionUniform = m_program->uniformLocation("lightPosition_wrld");
m_lightStrengthUniform = m_program->uniformLocation("lightStrength");
m_ambientStrengthUniform = m_program->uniformLocation("ambientStrength");
m_colorUniform = m_program->uniformLocation("color_mdl");
m_textureUniform = m_program->uniformLocation("textureSampler");
+ m_shadowUniform = m_program->uniformLocation("shadowMap");
m_positionAttr = m_program->attributeLocation("vertexPosition_mdl");
m_uvAttr = m_program->attributeLocation("vertexUV");
@@ -163,6 +165,13 @@ GLuint ShaderHelper::nModel()
return m_invTransModelMatrixUniform;
}
+GLuint ShaderHelper::depth()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_depthBiasMatrixUniform;
+}
+
GLuint ShaderHelper::lightP()
{
if (!m_initialized)
@@ -198,6 +207,13 @@ GLuint ShaderHelper::texture()
return m_textureUniform;
}
+GLuint ShaderHelper::shadow()
+{
+ if (!m_initialized)
+ qFatal("Shader not initialized");
+ return m_shadowUniform;
+}
+
GLuint ShaderHelper::posAtt()
{
if (!m_initialized)
diff --git a/src/datavis3d/utils/shaderhelper_p.h b/src/datavis3d/utils/shaderhelper_p.h
index 986ca826..42c5e9af 100644
--- a/src/datavis3d/utils/shaderhelper_p.h
+++ b/src/datavis3d/utils/shaderhelper_p.h
@@ -84,11 +84,13 @@ class ShaderHelper
GLuint view();
GLuint model();
GLuint nModel();
+ GLuint depth();
GLuint lightP();
GLuint lightS();
GLuint ambientS();
GLuint color();
GLuint texture();
+ GLuint shadow();
GLuint posAtt();
GLuint uvAtt();
@@ -112,13 +114,13 @@ class ShaderHelper
GLuint m_viewMatrixUniform;
GLuint m_modelMatrixUniform;
GLuint m_invTransModelMatrixUniform;
+ GLuint m_depthBiasMatrixUniform;
GLuint m_mvpMatrixUniform;
GLuint m_lightPositionUniform;
GLuint m_lightStrengthUniform;
GLuint m_ambientStrengthUniform;
GLuint m_textureUniform;
-
- //GLuint m_depthTexture; // currently unused
+ GLuint m_shadowUniform;
GLboolean m_initialized;
};
diff --git a/src/datavis3d/utils/texturehelper.cpp b/src/datavis3d/utils/texturehelper.cpp
index 8c3cd31b..4007953f 100644
--- a/src/datavis3d/utils/texturehelper.cpp
+++ b/src/datavis3d/utils/texturehelper.cpp
@@ -191,6 +191,46 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf
return textureid;
}
+GLuint TextureHelper::createDepthTexture(const QSize &size, GLuint &frameBuffer)
+{
+ GLuint depthtextureid;
+
+ // Create frame buffer
+ glGenFramebuffers(1, &frameBuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+
+ // Create depth texture for the shadow mapping
+ glGenTextures(1, &depthtextureid);
+ glBindTexture(GL_TEXTURE_2D, depthtextureid);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, size.width(), size.height(), 0,
+ GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // Attach texture to depth attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthtextureid, 0);
+
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+
+ // Verify that the frame buffer is complete
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ qCritical() << "Frame buffer creation failed" << status;
+ return 0;
+ }
+
+ // Restore the default framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return depthtextureid;
+}
+
void TextureHelper::deleteTexture(const GLuint *texture)
{
glDeleteTextures(1, texture);
diff --git a/src/datavis3d/utils/texturehelper_p.h b/src/datavis3d/utils/texturehelper_p.h
index fa1aa9d6..ea9ef03b 100644
--- a/src/datavis3d/utils/texturehelper_p.h
+++ b/src/datavis3d/utils/texturehelper_p.h
@@ -70,8 +70,10 @@ class TextureHelper : protected QOpenGLFunctions
GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false);
// Returns selection framebuffer and inserts generated texture id to texture parameters
GLuint createSelectionBuffer(const QSize &size, GLuint &texture, GLuint &depthTexture);
- // Returns selection texture and inserts generated framebuffers to fraembuffer parameters
+ // Returns selection texture and inserts generated framebuffers to framebuffer parameters
GLuint createSelectionTexture(const QSize &size, GLuint &frameBuffer, GLuint &depthBuffer);
+ // Returns depth texture and inserts generated framebuffer to parameter
+ GLuint createDepthTexture(const QSize &size, GLuint &frameBuffer);
void deleteTexture(const GLuint *texture);
private: