convert your legacy opengl code to modern opengl with qt

53
Convert your Legacy OpenGL Code to Modern OpenGL with Qt Dr. Roland Krause Integrated Computer Solutions

Upload: ics

Post on 07-Jan-2017

3.077 views

Category:

Software


23 download

TRANSCRIPT

Page 1: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Convert your Legacy OpenGL Code to Modern OpenGL with

QtDr. Roland Krause

Integrated Computer Solutions

Page 2: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

AbstractOpenGL is a powerful, low level graphics toolkit with a steep learning curve that allows access to accelerated GPU hardware. Using OpenGL developers achieve high-fidelity, animated graphics ubiquitous in games, screen productions and scientific software. Due to OpenGL’s native C-language API large scale, professional software development endeavors wanting to utilize the advantages of direct and accelerated graphics quickly become expensive and hard to maintain.This presentation gives a comprehensive overview of the many aspects of OpenGL development where Qt provides advanced interfaces that let the developer focus on the tasks at hand instead of dealing with repetitive and error-prone, platform dependent issues. From handling of Window related tasks, providing type-safe data-structures for Vertex Array Objects to managing Shader Programs, dealing with Textures, Frame Buffer Objects all the way to support for Debugging and Profiling of OpenGL Applications we show solutions to the most common issues any OpenGL program has to address.We are able to demonstrate why Qt is the best C++ framework for development of modern OpenGL based graphics applications.

Page 3: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Modern OpenGL with Qt

● OpenGL is an Application Programming Interface (API) for Rendering Graphics in 2D and 3D○ Widely used in CAD, Virtual Reality, Scientific Visualization, Information

Visualization, Flight Simulation, and Video Games. ○ Over 500 commands in Version 4.3○ Managed by the non-profit technology consortium Khronos Group.

● Designed as a Streamlined, Hardware Independent Interface ○ To be efficient usually implemented on graphics hardware (GPU)○ Independent of Operating System or Windowing System, Cross-platform

○ No functions for windowing tasks, managing state, user input, 3D models or reading image files

That’s where Qt comes into play!

Page 4: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

In the Olden Days...

● Glut (or SDL) was the way to platform independent code○ For platform dependent code there are WGL, AGL,

GLXint main(int argc, char** argv){

glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(resize); glutKeyboardFunc(keyboard); glutMainLoop(); return 0;

}

Page 5: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

A simple Triangle in Fixed Pipeline OpenGLvoid init(void){ glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH);}

void triangle(void){ glBegin (GL_TRIANGLES); glColor3f (1.0, 0.0, 0.0); glVertex2f (5.0, 5.0); glColor3f (0.0, 1.0, 0.0); glVertex2f (25.0, 5.0); glColor3f (0.0, 0.0, 1.0); glVertex2f (5.0, 25.0); glEnd();}

void display(void){ glClear (GL_COLOR_BUFFER_BIT); triangle (); glFlush ();}

Page 6: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Render a Scene with Modern OpenGL

1. Create OpenGL Context and Window2. Create and Manage the OpenGL Scene

○ Create Geometry■ Store Geometry in Vertex Buffer Objects (VBOs)■ Manage VBOs using Vertex Array Objects (VAOs)

○ Compile and Link Shaders into Shader Programs○ Configure the Rendering Pipeline○ Set Attribute Arrays, Uniforms, Textures, etc…

3. Render the Scene using OpenGL Primitives

Page 7: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Integration of OpenGL with Qt

● There are several possibilities when integrating OpenGL Rendering with Qt1. Native OpenGL rendering

using QWindow and QOpenGLContext2. QOpenGLWindow

○ Wrapper for QWindow that hides complexity○ Can be OpenGL Canvas with QPainter syntax

3. QOpenGLWidget○ QWidget based applications

4. QQuickFramebufferObject○ new since Qt-5.4

5. Rendering into the SceneGraph6. Custom QQuickItem

7

Page 8: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Create OpenGL Context and Window

● Since Qt 5 the class QWindow represents a window in the underlying windowing system○ In Qt 4, QWidget had both Window and Widget

functionality○ In Qt 5, QWindow is part of the gui module, QWidget is

in a separate and now optional module (widgets)○ Applications will typically use QWidget or QQuickView

to create user interfaces

● It is possible to render directly to a QWindow with a QOpenGLContext

● QWindow can be embedded in a QWidget

