Skip to content

Commit

Permalink
fix shadow and EDL not being exported in animations
Browse files Browse the repository at this point in the history
  • Loading branch information
NEDJIMAbelgacem authored and wonder-sk committed Mar 1, 2021
1 parent 96fd952 commit 0466ba3
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 167 deletions.
20 changes: 4 additions & 16 deletions src/3d/qgs3dmapscene.cpp
Expand Up @@ -1000,10 +1000,7 @@ void Qgs3DMapScene::onSkyboxSettingsChanged()

void Qgs3DMapScene::onShadowSettingsChanged()
{
QgsWindow3DEngine *windowEngine = dynamic_cast<QgsWindow3DEngine *>( mEngine );
if ( windowEngine == nullptr )
return;
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = windowEngine->shadowRenderingFrameGraph();
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();

QList<QgsDirectionalLightSettings> directionalLights = mMap.directionalLights();
QgsShadowSettings shadowSettings = mMap.shadowSettings();
Expand All @@ -1022,28 +1019,19 @@ void Qgs3DMapScene::onShadowSettingsChanged()

void Qgs3DMapScene::onDebugShadowMapSettingsChanged()
{
QgsWindow3DEngine *windowEngine = dynamic_cast<QgsWindow3DEngine *>( mEngine );
if ( windowEngine == nullptr )
return;
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = windowEngine->shadowRenderingFrameGraph();
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();
shadowRenderingFrameGraph->setupShadowMapDebugging( mMap.debugShadowMapEnabled(), mMap.debugShadowMapCorner(), mMap.debugShadowMapSize() );
}

void Qgs3DMapScene::onDebugDepthMapSettingsChanged()
{
QgsWindow3DEngine *windowEngine = dynamic_cast<QgsWindow3DEngine *>( mEngine );
if ( windowEngine == nullptr )
return;
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = windowEngine->shadowRenderingFrameGraph();
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();
shadowRenderingFrameGraph->setupDepthMapDebugging( mMap.debugDepthMapEnabled(), mMap.debugDepthMapCorner(), mMap.debugDepthMapSize() );
}

void Qgs3DMapScene::onEyeDomeShadingSettingsChanged()
{
QgsWindow3DEngine *windowEngine = dynamic_cast<QgsWindow3DEngine *>( mEngine );
if ( windowEngine == nullptr )
return;
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = windowEngine->shadowRenderingFrameGraph();
QgsShadowRenderingFrameGraph *shadowRenderingFrameGraph = mEngine->frameGraph();

bool edlEnabled = mMap.eyeDomeLightingEnabled();
double edlStrength = mMap.eyeDomeLightingStrength();
Expand Down
4 changes: 4 additions & 0 deletions src/3d/qgsabstract3dengine.h
Expand Up @@ -38,6 +38,8 @@ namespace Qt3DRender
class QFrameGraphNode;
}

class QgsShadowRenderingFrameGraph;

/**
* \ingroup 3d
* \brief Base class for 3D engine implementation. A 3D engine is responsible for setting up
Expand Down Expand Up @@ -94,6 +96,8 @@ class _3D_EXPORT QgsAbstract3DEngine : public QObject
*/
virtual QSurface *surface() const = 0;

virtual QgsShadowRenderingFrameGraph *frameGraph() = 0;

signals:
//! Emitted after a call to requestCaptureImage() to return the captured image.
void imageCaptured( const QImage &image );
Expand Down
137 changes: 18 additions & 119 deletions src/3d/qgsoffscreen3dengine.cpp
Expand Up @@ -36,29 +36,8 @@
#include <Qt3DRender/QViewport>
#include <QtGui/QOpenGLContext>


QgsOffscreen3DEngine::QgsOffscreen3DEngine()
{
// Set up the default OpenGL surface format.
QSurfaceFormat format;

// by default we get just some older version of OpenGL from the system,
// but for 3D lines we use "primitive restart" functionality supported in OpenGL >= 3.1
// Qt3DWindow uses this - requesting OpenGL 4.3 - so let's request the same version.
#ifdef QT_OPENGL_ES_2
format.setRenderableType( QSurfaceFormat::OpenGLES );
#else
if ( QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL )
{
format.setVersion( 4, 3 );
format.setProfile( QSurfaceFormat::CoreProfile );
}
#endif

format.setMajorVersion( 3 );
format.setDepthBufferSize( 32 ); // TODO: or 24? (used by QWindow3D)
format.setSamples( 8 );
QSurfaceFormat::setDefaultFormat( format );

// Set up a camera to point at the shapes.
mCamera = new Qt3DRender::QCamera;
Expand All @@ -80,19 +59,23 @@ QgsOffscreen3DEngine::QgsOffscreen3DEngine()
// component must be held by the root of the QEntity tree,
// so it is added to this one. The 3D scene is added as a subtree later,
// in setRootEntity().
mRoot = new Qt3DCore::QEntity();
mRoot = new Qt3DCore::QEntity;
mRenderSettings = new Qt3DRender::QRenderSettings( mRoot );
mRoot->addComponent( mRenderSettings );

mCamera->setParent( mRoot );

// Create the offscreen frame graph, which will manage all of the resources required
// for rendering without a QWindow.
createFrameGraph();
mOffscreenSurface = new QOffscreenSurface();
mOffscreenSurface->create();

mFrameGraph = new QgsShadowRenderingFrameGraph( mOffscreenSurface, mSize, mCamera, mRoot );
mFrameGraph->renderSurfaceSelector()->setExternalRenderTargetSize( mSize );
mFrameGraph->setShadowRenderingEnabled( false );
// Set this frame graph to be in use.
// the render settings also sets itself as the parent of mSurfaceSelector
mRenderSettings->setActiveFrameGraph( mSurfaceSelector );
mRenderSettings->setActiveFrameGraph( mFrameGraph->frameGraphRoot() );

// Set the root entity of the engine. This causes the engine to begin running.
mAspectEngine->setRootEntity( Qt3DCore::QEntityPtr( mRoot ) );
Expand All @@ -109,98 +92,18 @@ void QgsOffscreen3DEngine::setSize( QSize s )
{
mSize = s;

mTexture->setSize( mSize.width(), mSize.height() );
mDepthTexture->setSize( mSize.width(), mSize.height() );
mSurfaceSelector->setExternalRenderTargetSize( mSize );

mFrameGraph->setSize( mSize );
mCamera->setAspectRatio( float( mSize.width() ) / float( mSize.height() ) );
}

void QgsOffscreen3DEngine::setClearColor( const QColor &color )
{
mClearBuffers->setClearColor( color );
mFrameGraph->setClearColor( color );
}

void QgsOffscreen3DEngine::setFrustumCullingEnabled( bool enabled )
{
// TODO
Q_UNUSED( enabled )
}

void QgsOffscreen3DEngine::createRenderTarget()
{
mTextureTarget = new Qt3DRender::QRenderTarget;

// The lifetime of the objects created here is managed
// automatically, as they become children of this object.

// Create a render target output for rendering color.
mTextureOutput = new Qt3DRender::QRenderTargetOutput( mTextureTarget );
mTextureOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Color0 );

// Create a texture to render into.
mTexture = new Qt3DRender::QTexture2D( mTextureOutput );
mTexture->setSize( mSize.width(), mSize.height() );
mTexture->setFormat( Qt3DRender::QAbstractTexture::RGB8_UNorm );
mTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
mTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );

// Hook the texture up to our output, and the output up to this object.
mTextureOutput->setTexture( mTexture );
mTextureTarget->addOutput( mTextureOutput );

mDepthTextureOutput = new Qt3DRender::QRenderTargetOutput( mTextureTarget );
mDepthTextureOutput->setAttachmentPoint( Qt3DRender::QRenderTargetOutput::Depth );
mDepthTexture = new Qt3DRender::QTexture2D( mDepthTextureOutput );
mDepthTexture->setSize( mSize.width(), mSize.height() );
mDepthTexture->setFormat( Qt3DRender::QAbstractTexture::DepthFormat );
mDepthTexture->setMinificationFilter( Qt3DRender::QAbstractTexture::Linear );
mDepthTexture->setMagnificationFilter( Qt3DRender::QAbstractTexture::Linear );
mDepthTexture->setComparisonFunction( Qt3DRender::QAbstractTexture::CompareLessEqual );
mDepthTexture->setComparisonMode( Qt3DRender::QAbstractTexture::CompareRefToTexture );
// Hook up the depth texture
mDepthTextureOutput->setTexture( mDepthTexture );
mTextureTarget->addOutput( mDepthTextureOutput );
}

