From 161232582e7f7e7e6e991def2fe87d78e668d08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomi=20Korpip=C3=A4=C3=A4?= Date: Wed, 8 May 2013 11:05:24 +0300 Subject: Shadow mapping implementation Partially works, but mostly doesn't. Change-Id: I415833d07148d2aeae64c0c311e14766ab29ad5e Reviewed-by: Miikka Heikkinen --- src/datavis3d/engine/q3dbars.cpp | 8 +-- src/datavis3d/engine/q3dmaps.cpp | 103 ++++++++++++++++------------ src/datavis3d/engine/shaders/fragmentShadow | 55 ++++++++------- src/datavis3d/engine/shaders/vertexShadow | 9 ++- src/datavis3d/global/qdatavis3namespace.h | 7 +- src/datavis3d/utils/camerahelper.cpp | 32 +++++---- src/datavis3d/utils/camerahelper_p.h | 3 +- src/datavis3d/utils/shaderhelper.cpp | 4 +- src/datavis3d/utils/shaderhelper_p.h | 2 +- src/datavis3d/utils/texturehelper.cpp | 18 ++--- 10 files changed, 136 insertions(+), 105 deletions(-) diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp index 46bb3384..dc20a8c6 100644 --- a/src/datavis3d/engine/q3dbars.cpp +++ b/src/datavis3d/engine/q3dbars.cpp @@ -517,14 +517,14 @@ void Q3DBars::drawScene() glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(), - 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + 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); + GL_UNSIGNED_SHORT, (void *)0); // Free buffers glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -536,14 +536,14 @@ void Q3DBars::drawScene() glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(), - 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + 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); + (void *)0); // Free buffers glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/datavis3d/engine/q3dmaps.cpp b/src/datavis3d/engine/q3dmaps.cpp index 3ea4c435..78789bcd 100644 --- a/src/datavis3d/engine/q3dmaps.cpp +++ b/src/datavis3d/engine/q3dmaps.cpp @@ -64,6 +64,14 @@ //#define DISPLAY_RENDER_SPEED +// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light +// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway) +#define USE_WIDER_SHADOWS + +// You can verify that depth buffer drawing works correctly by uncommenting this. +// You should see the scene from where the light is +//#define SHOW_DEPTH_TEXTURE_SCENE + #ifdef DISPLAY_RENDER_SPEED #include #endif @@ -73,7 +81,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; +GLfloat distanceMod = 0.0f; Q3DMaps::Q3DMaps() : d_ptr(new Q3DMapsPrivate(this)) @@ -144,7 +152,9 @@ void Q3DMaps::initialize() d_ptr->m_isInitialized = true; // Update default light position - modDefaultLightPos = defaultLightPos;// * QVector3D(1.0f, 1.5f, 1.0f); +#ifndef USE_WIDER_SHADOWS + distanceMod = 1.0f; +#endif } void Q3DMaps::render() @@ -171,9 +181,7 @@ void Q3DMaps::render() } #endif - // If zoom selection is on, draw zoom scene - //drawZoomScene(); - // Draw bars scene + // Draw scene drawScene(); } @@ -204,9 +212,7 @@ 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(modDefaultLightPos); - //qDebug() << lightPos; - //lightPos = QVector3D(0.0f, 4.0f, zComp); // center of bars, 4.0f above - for testing + QVector3D lightPos = CameraHelper::calculateLightPosition(defaultLightPos, 0.0f, distanceMod); // Map adjustment direction to model matrix scaling GLfloat heightMultiplier = 0.0f; @@ -262,18 +268,29 @@ void Q3DMaps::drawScene() // Bind depth shader d_ptr->m_depthShader->bind(); + // Enable drawing to framebuffer 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 + glClear(GL_DEPTH_BUFFER_BIT); // Get the depth view matrix QMatrix4x4 depthViewMatrix; + // It may be possible to hack lightPos here if we want to make some tweaks to shadow depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -d_ptr->m_yAdjustment, zComp), QVector3D(0.0f, 1.0f, 0.0f)); + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed + //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix QMatrix4x4 depthProjectionMatrix; - depthProjectionMatrix.ortho(-10, 10, -10, 10, -10, 20); +#ifdef USE_WIDER_SHADOWS + // Use this for a bit exaggerated shadows + depthProjectionMatrix.perspective(60.0f, (GLfloat)d_ptr->m_sceneViewPort.width() + / (GLfloat)d_ptr->m_sceneViewPort.height(), 0.1f, 100.0f); +#else + // Use these for normal shadows, with the light further away + depthProjectionMatrix = projectionMatrix; +#endif #if 0 - // Draw background to depth buffer + // Draw background to depth buffer (You don't want to do this, except maybe for debugging purposes) if (d_ptr->m_backgroundObj) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -291,15 +308,14 @@ void Q3DMaps::drawScene() // 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); + 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); + (void *)0); // Free buffers glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -334,15 +350,13 @@ void Q3DMaps::drawScene() // 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); + 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); + glDrawElements(GL_TRIANGLES, d_ptr->m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); // Free buffers glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -351,13 +365,14 @@ void Q3DMaps::drawScene() glDisableVertexAttribArray(d_ptr->m_depthShader->posAtt()); } + // Disable drawing to framebuffer (= enable drawing to screen) 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 - // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper + // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) d_ptr->m_labelShader->bind(); glEnable(GL_TEXTURE_2D); QMatrix4x4 modelMatrix; @@ -421,14 +436,14 @@ void Q3DMaps::drawScene() glEnableVertexAttribArray(d_ptr->m_selectionShader->posAtt()); glBindBuffer(GL_ARRAY_BUFFER, d_ptr->m_barObj->vertexBuf()); glVertexAttribPointer(d_ptr->m_selectionShader->posAtt(), - 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + 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); + (void *)0); // Free buffers glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -491,7 +506,11 @@ void Q3DMaps::drawScene() heightMultiplier * barHeight + heightScaler, depthMultiplier * barHeight + depthScaler)); +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif QVector3D baseColor = Utils::vectorFromColor(d_ptr->m_theme->m_baseColor); QVector3D heightColor = Utils::vectorFromColor(d_ptr->m_theme->m_heightColor) @@ -565,39 +584,33 @@ void Q3DMaps::drawScene() d_ptr->m_areaSize.height() / d_ptr->m_scaleFactor)); modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#else MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; +#endif depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - 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(), - 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(), - modelMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->lightP(), lightPos); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->view(), viewMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->model(), modelMatrix); d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->nModel(), modelMatrix.inverted().transposed()); - d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->MVP(), - MVPMatrix); + d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->MVP(), MVPMatrix); d_ptr->m_backgroundShader->setUniformValue(d_ptr->m_backgroundShader->depth(), - depthBiasMVP); + depthMVPMatrix); 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, + // d_ptr->m_bgrTexture, d_ptr->m_depthTexture); + // TODO: Hack until everything works d_ptr->m_drawer->drawObject(d_ptr->m_backgroundShader, d_ptr->m_backgroundObj, - d_ptr->m_bgrTexture, d_ptr->m_depthTexture); + d_ptr->m_depthTexture, d_ptr->m_depthTexture); } // Disable textures @@ -740,8 +753,8 @@ void Q3DMaps::drawScene() // We have no ownership, don't delete. Just NULL the pointer. d_ptr->m_selectedBar = NULL; //if (d_ptr->m_zoomActivated && Q3DMapsPrivate::MouseOnOverview == d_ptr->m_mousePressed) { - //d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); - //d_ptr->m_zoomActivated = false; + //d_ptr->m_sceneViewPort = QRect(0, 0, width(), height()); + //d_ptr->m_zoomActivated = false; //} } /*else if (d_ptr->m_selectionMode >= ModeZoomRow && Q3DMapsPrivate::MouseOnScene == d_ptr->m_mousePressed) { @@ -1436,8 +1449,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 = new ShaderHelper(q_ptr, QStringLiteral(":/shaders/testDepthVert"), + // QStringLiteral(":/shaders/testDepthFrag")); m_labelShader->initialize(); } diff --git a/src/datavis3d/engine/shaders/fragmentShadow b/src/datavis3d/engine/shaders/fragmentShadow index 309c63fb..2c3c2ded 100644 --- a/src/datavis3d/engine/shaders/fragmentShadow +++ b/src/datavis3d/engine/shaders/fragmentShadow @@ -7,18 +7,36 @@ varying highp vec3 lightDirection_cmr; uniform highp float lightStrength; uniform highp float ambientStrength; -uniform highp vec3 lightPosition_wrld; uniform sampler2D textureSampler; -uniform sampler2DShadow shadowMap; +//uniform sampler2DShadow shadowMap; // use with version 2 +uniform sampler2D shadowMap; // use with version 1 -//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); -//} +// Version 1: Use this to see the shadow map void main() { - highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb; + float shadowFactor = 1.0; // default to '1' meaning "no shadow" + float epsilon = 0.1; // increase value to remove little artifacts + vec4 shadCoordsPD = shadowCoord / shadowCoord.w; + if (shadowCoord.w <= 0.0) { // ignore negative projection + shadowFactor = 1.0; + } else if (shadCoordsPD.x < 0.0 || shadCoordsPD.y < 0.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else if (shadCoordsPD.x >= 1.0 || shadCoordsPD.y >= 1.0) { // outside light frustum, ignore + shadowFactor = 1.0; + } else { + float shadow = texture2D(shadowMap, shadCoordsPD.xy).x; + if (shadow + epsilon < shadCoordsPD.z) { + shadowFactor = 0.0; + } + } + // shadow is dark gray, other parts bright yellow + gl_FragColor = vec4(0.8, 0.8, 0.0, 1.0) * shadowFactor + vec4(0.2, 0.2, 0.2, 1.0); +} + +// Version 2: Use this normally +/* +void main() { + highp vec3 materialDiffuseColor = vec3(0.8, 0.8, 0.0);//texture2D(textureSampler, UV).rgb; highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); @@ -36,26 +54,12 @@ void main() { highp float visibility = 1.0; highp float bias = 0.005; - //highp bias = 0.005 * tan(acos(cosTheta)); + + //highp float 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); - //} + visibility -= 0.8 * (1.0 - shadow2D(shadowMap, vec3(shadowCoord.xy, (shadowCoord.z - bias) / shadowCoord.w)).r); gl_FragColor.rgb = materialAmbientColor + @@ -63,3 +67,4 @@ void main() { visibility * materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha); gl_FragColor.a = 1.0; } +*/ diff --git a/src/datavis3d/engine/shaders/vertexShadow b/src/datavis3d/engine/shaders/vertexShadow index 04923f1a..24184376 100644 --- a/src/datavis3d/engine/shaders/vertexShadow +++ b/src/datavis3d/engine/shaders/vertexShadow @@ -7,7 +7,7 @@ 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; +uniform highp mat4 depthMVP; varying highp vec2 UV; varying highp vec3 position_wrld; @@ -16,9 +16,14 @@ varying highp vec3 eyeDirection_cmr; varying highp vec3 lightDirection_cmr; varying highp vec4 shadowCoord; +const highp mat4 bias = mat4(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); + void main() { gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); - shadowCoord = depthBiasMVP * vec4(vertexPosition_mdl, 1.0); + shadowCoord = bias * depthMVP * 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; diff --git a/src/datavis3d/global/qdatavis3namespace.h b/src/datavis3d/global/qdatavis3namespace.h index 2177b175..a4ca7c42 100644 --- a/src/datavis3d/global/qdatavis3namespace.h +++ b/src/datavis3d/global/qdatavis3namespace.h @@ -50,8 +50,11 @@ QTCOMMERCIALDATAVIS3D_BEGIN_NAMESPACE // Constants used in several files const GLfloat m_pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f; -const GLfloat zComp = 10.0f; // Compensation for z position; move all objects to positive z, as shader can't handle negative values correctly -const QVector3D defaultLightPos = QVector3D(0.0f, 3.0f, zComp); +// Compensation for z position; move all objects to positive z, as shader can't handle negative values correctly +const GLfloat zComp = 10.0f; +// Default light position. To have shadows working correctly, light should be as far as camera, or a bit further +// y position is added to the minimum height (or can be thought to be that much above or below the camera) +const QVector3D defaultLightPos = QVector3D(0.0f, 0.5f, zComp); const GLfloat defaultRatio = 1.0f / 1.6f; // default aspect ratio 16:10 // Enums used in several files diff --git a/src/datavis3d/utils/camerahelper.cpp b/src/datavis3d/utils/camerahelper.cpp index 7e9b7def..2e868cac 100644 --- a/src/datavis3d/utils/camerahelper.cpp +++ b/src/datavis3d/utils/camerahelper.cpp @@ -54,12 +54,12 @@ QVector3D m_up = QVector3D(0, 1, 0); QPoint m_previousMousePos(0, 0); -float m_xRotation = 0; -float m_yRotation = 0; -float m_defaultXRotation = 0; -float m_defaultYRotation = 0; +GLfloat m_xRotation = 0; +GLfloat m_yRotation = 0; +GLfloat m_defaultXRotation = 0; +GLfloat m_defaultYRotation = 0; -float m_rotationSpeed = 100; +GLfloat m_rotationSpeed = 100; // FUNCTIONS void CameraHelper::setRotationSpeed(int speed) @@ -91,9 +91,9 @@ QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, QMatrix4x4 viewMatrix; // Calculate mouse movement since last frame - float mouseMoveX = float(m_previousMousePos.x() - mousePos.x()) + GLfloat mouseMoveX = GLfloat(m_previousMousePos.x() - mousePos.x()) / (screenWidth / m_rotationSpeed); - float mouseMoveY = float(m_previousMousePos.y() - mousePos.y()) + GLfloat mouseMoveY = GLfloat(m_previousMousePos.y() - mousePos.y()) / (screenHeight / m_rotationSpeed); // Apply to rotations m_xRotation -= mouseMoveX; @@ -117,7 +117,7 @@ QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, // y rotation is always "clean" viewMatrix.rotate(m_yRotation, 1.0f, 0.0f, 0.0f); // handle zoom by scaling - viewMatrix.scale((float)zoom / 100.0f); + viewMatrix.scale((GLfloat)zoom / 100.0f); // Compensate for translation (if m_target is off origin) viewMatrix.translate(-m_target.x(), -m_target.y(), -m_target.z()); //qDebug() << m_xRotation << m_yRotation; @@ -131,12 +131,14 @@ QMatrix4x4 CameraHelper::calculateViewMatrix(const QPoint &mousePos, int zoom, return viewMatrix; } -QVector3D CameraHelper::calculateLightPosition(const QVector3D &lightPosition, float fixedRotation) +QVector3D CameraHelper::calculateLightPosition(const QVector3D &lightPosition, + GLfloat fixedRotation, GLfloat distanceModifier) { // Move light with camera QVector3D newLightPosition; - float xAngle; - float yAngle; + GLfloat radiusFactor = lightPosition.z() * (1.5f + distanceModifier); // for making sure light is outside the scene at its lowest point + GLfloat xAngle; + GLfloat yAngle; if (!fixedRotation) { xAngle = m_xRotation * m_pi / 180.0f; yAngle = m_yRotation * m_pi / 180.0f; @@ -144,10 +146,10 @@ QVector3D CameraHelper::calculateLightPosition(const QVector3D &lightPosition, f xAngle = fixedRotation * m_pi / 180.0f; yAngle = 0; } - float radius = lightPosition.y() * 2.0f; // set radius to match the highest height of the light - float zPos = radius * cos(xAngle) * cos(yAngle); - float xPos = radius * sin(xAngle) * cos(yAngle); - float yPos = lightPosition.y() * sin(yAngle); + GLfloat radius = (radiusFactor + lightPosition.y()); // set radius to match the highest height of the light + GLfloat zPos = radius * cos(xAngle) * cos(yAngle); + GLfloat xPos = radius * sin(xAngle) * cos(yAngle); + GLfloat yPos = (radiusFactor + lightPosition.y()) * sin(yAngle); // Keep light in the set position in relation to camera // TODO: Does not work perfectly yet; Light seems wrong when viewing scene from sides (or isometrically) newLightPosition = QVector3D(-xPos + lightPosition.x(), diff --git a/src/datavis3d/utils/camerahelper_p.h b/src/datavis3d/utils/camerahelper_p.h index e63061a2..68e7e5a2 100644 --- a/src/datavis3d/utils/camerahelper_p.h +++ b/src/datavis3d/utils/camerahelper_p.h @@ -82,7 +82,8 @@ class CameraHelper // Calcluate light position based on rotation. Call after calling calculateViewMatrix to get // up-to-date position static QVector3D calculateLightPosition(const QVector3D &lightPosition, - float fixedRotation = 0.0f); + GLfloat fixedRotation = 0.0f, + GLfloat distanceModifier = 0.0f); static void updateMousePos(const QPoint &mousePos); static void setCameraPreset(CameraPreset preset); }; diff --git a/src/datavis3d/utils/shaderhelper.cpp b/src/datavis3d/utils/shaderhelper.cpp index 86b3d964..f08daff0 100644 --- a/src/datavis3d/utils/shaderhelper.cpp +++ b/src/datavis3d/utils/shaderhelper.cpp @@ -92,7 +92,7 @@ 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_depthMatrixUniform = m_program->uniformLocation("depthMVP"); m_lightPositionUniform = m_program->uniformLocation("lightPosition_wrld"); m_lightStrengthUniform = m_program->uniformLocation("lightStrength"); m_ambientStrengthUniform = m_program->uniformLocation("ambientStrength"); @@ -169,7 +169,7 @@ GLuint ShaderHelper::depth() { if (!m_initialized) qFatal("Shader not initialized"); - return m_depthBiasMatrixUniform; + return m_depthMatrixUniform; } GLuint ShaderHelper::lightP() diff --git a/src/datavis3d/utils/shaderhelper_p.h b/src/datavis3d/utils/shaderhelper_p.h index 42c5e9af..d1c72ba5 100644 --- a/src/datavis3d/utils/shaderhelper_p.h +++ b/src/datavis3d/utils/shaderhelper_p.h @@ -114,7 +114,7 @@ class ShaderHelper GLuint m_viewMatrixUniform; GLuint m_modelMatrixUniform; GLuint m_invTransModelMatrixUniform; - GLuint m_depthBiasMatrixUniform; + GLuint m_depthMatrixUniform; GLuint m_mvpMatrixUniform; GLuint m_lightPositionUniform; GLuint m_lightStrengthUniform; diff --git a/src/datavis3d/utils/texturehelper.cpp b/src/datavis3d/utils/texturehelper.cpp index 4007953f..808ac309 100644 --- a/src/datavis3d/utils/texturehelper.cpp +++ b/src/datavis3d/utils/texturehelper.cpp @@ -195,23 +195,25 @@ 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_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.width(), size.height(), 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); + // Create frame buffer + glGenFramebuffers(1, &frameBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); + // Attach texture to depth attachment glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthtextureid, 0); -- cgit v1.2.3