スポンサーサイト

--年--月--日 --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

OpenGL でのレンダリングターゲットの変更(テクスチャに描画)

2005年10月25日 14:19

今日もプログラムの話(・∀・)

OpenGL について書かれているHPはいっぱいあるんだけど、それの拡張命令(ARB や EXTってつくやつ)については
全然説明しているHPがない。
ましてや日本語のHPだとまったくない!
ってことで、ちょっとだけやっぱりメモ帳代わりにブログに残しておきますw

最近のGPUでは浮動小数点のレンダリングバッファを使用できるのが当たり前になってきました。
これがあるとレンダリングレンジの幅がグンっと広がるのでHDRをした時きれいに表現できるわけですね。
HDRではパフォーマンスと人間の可視領域の関係から HALF(16ビットの浮動小数点) がよく使われます。

DirectX では普通に使えるんだけど、OpenGL では日本語のリファレンスにはのってなかったりするので記載しておきます。
んで、使い方はっていうと、、、

glTexImage2D でテクスチャを設定するときに使用する引数が EXT や ARB などで拡張されています。
これを使用することで浮動小数点バッファを作ることができるんですね~。

ってことで、以下に glTexImage2D で使用可能と思われる intternalfomat, format, type を列挙しますね。

  internalformat
    GL_RGBA
    GL_RGBA4
    GL_RGB5_A1
    GL_RGBA8
    GL_RGBA16
    GL_RGB10
    GL_RGB10_A2
    GL_RGBA16F_ARB
    GL_RGBA32F_ARB
    GL_RGB
    GL_RGB4
    GL_RGB5
    GL_RGB8
    GL_RGB16
    GL_RGB16F_ARB
    GL_RGB32F_ARB
    GL_ALPHA
    GL_ALPHA8
    GL_ALPHA16
    GL_ALPHA16F_ARB,
    GL_ALPHA32F_ARB,
    GL_INTENSITY
    GL_INTENSITY8
    GL_INTENSITY16
    GL_INTENSITY16F_ARB,
    GL_INTENSITY32F_ARB,
    GL_LUMINANCE
    GL_LUMINANCE8
    GL_LUMINANCE16
    GL_LUMINANCE16F_ARB
    GL_LUMINANCE32F_ARB
    GL_LUMINANCE_ALPHA
    GL_LUMINANCE8_ALPHA8
    GL_LUMINANCE16_ALPHA16
    GL_LUMINANCE_ALPHA16F_ARB
    GL_LUMINANCE_ALPHA32F_ARB,
    GL_DEPTH_COMPONENT
    GL_DEPTH_COMPONENT16
    GL_DEPTH_COMPONENT24
    GL_DEPTH_COMPONENT32,


  format
    GL_RGB
    GL_BGR
    GL_RGBA
    GL_BGRA
    GL_ABGR
    GL_ARGB
    GL_RED
    GL_GREEN
    GL_BLUE
    GL_ALPHA
    GL_LUMINANCE
    GL_LUMINANCE_ALPHA
    GL_DEPTH_COMPONENT


  type
    GL_BYTE
    GL_UNSIGNED_BYTE
    GL_SHORT
    GL_UNSIGNED_SHORT
    GL_INT
    GL_UNSIGNED_INT
    GL_HALF_FLOAT_ARB
    GL_FLOAT
    GL_2_BYTES,
    GL_3_BYTES,
    GL_4_BYTES,
    GL_DOUBLE,
    GL_UNSINGED_BYTE_3_3_2
    GL_UNSINGED_BYTE_2_3_3_REV
    GL_UNSIGNED_SHORT_4_4_4_4
    GL_UNSIGNED_SHORT_4_4_4_4_REV
    GL_UNSIGNED_SHORT_5_5_5_1
    GL_UNSIGNED_SHORT_1_5_5_5_REV
    GL_UNSIGNED_SHORT_5_6_5
    GL_UNSIGNED_SHORT_5_6_5_REV
    GL_UNSIGNED_INT_8_8_8_8
    GL_UNSIGNED_INT_8_8_8_8_REV
    GL_UNSIGNED_INT_10_10_10_2
    GL_UNSIGNED_INT_2_10_10_10_REV
    GL_UNSINGED_INT_24_8
    GL_UNSINGED_INT_8_24_REV


ざっと上げただけでこれぐらい。
まだまだ拡張されるかもしれないのでもっともっと増えるかもしれませんが、
とりあえず double のテクスチャバッファまで用意できるので当分の間これで充分な気がします。

それで、肝心の自分で用意したバッファに描画する方法ですが、、、
OpenGL で 自分で用意したレンダリングバッファ(レンダリングテクスチャ)に描画する方法はまだドラフトしてる最中(もう終わったのかな?)だったりします。
そんなわけで、これまた拡張関数を使って行います。
これまた日本語で書いてあるHPが見つからなかったのでここに乗っけておきますね。

