Remove threadeqopenglwidget example
It is neither documented nor very useful, and it has platform-specific issues as reported over the years. Remove it now as part of the example revamp initiative. Task-number: QTBUG-50278 Task-number: QTBUG-110093 Task-number: QTBUG-76054 Task-number: QTBUG-43209 Pick-to: 6.5 Change-Id: I6dadaf4162b4c19411c544b9f204c19e37aa740d Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
86a517ac78
commit
6462a454e3
@ -7,7 +7,6 @@ qt_internal_add_example(openglwindow)
|
||||
qt_internal_add_example(qopenglwindow)
|
||||
if(TARGET Qt6::Widgets)
|
||||
qt_internal_add_example(contextinfo)
|
||||
qt_internal_add_example(threadedqopenglwidget)
|
||||
qt_internal_add_example(2dpainting)
|
||||
qt_internal_add_example(hellogl2)
|
||||
qt_internal_add_example(qopenglwidget)
|
||||
|
@ -7,7 +7,6 @@ SUBDIRS = hellowindow \
|
||||
|
||||
qtHaveModule(widgets) {
|
||||
SUBDIRS += contextinfo \
|
||||
threadedqopenglwidget \
|
||||
2dpainting \
|
||||
hellogl2 \
|
||||
qopenglwidget \
|
||||
|
@ -1,41 +0,0 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(threadedqopenglwidget LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/opengl/threadedqopenglwidget")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui OpenGL OpenGLWidgets Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(threadedqopenglwidget
|
||||
renderer.cpp renderer.h
|
||||
glwidget.cpp glwidget.h
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h
|
||||
)
|
||||
|
||||
set_target_properties(threadedqopenglwidget PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(threadedqopenglwidget PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::OpenGL
|
||||
Qt6::OpenGLWidgets
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS threadedqopenglwidget
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -1,71 +0,0 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "glwidget.h"
|
||||
#include "renderer.h"
|
||||
|
||||
#include <qmath.h>
|
||||
#include <QGuiApplication>
|
||||
|
||||
GLWidget::GLWidget(QWidget *parent)
|
||||
: QOpenGLWidget(parent)
|
||||
{
|
||||
setMinimumSize(300, 250);
|
||||
|
||||
connect(this, &QOpenGLWidget::aboutToCompose, this, &GLWidget::onAboutToCompose);
|
||||
connect(this, &QOpenGLWidget::frameSwapped, this, &GLWidget::onFrameSwapped);
|
||||
connect(this, &QOpenGLWidget::aboutToResize, this, &GLWidget::onAboutToResize);
|
||||
connect(this, &QOpenGLWidget::resized, this, &GLWidget::onResized);
|
||||
|
||||
m_thread = new QThread;
|
||||
m_renderer = new Renderer(this);
|
||||
m_renderer->moveToThread(m_thread);
|
||||
connect(m_thread, &QThread::finished, m_renderer, &QObject::deleteLater);
|
||||
|
||||
connect(this, &GLWidget::renderRequested, m_renderer, &Renderer::render);
|
||||
connect(m_renderer, &Renderer::contextWanted, this, &GLWidget::grabContext);
|
||||
|
||||
m_thread->start();
|
||||
}
|
||||
|
||||
GLWidget::~GLWidget()
|
||||
{
|
||||
m_renderer->prepareExit();
|
||||
m_thread->quit();
|
||||
m_thread->wait();
|
||||
delete m_thread;
|
||||
}
|
||||
|
||||
void GLWidget::onAboutToCompose()
|
||||
{
|
||||
// We are on the gui thread here. Composition is about to
|
||||
// begin. Wait until the render thread finishes.
|
||||
m_renderer->lockRenderer();
|
||||
}
|
||||
|
||||
void GLWidget::onFrameSwapped()
|
||||
{
|
||||
m_renderer->unlockRenderer();
|
||||
// Assuming a blocking swap, our animation is driven purely by the
|
||||
// vsync in this example.
|
||||
emit renderRequested();
|
||||
}
|
||||
|
||||
void GLWidget::onAboutToResize()
|
||||
{
|
||||
m_renderer->lockRenderer();
|
||||
}
|
||||
|
||||
void GLWidget::onResized()
|
||||
{
|
||||
m_renderer->unlockRenderer();
|
||||
}
|
||||
|
||||
void GLWidget::grabContext()
|
||||
{
|
||||
m_renderer->lockRenderer();
|
||||
QMutexLocker lock(m_renderer->grabMutex());
|
||||
context()->moveToThread(m_thread);
|
||||
m_renderer->grabCond()->wakeAll();
|
||||
m_renderer->unlockRenderer();
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef GLWIDGET_H
|
||||
#define GLWIDGET_H
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QThread)
|
||||
|
||||
class Renderer;
|
||||
|
||||
class GLWidget : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GLWidget(QWidget *parent = nullptr);
|
||||
~GLWidget();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *) override { }
|
||||
|
||||
signals:
|
||||
void renderRequested();
|
||||
|
||||
public slots:
|
||||
void grabContext();
|
||||
|
||||
private slots:
|
||||
void onAboutToCompose();
|
||||
void onFrameSwapped();
|
||||
void onAboutToResize();
|
||||
void onResized();
|
||||
|
||||
private:
|
||||
QThread *m_thread;
|
||||
Renderer *m_renderer;
|
||||
};
|
||||
|
||||
#endif // GLWIDGET_H
|
@ -1,88 +0,0 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QScreen>
|
||||
#include <QShortcut>
|
||||
#include <QSurfaceFormat>
|
||||
#include <QOpenGLContext>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QCommandLineParser>
|
||||
#include <QCommandLineOption>
|
||||
#include "mainwindow.h"
|
||||
#include "glwidget.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
static QString getGlString(QOpenGLFunctions *functions, GLenum name)
|
||||
{
|
||||
if (const GLubyte *p = functions->glGetString(name))
|
||||
return QString::fromLatin1(reinterpret_cast<const char *>(p));
|
||||
return QString();
|
||||
}
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
QApplication a( argc, argv );
|
||||
|
||||
QCoreApplication::setApplicationName("Qt Threaded QOpenGLWidget Example");
|
||||
QCoreApplication::setOrganizationName("QtProject");
|
||||
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
QCommandLineOption singleOption("single", "Single thread");
|
||||
parser.addOption(singleOption);
|
||||
parser.process(a);
|
||||
|
||||
QSurfaceFormat format;
|
||||
format.setDepthBufferSize(16);
|
||||
QSurfaceFormat::setDefaultFormat(format);
|
||||
|
||||
// Two top-level windows with two QOpenGLWidget children in each.
|
||||
// The rendering for the four QOpenGLWidgets happens on four separate threads.
|
||||
|
||||
GLWidget topLevelGlWidget;
|
||||
QPoint pos = topLevelGlWidget.screen()->availableGeometry().topLeft() + QPoint(200, 200);
|
||||
topLevelGlWidget.setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example top level"));
|
||||
topLevelGlWidget.resize(200, 200);
|
||||
topLevelGlWidget.move(pos);
|
||||
topLevelGlWidget.show();
|
||||
auto *closeShortcut = new QShortcut(Qt::CTRL | Qt::Key_Q, &a, QApplication::closeAllWindows);
|
||||
closeShortcut->setContext(Qt::ApplicationShortcut);
|
||||
|
||||
const QString glInfo = getGlString(topLevelGlWidget.context()->functions(), GL_VENDOR)
|
||||
+ QLatin1Char('/') + getGlString(topLevelGlWidget.context()->functions(), GL_RENDERER);
|
||||
|
||||
const bool supportsThreading = !glInfo.contains(QLatin1String("nouveau"), Qt::CaseInsensitive)
|
||||
&& !glInfo.contains(QLatin1String("ANGLE"), Qt::CaseInsensitive)
|
||||
&& !glInfo.contains(QLatin1String("llvmpipe"), Qt::CaseInsensitive);
|
||||
|
||||
const QString toolTip = supportsThreading ? glInfo : glInfo + QStringLiteral("\ndoes not support threaded OpenGL.");
|
||||
topLevelGlWidget.setToolTip(toolTip);
|
||||
|
||||
std::unique_ptr<MainWindow> mw1;
|
||||
std::unique_ptr<MainWindow> mw2;
|
||||
if (!parser.isSet(singleOption)) {
|
||||
if (supportsThreading) {
|
||||
pos += QPoint(100, 100);
|
||||
mw1.reset(new MainWindow);
|
||||
mw1->setToolTip(toolTip);
|
||||
mw1->move(pos);
|
||||
mw1->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #1"));
|
||||
mw1->show();
|
||||
pos += QPoint(100, 100);
|
||||
mw2.reset(new MainWindow);
|
||||
mw2->setToolTip(toolTip);
|
||||
mw2->move(pos);
|
||||
mw2->setWindowTitle(QStringLiteral("Threaded QOpenGLWidget example #2"));
|
||||
mw2->show();
|
||||
} else {
|
||||
qWarning() << toolTip;
|
||||
}
|
||||
}
|
||||
|
||||
return a.exec();
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "glwidget.h"
|
||||
|
||||
MainWindow::MainWindow()
|
||||
{
|
||||
setMinimumSize(800, 400);
|
||||
GLWidget *glwidget1 = new GLWidget(this);
|
||||
glwidget1->resize(400, 400);
|
||||
|
||||
GLWidget *glwidget2 = new GLWidget(this);
|
||||
glwidget2->resize(400, 400);
|
||||
glwidget2->move(400, 0);
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class MainWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow();
|
||||
};
|
||||
|
||||
#endif
|
@ -1,267 +0,0 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "renderer.h"
|
||||
#include <qmath.h>
|
||||
#include <QOpenGLWidget>
|
||||
#include <QGuiApplication>
|
||||
|
||||
static const char VERTEX_SHADER[] = R"(attribute highp vec4 vertex;
|
||||
attribute mediump vec3 normal;
|
||||
uniform mediump mat4 matrix;
|
||||
varying mediump vec4 color;
|
||||
void main(void)
|
||||
{
|
||||
vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));
|
||||
float angle = max(dot(normal, toLight), 0.0);
|
||||
vec3 col = vec3(0.40, 1.0, 0.0);
|
||||
color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
gl_Position = matrix * vertex;
|
||||
}
|
||||
)";
|
||||
|
||||
static const char FRAGMENT_SHADER[] = R"(varying mediump vec4 color;
|
||||
void main(void)
|
||||
{
|
||||
gl_FragColor = color;
|
||||
}
|
||||
)";
|
||||
|
||||
Renderer::Renderer(QOpenGLWidget *w) :
|
||||
m_glwidget(w)
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::paintQtLogo()
|
||||
{
|
||||
vbo.bind();
|
||||
program.setAttributeBuffer(vertexAttr, GL_FLOAT, 0, 3);
|
||||
program.setAttributeBuffer(normalAttr, GL_FLOAT, vertices.count() * 3 * sizeof(GLfloat), 3);
|
||||
vbo.release();
|
||||
|
||||
program.enableAttributeArray(vertexAttr);
|
||||
program.enableAttributeArray(normalAttr);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
|
||||
|
||||
program.disableAttributeArray(normalAttr);
|
||||
program.disableAttributeArray(vertexAttr);
|
||||
}
|
||||
|
||||
// Some OpenGL implementations have serious issues with compiling and linking
|
||||
// shaders on multiple threads concurrently. Avoid this.
|
||||
Q_GLOBAL_STATIC(QMutex, initMutex)
|
||||
|
||||
void Renderer::render()
|
||||
{
|
||||
if (m_exiting)
|
||||
return;
|
||||
|
||||
QOpenGLContext *ctx = m_glwidget->context();
|
||||
if (!ctx) // QOpenGLWidget not yet initialized
|
||||
return;
|
||||
|
||||
// Grab the context.
|
||||
m_grabMutex.lock();
|
||||
emit contextWanted();
|
||||
m_grabCond.wait(&m_grabMutex);
|
||||
QMutexLocker lock(&m_renderMutex);
|
||||
m_grabMutex.unlock();
|
||||
|
||||
if (m_exiting)
|
||||
return;
|
||||
|
||||
Q_ASSERT(ctx->thread() == QThread::currentThread());
|
||||
|
||||
// Make the context (and an offscreen surface) current for this thread. The
|
||||
// QOpenGLWidget's fbo is bound in the context.
|
||||
m_glwidget->makeCurrent();
|
||||
|
||||
if (!m_inited) {
|
||||
m_inited = true;
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
QMutexLocker initLock(initMutex());
|
||||
QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
|
||||
vshader->compileSourceCode(VERTEX_SHADER);
|
||||
|
||||
QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
|
||||
fshader->compileSourceCode(FRAGMENT_SHADER);
|
||||
|
||||
program.addShader(vshader);
|
||||
program.addShader(fshader);
|
||||
program.link();
|
||||
|
||||
vertexAttr = program.attributeLocation("vertex");
|
||||
normalAttr = program.attributeLocation("normal");
|
||||
matrixUniform = program.uniformLocation("matrix");
|
||||
|
||||
m_fAngle = 0;
|
||||
m_fScale = 1;
|
||||
createGeometry();
|
||||
|
||||
vbo.create();
|
||||
vbo.bind();
|
||||
const int verticesSize = vertices.count() * 3 * sizeof(GLfloat);
|
||||
vbo.allocate(verticesSize * 2);
|
||||
vbo.write(0, vertices.constData(), verticesSize);
|
||||
vbo.write(verticesSize, normals.constData(), verticesSize);
|
||||
|
||||
m_elapsed.start();
|
||||
}
|
||||
|
||||
//qDebug("%p elapsed %lld", QThread::currentThread(), m_elapsed.restart());
|
||||
|
||||
glClearColor(0.1f, 0.2f, 0.2f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glFrontFace(GL_CW);
|
||||
glCullFace(GL_FRONT);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
QMatrix4x4 modelview;
|
||||
modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
|
||||
modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
|
||||
modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f);
|
||||
modelview.scale(m_fScale);
|
||||
modelview.translate(0.0f, -0.2f, 0.0f);
|
||||
|
||||
program.bind();
|
||||
program.setUniformValue(matrixUniform, modelview);
|
||||
paintQtLogo();
|
||||
program.release();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
m_fAngle += 1.0f;
|
||||
|
||||
// Make no context current on this thread and move the QOpenGLWidget's
|
||||
// context back to the gui thread.
|
||||
m_glwidget->doneCurrent();
|
||||
ctx->moveToThread(qGuiApp->thread());
|
||||
|
||||
// Schedule composition. Note that this will use QueuedConnection, meaning
|
||||
// that update() will be invoked on the gui thread.
|
||||
QMetaObject::invokeMethod(m_glwidget, "update");
|
||||
}
|
||||
|
||||
void Renderer::createGeometry()
|
||||
{
|
||||
vertices.clear();
|
||||
normals.clear();
|
||||
|
||||
qreal x1 = +0.06f;
|
||||
qreal y1 = -0.14f;
|
||||
qreal x2 = +0.14f;
|
||||
qreal y2 = -0.06f;
|
||||
qreal x3 = +0.08f;
|
||||
qreal y3 = +0.00f;
|
||||
qreal x4 = +0.30f;
|
||||
qreal y4 = +0.22f;
|
||||
|
||||
quad(x1, y1, x2, y2, y2, x2, y1, x1);
|
||||
quad(x3, y3, x4, y4, y4, x4, y3, x3);
|
||||
|
||||
extrude(x1, y1, x2, y2);
|
||||
extrude(x2, y2, y2, x2);
|
||||
extrude(y2, x2, y1, x1);
|
||||
extrude(y1, x1, x1, y1);
|
||||
extrude(x3, y3, x4, y4);
|
||||
extrude(x4, y4, y4, x4);
|
||||
extrude(y4, x4, y3, x3);
|
||||
|
||||
const int NumSectors = 100;
|
||||
const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
|
||||
|
||||
for (int i = 0; i < NumSectors; ++i) {
|
||||
qreal angle = i * sectorAngle;
|
||||
qreal sinAngle = sin(angle);
|
||||
qreal cosAngle = cos(angle);
|
||||
qreal x5 = 0.30 * sinAngle;
|
||||
qreal y5 = 0.30 * cosAngle;
|
||||
qreal x6 = 0.20 * sinAngle;
|
||||
qreal y6 = 0.20 * cosAngle;
|
||||
|
||||
angle += sectorAngle;
|
||||
sinAngle = sin(angle);
|
||||
cosAngle = cos(angle);
|
||||
qreal x7 = 0.20 * sinAngle;
|
||||
qreal y7 = 0.20 * cosAngle;
|
||||
qreal x8 = 0.30 * sinAngle;
|
||||
qreal y8 = 0.30 * cosAngle;
|
||||
|
||||
quad(x5, y5, x6, y6, x7, y7, x8, y8);
|
||||
|
||||
extrude(x6, y6, x7, y7);
|
||||
extrude(x8, y8, x5, y5);
|
||||
}
|
||||
|
||||
for (qsizetype i = 0; i < vertices.size(); ++i)
|
||||
vertices[i] *= 2.0f;
|
||||
}
|
||||
|
||||
void Renderer::quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4)
|
||||
{
|
||||
vertices << QVector3D(x1, y1, -0.05f);
|
||||
vertices << QVector3D(x2, y2, -0.05f);
|
||||
vertices << QVector3D(x4, y4, -0.05f);
|
||||
|
||||
vertices << QVector3D(x3, y3, -0.05f);
|
||||
vertices << QVector3D(x4, y4, -0.05f);
|
||||
vertices << QVector3D(x2, y2, -0.05f);
|
||||
|
||||
QVector3D n = QVector3D::normal
|
||||
(QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(x4 - x1, y4 - y1, 0.0f));
|
||||
|
||||
normals << n;
|
||||
normals << n;
|
||||
normals << n;
|
||||
|
||||
normals << n;
|
||||
normals << n;
|
||||
normals << n;
|
||||
|
||||
vertices << QVector3D(x4, y4, 0.05f);
|
||||
vertices << QVector3D(x2, y2, 0.05f);
|
||||
vertices << QVector3D(x1, y1, 0.05f);
|
||||
|
||||
vertices << QVector3D(x2, y2, 0.05f);
|
||||
vertices << QVector3D(x4, y4, 0.05f);
|
||||
vertices << QVector3D(x3, y3, 0.05f);
|
||||
|
||||
n = QVector3D::normal
|
||||
(QVector3D(x2 - x4, y2 - y4, 0.0f), QVector3D(x1 - x4, y1 - y4, 0.0f));
|
||||
|
||||
normals << n;
|
||||
normals << n;
|
||||
normals << n;
|
||||
|
||||
normals << n;
|
||||
normals << n;
|
||||
normals << n;
|
||||
}
|
||||
|
||||
void Renderer::extrude(qreal x1, qreal y1, qreal x2, qreal y2)
|
||||
{
|
||||
vertices << QVector3D(x1, y1, +0.05f);
|
||||
vertices << QVector3D(x2, y2, +0.05f);
|
||||
vertices << QVector3D(x1, y1, -0.05f);
|
||||
|
||||
vertices << QVector3D(x2, y2, -0.05f);
|
||||
vertices << QVector3D(x1, y1, -0.05f);
|
||||
vertices << QVector3D(x2, y2, +0.05f);
|
||||
|
||||
QVector3D n = QVector3D::normal
|
||||
(QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f));
|
||||
|
||||
normals << n;
|
||||
normals << n;
|
||||
normals << n;
|
||||
|
||||
normals << n;
|
||||
normals << n;
|
||||
normals << n;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef RENDERER_H
|
||||
#define RENDERER_H
|
||||
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLBuffer>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QVector3D>
|
||||
#include <QMatrix4x4>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QOpenGLWidget)
|
||||
|
||||
class Renderer : public QObject, protected QOpenGLFunctions
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Renderer(QOpenGLWidget *w);
|
||||
void lockRenderer() { m_renderMutex.lock(); }
|
||||
void unlockRenderer() { m_renderMutex.unlock(); }
|
||||
QMutex *grabMutex() { return &m_grabMutex; }
|
||||
QWaitCondition *grabCond() { return &m_grabCond; }
|
||||
void prepareExit() { m_exiting = true; m_grabCond.wakeAll(); }
|
||||
|
||||
signals:
|
||||
void contextWanted();
|
||||
|
||||
public slots:
|
||||
void render();
|
||||
|
||||
private:
|
||||
void paintQtLogo();
|
||||
void createGeometry();
|
||||
void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4);
|
||||
void extrude(qreal x1, qreal y1, qreal x2, qreal y2);
|
||||
|
||||
bool m_inited = false;
|
||||
qreal m_fAngle = 0;
|
||||
qreal m_fScale = 1;
|
||||
QList<QVector3D> vertices;
|
||||
QList<QVector3D> normals;
|
||||
QOpenGLShaderProgram program;
|
||||
QOpenGLBuffer vbo;
|
||||
int vertexAttr = 0;
|
||||
int normalAttr = 0;
|
||||
int matrixUniform = 0;
|
||||
QOpenGLWidget *m_glwidget = nullptr;
|
||||
QMutex m_renderMutex;
|
||||
QElapsedTimer m_elapsed;
|
||||
QMutex m_grabMutex;
|
||||
QWaitCondition m_grabCond;
|
||||
bool m_exiting = false;
|
||||
};
|
||||
|
||||
#endif // RENDERER_H
|
@ -1,13 +0,0 @@
|
||||
QT += widgets opengl openglwidgets
|
||||
|
||||
SOURCES += main.cpp \
|
||||
glwidget.cpp \
|
||||
mainwindow.cpp \
|
||||
renderer.cpp
|
||||
|
||||
HEADERS += glwidget.h \
|
||||
mainwindow.h \
|
||||
renderer.h
|
||||
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/opengl/threadedqopenglwidget
|
||||
INSTALLS += target
|
Loading…
Reference in New Issue
Block a user