スポンサーサイト

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

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

日本語では滅多に見ない cg プログラム解説

2006年03月30日 18:00

ってことで、第2部のプログラムネタっす。


あるけ が忘れることは無いとおもうけど、メモ代わりに書いておきます。
日本語で書いてる Cg や CgGL 関連のネタも少ないしね。

Google とかで「cgGLSetParameterPointer」や「cgGLEnableClientState」、「glBindBufferARB」、「glBufferDataARB」、「glGenBuffersARB」、「cgGetNamedParameter」なんかの用語で引っかかって飛んできた人に参考になればうれしいです。


Cg では頂点バッファやインデックスバッファを使ってポリゴンを描画することが出来ます。
ここで、問題となるのが頂点バッファをどうやって持つのか・・・。

Direct X(HLSL)なんかでは頂点宣言を使って1つの頂点がどういうデータで構成されているのかをシェーダーに教えています。
では、Cg ではどうするんでしょうか?


Cg では頂点宣言みたいな機能はありません。
シェーダー内のパラメーター(CGparameter 型)を取得してそのパラメーターにデータを関連付けます。
シェーダー内のパラメーターの取得方法は自動的にやることも出来るんですけど、説明が面倒なのでまた今度書きます。
ってことで、シェーダーの中身を知ってる場合限定で手続き型(要するに自動で判別は無理)ですけど、もう一つの方法を記述します。

cgGetNamedParameter 関数を使います。
この関数はシェーダープログラムの中の指定した名前の変数 or シェーダー定数を抽象化したもの(CGparameter 型)を返します。


帰ってきた CGparameter データを使ってシェーダーにデータを渡すわけです。

Cg では特定のパラメーターにデータを焼べる場合、CGparameter 型を使います。
プログラマーがわかりやすい言葉でいうと、シェーダープログラム内の変数のポインタって感じが近いかな。
もちろん、本当のポインタじゃないのでデータを与える時は関数を読んでやる必要があり、cgSetParameter1fv や cgSetParameter4fv、cgSetMatrixParameterfc なんかを使います。




さて、この CGparameter 、シェーダー内で使用される定数を設定する時に使うことはもちろん、シェーダーに頂点データを渡す場合にも使用します。
シェーダーに定数データを渡す方法は某3では他にもありますけど、PC(っていうか nVidia の開発キット)ではこれしか無いみたいです。
あるけ の探し方が悪いだけかもしれないので知ってる方は教えてくださるとうれしいです。



それで、どうやってデータを渡すか問ういうと、、、

cgGLSetParameterPointer 関数を使います。

この関数を使えば、シェーダーに入力パラメーターを渡せるわけです。
引数の説明とかは省きますが、使ってみればすぐわかるとおもいます。



さて、ここからが本題。
ここまでは別に特別なことは一切ありませんし、ノウハウなんてものも在りません。ほぼ教科書どおりの無いようです。

ここまでの説明でシェーダーにデータを入力するのは出来るんですけど、
これでは頂点バッファをすべてのパラメーターに対して用意するなんてことになっちゃいます。

こんな風に、、、




擬似コードなんで深く突っ込まないでねw
要望があればサンプル書きます。


CGparameter VShaderIN[3];
CGprogram  hVProg, hFProg;
GLuint    pVBO[3], hIBO;


// 頂点シェーダーを読む
hVProg = cgCreateProgram( hContext,
              enSourceType,
              (const S1 *)pBuffer,
              hProfile,
              "VSMain",
              NULL
      );

// フラグメントシェーダーを読む
hFProg = cgCreateProgram( hContext,
              enSourceType,
              (const S1 *)pBuffer,
              hProfile,
              "PSMain",
              NULL
      );

cgGLBindProgram( hVProg );

// 各頂点要素のパラメーターを取得
VShaderIN[0] = cgGetNamedParameter( hVProg, "In.Position" );
VShaderIN[1] = cgGetNamedParameter( hVProg, "In.Normal" );
VShaderIN[2] = cgGetNamedParameter( hVProg, "In.Color" );