Googleとかから「OpenGL」「Render」「Texture」とかのキーワードで検索してきた人が参考にしてくれたら幸いです。




PFNGLGENFRAMEBUFFERSEXTPROC      glGenFramebuffersEXT;
PFNGLBINDFRAMEBUFFEREXTPROC      glBindFramebufferEXT;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC    glFramebufferTexture2DEXT;
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;

// 関数ポインタを取得
void InitOpenGLExtension()
{
  glGenFramebuffersEXT    = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress( "glGenFramebuffersEXT" );
  glBindFramebufferEXT    = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress( "glBindFramebufferEXT" );
  glFramebufferTexture2DEXT  = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress( "glFramebufferTexture2DEXT" );
  glDeleteFramebuffersEXT   = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress( "glDeleteFramebuffersEXT" );
}


// レンダリングバッファを作成
void CreateRenderingBuffer( OUT GLuint *pFrame, OUT GLuint *pColor, OUT GLuint *pDepth, IN int width, IN int height )
{
  // フレームバッファオブジェクト、デプスとカラー用のテクスチャを作成
  glGenFramebuffersEXT( 1, pFrame );
  glGenTextures( 1, pColor );
  glGenTextures( 1, pDepth );

  // とりあえず、作るカラーバッファは HALF 型
  glBindTexture( GL_TEXTURE_2D, *pColor );
  glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, width, height, 0, GL_RGBA, GL_HALF_FLOAT_ARB, NULL );

  // 深度バッファも作成
  glBindTexture( GL_TEXTURE_2D, *pDepth );
  glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL );

  // テクスチャをフレームバッファオブジェクトにバインド
  glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *pFrame );
  glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, *pColor, 0 );
  glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, *pDepth, 0 );

  // デフォルトのレンダーターゲットに戻す
  glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
}




InitOpenGLExtension 関数で初期化して CreateRenderingBuffer 関数でレンダリングバッファを作成するわけですね。
後は、出来上がったレンダリングバッファに描画するんですけど、描画の仕方はっていうと、、、、

void Draw( IN GLuint frame )
{
  // バッファを変更
  glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, frame );
  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
  glViewport( 0, 0, render_width, render_height );

  // オブジェクトを描画
  ....


  // デフォルトのレンダーターゲットに戻し、ディスプレイに描画
  glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
  glViewport( 0, 0, screen_width, screen_height );


  // ポスト処理やらなにやらを行う。
  ....
}


