2012年05月25日

Qt CreatorでのGLEWの使用方法 その2

前回の続きです。

FBOの使用、2パスのレンダリング、ほぼMMDのようなカメラ操作を実装しました。
環境的には大体整ったかと思います。色々中途半端で放置中のものを何とか進めたいですね。

実行結果

マウスで視点を変えたりFBOにG-Bufferを出力してGUIのダイヤルで切り替えたりしています。



【Qtの最新記事】
posted by シンドラー at 19:48 | Comment(0) | TrackBack(0) | Qt | このブログの読者になる | 更新情報をチェックする

2012年05月22日

Qt CreatorでのGLEWの使用方法

また気がつくと1ヶ月以上経過していて困ったものです。

GUIが使えた方が色々と便利だと思いますので、Qtを使用してみることにしました。
Qt Creatorという統合開発環境があり、Visual Studioなどに慣れていれば容易にGUIプログラミングができそうです。

今回用いたバージョンは、Qt Creator 2.4.1 (Qt 4.7.4 (32 bit))です。
GLEWはいつのものかはわかりませんがそんなに古くは無いと思います。

QtはOpenGLをサポートしており、QGLWidgetクラスを使用すれば、GLSLを使用することができます。
Qtのものをそのまま使用すればいいとは思うのですが、昔GLEWを使用して作ったものが無駄になるのは悲しいので、QGLWidgetでGLEWを使用することにしました。

QtでGLSL準備

まずはQtでGLSLを使用できるまでの方法です。
こちらのページが大変参考になります。以後のお話は[1]と[3]をやった後のお話になっています。

参考サイト
[1] CreatorでOpenGL(v4.7対応): http://www10.atwiki.jp/bambooflow/pages/312.html
[2] QtでOpenGL : クラス: http://www10.atwiki.jp/bambooflow/pages/316.html
[3] Qt CreatorスタートガイドのCreating a Qt Widget Based Application

[1]ではcentralWidgetを格上げしていますが、スクロールバーなども使用してみたかったのでQWidgetとHorizontal Scroll Barを追加してVertical Layoutにしました。
Vertical Layoutなどは[3]が参考になりました。([3]はQt Creatorのようこそページにあります。)

qt_creator_001.png

GLSLを使用するためには、[2]のQGLShaderProgramを使用します。
シェーダのソースファイルのパスが、":/vshader.glsl"となっていますが、これはQtのリソースファイルになりますので、リソースファイルとして追加します。
このリソースファイルの追加方法も、[3]をやっておけばわかります。

GLEWの使用方法

続いてGLEWの使用方法です。
ポイントとしては、下記2点になります。
  • QGLWidgetより先にglew.h(+glut.h)をインクルードする。
  • QGLFunctionsはGLEWと競合してしまうのでインクルードしない。
ちなみにQGLFunctionsをインクルードすると、下記警告が出てビルドに失敗します。
#warning qglfunctions.h is not compatible with GLEW, GLEW defines will be undefined
#warning To use GLEW with Qt, do not include <QtOpenGL> or <QGLFunctions> after glew.h
これだけ読むとglew.hの前にQGLFunctionsをインクルードすれば良さそうですが、そうすると今度はgl.hがglew.hの前に宣言〜的なエラーがでます。

続いて、glewInit()をGLWidget::initializeGL()の最初の辺りで行っておきます。
これを忘れるとプログラムが突然終了してしまいます。

GLSLのプログラムはQtのものを使用しますので、シェーダの切替やテクスチャ名、シェーダにデータを渡すときのLocation等は、[2]で作成したprogramを使用して、program->programId()でシェーダプログラムの番号を取得します。

QtのGUI処理

続いてスクロールバーを動かしたときに視点を回転させる部分です。この辺の使い方はQt的に合っているのかどうかは分かりません。
Qtではメッセージ的なものをシグナル、そのシグナルが発生したときに呼ばれる関数をスロットというようです。
今、MainWindowクラスとGLWidgetクラスがあります。スクロールバーはMainWindow上に配置していますので、スクロールバーの値が変わったというシグナルは、MainWindowクラスに追加されます。
  1. GLWidgetクラスに、スクロールバーの値が変化したときに呼び出される関数を作成しておきます(setScrollValue(int))。
  2. 編集でmainwindow.uiをダブルクリックして、デザインを開きます。
  3. スクロールバーを右クリック→スロットへ移動を選択します。
  4. シグナルを選択するダイアログが表示されますので、valueChanged(int)を選択します。
  5. MainWindowクラスに、on_horizontalScrollBar_valueChanged(int value)といったクラスが追加されます。
  6. GLWidgetクラスのui(OpenGLWidgetという名前にしています)を通じて、GLWidgetクラスのメンバ関数setScrollValue(int)を呼び出します。
