한국어
Qt
 

스마트폰이 대중화되고 그에 맞춰 CPU단가도 점차 낮아지면서 임베디드 분야에서도(MCU를 주로 다루는 쪽이 아니라면..) 화면과 함께 GUI 을 제공하는 것이 최근 추세인것같다. 

 

또한 프로세서에 GPU가 기본적으로 장착되면서 고급화된 그래픽기술을 이용한 소프트웨어를 개발할 수 있게 되었고 이렇게 GPU와 함께 강력한 그래픽기술을 이용할 수 있게 하는 것이 OpenGL이나 Direct3D 같은 그래픽 API이며 이를 이용해 더 다양한 사용자 경험을 제공할 수 있게된다. 

 

셰이더

 

이런 그래픽 API들의 고급 기능을 이용하려면 셰이더라고 부르는 GPU내에서 동작되는 프로그램을 필요로 한다.

이는 적합한 Vertex(정점)셰이더와 Fragment(픽셀)셰이더의 구현과 적재 없이는 화면을 나타낼 수 없다는 것을 의미한다.

 

OpenGL은 스테이지(stage)로 분할된 렌더링 파이프라인(Rendering Pipeline)을 사용한다. 아래 그림은 단순화된 OpenGL 파이프라인인데 vertex shader와 fragment shader가 바로 프로그램 가능한 부분이다.

Rendering Pipeline.png

vertex shader는 vertex data를 받아서 해당 루틴이 끝날 때 내부 변수인 gl_position에 변환된 정점위치를 저장한다. 다음 스테이지에서 기본요소(점,선,삼각형)들이 2차원 프래그먼트 집합으로 변환되고, 이렇게 래스터 변환 단위에 생성된 정점 셰이더 데이터는 프래그먼트 셰이더에 입력되어 프래그먼트 연산을 수행하여 픽셀의 단일 컬러 gl_FragColor를 출력하게 된다.

 

OpenGL에서는 이 셰이더를 GLSL(OpenGL Shading Language)로, Direct3D에서는 HLSL(High Level Shader Language)로 작성하는데 Qt Qml에서는 백엔드에 따라서 둘 다 지원한다.

 

Qml로 GUI Application을 개발하는 경우 이렇게 사용자정의 셰이더를 구현하고 적재하기 위해 ShaderEffect와 ShaderEffectSource QML Type을 제공하며 이 타입을 이용하면 고급 그래픽효과들을 Qml내에서 직접 구현 할 수 있다.

 

아래는 간단한 ShaderEffect 및 GLSL 예제이다.

import QtQuick 2.11
import QtQuick.Window 2.11

Window {
    visible: true
    width: 350
    height: 200
    title: qsTr("Hello https://makersweb.net")

    Rectangle {
        anchors.fill: parent
        Row {
            anchors.centerIn: parent
            Image {
                id: img
                source: "qrc:/makersweb.png"
                width: 153
                height: 69
            }

            ShaderEffect {
                width: img.width;
                height: img.height
                property variant src: img
                vertexShader: "
                    uniform highp mat4 qt_Matrix;
                    attribute highp vec4 qt_Vertex;
                    attribute highp vec2 qt_MultiTexCoord0;
                    varying highp vec2 coord;
                    void main() {
                        coord = qt_MultiTexCoord0;
                        gl_Position = qt_Matrix * qt_Vertex;
                    }"
                fragmentShader: "
                    varying highp vec2 coord;
                    uniform sampler2D src;
                    uniform lowp float qt_Opacity;
                    void main() {
                        lowp vec4 tex = texture2D(src, coord);
                        gl_FragColor = vec4(vec3(dot(tex.rgb,
                                            vec3(0.344, 0.5, 0.156))),
                                                 tex.a) * qt_Opacity;
                    }"
            }
        }
    }
}

 

ShaderEffect를 이용하면 간단하게 그래픽 효과를 줄 수 있다.

logo_shadereffect.png

 

셰이더에서 변수의 타입과 한정자

 

기본변수 타입들 (더 많은 타입 정보는 다음 링크에 있다.)

Type

Meaning

void

for functions that do not return a value

bool

a conditional type, taking on values of true or false

int

a signed integer

uint

an unsigned integer

float

a single-precision floating-point scalar

double

a double-precision floating-point scalar

vec2

a two-component single-precision floating-point vector

vec3

a three-component single-precision floating-point vector

vec4

a four-component single-precision floating-point vector

mat2

a 2 × 2 single-precision floating-point matrix

mat3

a 3 × 3 single-precision floating-point matrix

mat4

a 4 × 4 single-precision floating-point matrix

sampler2D

a handle for accessing a 2D texture

sampler3D

a handle for accessing a 3D texture

 

lowp, mediump, highp