8

Page 9: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QOpenGLWindow

● Convenience subclass of QWindow to perform OpenGL painting○ Enhanced QWindow that allows easily creating

windows that perform OpenGL rendering ○ API compatible with QOpenGLWidget and similar to

the legacy QGLWidget. ○ No dependency on widgets module and better

performance.○ Optionally backed by a framebuffer object○ Default behavior (and thus performance) is equivalent

to QWindow.

9

Page 10: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Using QOpenGLWindow

● Subclass QOpenGLWindow and reimplement the following virtual functions:○ initializeGL() to perform OpenGL resource initialization○ resizeGL() to set up the transformation matrices and

other window size dependent resources○ paintGL() to issue OpenGL commands or draw using

QPainter

● To schedule a repaint, call update() ○ Note that this will not immediately result in a call to

paintGL(). ○ This is a slot so it can be connected to a QTimer::

timeout() signal to perform animation. 10

Page 11: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Simple Triangle in Modern OpenGL

void OpenGLScene::initialize() {...}

void OpenGLScene::createBuffers() {...}

void OpenGLScene::setupVertexArrayState() {...}

void OpenGLScene::paint(){ glClear( GL_COLOR_BUFFER_BIT ); if(!m_shaderProgram.isLinked()) return; m_shaderProgram.bind(); m_vao.bind(); m_shaderProgram.setUniformValue("MVP", m_projection); glDrawArrays(GL_TRIANGLES, 0, 3); m_shaderProgram.release();}

void OpenGLScene::resize(int w, int h) {...}

void OpenGLScene::createShaderProgram() {...}

let’s look closer at the code ...

Page 12: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QOpenGLWindow using QPainter

● QOpenGLWindow inherits QPaintDeviceWindow

● Allows opening a painter on itself and perform QPainter-based drawing:

