2014年10月27日

Normal Matrix についてのメモ

最近少しOpenGL 4.3辺りを試しているのですが、GLSLも結構変わっていますね。gl_ModelViewMatrixとかgl_NormalMatrixとか廃止?非推奨?になってるんですね。そういうわけで、uniform変数として渡す必要があり、glmを使ってModelViewProjection行列などは比較的簡単に作れたのですが、gl_NormalMatrixって何?って感じでした。調べてみると、ModelView行列の左上3x3の逆行列の転置で良いと書いていて、なんでそんな面倒な計算がいるのかなと思ったのですが、[1]などに説明がありました。

接線ベクトルと法線ベクトルの内積は本来0(直交)ですが、Model行列にスケーリングの要素が入っているなど、ModelView行列の3x3成分が直交基底になっていない場合は、内積が0にならなくなります。そのようなわけで、この3x3の行列を法線ベクトルにかけた後も法線ベクトルと接線ベクトルが直交するように導いていくと、最終的に逆行列を計算してから転置するということになるみたいです。

また、LookAt関数で計算したView行列は直交行列で、Model行列も回転と平行移動しかなければ直交行列なので、そういった場合は単純にModelView行列の3x3成分を使ったので構わないということのようです。

実行結果

トーラスに対してX軸方向に2倍するModel行列を使用する場合で試してみました。

ModelView行列の3x3をそのまま使った場合

NormalMatrix_002.png NormalMatrix_004.png

逆行列を計算して転置した場合

NormalMatrix_003.png NormalMatrix_005.png

ちゃんとしたNormal Matrixを使わないと周辺が暗くなってしまっていますね。スケーリングやせん断等はあまり使わないかもしれませんが。まぁこれでgl_NormalMatrixが使えなくても大丈夫ですね。

[1] http://www.lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix/

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

2014年10月24日

GSLを用いた球面調和関数の計算 その3

[1]の球面調和関数の説明に、いびつなウニという言葉が使われていていい表現だなと思いました。というわけで、いびつなウニを適当に表示してみることにしました。

入力画像として、[2]を使用させていただいております。[2]は"Photo by DAVID ILIFF. License: CC-BY-SA 3.0"ですので、加工したこのページの結果画像も同じライセンスになります。

実行結果

原画像から点をサンプリングして、明るさ(HSVのV)を中心からの距離にして描画したものです。カラーバッファをクリアせずに毎フレーム40000点ずつGL_POINTSで色はglColor4f(テクスチャのRGB,α=0.2);でやってます。ウニというより爆発っぽいですね。

sh_point_001.png

以下、これを球面調和関数で圧縮して適当な次数で展開したものを同様の方法で描画したものです。係数はRGBでやっていますので、実際には×3になります。

sh_point_002.png
maxL=0, 係数1個。ただの球です。

sh_point_003.png
maxL=1, 係数4個

sh_point_004.png
maxL=2, 係数9個

sh_point_005.png
maxL=3, 係数16個

sh_point_006.png
maxL=4, 係数25個

sh_point_007.png
maxL=5, 係数36個。maxLが3〜5ぐらいで十分と[1]には書かれていますね。

sh_point_008.png
maxL=6, 係数49個

sh_point_009.png
maxL=7, 係数64個

sh_point_010.png
maxL=8, 係数81個

sh_point_L20.png
maxL=20, 係数441個。このぐらいになるととげとげしすぎて遠ざかっている気がしますね…。遮蔽情報との内積を取る分には問題ないのでしょうか…。やっぱり3〜5ぐらいでいいのかもしれません。

[1] マイナビ:3Dグラフィックス・マニアックス 第68回
[2] WikipediaのPanorama画像
web拍手 by FC2
posted by シンドラー at 19:26 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2014年10月18日

点群やボリュームデータのポリゴン化について

球面調和関数などをモンテカルロ的な手法で計算した場合、基本点群ですので、可視化する場合点群をポリゴン化したいと思うと思います。以前は普通のマーチングキューブス法を使っていたのですが、その辺りの点群やボリュームデータからのポリゴン生成について調べていたら、Smooth Signed Distance[1]というソフトウェアがありました。昔試した気がする符号付き距離(Signed Distance)を使って等値面をポリゴン化するのだと思います。手法としてはDual Marching Cubes法などを使っているみたいです。おそらく。