// 頂点バッファオブジェクト作成
glGenBuffersARB( 3, pVBO );
glGenBuffersARB( 1, &hIBO );


// バッファを結びつける
glBindBufferARB( GL_ARRAY_BUFFER_ARB, pVBO[0] );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(float) * 3 * nVertexVol,
         pPosition, GL_STATIC_DRAW_ARB );  // 位置
          
glBindBufferARB( GL_ARRAY_BUFFER_ARB, pVBO[1] );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(float) * 3 * nVertexVol,
         pNormal, GL_STATIC_DRAW_ARB );    // 法線
          
glBindBufferARB( GL_ARRAY_BUFFER_ARB, pVBO[2] );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(float) * 4 * nVertexVol,
         pColor, GL_STATIC_DRAW_ARB );      // 色


// インデックスバッファを設定する
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, hIBO );
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * uIndexVol,
         pIndexStream, GL_STATIC_DRAW );



// 描画する
for(;;)
{
  cgGLBindProgram( hVProg );
  cgGLBindProgram( hPProg );
  
  glBindBufferARB( GL_ARRAY_BUFFER_ARB, pVBO[0] );
  cgGLEnableClientState( VShaderIN[0] );
  cgGLSetParameterPointer( VShaderIN[0], 3, GL_FLOAT, sizeof(float) * 3, 0 );
 
  glBindBufferARB( GL_ARRAY_BUFFER_ARB, pVBO[1] );
  cgGLEnableClientState( VShaderIN[1] );
  cgGLSetParameterPointer( VShaderIN[1], 3, GL_FLOAT, sizeof(float) * 3, 0 );
 
  glBindBufferARB( GL_ARRAY_BUFFER_ARB, pVBO[2] );
  cgGLEnableClientState( VShaderIN[2] );
  cgGLSetParameterPointer( VShaderIN[2], 4, GL_FLOAT, sizeof(float) * 4, 0 );
  
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, hIBO );
  glDrawElements( GL_TRIANGLE_STRIP, uIndexVol, GL_UNSIGNED_INT, 0 );
}






これでは1つの頂点を処理するたびに何回もキャッシュミスを発生してしまい、速度が全然出ません。
出来れば Direct X みたいに頂点バッファは法線や座標データ、接線などのデータが構造体としてまとまっていた状態で配列になっていたほうがキャッシュヒットもしやすく良いに決まってます。


そこで、Cg でも頂点バッファを一つしか使わない方法を教えちゃいます。
って、勿体ぶっても知ってる人は多いかもしれませんw
ちなみに、あるけ が探した限り、こういうサンプルは見たことありませんでした( ;Д⊂ヽ
(これもまた探し方がわr(ry )

まず、Direct X の様に頂点ごとに各要素をパックしたものを用意します。
次に、頂点バッファオブジェクトを一つ作成します。

そんでもって、cgGLSetParameterPointer に渡す最後のパラメーターを頂点構造体の要素ごとのオフセットにします。

ようするに、、、






typedef struct
{
  float  position[3];
  float  normal[3];
  float  color[4];
}
VTXDATA *pVertexStream;


// オフセットを取得
int pOffset[3] =
{
  (int)((VTXDATA *)0)->position,
  (int)((VTXDATA *)0)->normal,
  (int)((VTXDATA *)0)->color
};


・・・・途中まで省略・・・・



// 頂点バッファオブジェクト作成
glGenBuffersARB( 1, &hVBO );
glGenBuffersARB( 1, &hIBO );


// バッファを結びつける
glBindBufferARB( GL_ARRAY_BUFFER_ARB, hVBO );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof(VTXDATA) * nVertexVol,
         pVertexStream, GL_STATIC_DRAW_ARB );


// インデックスバッファを設定する
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, hIBO );
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * uIndexVol,
         pIndexStream, GL_STATIC_DRAW );