void paintGL() { QOpenGLFunctions *f = context()->functions(); f->glClear(GL_COLOR_BIT | GL_DEPTH_BUFFER_BIT); // issue some native OpenGL commands QPainter p(this); // draw using QPainter // animate continuously: schedule an update update(); }

12

Page 13: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Example: QOpenGLWindow-QPainter

13

Page 14: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● State machine that stores all data related to the OpenGL rendering state○ Most OpenGL functions set or retrieve some state○ Creating a window and an OpenGL context is not part

of the OpenGL specification● QOpenGLContext represents a native

OpenGL context○ Enables OpenGL rendering on a QSurface.○ Context allow to share resources with other contexts

with setShareContext()

OpenGL Context

14

Page 15: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QOpenGLContext

To create:● Create a QSurfaceFormat object

○ Set desired OpenGL version and profile ● Create the QOpenGLContext

○ Set the context format using the QSurfaceFormat object

● Finally call QOpenGLContext::create()○ Use return value or isValid() to check if the context was

successfully initialized● Before using any OpenGL QOpenGLContext

must be made current against a surface○ QOpenGLContext::makeCurrent(QSurface*)

15

Page 16: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● When OpenGL rendering is done○ Call swapBuffers() to swap the front and back buffers

of the surface at the end of the update function○ Newly rendered content becomes visible ○ QOpenGLContext requires to call makeCurrent() again

before starting rendering a new frame, after calling swapBuffers()

● QOpenGLWindow takes care of all of it!● Use QOpenGLContext::format() to retrieve info

on the context○ Returns a QSurfaceFormat○ OpenGL version, profile, etc...

QOpenGLContext

16

Page 17: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Converting Legacy Qt OpenGL Code

● When porting code from Qt4 to Qt5 we find that QGLWidget is marked obsolete

● The replacement, QOpenGLWidget, has the same familiar API but works differently

Qt4 Legacy Classes Qt5 Modern OpenGL Classes

QGLWidget QOpenGLWidget

QGLFormat QSurfaceFormat

QGLContext QOpenGLContext

Page 18: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QOpenGLWidget

● Can be used on Embedded Systems with eglfs and wayland plugins

● Uses same technology as QQuickWidget○ Unlike QGLWidget it is not a native window

● On desktop platforms, OpenGL 3.x and 4.x, including core profiles, are fully supported○ QGLWidget forced the usage of legacy, incomplete

utility classes like QGLFormat and QGLContext○ QOpenGLWidget uses the modern equivalents from

the QtGui module: QSurfaceFormat, QOpenGLContext

Page 19: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QOpenGLWidget Example

Page 20: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Important Differences QGLWidget vs QOpenGLWidget

● QOpenGLWidget always renders offscreen, using framebuffer objects.

● QGLWidget on the other hand uses a native window and surface. ○ Depending on platform native child widgets may have various limitations

(e.g. eglfs) ○ QOpenGLWidget avoids this by not creating a separate native window.

● Behavior of QOpenGLWidget is very similar to QOpenGLWindow ○ Update behavior can be set to PartialUpdateBlit or PartialUpdateBlend. ○ Contents are preserved between paintGL() calls so that incremental

rendering is possible.

Page 21: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QOpenGLWidget Hints

● When rendering everything in the view on every paint call:○ Important to call glClear() as early as possible in paintGL(). ○ Mobile GPUs can optimize reloads of the tile buffer.○ Omitting the clear call can lead to significant performance drops

● Avoid calling winId() on a QOpenGLWidget. ○ This function triggers the creation of a native window, resulting in reduced

performance and possibly rendering glitches.

● Putting other Widgets underneath and making the QOpenGLWidget transparent will not show as expected: ○ Widgets underneath will not be visible because QOpenGLWidget is

drawn before all other non-OpenGL widgets.○ Having widgets on top of the QOpenGLWidget, will function as expected.

● Alternative with Limitations is QOpenGLWindow with QWidget::createWindowContainer()

Page 22: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Qt’s OpenGL Support

● QOpenGLFunctions are convenience classes● Simplify writing of OpenGL code ● Hide complexities of extension handling ● Hide differences between OpenGL ES 2 and

desktop OpenGL○ Allow the use of OpenGL ES 2 functions on Desktop

OpenGL ○ No need to manually resolve OpenGL function pointers ○ Allowing cross-platform development of applications

targeting mobile or embedded devices

22

Page 23: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QAbstractOpenGLFunctions

● Family of classes that expose all functions for a given OpenGL version and profile○ OpenGL implementations on different platforms are

able to link to a variable number of OpenGL functions depending upon the OpenGL ABI on that platform

○ On many platforms most functions must be resolved at runtime, Options are: ■ Work with raw function pointers: QOpenGLContext::getProcAddress()

■ Use QOpenGLFunctions and only expose those functions common to OpenGL ES 2 and desktop OpenGL

23

Page 24: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QAbstractOpenGLFunctions (cont.)

● Provides better support for newer versions of OpenGL (especially 3.0 and higher)

● Ease development of desktop applications relying on modern, desktop-only OpenGL features

● QOpenGLFunctions_X_Y_PROFILE ○ Core and Compatibility Profiles○ Expose every core OpenGL function by way of a

corresponding member function○ Class for every valid combination of OpenGL version

and profile following the naming convention:QOpenGLFunctions_<MAJOR VERSION>_<MINOR VERSION>[_PROFILE]

24

Page 25: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Ensure QOpenGLContext is current before using it

● Call QOpenGLFunctions_X_Y_PROFILE::initializeOpenGLFunctions()

once before using it to resolve function pointers

Using QOpenGLFunctions_X_Y_PROFILE

25

Page 26: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Qt’s OpenGL Support

● Classes that wrap native OpenGL Resources○ QOpenGLBuffer, QOpenGLFramebufferObject

QOpenGLShaderProgram, OpenGLTexture, QOpenGLVertexArrayObject

● Qt GUI Module Contains ○ QMatrix4x4, QVector4D and QQuaternion○ Support common mathematical operations for 3D

graphics● Miscellaneous

○ Debugging, QOpenGLDebugLogger○ Timing, QOpenGLTimeMonitor, QOpenGLTimerQuery

26

Page 27: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

QOpenGLDebugLoggerQOpenGLDebugMessageQOpenGLTimeMonitorQOpenGLTimerQueryQOpenGLPaintDeviceQOpenGLTexture (Qt 5.3)QOpenGLWidget(Qt 5.4)QOpenGLWindow(Qt 5.4)

QOpenGLContextQOpenGLContextGroupQOpenGLVersionProfileQOpenGLFunctions*QOpenGLVertexArrayObjectQOpenGLBufferQOpenGLShaderQOpenGLShaderProgramQOpenGLFrameBufferObjectQOpenGLFrameBufferObjectFormat

Qt 5 and OpenGL Classes

27

Page 28: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Small program that runs on the GPU● Ran as part of the OpenGL pipeline● Programmable● Coded in GLSL (OpenGL Shading Language)● Makes rendering infinitely flexible

What is a Shader?

28

Page 29: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Simplified Pipeline

29

Page 30: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Shaders

● Two kinds of shaders:○ Shaders that deal with Vertices, i.E:

Vertex, Tessellation and Geometry shaders determine where on the screen a primitive is.

○ Fragment Shader uses that information to determine what color that fragment will be.

● Must have a version identifier at top of file● Must have a main() function● Each shader is compiled, then they are linked

together to make a shader program● Input/output interfaces must match, and are

checked at link time30

Page 31: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Vertex Shader○ Executed once for every vertex○ Input: Content of Vertex Buffer Arrays and Uniforms○ Output: Vertex position

● Fragment Shader○ Executed once for every fragment○ Input: Result of Rasterization after Vertex Shader○ Output: Candidate pixel color (aka Fragment)

Shader Basics

31

Page 32: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Preparing Shaders○ Compile vertex shader○ Compile fragment shader○ Configure attribute locations before linking○ Link both shaders into a shader program

● Preparing shaders with Qt vs pure OpenGL○ Much less code○ Less error prone

Prepare Shaders

32

Page 33: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Example: Use Qt to Create Shader Programvoid OpenGLScene::createShaderProgram(){ QByteArray version=OpenGLCheck::getShaderVersionString()+"\n"; QFile vtFile(":/vertex.vsh"); vtFile.open((QIODevice::ReadOnly | QIODevice::Text)); QFile fsFile (":/fragment.fsh"); fsFile.open((QIODevice::ReadOnly | QIODevice::Text)); if (!m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,version+vtFile.readAll())) { qWarning() << "Error in vertex shader:" << m_shaderProgram.log(); exit(1); } if (!m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,version+fsFile.readAll())) { qWarning() << "Error in fragment shader:" << m_shaderProgram.log(); exit(1); }#if defined ICS_OPENGL_ES2==1 m_shaderProgram.bindAttributeLocation("vertexPosition", 0); m_shaderProgram.bindAttributeLocation("vertexColor", 1);#endif if ( !m_shaderProgram.link() ) { qDebug() << "Error linking shader program:" << m_shaderProgram.log(); exit(1); }}

