DYTSrouce/src/viewer/OsgOpenGLWindow.cpp
2025-01-18 22:36:28 +08:00

196 lines
5.6 KiB
C++

#include "viewer/OsgOpenGLWindow.h"
#include "viewer/OSGRenderer.h"
#include <osgViewer/Viewer>
#include <osg/GL>
#include <QApplication>
#include <QKeyEvent>
#include <QInputDialog>
#include <QLayout>
#include <QMainWindow>
#include <QScreen>
#include <QWindow>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#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);
widget_->setAttribute(Qt::WA_PaintOnScreen, true);
widget_->setAttribute(Qt::WA_StaticContents, true);
widget_->setAttribute(Qt::WA_NoSystemBackground, true);
widget_->setAttribute(Qt::WA_OpaquePaintEvent, true);
widget_->setAttribute(Qt::WA_DontCreateNativeAncestors, false);
gw_ = new GraphicsWindowEx(0, 0, width(), height());
renderer_ = new OSGRenderer(this);
connect(renderer_, &OSGRenderer::RenderFlush, this, &OsgOpenGLWindow::OnRenderFlush, Qt::QueuedConnection);
connect(&timer_, &QTimer::timeout, this, &OsgOpenGLWindow::OnRender);
}
OsgOpenGLWindow::~OsgOpenGLWindow() {}
osgViewer::Viewer* OsgOpenGLWindow::getOsgViewer() {
return renderer_;
}
void OsgOpenGLWindow::initializeGL() {
//// Initializes OpenGL function resolution for the current context.
//initializeOpenGLFunctions();
//createRenderer();
//emit initialized();
QOpenGLContext* ctx = context();
dyt_check(nullptr != ctx);
ctx->doneCurrent();
gw_->SetSharedContext(context());
QApplication::postEvent(renderer_, new RenderBindGraphicsContextEvent(gw_));
setDefaultDisplaySettings();
double pixelRatio = screen()->devicePixelRatio();
gw_->UpdateWindowScale(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;
}
timer_.start(1000 / 60);
}
void OsgOpenGLWindow::resizeGL(int w, int h) {
double pixelRatio = screen()->devicePixelRatio();
gw_->UpdateWindowScale(pixelRatio);
QApplication::postEvent(renderer_, new GraphicsWindowResizeEvent(gw_, w * pixelRatio, h * pixelRatio));
}
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) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->keyPressEvent(event);
}
void OsgOpenGLWindow::keyReleaseEvent(QKeyEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->keyReleaseEvent(event);
}
void OsgOpenGLWindow::mousePressEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mousePressEvent(event);
}
void OsgOpenGLWindow::mouseReleaseEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mouseReleaseEvent(event);
}
void OsgOpenGLWindow::mouseDoubleClickEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mouseDoubleClickEvent(event);
}
void OsgOpenGLWindow::mouseMoveEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mouseMoveEvent(event);
}
void OsgOpenGLWindow::wheelEvent(QWheelEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->wheelEvent(event);
}
void OsgOpenGLWindow::setDefaultDisplaySettings() {
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
ds->setNvOptimusEnablement(1);
ds->setStereo(false);
}
void OsgOpenGLWindow::OnRenderFlush() {
shaderTextureId_ = gw_->GetFrameBufferId();
updateTexture_ = true;
}
void OsgOpenGLWindow::OnRender() {
requestUpdate();
}