«第9回 GLSL によるシャドウマッピング 最新 キューブマッピングで FBO を使ってみる»

床井研究室

※このブログは遅くとも 2027 年 3 月に管理者の定年退職により閉鎖します (移転先は管理者本人共々模索中)

■ 2006年06月23日 [OpenGL][テクスチャ] 3D テクスチャ

2010年12月17日 19:26更新

コメントスパム

6月18日の深夜にコメントスパムにさらされました.なぜか RDF ファイルも壊されてしまいました.ちくちく手で復旧したのですが,そのせいで記事の更新日時が変わってしまいました.その後,tdiary にコメントスパム対策のプラグインを追加しました.このブログではトラックバックスパムやリファラのスパムを嫌ってこれらを表示しないようにしているのですが,コメントを通じてはとても重要な情報を頂いていますので,今後もこのスタイルでいくつもりです.

ソリッドテクスチャ

授業でデモしようと思ってソリッドテクスチャのサンプルプログラムを作ろうと思ってたんですけど,テクスチャに使おうと思ったノイズの関数がなかなかうまく書けず,結局間に合いませんでした.ノイズを生成する関数はとりあえず自分が書きやすい方法で書いたのですけど,こんな書き方してりゃ遅いだろうなぁと思った通り遅いです.

プログラムは以前に質問された「視点を移動するのではなく,物体をぐるぐる回す方法は?」の回答のおまけで作ったキャッピングのプログラムをベースにしました.これはユーザ定義のクリップ面を使って物体を切り取り,ステンシルバッファを使って切り口にふたをする手法を使っています.細かい解説は,また後日,気力があれば書きたいと思います.テクスチャを変更する時は,PATTERN という記号定数を変更してコンパイルし直してください.

チェッカーボード ノイズ
Perlin ノイズ Turbulence

マウスをドラッグすると,断面を動かせます.glTexImage3D() を使っているので,OpenGL 1.2 以降であれば動くと思いますが,ビデオカードによってはソフトウェアエミュレーションになって,とても遅いかもしれません.

コメント(8) [コメントを投稿する]
pol 2006年06月23日 23:21

はじめまして。いつも記事を参考にさせて頂いております。<br>質問なのですが、GLSLに逆行列を求める関数や演算子は無いのでしょうか?<br>GLSLのドキュメントを読んでも逆行列を求める関数等が書いてないようなので自分で実装するしかないのでしょうか。<br>逆行列を求める基本的な演算がHLSLでも無いようなので、シェーダで逆行列を計算することってほとんどないのでしょうか・・・

とこ 2006年06月24日 12:18

pol さま,はじめまして.コメントありがとうございます.<br> GLSL や OpenGL 自体にも逆行列を求める関数は無いようです.一般的に逆行列を求めることは少々複雑な処理ですし,計算コストもかかります.だから「ものの本」 (Realtime Rendering とか) には,どうやって逆行列を求めずに逆変換を行うかについてページが割いてあったりします.<br> 実際 CG で頻繁に使われるのは,平行移動やスケーリング,回転といった変換の組み合わせです.これらはそれぞれ逆変換を簡単に求めることができますから,一般的に逆行列を求めるよりも,それぞれの逆変換を求めて逆順に掛け合わせた方が,手っ取り早くて確実でしょう.回転の変換の場合,GLSL だとかけ算の順序だけで変換/逆変換を切り替えられますよね.<br> もし,どうしても逆行列が必要になるのなら,シェーダ内で計算するより,CPU 側であらかじめ計算しておいた方がいいのではないかと思います.このブログのバンプマッピングのサンプル ( http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20050826 ) に含まれる matrix.cpp にも,4x4 行列の逆行列を求める関数 inverse() を用意していますので,よかったら参考にしてください(実は適当に作ったので信頼性に自信が無いんですが).

pol 2006年06月24日 13:44

お答えいただきありがとうございます。<br>ピクセルシェーダ上でレイトレーシングしようと、三角形とレイの交差判定処理を書いていたのですが<br>レイと三角形の交差判定で<br>三角形が(0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)<br>の単位三角形になるような行列を求める必要があり、その計算に逆行列が必要だったのです。逆行列を計算しなくても求められそうなんですが、かなり面倒そうなので逆行列を求めるGLSLの関数とかを使いたかったのです。<br>CPUで逆行列を求めるとGPUへ三角形と同じ数の逆行列を送らないといけないので効率が悪くなりそうです。<br>結局、逆行列を使わずに三角形とレイを交差判定する別のアルゴリズムに変えました。<br>CG分野では逆行列を求めないようにしているということがわかり勉強になりました。

