diff --git a/src/viewer/GraphicsWindowEx.h b/src/viewer/GraphicsWindowEx.h index 6d7adcdd..2cb4d5d7 100644 --- a/src/viewer/GraphicsWindowEx.h +++ b/src/viewer/GraphicsWindowEx.h @@ -46,6 +46,9 @@ public: void UpdateWindowScale(float scale) { windowScale_ = scale; } + unsigned int GetFrameBufferId() const { + return frameBufferId_; + } public: void keyPressEvent(class QKeyEvent* event); diff --git a/src/viewer/OSGRenderer.cpp b/src/viewer/OSGRenderer.cpp index 2c7af4fa..f457c6f2 100644 --- a/src/viewer/OSGRenderer.cpp +++ b/src/viewer/OSGRenderer.cpp @@ -78,6 +78,15 @@ void OSGRenderer::Resize(osg::GraphicsContext* gc, int width, int height) { window->resized(0, 0, width, height); } +void OSGRenderer::Render() { + frame(); + emit RenderFlush(); +} + +void OSGRenderer::Destoy() { + done(); +} + bool OSGRenderer::event(QEvent* event) { switch (event->type()) { case INIT: { @@ -85,12 +94,20 @@ bool OSGRenderer::event(QEvent* event) { Init(e->gc_.get()); return true; } + case RENDER: { + Render(); + return true; + } case RESIZE: { GraphicsWindowResizeEvent* e = reinterpret_cast(event); Resize(e->gc_.get(), e->width_, e->height_); return true; } - + case DESTROY: { + GraphicsWindowResizeEvent* e = reinterpret_cast(event); + Resize(e->gc_.get(), e->width_, e->height_); + return true; + } } return QObject::event(event); } diff --git a/src/viewer/OSGRenderer.h b/src/viewer/OSGRenderer.h index 9fa56f53..fcc4cb9e 100644 --- a/src/viewer/OSGRenderer.h +++ b/src/viewer/OSGRenderer.h @@ -25,9 +25,9 @@ namespace { enum RenderEvent { INIT = QEvent::Type(QEvent::User + 1), - RENDER_START, + RENDER, RESIZE, - RENDER_STOP + DESTROY }; struct RenderBindGraphicsContextEvent : public QEvent { @@ -62,9 +62,14 @@ public: bool event(QEvent* event) override; +Q_SIGNALS: + void RenderFlush(); + private: void Init(osg::GraphicsContext* gc); void Resize(osg::GraphicsContext* gc, int width, int height); + void Render(); + void Destoy(); private: bool isInited_{ false }; diff --git a/src/viewer/OsgOpenGLWindow.cpp b/src/viewer/OsgOpenGLWindow.cpp index 305607cf..1731290b 100644 --- a/src/viewer/OsgOpenGLWindow.cpp +++ b/src/viewer/OsgOpenGLWindow.cpp @@ -11,15 +11,47 @@ #include #include #include +#include +#include +#include "config.h" +#include "common/SpdLogger.h" #include "viewer/GraphicsWindowEx.h" +static const char* vertexShaderSource = +"#version 330\n" +"out vec2 uv;\n" +"void main(void)\n" +"{\n" +"vec2 pos[] = vec2[](vec2(-1.0, -1.0),\n" +"vec2( 1.0, -1.0),\n" +"vec2(-1.0, 1.0),\n" +"vec2( 1.0, 1.0));\n" +"vec2 uvpos[] = vec2[](vec2(0, 0.0),\n" +"vec2( 1.0, 0.0),\n" +"vec2(0.0, 1.0),\n" +"vec2( 1.0, 1.0));\n" +"gl_Position = vec4(pos[gl_VertexID], 0.0, 1.0);\n" +"uv = uvpos[gl_VertexID];\n" +"}\n"; + +static const char* fragmentShaderSource = +"#version 330\n" +"in vec2 uv;\n" +"uniform sampler2D tex;\n" +"out vec4 vFragColor;" +"void main() {\n" +" vFragColor = vec4(texture(tex, uv).rgb, 1.0);\n" +"}\n"; + + OsgOpenGLWindow::OsgOpenGLWindow(QWidget* parent) : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, nullptr) { widget_ = QWidget::createWindowContainer(this); renderer_ = new OSGRenderer(this); + connect(renderer_, &OSGRenderer::RenderFlush, this, &OsgOpenGLWindow::OnRenderFlush); } OsgOpenGLWindow::~OsgOpenGLWindow() @@ -45,12 +77,36 @@ void OsgOpenGLWindow::initializeGL() //emit initialized(); context()->doneCurrent(); gw_->SetSharedContext(context()); - QApplication::postEvent(this, new RenderBindGraphicsContextEvent(gw_)); + QApplication::postEvent(renderer_, new RenderBindGraphicsContextEvent(gw_)); double pixelRatio = screen()->devicePixelRatio(); gw_->UpdateWindowScale(pixelRatio); - QApplication::postEvent(this, new GraphicsWindowResizeEvent(gw_, width() * pixelRatio, height() * pixelRatio)); + QApplication::postEvent(renderer_, new GraphicsWindowResizeEvent(gw_, width() * pixelRatio, height() * pixelRatio)); + QApplication::postEvent(renderer_, new QEvent(QEvent::Type(RENDER))); + + context()->makeCurrent(this); + + shaderProgram_ = new QOpenGLShaderProgram(this); + vao_ = new QOpenGLVertexArrayObject(this); + if (!vao_->create()) { + LOG_ERROR( "Failed to create VAO"); + return; + } + + if (!shaderProgram_->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource)) { + LOG_ERROR( "Failed to add vertex shader"); + return; + } + if (!shaderProgram_->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource)) { + LOG_ERROR( "Failed to add fragment shader"); + return; + } + + if (!shaderProgram_->link()) { + LOG_ERROR( "Failed to link shader program, {}", shaderProgram_->log().toLocal8Bit().constData()); + return; + } } void OsgOpenGLWindow::resizeGL(int w, int h) @@ -58,17 +114,27 @@ void OsgOpenGLWindow::resizeGL(int w, int h) Q_ASSERT(m_renderer); double pixelRatio = screen()->devicePixelRatio(); gw_->UpdateWindowScale(pixelRatio); - QApplication::postEvent(this, new GraphicsWindowResizeEvent(gw_, w * pixelRatio, h * pixelRatio)); + QApplication::postEvent(renderer_, new GraphicsWindowResizeEvent(gw_, w * pixelRatio, h * pixelRatio)); } -void OsgOpenGLWindow::paintGL() -{ - OpenThreads::ScopedReadLock locker(_osgMutex); - if (_isFirstFrame) { - _isFirstFrame = false; - m_renderer->getCamera()->getGraphicsContext()->setDefaultFboId(defaultFramebufferObject()); - } - m_renderer->frame(); +void OsgOpenGLWindow::paintUnderGL() { + if (0 == shaderTextureId_) { + return; + } + + QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions(); + f->glViewport(0, 0, width() * devicePixelRatio(), height() * devicePixelRatio()); + f->glBindTexture(GL_TEXTURE_2D, shaderTextureId_); + dyt_check(nullptr != shaderProgram_); + dyt_check(shaderProgram_->bind()); + QOpenGLVertexArrayObject::Binder vaoBinder(vao_); + f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + shaderProgram_->release(); + + if (updateTexture_) { + updateTexture_ = false; + QApplication::postEvent(renderer_, new QEvent(QEvent::Type(RENDER))); + } } void OsgOpenGLWindow::keyPressEvent(QKeyEvent* event) @@ -136,3 +202,8 @@ void OsgOpenGLWindow::createRenderer() double pixelRatio = screen()->devicePixelRatio(); m_renderer->setupOSG(width(), height(), pixelRatio);*/ } + +void OsgOpenGLWindow::OnRenderFlush() { + shaderTextureId_ = gw_->GetFrameBufferId(); + updateTexture_ = true; +} diff --git a/src/viewer/OsgOpenGLWindow.h b/src/viewer/OsgOpenGLWindow.h index 8fc5fc9b..d4dac79e 100644 --- a/src/viewer/OsgOpenGLWindow.h +++ b/src/viewer/OsgOpenGLWindow.h @@ -63,9 +63,7 @@ protected: void initializeGL() override; void resizeGL(int w, int h) override; - - //! lock scene graph and call osgViewer::frame() - void paintGL() override; + void paintUnderGL() override; //! called before creating renderer virtual void setDefaultDisplaySettings(); @@ -80,12 +78,17 @@ protected: void createRenderer(); +private: + void OnRenderFlush(); + private: QWidget* widget_{ nullptr }; osg::ref_ptr gw_; OSGRenderer* renderer_{ nullptr }; class QOpenGLShaderProgram* shaderProgram_{nullptr}; class QOpenGLVertexArrayObject* vao_{ nullptr }; + uint32_t shaderTextureId_{ 0 }; + bool updateTexture_{ false }; }; #endif // OSGQOPENGLWINDOW_H