Page 34: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Create buffer object● Bind the buffer, making it the active buffer● Copy the data to the buffer

// Triangle vertices float vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.6f, 0.0f }; // Create a static buffer for vertex data m_vertexBuffer.create(); // Set usage pattern to Static Draw, (the data won't change) m_vertexBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw ); // Bind the buffer to the current OpenGL context m_vertexBuffer.bind(); // Copy the data to the buffer m_vertexBuffer.allocate( vertices, 3 * 3 * sizeof( float ) );

Creating a VBO

34

Page 35: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Vertex Attributes

● We have the data (in VBOs)● We have the shaders compiled● How do we map the data to the shader

attributes?In OpenGL-ES, after compiling shaders and before linking:

m_shaderProgram.bindAttributeLocation("vertexPosition", 0);

This assigns the attribute vertexPosition the first location (0)

35

Page 36: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Mapping Attribute Data in Shaders

● When using Desktop OpenGL (version 3.2 and higher) locations are set in the shaders:#if __VERSION__ > 320layout(location = 0) in vec3 vertexPosition;layout(location = 1) in vec3 vertexColor;out vec3 color;#elseattribute vec3 vertexPosition;attribute vec3 vertexColor;varying lowp vec3 color;#endif

Page 37: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● VBO data is mapped to shader attribute locations