// 描画する
for(;;)
{
  cgGLBindProgram( hVProg );
  cgGLBindProgram( hPProg );
  
  glBindBufferARB( GL_ARRAY_BUFFER_ARB, hVBO );
  
  cgGLEnableClientState( VShaderIN[0] );
  cgGLEnableClientState( VShaderIN[1] );
  cgGLEnableClientState( VShaderIN[2] );
  
  cgGLSetParameterPointer( VShaderIN[0], 3, GL_FLOAT, sizeof(float) * 3, pOffset[0] );
  cgGLSetParameterPointer( VShaderIN[1], 3, GL_FLOAT, sizeof(float) * 3, pOffset[1] );
  cgGLSetParameterPointer( VShaderIN[2], 4, GL_FLOAT, sizeof(float) * 4, pOffset[2] );
  
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, hIBO );
  glDrawElements( GL_TRIANGLE_STRIP, uIndexVol, GL_UNSIGNED_INT, 0 );
}





こんな感じに書きます。

動くかどうかはわかりませんがw
ニュアンスで読んでください(´ω`)

blog_rank
スポンサーサイト

「土地、ただで上げます」

2006年03月24日 16:39

ちょっと気になるニュース。

________________________________________________________________________________

「土地、ただで上げます」
http://www.tokyo-np.co.jp/00/tokuho/20060322/mng_____tokuho__000.shtml

 「定住してくれる人には、土地を無償で差し上げます」。サケの水揚げ日本一の町、
オホーツク海に面した北海道標津(しべつ)町が、“移民”を呼びかけている。一区画
百二十坪、条件は三年以内に家を建てて住むこと。なかなか魅力的な話だが、クマ
が出没するような原野では困ってしまう。どんな土地なのか、見てきた。

 これが地吹雪というものなのか…。強風が積もった雪を巻き上げ、一瞬目の前が
真っ白になる。地元の人たちは口をそろえて「『彼岸荒れ』というんですよ」。春が近
づく彼岸のころに天気が一時荒れるのだ。
 標津町は漁業と酪農の町。北方領土の国後島は目と鼻の先だ。東京から中標津
空港は直行便で一時間四十分、路線バスで空港-中標津(十分・二百三十円)、
中標津-標津(三十分・五百九十円)。「北の最果て」を覚悟していたが、簡単にたど
り着いた。地形は平野で、広い幹線道路沿いに商店や家が並ぶ。意外に「街」だ。冬
の最低気温はマイナス二〇度だが、雪は少なく、屋根の雪下ろしは必要ないそうだ。
 「『電気通ってますか』と聞かれます。辺ぴなところだと思われているんですね」と
標津町企画振興課の山口将悟さんは苦笑する。
 計画発表後、全国から問い合わせがあり、テレビで紹介された日は電話が鳴り続け
た。通常一万件の町役場のホームページのアクセスは、二日間で百十万件を突破した。
 土地はタダの「町営定住促進団地」は、町の中心地に近く、町立病院、特別養護老人
ホーム、保健福祉センターまで徒歩五分。幼稚園、小、中、高校も二キロ圏内。クマが
すむような山間地ではない。晴れの日は知床連山が見える。
 一区画百二十-百四十坪、全五十八区画のうち、二十八区画を今年十月から分譲
する。インターネットはADSLが利用できる。町内に土地がない町民も対象だ。

________________________________________________________________________________


ネットトレードで生計立てれる人ならここで暮らすのも全然ありかもw
最近株やってるけど全然儲けれて無い あるけ でした(・∀・)

夢のある仕事

2006年03月23日 10:29

結構前の古い話題だけど、、、

「三菱重工が、サンダーバードのスーパーメカや基地一式を受注」
http://www.mhi-ir.jp/news/sec1/200602014431.html


こっちは去年のヤツ

「三菱重工がガンダム本体製造に参入」
http://www.mhi-ir.jp/news/sec1/200502044313.html


これ自体は「前田建設 ファンタジー営業部」のパクリだろうけど、こういう夢のある仕事っていうか夢を見れる仕事をいつまでもやりたいよね。

本家本元の「前田建設 ファンタジー営業部」
http://www.maeda.co.jp/fantasy/index.html




最近の記事


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