動画であそぼう: シェーダーエフェクトとマルチメディア

この記事は Qt Blog の "Pimp my video: shader effects and multimedia" を翻訳したものです。
執筆: Gareth Stockwell, 2012年2月29日

はじめに

Qt Quick のアプリケーションでのシェーダー言語によるエフェクトが注目を集めてきています。シェーダー言語の基本さえ分かってしまえば、Qt Quick のアプリケーションにシェーダーを埋め込むのは本当に簡単で、素晴らしいビジュアルエフェクトが驚くほど少ないソースコードで実現できます。

今までブログでは取り上げてきませんでしたが、(動画再生やカメラの映像などの)マルチメディアのコンテンツへのシェーダーエフェクトの適用も、他の QML 要素と同様に簡単にできます。この記事は QtMultimedia とシェーダーの組み合わせについて紹介したいと思います。

どのようなエフェクトが使用できるかは、デモを見てもらうのが一番です。ということでこの動画からはじめましょう。

qmlvideofx デモ: デスクトップ Linux 上の Qt 5

この動画は Qt Quick 2 のデモアプリで、デスクトップの Linux で動いています。(フレームレートを計算するためにシーングラフのシグナルを監視したり、ファイルからシェーダーを読み込むための)補助的な C++ のコードを除くと、このアプリはすべて QML で書かれています。

詳細

以前に紹介したとおり、Qt Quick 2 では QML の ShaderEffect 要素を通してシェーダーエフェクトをサポートしています。これを動画やカメラのファインダーに対して適用するのは他の QML の要素に対して適用するのとなにも変わりません。以下のコードでは動画ファイルの再生にゆらめき効果を適用した例です。

import QtQuick 2.0
import QtMultimedia 5.0

Rectangle {
width: 600
height: 400

MediaPlayer {
id: mediaPlayer
autoplay: true
source: "test.ogg"
}

VideoOutput {
id: videoOutput
anchors.fill: parent
source: mediaPlayer
}

ShaderEffect {
anchors.fill: parent

// Properties which will be passed into the shader as uniforms
property real amplitude: 0.02
property real frequency: 20
property real time: 0

NumberAnimation on time {
loops: Animation.Infinite
from: 0
to: Math.PI * 2
duration: 600
}

property variant source: ShaderEffectSource {
sourceItem: videoOutput
hideSource: true
}

fragmentShader: "
uniform highp float amplitude;
uniform highp float frequency;
uniform highp float time;
uniform sampler2D source;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
highp vec2 p = sin(time + frequency * qt_TexCoord0);
highp vec2 tc = qt_TexCoord0 + amplitude * vec2(p.y, -p.x);
gl_FragColor = qt_Opacity * texture2D(source, tc);
}
"
}
}

動画再生の代わりにカメラのファインダーに対してエフェクトを適用するには、ただ単に Video 要素を Camera 要素に替えるだけです。

今回の qmlvideofx のデモでは、それぞれのエフェクトは ShaderEffect を継承した QML の要素として実装されていて、メニューでエフェクトが切り替えられた場合に、これらの要素を動的に読み込み適用するようになっています。それぞれのソース(画像、動画、カメラ)も同様に QML 要素になっていて、必要に応じて動的に読み込んでいます。

それぞれのエフェクトのパラメーター(Pixelate の 'granularity' や Magnify の 'radius' と 'diffraction' など)は ListModel として実装していて、スライダーを作成するのに使われています。これによってパラメーターの値が変更できるようになっています。

コード(Qt 5.x)

qmlvideofx のデモは qtmultimedia リポジトリの中にすでに含まれています。
https://qt.gitorious.org/qt/qtmultimedia/trees/master/examples/video/qmlvideofx

Qt 5.0 がリリースされるまでは、自分でソースコードからビルドしてこのデモを試す必要があります。この手順は こちらの Wiki ページ にまとまっています。このデモを動かすために必要な Qt のモジュールだけをクローンする場合、以下のようにすることもできます。

$QTDIR/init-repository --module-subset=qtbase,qtdeclarative,qtjsbackend,qtmultimedia,qtxmlpatterns

コード(Qt 4.x)

Qt Quick 1 自体ではシェーダーエフェクトをサポートしていませんが、Qt 4.7.4 以降に含まれる Qt.labs.shaders プラグインを使うことで利用可能です。Qt 4 でのデモは以下から取得してください。
https://qt.gitorious.org/qt-mobility/qt-mobility/trees/master/demos/video/qmlvideofx

デスクトッププラットフォームでの動作(Linux と Windows で確認)に加えて、Qt 4 版のデモはモバイル端末上でも動作するでしょう。以下の動画は、Symbian 端末(Nokia 701)で動かしてみたものです。

qmlvideofx デモ: Symbian(Nokia 701) 上の Qt 4

デスクトップ版とほんの少し UI が異なることに気づいた方もいるでしょう。柔軟な Qt Quick のおかげで、レイアウト用の QML ファイルを1つ差し替えただけでこれはできました。

ここで注意が必要です。このアプリは現在の Symbian プラットフォームのバージョンでは動作しません。これは動画のデコーダーの出力結果を OpenGL ES でテクスチャとして扱える必要があるためです。動画とグラフィックススタックをこのように連携させるための EGL 拡張(EGL_NOK_image_endpoint2) が今後の Symbian のリリースに追加される予定です。これがリリースされた場合には QtMultimediaKit は自動的に対応するため(QTMOBILITY-1818)、このデモも動作するでしょう。

一方、Nokia N9 では現時点でも動作します。以下の動画を御覧下さい。

qmlvideofx デモ: MeeGo Harmattan(Nokia N9) 上の Qt 4

おわりに

今までシェーダーエフェクトの素晴らしさに気づいていなかった方も、この記事で納得してもらえたらいいなと思います。最後に関連するコンテンツへのリンクを貼っておきます。


Blog Topics:

Comments