Skip to content

Commit 5b6624f

Browse files
committed
Add OpenGL example
1 parent df1fa27 commit 5b6624f

18 files changed

+1082
-1
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,5 +385,5 @@ MigrationBackup/
385385
FodyWeavers.xsd
386386
/ build
387387
/Settings.ini
388-
.vscode/settings.json
388+
.vscode/
389389
/.settings

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ add_subdirectory(autohide)
99
add_subdirectory(autohidedragndrop)
1010
add_subdirectory(emptydockarea)
1111
add_subdirectory(dockindock)
12+
add_subdirectory(openGL)

examples/examples.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ SUBDIRS = \
55
autohidedragndrop \
66
centralwidget \
77
simple \
8+
openGL \
89
hideshow \
910
sidebar \
1011
deleteonclose \

examples/openGL/CMakeLists.txt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
3+
project(OpenGLExample VERSION ${VERSION_SHORT})
4+
5+
find_package(
6+
QT NAMES Qt6
7+
COMPONENTS Core
8+
Gui
9+
Widgets
10+
Charts
11+
OpenGLWidgets
12+
Quick
13+
QuickWidgets
14+
REQUIRED)
15+
find_package(
16+
Qt${QT_VERSION_MAJOR}
17+
COMPONENTS Core
18+
Gui
19+
Widgets
20+
Charts
21+
OpenGLWidgets
22+
Quick
23+
QuickWidgets
24+
REQUIRED)
25+
26+
set(CMAKE_INCLUDE_CURRENT_DIR ON)
27+
28+
add_executable(
29+
${PROJECT_NAME} WIN32
30+
main.cpp
31+
mainwindow.cpp
32+
mainwindow.h
33+
glwindow.cpp
34+
glwindow.h
35+
glwidget.h
36+
glwidget.cpp
37+
logo.cpp
38+
logo.h)
39+
40+
target_include_directories(${PROJECT_NAME}
41+
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
42+
target_link_libraries(${PROJECT_NAME}
43+
PRIVATE qtadvanceddocking-qt${QT_VERSION_MAJOR})
44+
45+
# Resources:
46+
set(esource_files "qtlogo.png")
47+
48+
qt_add_resources(${PROJECT_NAME} "OpenGLExample" PREFIX "/" FILES
49+
${esource_files})
50+
51+
target_link_libraries(
52+
${PROJECT_NAME}
53+
PUBLIC Qt${QT_VERSION_MAJOR}::Core
54+
Qt${QT_VERSION_MAJOR}::Gui
55+
Qt${QT_VERSION_MAJOR}::Widgets
56+
Qt${QT_VERSION_MAJOR}::Charts
57+
Qt${QT_VERSION_MAJOR}::OpenGLWidgets
58+
Qt${QT_VERSION_MAJOR}::Quick
59+
Qt${QT_VERSION_MAJOR}::QuickWidgets)
60+
61+
set_target_properties(
62+
${PROJECT_NAME}
63+
PROPERTIES AUTOMOC ON
64+
AUTORCC ON
65+
AUTOUIC ON
66+
CXX_STANDARD 14
67+
CXX_STANDARD_REQUIRED ON
68+
CXX_EXTENSIONS OFF
69+
VERSION ${VERSION_SHORT}
70+
EXPORT_NAME "Qt Advanced Docking System OpenGL Example"
71+
ARCHIVE_OUTPUT_DIRECTORY
72+
"${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
73+
LIBRARY_OUTPUT_DIRECTORY
74+
"${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
75+
RUNTIME_OUTPUT_DIRECTORY
76+
"${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin")
77+
78+
# Define include directories
79+
target_include_directories(
80+
${PROJECT_NAME}
81+
PRIVATE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
82+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/examples/openGL>
83+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${INSTALL_NAME}>)
84+
85+
install(
86+
TARGETS ${PROJECT_NAME}
87+
BUNDLE DESTINATION .
88+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
89+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
90+
91+
qt_generate_deploy_app_script(TARGET ${PROJECT_NAME} OUTPUT_SCRIPT
92+
deploy_script NO_UNSUPPORTED_PLATFORM_ERROR)
93+
install(SCRIPT ${deploy_script})

examples/openGL/glwidget.cpp

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
// Copyright (C) 2016 The Qt Company Ltd.
2+
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3+
4+
#include "glwidget.h"
5+
#include <QMouseEvent>
6+
#include <QOpenGLShaderProgram>
7+
#include <QCoreApplication>
8+
#include <math.h>
9+
10+
bool GLWidget::m_transparent = false;
11+
12+
GLWidget::GLWidget(QWidget *parent)
13+
: QOpenGLWidget(parent)
14+
{
15+
m_core = QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile;
16+
// --transparent causes the clear color to be transparent. Therefore, on systems that
17+
// support it, the widget will become transparent apart from the logo.
18+
if (m_transparent) {
19+
QSurfaceFormat fmt = format();
20+
fmt.setAlphaBufferSize(8);
21+
setFormat(fmt);
22+
}
23+
24+
// Force the display of OpenGL
25+
setAttribute(Qt::WA_AlwaysStackOnTop);
26+
}
27+
28+
GLWidget::~GLWidget()
29+
{
30+
cleanup();
31+
}
32+
33+
QSize GLWidget::minimumSizeHint() const
34+
{
35+
return QSize(50, 50);
36+
}
37+
38+
QSize GLWidget::sizeHint() const
39+
{
40+
return QSize(400, 400);
41+
}
42+
43+
static void qNormalizeAngle(int &angle)
44+
{
45+
while (angle < 0)
46+
angle += 360 * 16;
47+
while (angle > 360 * 16)
48+
angle -= 360 * 16;
49+
}
50+
51+
void GLWidget::setXRotation(int angle)
52+
{
53+
qNormalizeAngle(angle);
54+
if (angle != m_xRot) {
55+
m_xRot = angle;
56+
emit xRotationChanged(angle);
57+
update();
58+
}
59+
}
60+
61+
void GLWidget::setYRotation(int angle)
62+
{
63+
qNormalizeAngle(angle);
64+
if (angle != m_yRot) {
65+
m_yRot = angle;
66+
emit yRotationChanged(angle);
67+
update();
68+
}
69+
}
70+
71+
void GLWidget::setZRotation(int angle)
72+
{
73+
qNormalizeAngle(angle);
74+
if (angle != m_zRot) {
75+
m_zRot = angle;
76+
emit zRotationChanged(angle);
77+
update();
78+
}
79+
}
80+
81+
void GLWidget::cleanup()
82+
{
83+
if (m_program == nullptr){
84+
return;
85+
}
86+
makeCurrent();
87+
m_logoVbo.destroy();
88+
delete m_program;
89+
m_program = nullptr;
90+
doneCurrent();
91+
QObject::disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup);
92+
}
93+
94+
static const char *vertexShaderSourceCore =
95+
"#version 150\n"
96+
"in vec4 vertex;\n"
97+
"in vec3 normal;\n"
98+
"out vec3 vert;\n"
99+
"out vec3 vertNormal;\n"
100+
"uniform mat4 projMatrix;\n"
101+
"uniform mat4 mvMatrix;\n"
102+
"uniform mat3 normalMatrix;\n"
103+
"void main() {\n"
104+
" vert = vertex.xyz;\n"
105+
" vertNormal = normalMatrix * normal;\n"
106+
" gl_Position = projMatrix * mvMatrix * vertex;\n"
107+
"}\n";
108+
109+
static const char *fragmentShaderSourceCore =
110+
"#version 150\n"
111+
"in highp vec3 vert;\n"
112+
"in highp vec3 vertNormal;\n"
113+
"out highp vec4 fragColor;\n"
114+
"uniform highp vec3 lightPos;\n"
115+
"void main() {\n"
116+
" highp vec3 L = normalize(lightPos - vert);\n"
117+
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
118+
" highp vec3 color = vec3(0.39, 1.0, 0.0);\n"
119+
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
120+
" fragColor = vec4(col, 1.0);\n"
121+
"}\n";
122+
123+
static const char *vertexShaderSource =
124+
"attribute vec4 vertex;\n"
125+
"attribute vec3 normal;\n"
126+
"varying vec3 vert;\n"
127+
"varying vec3 vertNormal;\n"
128+
"uniform mat4 projMatrix;\n"
129+
"uniform mat4 mvMatrix;\n"
130+
"uniform mat3 normalMatrix;\n"
131+
"void main() {\n"
132+
" vert = vertex.xyz;\n"
133+
" vertNormal = normalMatrix * normal;\n"
134+
" gl_Position = projMatrix * mvMatrix * vertex;\n"
135+
"}\n";
136+
137+
static const char *fragmentShaderSource =
138+
"varying highp vec3 vert;\n"
139+
"varying highp vec3 vertNormal;\n"
140+
"uniform highp vec3 lightPos;\n"
141+
"void main() {\n"
142+
" highp vec3 L = normalize(lightPos - vert);\n"
143+
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
144+
" highp vec3 color = vec3(0.39, 1.0, 0.0);\n"
145+
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
146+
" gl_FragColor = vec4(col, 1.0);\n"
147+
"}\n";
148+
149+
void GLWidget::initializeGL()
150+
{
151+
// In this example the widget's corresponding top-level window can change
152+
// several times during the widget's lifetime. Whenever this happens, the
153+
// QOpenGLWidget's associated context is destroyed and a new one is created.
154+
// Therefore we have to be prepared to clean up the resources on the
155+
// aboutToBeDestroyed() signal, instead of the destructor. The emission of
156+
// the signal will be followed by an invocation of initializeGL() where we
157+
// can recreate all resources.
158+
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup, Qt::UniqueConnection);
159+
160+
initializeOpenGLFunctions();
161+
glClearColor(0, 0, 0, m_transparent ? 0 : 1);
162+
163+
m_program = new QOpenGLShaderProgram;
164+
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_core ? vertexShaderSourceCore : vertexShaderSource);
165+
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_core ? fragmentShaderSourceCore : fragmentShaderSource);
166+
m_program->bindAttributeLocation("vertex", 0);
167+
m_program->bindAttributeLocation("normal", 1);
168+
m_program->link();
169+
170+
m_program->bind();
171+
m_projMatrixLoc = m_program->uniformLocation("projMatrix");
172+
m_mvMatrixLoc = m_program->uniformLocation("mvMatrix");
173+
m_normalMatrixLoc = m_program->uniformLocation("normalMatrix");
174+
m_lightPosLoc = m_program->uniformLocation("lightPos");
175+
176+
// Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x
177+
// implementations this is optional and support may not be present
178+
// at all. Nonetheless the below code works in all cases and makes
179+
// sure there is a VAO when one is needed.
180+
m_vao.create();
181+
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
182+
183+
// Setup our vertex buffer object.
184+
m_logoVbo.create();
185+
m_logoVbo.bind();
186+
m_logoVbo.allocate(m_logo.constData(), m_logo.count() * sizeof(GLfloat));
187+
188+
// Store the vertex attribute bindings for the program.
189+
setupVertexAttribs();
190+
191+
// Our camera never changes in this example.
192+
m_camera.setToIdentity();
193+
m_camera.translate(0, 0, -1);
194+
195+
// Light position is fixed.
196+
m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70));
197+
198+
m_program->release();
199+
}
200+
201+
void GLWidget::setupVertexAttribs()
202+
{
203+
m_logoVbo.bind();
204+
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
205+
f->glEnableVertexAttribArray(0);
206+
f->glEnableVertexAttribArray(1);
207+
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
208+
nullptr);
209+
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
210+
reinterpret_cast<void *>(3 * sizeof(GLfloat)));
211+
m_logoVbo.release();
212+
}
213+
214+
void GLWidget::paintGL()
215+
{
216+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
217+
glEnable(GL_DEPTH_TEST);
218+
glEnable(GL_CULL_FACE);
219+
220+
m_world.setToIdentity();
221+
m_world.rotate(180.0f - (m_xRot / 16.0f), 1, 0, 0);
222+
m_world.rotate(m_yRot / 16.0f, 0, 1, 0);
223+
m_world.rotate(m_zRot / 16.0f, 0, 0, 1);
224+
225+
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
226+
m_program->bind();
227+
m_program->setUniformValue(m_projMatrixLoc, m_proj);
228+
m_program->setUniformValue(m_mvMatrixLoc, m_camera * m_world);
229+
QMatrix3x3 normalMatrix = m_world.normalMatrix();
230+
m_program->setUniformValue(m_normalMatrixLoc, normalMatrix);
231+
232+
glDrawArrays(GL_TRIANGLES, 0, m_logo.vertexCount());
233+
234+
m_program->release();
235+
}
236+
237+
void GLWidget::resizeGL(int w, int h)
238+
{
239+
m_proj.setToIdentity();
240+
m_proj.perspective(45.0f, GLfloat(w) / h, 0.01f, 100.0f);
241+
}
242+
243+
void GLWidget::mousePressEvent(QMouseEvent *event)
244+
{
245+
m_lastPos = event->position().toPoint();
246+
}
247+
248+
void GLWidget::mouseMoveEvent(QMouseEvent *event)
249+
{
250+
int dx = event->position().toPoint().x() - m_lastPos.x();
251+
int dy = event->position().toPoint().y() - m_lastPos.y();
252+
253+
if (event->buttons() & Qt::LeftButton) {
254+
setXRotation(m_xRot + 8 * dy);
255+
setYRotation(m_yRot + 8 * dx);
256+
} else if (event->buttons() & Qt::RightButton) {
257+
setXRotation(m_xRot + 8 * dy);
258+
setZRotation(m_zRot + 8 * dx);
259+
}
260+
m_lastPos = event->position().toPoint();
261+
}

0 commit comments

Comments
 (0)