こんな感じになります。
frame は CreateRenderingBuffer 関数で作成したフレームバッファオブジェクトのことです。
必ず最後にデフォルトのレンダーターゲットに戻して、それに描画しないとだめです。
じゃないと表示されません('A`)

また、最後にフレームバッファオブジェクトとテクスチャオブジェクトを削除しましょう。
フレームバッファオブジェクトの削除は glDeleteFramebuffersEXT 関数を使用します。

サンプルは、、、後日UPしますw
スポンサーサイト

is系関数

2005年10月24日 14:18

今日は標準関数にある is系 のプログラムの話。


っていっても、わりと最近やっている Cg言語 とかの話じゃなくて、物凄いローテクな話なんだけどね(´・ω・`)
ブログをメモ帳代わりに使ったりしてるから、こういう細かいことを記録しておくのが便利なんだよねー。
そのうちまとめて、最新のCG関連のことも書きます。
その時はサンプルプログラムとかも書けるかな?


それでは本題。
っていっても、タイトル通り is系 の関数についての話です。
is系の関数っていうのは、文字コード(下記で説明するのはバイトコード。もちろんマルチバイトを扱う isw系 の関数もある)が
条件に当てはまるかどうかチェックする関数。
その条件って言うのはそれぞれの関数ごとに決まっていて、関数名と条件を書くと、、、

 isalnum
  英数字 (A ~ Z、a ~ z、または 0 ~ 9)。
 isalpha
  英字 (A ~ Z または a ~ z)。
 __isascii
  ASCII 文字 (0x00 ~ 0x7F)。
 iscntrl
  制御文字 (0x00 ~ 0x1F または 0x7F)。
 __iscsym
  英字、アンダースコア (_)、または数字。
 __iscsymf
  英字またはアンダースコア (_)。
 isdigit
  10 進数 (0 ~ 9)。
 isgraph
  空白 ( ) を除く印字可能な文字。
 islower
  英小文字 (a ~ z)。
 isprint
  空白を含む印字可能な文字 (0x20 ~ 0x7E)。
 ispunct
  区切り記号。
 isspace
  空白文字 (0x09 ~ 0x0D または 0x20)。
 isupper
  英大文字 (A ~ Z)。
 isxdigit
  16 進数 (A ~ F、a ~ f、または 0 ~ 9)。

って感じになります。

別に自分で書いた関数で置き換えることもできるけど、
最適化までしてるであろう関数をわざわざフルスクラッチでおこす必要もないので、積極的に使用しましょう。

標準ライブラリに入ってるのに存在すら知らない関数って多いんだよねw

列と行

2005年10月19日 11:38

3Dプログラムをやってると行列を絶対扱うことになるわけですが、
さて、この行列、列と行からなっています。

いっつも、「あれ?列って縦だっけ?横だっけ?」と悩むんで、ブログに書き残しておこうかと思いますw

それで結論はっていうと、、、
 行(row)   :横
 列(column)  :縦
ですね。

なので 4x5 の行列は4行5列の行列って意味なので、、、
 11, 12, 13, 14, 15
 21, 22, 23, 24, 25
 31, 32, 33, 34, 35
 41, 42, 43, 44, 45
ってなります。

簡単なことだけど、意外と忘れてたりします。
そんでもって、cgGL でシェーダーに行列を設定するときに呼び出す関数では
列のオーダーで渡すのか行のオーダーで渡すのかでコールする関数名が違ったりします。
また、もちろん列ベクトルと行ベクトルを掛けた結果が行列にもなったりしますから
(当然掛ける方向によって出来上がる行列は変わってくる)
結構重要な違いだったりするわけですね。

おぱくえ

2005年10月18日 12:05

さてさて、今度は仕事でもやってるプログラムのことを。

今日、nVidia の CGToolKit をぼーっと眺めていたら、懐かしい表現が出てました。
オペーク型(スペルは opaque 和名:不完全型)っていうんですけど、あまり知りませんよね。
あるけ がこれをはじめて知ったのは某コンシューマゲーム機のミドルウェアをいじってる時です。

C++ で使う mutable と同じぐらい、名前の使用頻度があまりなさそうな気がします。


んでもって、このオペーク型、何に使うかといいますと、、、
C言語でカプセル化を行うときに使用します。
ライブラリ提供者がライブラリ使用者に対して構造体にアクセスするのを禁止したいときですね。
(ライブラリ駆動情報など重要な情報で改変されるとライブラリが正常に機能しなくなる場合など)

C++では private 宣言があるのでまったく使う必要がありませんが、C言語で隠蔽化を行おうとすると、
これを使わなければできません。

んでもって、これの書き方はというと、、、

通常の構造体宣言では、

 //!< プロトタイプ宣言
 typedef struct tagHuman,     *LPHUMAN;
 
 //! 実態宣言
 struct tagHuman
 {
   char  name[0x100];
   int  age;
 };
 
 
なんてヘッダーに書いたりしますが、
オペーク型にしたい場合は、ヘッダーに構造体情報を書きません。
要するに、プロトタイプ宣言だけ書くわけですね。

 //!< プロトタイプ宣言
 typedef struct tagHuman,     *HHUMAN;
 
こうすることで、構造体のメンバを隠蔽することができるわけです。
けど、「そんなことして大丈夫なの?」って思いますよね。
実は、ここで上に上げた例でちゃんと動くように、ちょっといつもと異なる部分があるんです。
普通、typedef 宣言した場合、実態も宣言しますよね。

 typedef struct tagHuman,     HUMAN, *HHUMAN;

こんな感じに。
けど、上の例ではポインタ型しか宣言してません。
実は、ポインタ型だけ宣言することで、メンバ情報などの実態宣言を省略することができるのです。
要するに、HHUMAN だけを渡すような関数を使用する分には、 tagHuman 構造体の中身を知らなくてもいいわけなので、
リンカも詳しく突っ込んでこないんですね。

もし、ポインタじゃなくて、インスタンスを生成するような HUMAN を一緒に typedef してしまった場合は、
実態宣言ももちろん必要になります。
(リンカが「おまい、どこにも実態がないやんかボケ」と突っ込んでくる)

ライブラリの中でだけ意味が通じればいい構造体などを利用する場合はオペーク型を使用すると便利だしスマートです。



こうやって突然思いついたこと、記録できるのは blog のいいところだね~。

今日から、、、

2005年10月18日 03:07

ってなわけで、今日からぶろぐなんていうのを始めてみます。

その日に思ったことなんぞを書いていこうかなーなんて思っています。
あと、ちょっとだけプログラムのことなんかも書くかも。

前やっていたHPは3ヶ月ぐらいしか持たなかったけど今回はどれぐらい持つかな


最近の記事


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。