void QgsOffscreen3DEngine::createFrameGraph()
{
// Firstly, create the offscreen surface. This will take the place
// of a QWindow, allowing us to render our scene without one.
mOffscreenSurface = new QOffscreenSurface();
mOffscreenSurface->setFormat( QSurfaceFormat::defaultFormat() );
mOffscreenSurface->create();

// Hook it up to the frame graph.
mSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector( mRenderSettings );
mSurfaceSelector->setSurface( mOffscreenSurface );
mSurfaceSelector->setExternalRenderTargetSize( mSize );

// Create a texture to render into. This acts as the buffer that
// holds the rendered image.
mRenderTargetSelector = new Qt3DRender::QRenderTargetSelector( mSurfaceSelector );
createRenderTarget();
// the target selector also sets itself as the parent of mTextureTarget
mRenderTargetSelector->setTarget( mTextureTarget );

// Create a node used for clearing the required buffers.
mClearBuffers = new Qt3DRender::QClearBuffers( mRenderTargetSelector );
mClearBuffers->setClearColor( QColor( 100, 100, 100, 255 ) );
mClearBuffers->setBuffers( Qt3DRender::QClearBuffers::ColorDepthBuffer );

// Create a viewport node. The viewport here just covers the entire render area.
mViewport = new Qt3DRender::QViewport( mRenderTargetSelector );
mViewport->setNormalizedRect( QRectF( 0.0, 0.0, 1.0, 1.0 ) );

// Create a camera selector node, and tell it to use the camera we've ben given.
mCameraSelector = new Qt3DRender::QCameraSelector( mViewport );
mCameraSelector->setCamera( mCamera );

// Add a render capture node to the frame graph.
// This is set as the next child of the render target selector node,
// so that the capture will be taken from the specified render target
// once all other rendering operations have taken place.
mRenderCapture = new Qt3DRender::QRenderCapture( mRenderTargetSelector );
mFrameGraph->setFrustumCullingEnabled( false );
}

