2013年3月10日日曜日

GLSL memo: そこにUINT16なテクスチャーを使いたいとするじゃろう?

例えばkinectのdepth出力(11Bits/pixel : UINT16)みたいなUINT16なデータをそのままGPUにGLSLでぶっ込みたいとする。頂点データではなくテクスチャーでぶっ込むとする。OpenGLリファレンスなど見つつテクスチャーの転送(glTexImage2D, etc.)を次の様に書いて、

glTexImage2D(
  GL_TEXTURE_2D, 0, GL_RED,
  v.width(), v.height(), 0,
  GL_R16UI, GL::GLenum(GLEW::VERTEX_ATTRIBUTE::UINT16),
  boost::gil::interleaved_view_get_raw_data(v)
);

これで今日もまた3数時間くらい悩んでしまった。ちなみに悩みながらJagabee1つと生生姜生噛り3cmくらいともずくスープ3個が消えていった。あときび砂糖100gくらい。

(第8引数がちょっとカオスに見えるのは、これはC APIを隠蔽する目的のC++ライブラリーの中という事で、第9引数はライブラリーがユーザーコードからテクスチャーデータを受け取る際にBoost.GILで投げられる様にしている為で、何れも今回の本質ではないのでそこはあまり気にせず。)

問題は第7引数に投げている GL_R16UI でした。

これは、

glTexImage2D(
  GL_TEXTURE_2D, 0, GL_RED,
  v.width(), v.height(), 0,
  GL_RED, GL::GLenum(GLEW::VERTEX_ATTRIBUTE::UINT16),
  boost::gil::interleaved_view_get_raw_data(v)
);

GL_RED にすれば期待通りの動作をしてくれる。

リファレンスのテーブルばかり見ていたのだけど、仮引数 format の説明にちゃんとGL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRAから選んでねって書いてある。

なんでこれを間違えちゃったかと言うと、仮引数 internalFormat と format がいつの間にやら脳内で認識交換されちゃってた。リファレンスにはちゃんと書いてある通りだから、勘違いコード書いて悩んでる方も悪いんだけど、原因がここかそこかどこかってこの関数のみならずテクスチャーサンプラーをuniformで強引に扱う仕様のAPI周りやそもそものテクスチャーバッファー周りなども疑って、ぐるっと周囲を一周してよーやく帰ってきて気付いた感じ。C APIだるす(´;ω;`)ブワッ

こんな具合で今日もGLSLでハマってたーよ(;´∀`)
まあ、この辺はD3D/HLSLでも似たような地雷原だった気もするけど。

0 件のコメント:

コメントを投稿