Русскоязычный портал о QML и QtQuick, QmlPortal What the duck

Каталог статей

Главная » Статьи » QML для профессионалов

Qt Quick 2 QML Scene Graph + GLSL fragment shader

Данная статья является кратким переводом статьи "Qt Quick 2 QML Scene Graph GLSL fragment shader tutorial".


Сборка Qt с Scene Graph

Чтобы получить работающий scene graph, вы должны собрать специальную версию QT. Итак, выкачиваем и собираем: 

$ git clone git://gitorious.org/qt/staging.git
$ cd staging
$ git checkout -b qtquick2 origin/qml-team/qtquick2
$ ./configure -developer-build -opensource -confirm-license -fast \
     -nomake demos -nomake examples \
     && nice make -j5

Когда это будет сделано, вы найдете qmlscene binary в staging/bin. Это просмотрщик для файлов Scene Graph QML, 

Прописываем переменные окружения:

$ env -i LD_LIBRARY_PATH=$QTDIR/lib DISPLAY=:0 $QTDIR/bin/qmlscene \
    whatever.qml


Первые шаги с Qt Quick 2

Написание кода в Qt Quick 2 очень похоже на написание кода в Qt Quick 1 и это неудивительно. Конечно, мы импортируем QtQuick 2.0 в начале вместо QtQuick 1.x, но кроме которого все выглядит одинаково. Давайте идти вперед и создадим новый "Qt Quick UI” проект. Получаем:

import Qt Quick 1.0

Rectangle {
    width: 360
    height: 360
    Text {
        anchors.centerIn: parent
        text: "Hello World"
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }
}

Измените импорт на версию 2.0 и запустите этот код, используя qmlscene. Он должен работать нормально. 
Теперь начинается самое интересное smile
Удалите элемент Text, найдите где-нибудь веселую картинку и добавьте в код элементы Image, Item и Text, как показано ниже: 

import QtQuick 2.0

Rectangle {
    width: 512
    height: 512

    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }

    Image {
        id: kitty
        source: "kitty.png"
    }

    Item {
        id: scrollercontainer
        anchors.fill: parent

        Text {
            id: scroller
            text: "Hello QtQuick world!"
            color: "white"
            font.pixelSize: 80
            anchors.verticalCenter: parent.verticalCenter
        }
    }
}


ShaderEffectSource

Добавим элементы ShaderEffectSource для картинки и для текста: 

    ShaderEffectSource {
        id: kitty_source
        sourceItem: kitty
    }

    ShaderEffectSource {
        id: scroller_source
        sourceItem: scrollercontainer
    }

ShaderEffectSource - это невидимый элемент, который связывает исходный элемент с шейдером.


Первый эффект

Итак, исходные элементы подготовлены, можно подготавливать первый эффект. Для этого мы создадим ShaderEffectItem. Это - видимый элемент, который фактически является визуальным представлением оригинальной, невидимой, картинки. Реальная работа будет сделана посредством GLSL, т.е. содержанием свойства fragmentShader:

    ShaderEffectItem {
        id: kitty_effect
        anchors.fill: parent

        property variant source : kitty_source

        fragmentShader: "
        varying highp vec2 qt_TexCoord0;
        uniform lowp sampler2D source;
        void main() {
            gl_FragColor = texture2D(source, qt_TexCoord0);
        }"
    }
Шэйдер выше - простая операция передачи, в которой он показывает исходное неизменное изображение. Синатаксис схож с C, выполнение начинается с main(). То, что реально делает shader, это выбор цвета "фрагмента" (то есть пиксела) посредством чтения переменной gl_FragColor. gl_FragColor - это вектор с четырьмя компонентами в формате RGBA, все компоненты имеют значения в пределах от от 0 до 1. Для отображения оригинальной картинки фильтр должен выбирать соответствующие пиксели из исходного изображения. Это делается посредством функции texture2D(). Функция имеет два параметра: текстура и двукомпонентный вектор (x, y), указывающий на точку исходного изображения (значение - от 0 до 1). 

Подробную информацию о GLSL вы можете получить здесь:

Немного движения.

    ShaderEffectItem {
        id: kitty_effect
        anchors.fill: parent

        property real angle : 0.0
        PropertyAnimation on angle {
            to: 360.0
            duration: 800
            loops: Animation.Infinite
        }

        property variant source : kitty_source

        fragmentShader: "
        varying highp vec2 qt_TexCoord0;
        uniform lowp sampler2D source;
        uniform highp float angle;
        void main() {
            highp float texAngle = 0.0;
            if (qt_TexCoord0.x != 0.0 || qt_TexCoord0.y != 0.0) {
                texAngle = atan(qt_TexCoord0.y - 0.5, qt_TexCoord0.x - 0.5);
            }
            gl_FragColor = vec4(sin(texAngle + radians(angle)),
                                sin(texAngle + radians(angle - 120.0)),
                                sin(texAngle + radians(angle - 240.0)),
                                1.0)
                           * texture2D(source, qt_TexCoord0);
        }"
    }

