diff options
author | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-05-07 09:32:14 +0300 |
---|---|---|
committer | Tomi Korpipää <tomi.korpipaa@digia.com> | 2013-05-07 09:56:54 +0300 |
commit | bec634f4141be5300ab2354d784186f9c95a8db5 (patch) | |
tree | 037a98441db507542c109dffbc249c8a60c6ae62 /src/datavis3d | |
parent | 7c29e6efc4dcb1393f90e90dc2e5e2ef242edd41 (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.qrc | 6 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dmaps.cpp | 235 | ||||
-rw-r--r-- | src/datavis3d/engine/q3dmaps_p.h | 5 | ||||
-rw-r--r-- | src/datavis3d/engine/shaders/fragmentDepthTest | 7 | ||||
-rw-r--r-- | src/datavis3d/engine/shaders/fragmentShader | 42 | ||||
-rw-r--r-- | src/datavis3d/engine/shaders/fragmentShaderDepth | 3 | ||||
-rw-r--r-- | src/datavis3d/engine/shaders/fragmentShadow | 65 | ||||
-rw-r--r-- | src/datavis3d/engine/shaders/vertexDepthTest | 9 | ||||
-rw-r--r-- | src/datavis3d/engine/shaders/vertexShaderDepth | 8 | ||||
-rw-r--r-- | src/datavis3d/engine/shaders/vertexShadow | 29 | ||||
-rw-r--r-- | src/datavis3d/utils/shaderhelper.cpp | 16 | ||||
-rw-r--r-- | src/datavis3d/utils/shaderhelper_p.h | 6 | ||||
-rw-r--r-- | src/datavis3d/utils/texturehelper.cpp | 40 | ||||
-rw-r--r-- | src/datavis3d/utils/texturehelper_p.h | 4 |
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: |