한국어
Qt
 

이 글에서는 Qt Quick 2 응용프로그램을 개발할 때 사용자 정의 OpenGL 렌더링과 통합하는 방법을 소개한다.

 

OpenGL 코드를 Qt Quick에 통합하는 방법을 설명하기 앞서 Qt Quick 2가 장면을 렌더링하는 방법에 대해 알아보자.

 

Qt Quick 2는 OpenGL과 전용 렌더링 스레드를 활용하여 Qt Quick 요소를 렌더링한다.

초당 60프레임의 안정적인 그리기, 특수효과(그림자, 입자, 흐림 등)를 추가하고 부드러운 애니메이션을 위해 OpenGL 기반 렌더링은 필수이다. 렌더러가 메인 스레드(main()을 실행하는 스레드)와 다른 전용 렌더 스레드를 사용하는 데에는 다음과 같이 두 가지 이유가 있다.

  1. CPU가 바쁘거나 주 스레드가 블로킹 함수 호출에 있어도 UI가 멈추지 않도록 할 수 있다.(애니메이션이 60fps로 계속 유지됨)

  2. 1번과 대칭적으로 우연히 GPU가 장면을 렌더링하는 데 너무 느려질 경우, 메인 스레드가 GPU에 영향 받지 않도록 할 수 있다. 

이 전용 스레드는 기본적으로 Qt 5.6에서 지원하는 모든 플랫폼에서 사용된다.(Windows의 ANGLE 만 제외)

 

 

OpenGL 렌더링과 Qt Quick 2의 통합

 

Qt Quick 2는 Scene Graph 구조를 사용하여 렌더링한다.

Scene Graph의 정확한 정의는 트리 구조의 노드 모음인데 트리는 QML 장면의 QQuickItem 유형으로 빌드되며 내부적으로 렌더러가 장면을 처리한다.

 

Scene Graph의 렌더링은 전적으로 QQuickWindow 클래스에서 내부적으로 이루어지며 액세스 할 수 있는 공개 API가 없다. 그러나 렌더링 파이프 라인에는 사용자가 응용 프로그램 코드를 첨부 할 수 있는 곳이 몇 군데 있으며, 이 부분을 이용해 사용자 정의 Scene Graph 컨텐츠를 추가하거나 원시 OpenGL 컨텐츠를 렌더링한다.

 

예를들어 응용 프로그램은 QQuickItem을 서브클래싱하는 사용자 정의 아이템의 QQuickItem::updatePaintNode()함수를 재정의하여 작은 트리 노드(QSGNode)를 렌더러로 반환한다. 메인 스레드가 일시 중지하여 렌더링 스레드와 동기화될 때 렌더링 스레드가 장면의 모든 시각적 요소에서 QQuickItem::updatePaintNode()함수를 안전하게 호출한다.

qnite 오픈소스프로젝트는 이 방법을 이용하여 그래프를 렌더링하는 좋은 예제 라이브러리이다. https://github.com/evonove/qnite

qnite.png

 

또다른 예는 QQuickWindow::beforeRendering() 및 QQuickWindow::afterRendering() 시그널에 연결하여 Scene Graph가 렌더링되는 것과 동일한 컨텍스트로 직접 OpenGL 렌더링을 수행 할 수 있다.

시그널 이름에서 알 수 있듯이 사용자는 QtQuick 장면 아래 또는 그 위에 OpenGL 컨텐츠를 렌더링 할 수 있다. 이러한 방식으로 통합하면 얻을 수 있는 이점은 렌더링을 수행하는 데 추가 프레임 버퍼 나 메모리가 필요하지 않다는 것이다.

단점은 QtQuick이 언제 신호를 호출할지에 의존하는 것인데, 이것이 OpenGL 애플리케이션이 그릴 수 있는 유일한 시간이다.

다음 링크의 예제는 이러한 시그널을 사용하여 그리는 방법을 보여준다.

