Skip to content

Commit 9a4729e

Browse files
committed
Improve OpenGLExample
1 parent 5458e5a commit 9a4729e

File tree

11 files changed

+691
-43
lines changed

11 files changed

+691
-43
lines changed

examples/openGL/CMakeLists.txt

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 3.5)
22

33
project(OpenGLExample VERSION ${VERSION_SHORT})
44

5+
set(CMAKE_AUTOUIC ON)
6+
set(CMAKE_AUTOMOC ON)
7+
set(CMAKE_AUTORCC ON)
8+
59
find_package(
610
QT NAMES Qt6
711
COMPONENTS Core
@@ -11,7 +15,9 @@ find_package(
1115
OpenGLWidgets
1216
Quick
1317
QuickWidgets
18+
ShaderTools
1419
REQUIRED)
20+
1521
find_package(
1622
Qt${QT_VERSION_MAJOR}
1723
COMPONENTS Core
@@ -21,19 +27,23 @@ find_package(
2127
OpenGLWidgets
2228
Quick
2329
QuickWidgets
30+
ShaderTools
2431
REQUIRED)
2532

2633
set(CMAKE_INCLUDE_CURRENT_DIR ON)
2734

28-
add_executable(
29-
${PROJECT_NAME} WIN32
35+
qt_add_executable(
36+
${PROJECT_NAME}
37+
WIN32
3038
main.cpp
3139
mainwindow.cpp
3240
mainwindow.h
3341
glwindow.cpp
3442
glwindow.h
3543
glwidget.h
3644
glwidget.cpp
45+
fbitem.cpp
46+
fbitem.h
3747
logo.cpp
3848
logo.h)
3949

@@ -42,11 +52,31 @@ target_include_directories(${PROJECT_NAME}
4252
target_link_libraries(${PROJECT_NAME}
4353
PRIVATE qtadvanceddocking-qt${QT_VERSION_MAJOR})
4454

55+
qt_add_qml_module(
56+
${PROJECT_NAME}
57+
URI
58+
fbitem
59+
QML_FILES
60+
"test.qml"
61+
RESOURCE_PREFIX
62+
/openGL
63+
NO_RESOURCE_TARGET_PATH)
64+
65+
qt6_add_shaders(
66+
${PROJECT_NAME}
67+
"shaders"
68+
PRECOMPILE
69+
OPTIMIZED
70+
PREFIX
71+
"/openGL"
72+
FILES
73+
"wobble.frag")
74+
4575
# Resources:
46-
set(esource_files "qtlogo.png")
76+
set(resource_files "qtlogo.png")
4777

4878
qt_add_resources(${PROJECT_NAME} "OpenGLExample" PREFIX "/" FILES
49-
${esource_files})
79+
${resource_files})
5080

5181
target_link_libraries(
5282
${PROJECT_NAME}
@@ -90,4 +120,16 @@ install(
90120

91121
qt_generate_deploy_app_script(TARGET ${PROJECT_NAME} OUTPUT_SCRIPT
92122
deploy_script NO_UNSUPPORTED_PLATFORM_ERROR)
123+
93124
install(SCRIPT ${deploy_script})
125+
126+
qt_generate_deploy_qml_app_script(
127+
TARGET
128+
${PROJECT_NAME}
129+
OUTPUT_SCRIPT
130+
qml_deploy_script
131+
MACOS_BUNDLE_POST_BUILD
132+
NO_UNSUPPORTED_PLATFORM_ERROR
133+
DEPLOY_USER_QML_MODULES_ON_UNSUPPORTED_PLATFORM)
134+
135+
install(SCRIPT ${qml_deploy_script})

examples/openGL/fbitem.cpp

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
// Copyright (C) 2017 The Qt Company Ltd.
2+
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3+
4+
#include "fbitem.h"
5+
#include <QOpenGLFramebufferObject>
6+
#include <QOpenGLFunctions>
7+
#include <QMatrix4x4>
8+
9+
FbItem::FbItem(QQuickItem *parent)
10+
: QQuickFramebufferObject(parent),
11+
m_target(0, 0, -1),
12+
m_syncState(AllNeedsSync),
13+
m_multisample(false)
14+
{
15+
}
16+
17+
QQuickFramebufferObject::Renderer *FbItem::createRenderer() const
18+
{
19+
return new FbItemRenderer(m_multisample);
20+
}
21+
22+
void FbItem::setEye(const QVector3D &v)
23+
{
24+
if (m_eye != v) {
25+
m_eye = v;
26+
m_syncState |= CameraNeedsSync;
27+
update();
28+
}
29+
}
30+
31+
void FbItem::setTarget(const QVector3D &v)
32+
{
33+
if (m_target != v) {
34+
m_target = v;
35+
m_syncState |= CameraNeedsSync;
36+
update();
37+
}
38+
}
39+
40+
void FbItem::setRotation(const QVector3D &v)
41+
{
42+
if (m_rotation != v) {
43+
m_rotation = v;
44+
m_syncState |= RotationNeedsSync;
45+
update();
46+
}
47+
}
48+
49+
int FbItem::swapSyncState()
50+
{
51+
int s = m_syncState;
52+
m_syncState = 0;
53+
return s;
54+
}
55+
56+
FbItemRenderer::FbItemRenderer(bool multisample)
57+
: m_inited(false),
58+
m_multisample(multisample),
59+
m_dirty(DirtyAll)
60+
{
61+
m_camera.setToIdentity();
62+
m_baseWorld.setToIdentity();
63+
m_baseWorld.translate(0, 0, -1);
64+
m_world = m_baseWorld;
65+
}
66+
67+
void FbItemRenderer::synchronize(QQuickFramebufferObject *qfbitem)
68+
{
69+
FbItem *item = static_cast<FbItem *>(qfbitem);
70+
int syncState = item->swapSyncState();
71+
if (syncState & FbItem::CameraNeedsSync) {
72+
m_camera.setToIdentity();
73+
m_camera.lookAt(item->eye(), item->eye() + item->target(), QVector3D(0, 1, 0));
74+
m_dirty |= DirtyCamera;
75+
}
76+
if (syncState & FbItem::RotationNeedsSync) {
77+
m_rotation = item->rotation();
78+
m_dirty |= DirtyWorld;
79+
}
80+
}
81+
82+
struct StateBinder
83+
{
84+
StateBinder(FbItemRenderer *r)
85+
: m_r(r) {
86+
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
87+
f->glEnable(GL_DEPTH_TEST);
88+
f->glEnable(GL_CULL_FACE);
89+
f->glDepthMask(GL_TRUE);
90+
f->glDepthFunc(GL_LESS);
91+
f->glFrontFace(GL_CCW);
92+
f->glCullFace(GL_BACK);
93+
m_r->m_program->bind();
94+
}
95+
~StateBinder() {
96+
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
97+
m_r->m_program->release();
98+
f->glDisable(GL_CULL_FACE);
99+
f->glDisable(GL_DEPTH_TEST);
100+
}
101+
FbItemRenderer *m_r;
102+
};
103+
104+
void FbItemRenderer::updateDirtyUniforms()
105+
{
106+
if (m_dirty & DirtyProjection)
107+
m_program->setUniformValue(m_projMatrixLoc, m_proj);
108+
109+
if (m_dirty & DirtyCamera)
110+
m_program->setUniformValue(m_camMatrixLoc, m_camera);
111+
112+
if (m_dirty & DirtyWorld) {
113+
m_program->setUniformValue(m_worldMatrixLoc, m_world);
114+
QMatrix3x3 normalMatrix = m_world.normalMatrix();
115+
m_program->setUniformValue(m_normalMatrixLoc, normalMatrix);
116+
}
117+
118+
if (m_dirty & DirtyLight)
119+
m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70));
120+
121+
m_dirty = 0;
122+
}
123+
124+
void FbItemRenderer::render()
125+
{
126+
ensureInit();
127+
128+
if (m_vao.isCreated())
129+
m_vao.bind();
130+
else
131+
setupVertexAttribs();
132+
133+
StateBinder state(this);
134+
135+
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
136+
f->glClearColor(0, 0, 0, 0);
137+
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
138+
139+
if (m_dirty & DirtyWorld) {
140+
m_world = m_baseWorld;
141+
m_world.rotate(m_rotation.x(), 1, 0, 0);
142+
m_world.rotate(m_rotation.y(), 0, 1, 0);
143+
m_world.rotate(m_rotation.z(), 0, 0, 1);
144+
}
145+
146+
updateDirtyUniforms();
147+
148+
f->glDrawArrays(GL_TRIANGLES, 0, m_logo.vertexCount());
149+
150+
if (m_vao.isCreated())
151+
m_vao.release();
152+
}
153+
154+
QOpenGLFramebufferObject *FbItemRenderer::createFramebufferObject(const QSize &size)
155+
{
156+
m_dirty |= DirtyProjection;
157+
m_proj.setToIdentity();
158+
m_proj.perspective(45.0f, GLfloat(size.width()) / size.height(), 0.01f, 100.0f);
159+
160+
QOpenGLFramebufferObjectFormat format;
161+
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
162+
format.setSamples(m_multisample ? 4 : 0);
163+
return new QOpenGLFramebufferObject(size, format);
164+
}
165+
166+
void FbItemRenderer::ensureInit()
167+
{
168+
if (m_inited)
169+
return;
170+
171+
m_inited = true;
172+
173+
initBuf();
174+
initProgram();
175+
}
176+
177+
void FbItemRenderer::initBuf()
178+
{
179+
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao);
180+
181+
m_logoVbo.create();
182+
m_logoVbo.bind();
183+
m_logoVbo.allocate(m_logo.constData(), m_logo.count() * sizeof(GLfloat));
184+
185+
setupVertexAttribs();
186+
}
187+
188+
void FbItemRenderer::setupVertexAttribs()
189+
{
190+
m_logoVbo.bind();
191+
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
192+
f->glEnableVertexAttribArray(0);
193+
f->glEnableVertexAttribArray(1);
194+
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), nullptr);
195+
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
196+
m_logoVbo.release();
197+
}
198+
199+
static const char *vertexShaderSource =
200+
"attribute vec4 vertex;\n"
201+
"attribute vec3 normal;\n"
202+
"varying vec3 vert;\n"
203+
"varying vec3 vertNormal;\n"
204+
"uniform mat4 projMatrix;\n"
205+
"uniform mat4 camMatrix;\n"
206+
"uniform mat4 worldMatrix;\n"
207+
"uniform mat3 normalMatrix;\n"
208+
"void main() {\n"
209+
" vert = vertex.xyz;\n"
210+
" vertNormal = normalMatrix * normal;\n"
211+
" gl_Position = projMatrix * camMatrix * worldMatrix * vertex;\n"
212+
"}\n";
213+
214+
static const char *fragmentShaderSource =
215+
"varying highp vec3 vert;\n"
216+
"varying highp vec3 vertNormal;\n"
217+
"uniform highp vec3 lightPos;\n"
218+
"void main() {\n"
219+
" highp vec3 L = normalize(lightPos - vert);\n"
220+
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
221+
" highp vec3 color = vec3(0.39, 1.0, 0.0);\n"
222+
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
223+
" gl_FragColor = vec4(col, 1.0);\n"
224+
"}\n";
225+
226+
void FbItemRenderer::initProgram()
227+
{
228+
m_program.reset(new QOpenGLShaderProgram);
229+
m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
230+
m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
231+
m_program->bindAttributeLocation("vertex", 0);
232+
m_program->bindAttributeLocation("normal", 1);
233+
m_program->link();
234+
m_projMatrixLoc = m_program->uniformLocation("projMatrix");
235+
m_camMatrixLoc = m_program->uniformLocation("camMatrix");
236+
m_worldMatrixLoc = m_program->uniformLocation("worldMatrix");
237+
m_normalMatrixLoc = m_program->uniformLocation("normalMatrix");
238+
m_lightPosLoc = m_program->uniformLocation("lightPos");
239+
}

0 commit comments

Comments
 (0)