m_shaderProgram.bind();m_vertexBuffer.bind();int vertexLocation = m_shaderProgram.attributeLocation("vertexPosition"); m_shaderProgram.setAttributeBuffer(

vertexLocation, // layout locationGL_FLOAT, // data's type0, // Offset to data in buffer3); // number of components (3 for x,y,z)

○ Bind the shader program○ Bind the VBO containing the attribute data○ Enable the desired vertex attribute array location○ Set the attribute buffer to desired attribute location, set

number of components and stride○ Supports VBOs with interleaved data

Vertex Attribute Arrays

37

Page 38: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Defining Uniform Values in Qt

● Yep, It is that simple! OpenGLShaderProgram has a myriad ways to do it, e.g.: m_shaderProgram.bind();// Get the location of uniform value "uni" in the shader. int uniLocation = m_shaderProgram.uniformLocation("uni");// Then update the value m_shaderProgram.setUniformValue(uniLocation,uniValue);// Or in one step m_shaderProgram.setUniformValue("uni",0.8f,0.5f,0.5f);

● If the value changes during an animation this code would go in the updateGL function

● If it is static it could go into initializeGL after the shader program has been linked and bound

38

Page 39: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Deprecated OpenGL Matrix Stack

● OpenGL Desktop version < 3 used to have “built in” matrix stacks and related functionality for dealing with transformations and projections○ glRotate*, glTranslate*, glScale*○ glMatrixMode(), glPushMatrix(), glPopMatrix()○ glLoadIdentity()○ glFrustum(), gluPerspective(...), gluLookAt(..)

● All of these are now deprecated and should/can no longer be used

39

Page 40: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Fortunately, it is very easy to achieve the same functionality with more flexibility using Qt

● There are functions to:○ Create or set a matrix to the identity matrix

■ Identity matrix is a diagonal matrix with all elements being 1. When multiplied with a vector the result will be the same vector.

○ Translate, Scale, Rotate○ Create a (view) matrix representing a “camera”○ Create perspective or orthographic projection matrix

● And then one can use QStack, QVector, QList and gain ultimate flexibility

Matrices, Qt to the Rescue

40

Page 41: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Contains convenient functions for handling Model, View, and Projection Matrices○ QMatrix4x4::translate()○ QMatrix4x4::scale()○ QMatrix4x4::rotate() ○ QMatrix4x4::lookAt()○ QMatrix4x4::perspective()○ QMatrix4x4::ortho()

QMatrix4x4

41

Page 42: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Example from porting our Glut Applicationvoid resize (int w, int h){ glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (w <= h) gluOrtho2D (0.0, 30.0, 0.0, 30.0 * (GLfloat) h/(GLfloat) w); else gluOrtho2D (0.0, 30.0 * (GLfloat) w/(GLfloat) h, 0.0, 30.0); glMatrixMode(GL_MODELVIEW);}

● Set the current MatrixMode such that subsequent matrix operations apply to the projection matrix stack

● Load the Identity Matrix and then apply an orthogonal projection transformation

● Set the current MatrixMode back to the model-view stack

Page 43: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

class OpenGLScene : public QOpenGLFunctions{... QMatrix4x4 m_projection;...

void OpenGLScene::resize(int w, int h){ glViewport( 0, 0, w, h ); float a = (float)w/(float)h; float l=30.0; m_projection.setToIdentity(); if (w<=h) m_projection.ortho(0,l,0,l/a, -1.0, 1.0f); else m_projection.ortho(0,l*a,0,l, -1.0, 1.0f);}

void OpenGLScene::paint(){... // Set MVP uniform to projection matrix // since modelview is identity m_shaderProgram.setUniformValue("MVP", m_projection);...

Equivalent in Modern OpenGL with QtVertex Shader Code:attribute vec3 vertexPosition;void main(){... // Calculate the vertex position gl_Position = MVP*vec4(vertexPosition, 1.0 );...}

Page 44: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Qt- 5.2 introduces QOpenGLTexture to encapsulate an OpenGL texture object○ Makes it easy to work with OpenGL textures

○ Simplifies dealing with dependencies upon the capabilities of an OpenGL implementation

● Typical usage pattern for QOpenGLTexture is○ Instantiate the object specifying the texture target type

○ Set properties that affect storage requirements e.g. storage format, dimensions

○ Allocate server-side storage○ Optionally upload pixel data○ Optionally set any additional properties e.g. filtering and border options○ Render with texture or render to texture

○ In the common case of simply using a QImage as the source of texture pixel data most of the above steps are performed automatically.

QOpenGLTexture

44

Page 45: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Qt simplifies the process with:○ QOpenGLFramebufferObject class

▪ Represents OpenGL FBO▪ By default creates 2D texture for rendering target▪ Function to return the OpenGL texture id

● Can be used for texture rendering

▪ Function to return rendered scene as a QImage○ QOpenGLFramebufferObjectFormat()

▪ Specify format and attachments of FBO

Qt Support for FBO

45

Page 46: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Qt and OpenGL Extensions

● A list of all OpenGL extensions supported by the current context can be retrieved with a call to QSet<QByteArray> QOpenGLContext:: extensions() const

The context or a sharing context must be current.● Resolve the entry points if the extension introduces a new

API: QOpenGLContext::getProcAddress(). ● QtOpenGLExtensions module contains a class for every

OpenGL extension in the Khronos registry that introduces new API.

46

Page 47: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

OpenGL Debugging with Qt

● OpenGL programming can be error prone○ Black screen syndrom. There is no indication what is going on?○ To be sure that no errors are being returned from OpenGL

implementation check glGetError after every API call○ OpenGL errors stack up so need to use this in a loop. ○ Additional information e.g. performance issues, warnings about using

deprecated APIs are not reported through the ordinary OpenGL error reporting mechanisms

● QOpenGLDebugLogger enables logging of OpenGL debugging messages○ Provides access to the OpenGL debug log if OpenGL implementation

supports it (by exposing the GL_KHR_debug extension)

○ Messages from the OpenGL server will either be logged in an internal OpenGL log or passed in "real-time", i.e. as they're generated from OpenGL, to listeners

47

Page 48: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

OpenGL Debugging with Qt

● Creating an OpenGL Debug Context○ OpenGL implementations are allowed not to create any debug output at

all, unless the OpenGL context is a debug context○ Set QSurfaceFormat::DebugContext format option on the

QSurfaceFormat used to create the QOpenGLContext object:format.setOption(QSurfaceFormat::DebugContext);

● Creating and Initializing a QOpenGLDebugLogger○ QOpenGLDebugLogger is a simple QObject-derived class

○ Create an instance and initialize it before usage by calling initialize() with a current OpenGL context:QOpenGLContext *ctx = QOpenGLContext::currentContext();QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);logger->initialize();

○ Note that GL_KHR_debug extension must be available in the context in order to access the messages logged by OpenGL

○ You can check the presence of this extension by calling:ctx->hasExtension(QByteArrayLiteral("GL_KHR_debug")) 48

Page 49: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Qt OpenGL Debug Messages

● Reading the Internal OpenGL Debug Log○ Messages stored in the internal log of debug messages can be retrieved

by using the loggedMessages() functionQList<QOpenGLDebugMessage> messages = logger->loggedMessages();foreach (const QOpenGLDebugMessage &message, messages) qDebug() << message;

○ Internal log has limited size; Older messages will get discarded to make room for new incoming messages

● Real-time logging of messages○ Receive a stream of debug messages from the OpenGL server as they

are generated by the implementation ○ Connect a slot to the messageLogged() signal, and start logging by

calling startLogging():connect(logger, &QOpenGLDebugLogger::messageLogged, receiver, &LogHandler::handleLoggedMessage);logger->startLogging();

● Similarly, logging can be disabled at any time by calling the stopLogging() function.

49

Page 50: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Measure GPU execution time of OpenGL calls● Use to profile an application’s rendering

performance● Timed results in nanoseconds● Create and set number of samples that will be

taken, e.g:

m_timeMonitor = new QOpenGLTimeMonitor(this);m_timeMonitor->setSampleCount(3);if (!m_timeMonitor->create())

...Handle error

QOpenGLTimeMonitor

50

Page 51: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● QOpenGLTimeMonitor::recordSample() to record interval

m_timeMonitor->recordSample();glClear( GL_COLOR_BUFFER_BIT );m_timeMonitor->recordSample();glDrawArrays( GL_TRIANGLES, 0, 3 );m_timeMonitor->recordSample();

QOpenGLTimeMonitor

51

Page 52: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

● Call waitForSamples() or waitForIntervals() to retrieve samples or intervals (in nanoseconds)QVector<GLuint64> samples = m_timeMonitor->waitForSamples();QVector<GLuint64> intervals = m_timeMonitor->waitForIntervals();

o These functions block until values are readyo Call isResultAvailable() to prevent blocking

● Reset to use againm_timeMonitor->reset();

QOpenGLTimeMonitor

52

Page 53: Convert Your Legacy OpenGL Code to Modern OpenGL with Qt

Conclusion

● Qt has many classes that make working with OpenGL much more efficient.

● Cross platform capabilities of Qt enhance the portability of OpenGL applications greatly.

● Developer efficiency translates directly to maintenance costs and time to market.

● Qt is an ideal SDK for porting of legacy scientific applications with requirements for high performance visualization.