한국어
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 85857
179 Qt 응용프로그램에 Web 구성 요소를 표시 with Servo newfile makersweb 2024.04.27 1
178 Qt Creator 에서 GitHub Copilot 사용하기 file makersweb 2024.04.13 139
177 QtQuick 애플리케이션에 Rive 애니메이션 통합 makersweb 2024.03.31 291
176 Qbs 프로젝트를 정의하기 위해 사용되는 몇가지 중요한 아이템들 file makersweb 2019.10.13 296
175 Qt 6.4에 추가될 Qt Quick 3D Physics file makersweb 2022.08.07 343
174 HTTPS URL을 연결할 때 SslHandshakeFailedError 오류 makersweb 2022.07.31 355
173 Qt Android 앱에 AdMob 배너달기 file makersweb 2021.12.04 392
172 그래픽 소프트웨어에서 디자인 내보내기 (Exporting Designs from Graphics Software) j2doll 2020.12.25 413
171 Binding 타입으로 객체 속성 간 묶기 makersweb 2022.03.04 420
170 Base64로 인코딩된 파일을 복원 makersweb 2023.08.06 425
169 VirtualKeyboard 스타일 커스터 마이징 makersweb 2022.03.13 462
168 Android 애플리케이션 서명 구성 file makersweb 2023.12.17 474
167 Qt Quick Controls 2에 네이티브 데스크탑 스타일 추가 file makersweb 2020.11.23 486
166 하드디스크 드라이브 여유 공간 계산 file makersweb 2023.01.15 488
165 앱을 종료할 때 QML 바인딩 오류를 피하는 방법 makersweb 2021.08.08 498
164 안드로이드용 Qt 6.2 makersweb 2021.10.02 504
163 성능 고려 및 제안 사항 makersweb 2022.03.07 505
162 QRhi 에 대해서 file makersweb 2023.12.29 506
161 QML의 사용자 정의 Image makersweb 2023.09.17 534
160 Qt Safe Renderer 개요 file makersweb 2022.09.08 541