https://doc.qt.io/qt-5/qtquick-scenegraph-openglunderqml-example.html

 

다른 대안은 QQuickFramebufferObject를 생성하여 렌더링 한 다음 Scene Graph에 텍스처로 표시하는 것이다.

Qt 5.2부터 새로 추가된 접근 방법으로 QQuickFramebufferObject와 QQuickFramebufferObject::Renderer를 서브클래싱하여 사용한다.

서브 클래스는 createRenderer() 가상 함수를 다시 구현해야 한다. 이 팩토리 함수는 Scene Graph의 렌더링 스레드에서 호출되고 리턴된 QQuickFramebufferObject::Renderer 서브 클래스는 이 렌더링 스레드에서 사용된다.

 

QQuickFramebufferObject::Renderer 는 자체 렌더링 (render())함수 내부에서만 사용할 수 있는 자체 update() 함수로 다음 프레임에서 내용의 재 렌더링을 예약할 수 있다.

 

▲QQuickFramebufferObject 클래스를 이용한 사용자 OpenGL 코드와 Qt Quick통합

 

다음 링크의 예제는 이를 수행하는 방법을 보여준다.

https://doc.qt.io/qt-5/qtquick-scenegraph-textureinsgnode-example.html

 

 

다음 링크 페이지의 내용을 참고, 요약하였다.

https://www.qt.io/blog/2015/05/11/integrating-custom-opengl-rendering-with-qt-quick-via-qquickframebufferobject

https://www.kdab.com/integrating-opengl-with-qt-quick-2-applications-part-1/

번호 제목 글쓴이 날짜 조회 수
공지 Qt프로그래밍(QtQuick) Beginner를 위한 글 읽는 순서 운영자 2019.01.05 91023
28 웹기반 Qt Design Viewer [2] file makersweb 2019.10.23 1977
» OpenGL 렌더링을 QtQuick과 통합하는 방법 file makersweb 2019.10.01 2962
26 QML내에서의 시그널, 슬롯 시스템 makersweb 2019.09.29 7898
25 C++로 구현된 모델을 QML의 ListView에서 참조 file makersweb 2019.09.07 5739
24 QSocketNotifier로 파일 디스크립터의 활동감지 makersweb 2019.08.28 2412
23 열거형(enum)을 QML에서 사용하는 방법과 문자열(QString)로 얻기 makersweb 2019.08.20 4714
22 [Qt] Google Play의 향후 요구 사항을 준수하는 방법 [2] j2doll 2019.07.29 1554
21 Qt Quick Controls 2사용 및 스타일 설정 file makersweb 2019.06.07 6979
20 QML 강좌 - 동적 Listing (ListView) file makersweb 2019.06.01 11023
19 QtCreator Design으로 GUI만들기 (QML로 만드는 Hello World -2) [1] file makersweb 2019.05.26 16287
18 QML에서 멀티 스레드(multithreading) 프로그래밍 file makersweb 2019.05.25 3149
17 QML과 QtQuick 모듈 개념과 기본 타입들 makersweb 2019.04.26 14359
16 QML 전역 객체 (Global Object) file makersweb 2019.04.10 1671
15 tslib의 ts_calibrate를 응용해서 Qt로 터치보정기능 구현 file makersweb 2019.04.06 2025
14 GPU가 없는 장치에서 Qt Quick을 사용 makersweb 2019.04.02 2467
13 Qml 기본 컴포넌트 강좌 (4) - 모델 리스팅(Listing) file 운영자 2019.02.23 6131
12 Qml 기본 컴포넌트 강좌 (3) - 배치(positioning) 컴포넌트 file 운영자 2019.02.10 5681
11 Qml 기본 컴포넌트 강좌 (2) [2] file makersweb 2019.01.05 9506
10 Qml 기본 컴포넌트 강좌 (1) file makersweb 2019.01.03 13292
9 Qml과 C++로 구현하는 GUI어플리케이션 file makersweb 2018.12.25 15244