void MainWindow::on_horizontalScrollBar_valueChanged(int value)
{
ui->OpenGLWidget->setScrollValue(value);
}
外部ライブラリの追加方法

後はOpenCVや自作のライブラリなどを使用する場合は、そのフォルダの設定を行います。

編集のところのHelloGL.proというプロジェクトファイルをダブルクリックで開きます。
開いたファイルを右クリックすると、ライブラリを追加...というメニューがありますので、それを選択します。
外部ライブラリを選択して「次へ」を押します。
ライブラリファイルとインクルードパスを設定して、プラットフォームやリンク方法を選び、「次へ」で追加します。
そうするとINCLUDEPATHやライブラリのリンクが追記され、使用できるようになります。
(Program Filesのように空白が入る場合は""でくくるなど対策が必要)

Qtのイベント処理

マウスホイールでターゲットからカメラまでの距離を変えたかったので、マウスホイールのイベントを追加しました。
GLWidgetはQWidgetクラスを継承していますので、マウスホイールのイベントを受け取ることができます。

マウスホイールに関するヘッダのインクルード:glwidget.hでQWheelEventをインクルードします。
ホイールイベントの関数(void wheelEvent(QWheelEvent *event);)をヘッダに追加します。
ホイールイベントが発生したときの処理をglwidget.cppに記述します。
void GLWidget::wheelEvent(QWheelEvent *event)
{
int numDegrees = event->delta() / 8;
int numSteps = numDegrees / 15;

m_cameraDistance -= numSteps;
updateGL();
event->accept();
}
実行結果




PMDファイルのねんどろいどみくさんを表示してみました。
スクロールバーで回転、ホイールで前後しています。
GLUTとGLEWを使用したものですので、昔のものが一応利用できそうです。

posted by シンドラー at 19:56 | Comment(0) | TrackBack(0) | Qt | このブログの読者になる | 更新情報をチェックする

2012年04月11日

1枚の写真からの単純な3次元形状復元について

1枚の写真から直方体を生成します。
単純な方法ですので、消失点が1点のものにしか使えません。

1.3次元形状が直方体1個で済む画像を探す
2.奥の平面を構成する4画素を選択する
3.この点はあるワールド座標にモデルビュープロジェクション行列を掛けた結果得られた座標と考え、画素値(Px,Py)を4次元座標(Vx, Vy, Vz, Vw)に変換する
Vx = 2.0*Px/width-1.0;
Vy = 2.0*Py/height-1.0;
Vz = 0.9; // 適当
Vw = 1.0; // 座標なので1.0
5.視点や視野角などを適当に決定し、モデルビュープロジェクション行列の逆行列を計算する
6.計算した逆行列を4頂点V0~V4に掛ければ、適当なワールド座標が求まる
7.面の法線方向に4頂点を移動させた所の4頂点(計8頂点)で直方体が完成
8.奥行きVzが等しいと仮定していたため、法線ベクトルを手動で動かして補正する
9.頂点座標とテクスチャ座標をファイルに出力する
テクスチャの座標は直方体を構成する面ごとに展開して線形補間しました。

実行画面
下記サイトの写真を使用させていただきました。
フリー写真素材 Futta.NET:http://www.futta.net/
マウスで4点をクリックしてキーボードで補正しています。


.objで出力して、Blenderで.xに変換してMMDで読み込んでみました。
カメラを動かすと破綻するので使い道がありませんね。
キューブマッピングなどを使っていないので浮いて見えますし。


歩きモーションは下記動画のものを使用させていただきました。
http://www.nicovideo.jp/watch/sm9554606
posted by シンドラー at 20:42 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年03月29日

G-bufferと等高線の描画

Hardware-Accelerated Global Illumination by Image Space Photon Mappingというものがありましたので、少し試してみようかなと考えています。

http://www.youtube.com/watch?v=GckOkpeJ3BY

論文を読んでいるとG-bufferというものがでてきました。遅延シェーディングに使うバッファのことみたいですね。

[1] "Comprehensible rendering of 3-d shapes"
[2] http://d.hatena.ne.jp/hanecci/20100102
[3] http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20101208

[1]の論文の中に、等高線の表示があったので脱線して試してみました。
3.4のハッチングも試してみたかったのですが、良くわかりませんでした。

実行結果

G-bufferとして鏡面反射色、テクスチャ色、深度値、UV値、法線ベクトルをFBOに出力しました。背景が白なのでその部分は気にしないでください。

contour_specular.png contour_texture.png contour_depth.png contour_uv.png contour_normal.png