Усложним эффект.

    ShaderEffectItem {
        ...
        fragmentShader: "
        ...
        void main() {
            highp float texAngle = 0.0;
            if (qt_TexCoord0.x != 0.0 || qt_TexCoord0.y != 0.0) {
                texAngle = atan(qt_TexCoord0.y - 0.5, qt_TexCoord0.x - 0.5);
            }
            highp float skew = sqrt(pow(qt_TexCoord0.x - 0.5, 2.0)
                                    + pow(qt_TexCoord0.y - 0.5, 2.0))
                               * 10.0;
            highp vec4 colorwheel = vec4(sin(texAngle + radians(angle) - skew),
                                   sin(texAngle + radians(angle - 120.0) - skew),
                                   sin(texAngle + radians(angle - 240.0) - skew),
                                   1.0);
            highp vec4 texpixel = texture2D(source, qt_TexCoord0);
            gl_FragColor = colorwheel * texpixel;
        }"
    }

Колебания бэкграунда.

    ShaderEffectItem {
        ...
        fragmentShader: "
        ...
        void main() {
            ...
            highp float wavefactor = 0.03;
            highp float wave_x = qt_TexCoord0.x + wavefactor
                           * sin(radians(angle + qt_TexCoord0.x * 360.0));
            highp float wave_y = qt_TexCoord0.y + wavefactor
                           * cos(radians(angle + qt_TexCoord0.y * 360.0));
            highp vec4 texpixel = texture2D(source, vec2(wave_x, wave_y));
            gl_FragColor = colorwheel * texpixel;
        }"
    }
Бегущая строка.

Добавим текст и заставим его скроллиться:

        Text {
            id: scroller
            text: "Hello QtQuick world! Hello QtQuick world! " +
"Hello QtQuick world! Hello QtQuick world! " +
"Hello QtQuick world! Hello QtQuick world! " +
"Hello QtQuick world! Hello QtQuick world! "
            color: "white"
            font.pixelSize: 80
            anchors.verticalCenter: parent.verticalCenter
            PropertyAnimation on x {
                from: scrollercontainer.width
                to: -scroller.width
                duration: 800 * (scroller.width / 100)
                loops: Animation.Infinite
            }
        }


В результате должно получится примерно следующее:





Источник: http://ilkka.github.com/blog/2011/03/04/qtquick_2_scenegraph_glsl_fragment_shader_tutorial/
Категория: QML для профессионалов | Добавил: CYAN (24.07.2011) | Автор: C_Y_A_N E W
Просмотров: 4683 | Комментарии: 1 | Теги: QML Scene Graph, Qt Quick 2, GLSL fragment shader | Рейтинг: 5.0/2
Всего комментариев: 1
1 Realraita  
спасибо за интересный блог

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Категории раздела

Все статьи [0]
Обучение QML [8]
Статьи с базовой информацией о языке QML
Статьи по QML [6]
Статьи по QML
QML для профессионалов [4]
Статьи по QML-темам повышенной сложности
Ссылки на видео [5]
Ссылки на видео с демонстрацией возможностей QML
Ссылки на материалы по QML в интернете [2]
Ссылки на полезные материалы по QML в интернете
Обо всём [1]
Статьи на разные темы, не имеющие отношение к QML и QtQuick

Поиск на сайте

Облако тэгов

kinetic scroll анимация интерфейса кинетик скролл создание интерфейса path view qml видео демонстрация qml QML Component QML Grid Demo QML browser plugin просмотр QML форм QML signal QML Transition базовые типы QML QML Text пример QML экспорт qml из GIMP QML Rectangle color picker QML MouseArea qml export QML State экспорт QML из Photoshop QML QtQuick Web-browser Набор виджетов для QML статьи о QML на русском языке MeegoHarmattan N9/N950 game Sprite Animation GLSL fragment shader Qt Quick 2 Анимация Easing Easing curves Сглаживающие кривые C++ QGraphicsView Q_INVOKABLE Интеграция QML и C++ QML Particle System QtQuick.Particles QML Scene Graph javascript глобальные переменные Qt Mobility QtMultimediaKit map QtMobility.location Debian package Harmattan QtCreator D.U.C.K. H.U.N.T. QML пример

Статистика сайта

Статей: 26
Новостей: 6
Файлов: 10
Форум: 19/46
Коментариев: 6

Посетители

Полезные ресурсы

сайт Российского Qt сообщества The FRUCT program Российская сеть MeeGo пользователей и разработчиков