한국어
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에서 샘플링 할 것으로 예상한다.

이 글과 연관된 다른 글
  1. [2020/05/22] ShaderEffect QML Type을 이용한 버튼 클릭 효과 by makersweb (32)
  2. [2019/11/20] Qt3D의 QML 타입으로 3D렌더링 by makersweb (349)
  3. [2019/10/01] OpenGL 렌더링을 QtQuick과 통합하는 방법 by makersweb (358)
  4. [2018/12/05] Qml에서 커튼효과 구현 예제 - Shader Effects by 운영자 (435)
  5. [2018/02/01] 재밌는 퀴즈로 쉐이더 프로그래밍 배우기 by makersweb (283)
번호 제목 글쓴이 날짜 조회 수
공지 Qt프로그래밍(QtQuick) Beginner를 위한 글 읽는 순서 운영자 2019.01.05 10940
» ShaderEffect QML Type 을 이용한 그래픽효과 file makersweb 2018.12.09 727
36 Qml에서 커튼효과 구현 예제 - Shader Effects file 운영자 2018.12.05 435
35 안드로이드 Qt 프로그래밍 file makersweb 2018.11.30 4045
34 리눅스에서 Qt4.8기반 어플리케이션의 한글입력 file makersweb 2018.11.29 685
33 QML에서 동적으로 텍스트 다국어 처리 file makersweb 2018.11.04 1287
32 Qt Installer Framework - 패키징, 설치프로그램 제작 file makersweb 2018.10.14 3563
31 Qt 응용프로그램 배포(windows) file makersweb 2018.10.10 3783
30 소스코드에서 환경변수 가져오기와 설정하기 makersweb 2018.10.08 590
29 표를 만들고 PDF문서로 출력하기 file makersweb 2018.09.30 567
28 Qml에서 키보드 입력 이벤트 핸들링 file makersweb 2018.08.09 961
27 Qml 어플리케이션 정적 빌드 file makersweb 2018.07.27 732
26 Qt Bluetooth 관련 기능 확인 사항 makersweb 2018.07.10 363
25 Qml 및 C++개발시 유용한 팁 makersweb 2018.04.06 2395
24 Qt Version확인 방법 makersweb 2018.03.29 1023
23 초보자를 위한 첫번째 프로젝트 - QML로 만드는 Hello World file makersweb 2018.03.16 5099
22 Windows에서 라즈베리파이3 Qt 어플리케이션 개발 및 원격 실행 file makersweb 2018.02.23 3452
21 Windows에서 라즈베리파이3용 Qt5.10.0 크로스컴파일 [12] file makersweb 2018.02.23 7227
20 Windows환경에서 mingw로 Qt 5.10 정적(static)빌드 file makersweb 2018.02.01 3193
19 다국어 지원 어플리케이션 개발 file makersweb 2018.01.27 1232
18 Qt 어플리에이션 전역에 폰트 설정 makersweb 2018.01.24 1841