深度値のSobelエッジ×UV値の等高線×(鏡面反射色+テクスチャ色)の結果が次のようになります。

contour_001.png

U値で縦の等高線、V値で横の等高線が出てきます。
式は[1]の(7)〜(14)まで使用しました。

引続き脱線して、次も遅延レンダリングで何か試してみたいと思います。
posted by シンドラー at 22:44 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年03月14日

バンプマッピングのテスト

バンプマッピングを試してみることにしました。
テクスチャと接線、従法線の関係がいまいちよく分かりません。

手順
1. モデルを読込む
2. 適当に法線ベクトルから接線ベクトルを生成する
3. モデルのテクスチャ画像をグレースケールに変換する
4. グレースケールに変換したものを高さマップと考えて3x3のSobelフィルタでdu, dv, nを計算[1]
5. 接線情報をGPUに渡してバンプマッピング[2][3]
6. おまけでブルーム効果

実行結果

下記動画のモデルを使用させていただきました。



テクスチャにSobelフィルタを掛けて法線ベクトルを計算して0.0~1.0の間に変換して保存したものが下記のものです。
GIMPでノーマルマップ生成でSobel3x3を選んだ時と大体同じ感じになると思います。

bumptex.png

強めにしているのでノイズが入っていますね。まぁそれも模様ということで。

実行結果

左が通常のレンダリング、右が上の手順でレンダリングしたものです。サイズが小さいと全然違いがわかりませんね。

 

接線の計算が怪しいのでもう少し調べた方が良さそうです。

参考サイト
[1] http://www.t-pot.com/program/71_wave/index.html
[2] http://www.arakin.dyndns.org/glsl_bump.php
[3] http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20051014
[4] http://marupeke296.com/DXPS_No12_CalcTangentVectorSpace.html
posted by シンドラー at 20:27 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年03月06日

HDR画像のトーンマッピングについて その3

HDRレンダリングについて下記サイトの041〜051まで読みました。
http://news.mynavi.jp/column/graphics/041/index.html

ブルーム効果というものを試してみました。
http://news.mynavi.jp/column/graphics/050/index.html
MMEでいうところのAuto Luminousのような感じでしょうか。

本来はシェーダ側で全部やる気がしますが、手抜きでOpenCVを使用しています。
そんなわけで今回のはリアルタイムでは動いていません。

手順
1. HDRテクスチャを使ってFBOにレンダリング
2. 閾値より明るい画素の画像を生成
4. OpenCVのcvResizeとcvSmoothを使用してブルーム画像を作成
5. 結果を加算してからトーンマッピング

注意点?として、FBOにレンダリングしてその結果を取得した場合はfloat型でデータを取得できますが、glReadPixelsを使用した場合は、型にGL_FLOATを指定しても0.0〜1.0の間に切り詰められてしまうようです。

実行結果

ブルーム画像(左)と実行結果(右)

blumeImage.png hdr_blume_001.png

1/2, 1/4, 1/8, 1/16, 1/32の5枚の縮小画像を作成し、cvSmoothでぼかしてcvResizeで元の大きさに戻してcvAddで加算したものが左の画像です。
もっと広範囲にぼかした方がよさそうですね。



本来は閾値ではなく平均輝度などからブルームに使用する画素を決定するようですので、その辺りの影響かトーンマッピングの影響かはわかりませんが、角度によって明るさが変わってしまっています。

posted by シンドラー at 23:42 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年03月05日

HDR画像のトーンマッピングについて その2

PMDファイルのテクスチャにHDR画像を使用してみました。
.sph, .spaのファイルがある場合に、HDR画像に置き換えただけです。

HDR画像は下記サイトものを使用させていただきました。

http://unparent.com/photos_probes.html

スフィアマップHDR画像

probe_orig.png probe_tone.png

HDR画像(左)とトーンマッピング画像(右)です。サイズは縮小してあります。

実行結果

   通常の画像     HDR画像     トーンマッピング

non_hdr_001.png hdr_001.png hdr_tone_001.png



トーンマッピング後は通常のLDR画像ですが、HDR画像を使った場合とあまり変わらない気がしますね。

posted by シンドラー at 00:20 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2012年03月04日

HDR画像のトーンマッピングについて

最近はHigh Dynamic Range(HDR)画像を使ったImage based lightingなどが使われているようですので、ちょっと試してみることにしました。
HDR画像というのは基本float型でRGB値を持っており、普通は0〜1の範囲ですが明るい部分は1.0を軽く超えるような画像です。

HDR画像の読込みには[1]のソースコードを、サンプル画像は[2]のサイトのものを使用させていただいております。
何か問題がありましたらお知らせください。