[1]にも書いてありますが、CMakeを使えばVisual Studioでも簡単にコンパイルできました。サンプルの点群がPlyファイルで用意されており、コマンドラインで変換してMeshLabで表示したところ、少ない点群でもある程度の再構築ができているようでした。
というわけで、偏りのない球面上の点40000点をPlyファイルとして出力して、それを再構築してみました。点と法線ベクトルもいるみたいですので、球面調和関数の場合、法線ベクトルって簡単に計算できるのでしょうかね。中心からその点へのベクトルでも別にいいのかもしれませんが。

実行結果
ssd_recon.exe 変換前.ply 変換後.ply

変換前の点群
PolyVox_002.png

変換後のポリゴン
PolyVox_003.png PolyVox_004.png

Plyのヘッダ部分は下記のようになって、後は頂点座標と法線ベクトルを出力するだけですので、簡単に変換前のPlyを作成することができます。
  ply
format ascii 1.0
element vertex 40000
property float x
property float y
property float z
property float nx
property float ny
property float nz
end_header
0.127388 0.991853 0.000542 0.127388 0.991853 0.000542
...
今回表面の点だけでしたが、中身が詰まっている場合などはどうなるんでしょうかね。基本Kinect等で取得した表面点群だけなのでしょうか。

その他気になったライブラリとして、PolyVox[2]というzlibライセンスのものがあったので少し試してみることにします。

1. ダウンロードとビルド
[3]のダウンロードからリポジトリをダウンロードできます。ソースをチェックアウトしてもいいかと思います。次に、CMakeを使ってビルドします。便利ですねCMake GUI。

2. 使用するための準備
libraryというフォルダ内に、PolyVoxCoreとPolyVoxUtilというフォルダがあり、そこにヘッダファイルなどが入っているようです。ビルドしたらPolyVoxCore.libとPolyVoxUtil.libが生成されていると思います。おそらくCMakeの設定等でDLL出力もできるのではないかと思いますが、未確認です。
追加のインクルードディレクトリを指定して、PolyVoxCore.libとPolyVoxUtil.libをリンカに追加すれば準備完了です。

3. 球のテスト
ドキュメントのユーザマニュアルのTutorial 1 - Basic useに解説があります。ライブラリのサンプルプログラムにも色々含まれていますので、基本的にはそれを参考にすれば良いかと思います。

中心からの距離に応じて0か255の値に設定し、表面ポリゴンを生成するようです。この際、ボクセルの最大値の半分の値(今回は255の半分で127)を閾値とした表面ができるようです。このサンプルではCubicSurfaceExtractorWithNormalsを使用していてキューブベースの表面となっていますが、MarchingCubesSurfaceExtractorを使うと、マーチングキューブス法で生成されたもう少し滑らかな表面ができるようです。

BasicDemoでは、Qtを使ってレンダリングしていますが、OpenGLのサンプルにはOpenGLだけを使ったサンプルもあったと思います。今回は自分のプログラムに組込んでみます。

実行結果

PolyVox_001.png

点群しかない場合、結局ボリュームデータをどう作るかという問題になってしまいますので、ポリゴン化だけしたいのであれば前者でコマンドラインでというのでいいのかもしれません。

[1] http://mesh.brown.edu/ssd/software.html
[2] http://www.volumesoffun.com/polyvox-about/
[3] https://bitbucket.org/volumesoffun/polyvox/
web拍手 by FC2
posted by シンドラー at 02:09 | Comment(0) | TrackBack(0) | OpenGL & Metasequoia | このブログの読者になる | 更新情報をチェックする

2014年10月04日

GSLを用いた球面調和関数の計算 その2

前回の続きです。今回は圧縮と展開のテストです。

[1]のSH Projectionのところで、今回は球面上で等確率にサンプリングしているため、半径1の球の表面積4πを、サンプル数Nで割れば微小面積dSになるため、p.16の式のように、光源の明るさ(色)とylmの総和を計算して4π/Nを掛けてあげるだけで圧縮することができるようです。