とこ 2006年06月24日 23:25

pol さま,これは素人の戯言だと思って聞き流してください.<br> お話の内容で必要になる 3x3 行列の逆行列であれば,簡単確実に求めることができます(要素数も6個で済むんじゃないでしょうか).そこで,まず全ての三角形について,CPU で逆行列を求めます.これを,例えば<行列の要素数>×<三角形数>の配列に格納し,テクスチャとして GPU に読み込みます.そしてピクセルシェーダでこのテクスチャをサンプリングして,各三角形に対する逆行列を得ます.ピクセルシェーダに三角形の頂点座標値を送るにしてもテクスチャを使わざるを得ないと思うので,ピクセルシェーダにデータを送るコストは変わらないでしょう.<br> これを実現するためには浮動小数点テクスチャが使える必要がありますけど,テクスチャ座標を適切に設定したポリゴンを1枚描くだけで各三角形の交差判定の結果が一気に得られます.ただし,ピクセルシェーダ内で面積座標などを計算して交差判定するのとどっちが速いかわかりませんが.

ケロリ 2010年12月16日 20:36

はじめまして。最近このサイトを見つけて、過去の記事も含め、非常に参考にさせていただいております。<br>全く時期はずれで(記事掲載から4年半もたっている、、、)申し訳ありませんが、質問させてください。<br>現在、医用画像(CTやMRI)のボリュームレンダリングのソフトを作成しているところなのですが、glTexImage3D()で2バイト・データのテクスチャをうまく扱えずに困っています。<br>glPixelStorei( GL.GL_UNPACK_ALIGNMENT, 2 );<br>glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16, x, y, z, 0, <br>GL_LUMINANCE, GL.GL_SHORT, data);<br>:<br>としています。一応、エラーは出ていないのですが、<br>Fragment Shaderで<br> float d = texture3D( texture_data, t ).x;<br>としてボクセル(テクスチャ)の値を取り出しているのですが、<br>この値が元画像値(0〜8000)とは全くかけ離れた値が<br>帰ってきます。<br>う〜ん、どうすればよいのでしょうか?ご助言をお願いします。

ケロリ 2010年12月16日 20:38

訂正です。<br>glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16 ではなく<br>glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE16 です。

とこ 2010年12月16日 21:45

ケロリさま,<br>internalFormat に GL_LUMINANCE16 (GL_RGBA 等でも) を指定した場合, data に指定したデータは type に指定した型に従ってスケーリングされクランプされて, [0, 1] の範囲に丸められてテクスチャメモリに格納されます. したがって type が GL_SHORT の場合, シェーダプログラム側でサンプリングしたテクスチャの値を 32767 倍する必要があると思います. このとき負の値は扱うことができません.<br>お使いのビデオカードが OpenGL 3.0 に対応しているか, GL_ARB_texture_float 拡張機能 http://www.opengl.org/registry/specs/ARB/texture_float.txt や GL_EXT_texture_integer 拡張機能 http://www.opengl.org/registry/specs/EXT/texture_integer.txt をサポートしていれば, data の値をそのままシェーダプログラムで参照できます. short データを参照するなら, internalFormat に GL_R16I, format に GL_RED, type に GL_SHORT を指定してください. http://www.opengl.org/sdk/docs/man3/xhtml/glTexImage3D.xml

ケロリ 2010年12月17日 19:26

ご返答ありがとうございます。<br>> スケーリングされクランプされて, [0, 1] の範囲に丸められてテクスチャメモリに格納されます<br>恥ずかしながら、全く知りませんでした。確かにtexture3D() * 32767 でいい値になるようです。<br>初歩的なことを質問して申し訳ありませんでした。<br>あとは、、GLSLを勉強させていただきます。これからもよろしくお願いします。


編集 «第9回 GLSL によるシャドウマッピング 最新 キューブマッピングで FBO を使ってみる»