今回は、HDR画像を見やすくするためのトーンマッピングを試してみました[3]。
参考サイトの通りにやったわけではないからかどうかわかりませんが、[2]のページの結果とは異なっているようです(赤色が強い?)。

[4]では輝度Lの計算がL=0.27R+0.67G+0.06Bで一般的なYCrCb変換式の係数と異なっているのでその辺りの影響かもしれません。

実行結果

0〜255で255を超えたものは255にした画像(左)とトーンマッピングを用いたもの(右)

cathedral_orig.png cathedral_tone.png

フォトンマッピングで計算した結果などもこういった処理をした方がいいんでしょうかね。

参考サイト
[1] http://www.graphics.cornell.edu/~bjw/rgbe.html
[2] http://www.anyhere.com/gward/hdrenc/pages/originals.html
[3] http://www.t-pot.com/program/123_ToneMapping/index.html
[4] http://msdn.microsoft.com/ja-jp/library/bb173486%28v=VS.85%29.aspx
posted by シンドラー at 02:47 | Comment(0) | TrackBack(0) | Image Processing | このブログの読者になる | 更新情報をチェックする

2012年02月29日

誤差拡散法による減色について

[1]の本を読んでいて、誤差拡散法がなんとなく面白そうだったので試してみました。

PC98の時代はカラーパレットが4096色で、実際に使用できるのが16色という感じだったようですので、今回は原画像をRGB16x16x16の4096色に減色し、そこから16色選んでさらに減色してみることにしました。

[2]のサイトにカラーでやる場合について書かれていました。

メディアンカット法は実装していませんので、すればよくなるかもしれません。
今はヒストグラム数が一番多い色からN個とる方法Aと、C-Means法でN個選ぶ方法Bで試しています。

実行結果

(左)原画像 (中)4096色に減色 (右)4096色で誤差拡散法

Lenna.bmp lenna_4096_0.png lenna_4096.png

(富士山原画像は省略) fuji_4096_0.png fuji_4096.png 

富士山画像は誤差拡散法を使わないと擬似輪郭が気になりますね。

256色(A, B)

lenna_256.png lenna_256_2.png

fuji_256.png fuji_256_2.png

誤差拡散法を使えば256色でも十分な気がしますね。256色の場合はAの方が良さそうな結果でした。

16色(A, B)

lenna_16.png lenna_16_2.png

fuji_16.png fuji_16_2.png

16色でもBの方ならなんとか見られるレベルですね。
まぁ時代的に減色はあまり意味がない気もしますがエフェクトの一種としていいかもしれません。
誤差拡散法は並列処理に向いていない気がするのであれですが。

富士山の画像は[3]の画像を使用させていただいております。
著者:NNE様
クリエイティブコモンズライセンスの表示・継承ですので、ここの画像もそれに従います。

参考文献
[1] CG-ARTS協会,“コンピュータグラフィックス”, 2004
[2] http://koujinz.cocolog-nifty.com/blog/2009/04/24bit-8bit-a879.html
[3] http://free-photo.gatag.net/2010/05/23/120000.html

posted by シンドラー at 20:03 | Comment(0) | TrackBack(0) | Image Processing | このブログの読者になる | 更新情報をチェックする

2012年02月22日

Bulletのレイキャスティングについて その6

Bulletのレイキャスティングを使って、MMD+MMEなどで良く用いられているSSAOを試してみました。
計算時間は512x512で数分かかります。

参考サイト
[1] http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20101122
[2] http://d.hatena.ne.jp/shuichi_h/20100318/

手順は以下のようにしました。

1. 視点から近クリップ面にレイを飛ばす
2. 当たったら、そこからn本のレイを拡散反射方向に飛ばす
3. n本中a本が衝突せず、残りの(n-a)本が衝突した場合、a/nの値をバッファに格納する
4. 3.で計算した値をガウスフィルタでぼかす
5. フィルタを掛けた結果をそこの色に掛けて最終的な色にする

2.のところがやはり時間がかかりますね。512x512=262,144で、そこから×n倍ですので、例えば500本飛ばしたら131,072,000本のレイを飛ばすことになります。

実行結果

200本飛ばしてフィルタなしが左、500本飛ばしてフィルタあり(5x5のガウスフィルタ)が右になります。
狭い部屋でレイを飛ばす距離を長くしているので、ほぼどこかに当たって暗くなるため無理やり明るくしています。

bullet_ssao_001.png bullet_ssao_002.png続きを読む
posted by シンドラー at 21:16 | Comment(0) | TrackBack(0) | Bullet | このブログの読者になる | 更新情報をチェックする