void QgsOffscreen3DEngine::setRootEntity( Qt3DCore::QEntity *root )
Expand All @@ -213,7 +116,9 @@ void QgsOffscreen3DEngine::setRootEntity( Qt3DCore::QEntity *root )

// Parent the incoming scene root to our current root entity.
mSceneRoot = root;
mSceneRoot->setParent( mAspectEngine->rootEntity().data() );
mSceneRoot->setParent( mRoot );
root->addComponent( mFrameGraph->forwardRenderLayer() );
root->addComponent( mFrameGraph->castShadowsLayer() );
}

Qt3DRender::QRenderSettings *QgsOffscreen3DEngine::renderSettings()
Expand All @@ -238,17 +143,11 @@ QSurface *QgsOffscreen3DEngine::surface() const

void QgsOffscreen3DEngine::requestCaptureImage()
{
if ( mReply )
{
QgsDebugMsgLevel( QStringLiteral( "already having a pending capture, skipping" ), 2 );
return;
}
mReply = mRenderCapture->requestCapture();
connect( mReply, &Qt3DRender::QRenderCaptureReply::completed, this, [ = ]
Qt3DRender::QRenderCaptureReply *captureReply;
captureReply = mFrameGraph->renderCapture()->requestCapture();
connect( captureReply, &Qt3DRender::QRenderCaptureReply::completed, this, [ = ]
{
QImage image = mReply->image();
mReply->deleteLater();
mReply = nullptr;
emit imageCaptured( image );
emit imageCaptured( captureReply->image() );
captureReply->deleteLater();
} );
}
23 changes: 4 additions & 19 deletions src/3d/qgsoffscreen3dengine.h
Expand Up @@ -48,6 +48,8 @@ namespace Qt3DLogic
class QLogicAspect;
}

#include "qgsshadowrenderingframegraph.h"

#define SIP_NO_FILE

/**
Expand Down Expand Up @@ -81,16 +83,12 @@ class _3D_EXPORT QgsOffscreen3DEngine : public QgsAbstract3DEngine

void requestCaptureImage() override;

private:
void createRenderTarget();
void createFrameGraph();

QgsShadowRenderingFrameGraph *frameGraph() override { return mFrameGraph; }
private:

QSize mSize = QSize( 640, 480 );
Qt3DRender::QCamera *mCamera = nullptr;
QOffscreenSurface *mOffscreenSurface = nullptr;
Qt3DRender::QRenderCaptureReply *mReply = nullptr;

// basic Qt3D stuff
Qt3DCore::QAspectEngine *mAspectEngine = nullptr; // The aspect engine, which holds the scene and related aspects.
Expand All @@ -100,20 +98,7 @@ class _3D_EXPORT QgsOffscreen3DEngine : public QgsAbstract3DEngine
Qt3DCore::QNode *mSceneRoot = nullptr; // The scene root, which becomes a child of the engine's root entity.
Qt3DCore::QEntity *mRoot = nullptr;

// render target stuff
Qt3DRender::QRenderTarget *mTextureTarget = nullptr;
Qt3DRender::QRenderTargetOutput *mTextureOutput = nullptr;
Qt3DRender::QTexture2D *mTexture = nullptr;
Qt3DRender::QRenderTargetOutput *mDepthTextureOutput = nullptr;
Qt3DRender::QTexture2D *mDepthTexture = nullptr;

// frame graph stuff
Qt3DRender::QRenderSurfaceSelector *mSurfaceSelector = nullptr;
Qt3DRender::QRenderTargetSelector *mRenderTargetSelector = nullptr;
Qt3DRender::QViewport *mViewport = nullptr;
Qt3DRender::QClearBuffers *mClearBuffers = nullptr;
Qt3DRender::QCameraSelector *mCameraSelector = nullptr;
Qt3DRender::QRenderCapture *mRenderCapture = nullptr; // The render capture node, which is appended to the frame graph.
QgsShadowRenderingFrameGraph *mFrameGraph = nullptr;

};

Expand Down

0 comments on commit 0466ba3

Please sign in to comment.