정밀도 한정자는 실수나 정수에 기반한 모든 변수의 정밀도를 지정하는 데 사용될 수 있다. 변수가 정밀도 한정자 없이 선언되면 그 변수는 기본 정밀도를 가진다.

 

Uniform 

uniform 변수는 "외부"에서 정점 또는 프래그먼트 셰이더와 통신하는 데 사용되며 셰이더에서는 uniform 한정자를 사용하여 변수를 선언한다.

uniform 변수는 읽기 전용이며 모든 정점에서 동일한 값을 가진다.

 

Attribute

버텍스 Attributes은 "외부"에서 버텍스 셰이더로 통신하는 데 사용되며 uniform변수와는 달리 정점마다 값이 제공된다.(그리고 모든 정점에 대해 전역 적으로 제공되지않음) 법선이나 위치와 같은 내장 된 정점 attribute이 있거나 사용자 정의의 정점 attribute을 지정할 수 있다.

마지막으로 fragment shader에서는 attribute를 정의할 수 없다.

 

Varying

Varying 변수는 Vertex와 Fragment Shader 사이의 공유할 수 있는 변수를 제공한다.

버텍스 셰이더에서 Varying 변수를 정의하면 렌더링되는 primitive에 대해 해당 값이 보간되고 프래그먼트 셰이더에서는 보간된 값에 액세스할 수 있다.

 

미리 정의된 변수

 

위의 Vertex와 Fragment Shader 예제에서 qt_ 접두어가 붙은 변수들을 볼수있는데 이것들은 Qt에서 기본으로 제공하는 변수들이며 아래와 같이 몇가지가 미리정의 되어있다. 

 

qt_Matrix - 조합 된 변환 행렬(모델-뷰-투영 행렬), 이 행렬은 3D그래픽에서 3개의 매우 중요한 변환 행렬의 결과이다.

qt_Opacity - 결합 된 불투명도

qt_Vertex - 정점 위치

qt_MultiTexCoord0 - 텍스쳐 좌표. 좌측 상단은 (0, 0), 우측 하단은 (1, 1)

qt_TexCoord0 - 셰이더간 공유되는 텍스쳐 좌표. 기본 버텍스 셰이더에서 텍스처 좌표가 highp vec2 qt_TexCoord0으로 변하고, source라는 이름의 sampler2D에서 샘플링 할 것으로 예상한다.

번호 제목 글쓴이 날짜 조회 수
공지 Qt프로그래밍(QtQuick) Beginner를 위한 글 읽는 순서 운영자 2019.01.05 85170
56 tslib의 ts_calibrate를 응용해서 Qt로 터치보정기능 구현 file makersweb 2019.04.06 1344
55 GPU가 없는 장치에서 Qt Quick을 사용 makersweb 2019.04.02 1846
54 QTextCodec클래스를 사용하여 유니코드와 EUC-KR 변환 makersweb 2019.03.25 2843
53 qInstallMessageHandler를 이용한 디버그 메세지 출력 제어하기 makersweb 2019.02.25 1331
52 Qt5기반 독립 프로세스(out-of-process)로 동작하는 가상키보드(virtual keyboard) file makersweb 2019.02.24 2598
51 Qml 기본 컴포넌트 강좌 (4) - 모델 리스팅(Listing) file 운영자 2019.02.23 5234
50 Qt Bluetooth를 이용한 시리얼(Serial) 통신 file makersweb 2019.02.17 3478
49 Qml 기본 컴포넌트 강좌 (3) - 배치(positioning) 컴포넌트 file 운영자 2019.02.10 4814
48 QString 문자열 다루기 예제 운영자 2019.01.26 39465
47 Qt SQL을 이용한 가벼운 데이터베이스 다루기 [1] file 운영자 2019.01.23 6865
46 구글 클라우드 Speech-To-Text API를 Qt기반(C++, Qml)테스트 [7] file makersweb 2019.01.20 2605
45 QNetworkAccessManager를 통해 HTTP POST 하는 예제 makersweb 2019.01.17 4698
44 Qt응용프로그램 실행 시 콘솔창(터미널)같이 띄우기 file makersweb 2019.01.16 4415
43 안드로이드 가상장치 사용 file makersweb 2019.01.13 1059
42 Qml 기본 컴포넌트 강좌 (2) [2] file makersweb 2019.01.05 8566
41 Qml 기본 컴포넌트 강좌 (1) file makersweb 2019.01.03 11929
40 QtWayland와 ivi-compositor file makersweb 2018.12.27 2392
39 Qml과 C++로 구현하는 GUI어플리케이션 file makersweb 2018.12.25 13789
38 싱글터치 스크린 및 임베디드 리눅스 기반에서 Qt 터치입력 makersweb 2018.12.24 1382
» ShaderEffect QML Type 을 이용한 그래픽효과 file makersweb 2018.12.09 2090