展開する場合は、p.17のように圧縮した係数に元の関数値を掛けて総和をとればできるということになります。

実行結果

[2]のスカイドーム画像を使用させていただいております。

skydome012.png
原画像を縮小したもの

10000点のサンプリング点から、元のHDR画像の色を取得して、係数を計算して圧縮してから、その係数を使って展開した画像です。並列計算せずにCPUだけで計算したのでl=150の時は半日ぐらいかかってます…。

sh_deco_l4.png
l=4

sh_deco_l8.png
l=8

sh_deco_l12.png
l=12

sh_deco_l16.png
l=16

sh_deco_l150.png
l=150

前回の結果からこうなりそうな気がしていたんですが、やっぱりリギングがひどいですね。サンプリング数10000点が少ないのか、元画像を再現するためにはlが150でも足りないのか、何か間違えているのか…。

リギングを減らすためには、フーリエ変換と同じように窓関数を掛けてあげるといようなことが書かれていますね[3]。

おまけ

最後の画像を100回ぐらいガウスフィルタを掛けてみました。原画像に近いのは近いんですかね。

gauss_100.png

[1] http://www.research.scea.com/gdc2003/spherical-harmonic-lighting.pdf
[2] http://www.nicovideo.jp/watch/sm10968092
[3] http://www.ppsloan.org/publications/StupidSH36.pdf

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

2014年10月02日

GSLを用いた球面調和関数の計算

気が付くとほぼ1カ月更新していないので広告が出る前に更新しておきたいと思います。困ったものです。

球面調和関数の計算など、自前でやると精度や速度の面で怪しいので、GSLを使ってある程度高次まで計算してみることにしました。

今回はGSL(GNU Scientific Library)を使ってみます。名前からしてGPLなので公開する場合は気を付ける必要があります。

1. Windows, 64bitでのGSLの使い方
32bitのバイナリはあるのですが、64bitでVisual Studioを使う場合などは面倒なようです。今回は[1]のCMake対応のものを使用させていただきました。

2. 球面調和関数について
この辺りは以前も参考にさせていただいた[2][3]あたりでやっています。主に[3]の式やソースコードを参考にさせていただきました。

2.1. 球面上に偏りのない(unbiased)点の生成
モンテカルロ的な手法でthetaとphiをランダムに生成する場合、そのままやってしまうとサンプリングにかなり偏りが出てしまいます。以前はこれをそのままやっていたので上下が明るくなりすぎていたようです。[3]のp.6に一様乱数から偏りのないtheta, phiを生成する式が載っています。フォトンマッピングの時にも見たような気がしますね。

2.2. 正規化SHの計算
[3]のp.11には、正規化項Kが入った式が載っていますが、GSLを使用する場合、正規化されたルジャンドル陪関数を計算する関数gsl_sf_legendre_sphPlmがありますので、それを使用します([4]のp.86)。注意点としては、この関数の引数mは0以上の値をとりますので、m<0の場合は-mを引数として渡してあげる必要があります。また、マニュアルに書かれていますが、lが約150を超える場合にはオーバーフローを起こしてしまうようなので、GSLを使用する場合にはそこぐらいが限界のようです。

実行結果

適当な半透明の点をglClearせずに重ねていっただけのものです。正が緑、負が赤で、正規化SHの値をl倍して見やすくしています。

l1_m1.png
l=1, m=1

l4_m3.png
l=4, m=3

l10_m6.png
l=10, m=6

l20_m11.png
l=20, m=11

l50_m26.png
l=50, m=26

l100_m51.png
l=100, m=51

l150_m76.png
l=150, m=76

l150_m0.png
l=150, m=0

次は高次まで使うとキューブマップやスフィアマップをどれくらいまでちゃんと近似できるのか試してみたいと思います。実用性はないと思いますが。

[1] https://github.com/ampl/gsl
[2] http://asura.iaigiri.com/OpenGL/gl68.html
[3] http://www.research.scea.com/gdc2003/spherical-harmonic-lighting.pdf
[4] http://www.cbrc.jp/~tominaga/translations/gsl/gsl-1.15/gsl115.pdf

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