SolarisでOpenGLを使う
1 概要
このページはSolarisでOpenGLを使ったプログラムを作ろう。という内容です。
2 参考書籍
これしかありません。
「OpenGL Programming for the X Window System(日本語版)」
マーク・キルガード著(ISBN 4-7952-9703-7 8500円)
これしかないということはだいたいこれがあれば何とかなると言うことです。
3 前提知識
基本的にX Window System上で動くプログラムを作る知識が必要になります。
また、当然ですがOpenGLのインタフェースはC言語ですのでCまたはC++の知識が必須となります。
そのほかの言語を使用する場合はさらにその言語でC言語インタフェースの関数を呼び出すための知識が必要となります。
また、ここではXtとMotifを使用して作るため、Motifに関する知識も必要となります。しかし、Unixに関する知識はあまり必要なさそうです。
4 上記前提知識に関する参考書籍
CやC++は何とかしてください。ここが一番大変だったりしますが。
Motifに関する情報は、実は余り多くありません。とりあえず、Forte C++のマニュアルでも読んでおいてください。
英語が得意なら、Open Motif - Document Supplementでも参考にしてみてください。
あと、かなり古いが日立がMotifのマニュアルを出している。この辺から申し込めば買えるかも知れません。
5 GLUTは?
GLUTを使えばウインドウシステムを知らなくてもOpenGLのプログラムが作れるそうです。GLUTは上記の本を書いたマ〜クが作ったそうで、同じ本の中にかなり詳しく説明があります。
しかし、ここえでゃGLUTを使いません。せっかくSolaisであり、普通にMotifが使えるのですからMotifを使わなくてはもったいないでしょう。(意味わかんね)
6 開発環境
ForteC++ 6.0という統合開発環境を使用しています。
特にここで重要となるのは(プログラムの構造に影響を与えるものは)、WorkshopVisualというツールです。
このツールは、Motifを使用したウインドウを表示させるコードを自動生成していくれるという優れものです。VB並みとはいきませんが、VC++ぐらいには何とかなります(給料4ヶ月ぶんだけあり、Motif以外にもJava、MFC用のコード生成できる様です)。
使った感じではMFCより自由性が高く、使いやすく、めんどくさいといった感じでしょうか。しかし、やはり日本語資料が充実しているため、ほとんど不自由しません。
また、xmanを使用し、manページのエントリを一覧表示させ、X及びMotifの関数名を適当にあたりをつけて調べる、という方法もあります。
これはある程度範囲が絞られているとき有効です。ただ、表示される文字がすべて英語なので、読むのに苦労させられます。
7 ウィジットの構造
初心者であるため、とりあえずウィジットの構造は2の本の116ページにあるのと同じ構造にしておきました。しかし、WorkshopVisualではOpenGL用描画ウィジットは生成できないため、以下のような方法を採りました。
Workshop Visualで以下の構造のウィジットを構築
一番上にアプリケーションシェル
その下に、フォーム・ウィジット
フォームの子としてメニューバーとフレームウィジットを追加
コールバックを登録します。
フォーム構築時のコールバック
アプリケーションシェルが閉じられるときのコールバック
8 プログラム
肝心のプログラムは以下のようになっています。
フォームの「作成」コールバックにOpenGL描画用をウィジットを構築するコードを記述します。
引数としてフォームウィジットのWidgetがwとして与えられるものとします。
Display *dpy;
Widget glw;
XVisualInfo *visinfo;
Colormap cmap;
int dblbuf[] = {
GLX_RGBA, GLX_DEPTH_SIZE, 12,
GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, None };
// ディスプレイを取得
dpy = XtDisplay( w );
// ビジュアルを取得する(ダブルバッファ)
visinfo = glXChooseVisual( dpy, DefaultScreen( dpy ), dblbuf );
if ( NULL == visinfo ){
printf( "ダブルバッファビジュアルが取得できない\n" );
return false;
}
// カラーマップを探す
if ( !getShareableColormap(visinfo, dpy, &cmap ) )
return false;
// ウィジットを構築
glw = XtVaCreateManagedWidget(
"glxarea", // 名前
glwMDrawingAreaWidgetClass,// OpenGL用ウィジット
w, // 親ウィジット(フレーム)
GLwNvisualInfo, visinfo, // ビジュアルを指定
XtNcolormap, cmap, // カラーマップを指定
NULL );
// コールバックを登録
// 構築
XtAddCallback( glw, GLwNginitCallback, NEvent::OnCreate_GLW, NULL );
// 表示
XtAddCallback( glw, GLwNexposeCallback, NEvent::OnExpose_GLW, NULL );
// サイズ変更
XtAddCallback( glw, GLwNresizeCallback, NEvent::OnResize_GLW, NULL );
// 入力
XtAddCallback( glw, GLwNinputCallback, NEvent::OnInput_GLW, NULL );
XtRealizeWidget( XtParent( XtParent( w ) ) );
return true;
上記のコールバックを登録する部分の「NEvent::」はそういう名前空間を定義し、その中の関数のポインタを登録しているからです。無視していただいてかまいません。
また「XtRealizeWidget( XtParent( XtParent( w ) ) );」という情けないコードはとりあえずアプリケーションシェルをリアライズしたいんだと思ってください。この一文がないとサイズ変更コールバックが呼ばれず、うまくプログラムが動きません。
そして、getShareableColormap関数は2の本の50ページに書かれているものにちょっと手を加えて使用しています。(といってもロジックはなにも変わっていません。本に書かれているコードにいささか問題があるのです。)
以下のようになっています。
// カラーマップを探す関数
// ビジュアルとディスプレイを渡し、pcにカラーマップを返す
// 失敗したら偽を返す
bool getShareableColormap( XVisualInfo *vi, Display *dpy, Colormap *pc )
{
Status stat;
XStandardColormap *standardCmaps;
int i;
int numCmaps;
// チェック
if ( vi->c_class != TrueColor ){
printf( "TrueColorでないビジュアルをサポートしていない\n" );
return false;
}
// TrueColorで標準カラーマップがない場合、共有されないのを作る
stat = XmuLookupStandardColormap(
dpy,
vi->screen,
vi->visualid,
vi->depth,
XA_RGB_DEFAULT_MAP,
False,
True
);
if ( 1 == stat ){
stat = XGetRGBColormaps(
dpy,
RootWindow( dpy, vi->screen ),
&standardCmaps,
&numCmaps,
XA_RGB_DEFAULT_MAP
);
if ( 1 == stat ){
for ( i = 0; i < numCmaps; i++ ){
if ( standardCmaps[i].visualid == vi->visualid ){
(*pc) = standardCmaps[i].colormap;
XFree( standardCmaps );
return true;
}
}
}
}
(*pc) = XCreateColormap(
dpy,
RootWindow( dpy, vi->screen ),
vi->visual,
AllocNone
);
return true;
}
上述のvi->c_classはC言語を使用している場合はvi->classとなります。
「名前空間」とか言っているあたりからおわかりかと思いますが、私はC++を使用しています。「class」という単語はC++の予約語に含まれるため、ヘッダファイル中で「c_class」として定義されるようになっています。
また、本の中ではカラーマップとかビジュアルとかについていろいろと言っていますが、Solarisを使っている場合、ほとんど気にする必要はないようです。
そして構築とサイズ変更のプログラムです。
(構築されたOpenGL描画用ウィジットのWidgetがwとして与えられる。また、hRCはGLXContext型の変数)
XVisualInfo *pVI;
// レンダリングコンテキストを構築
XtVaGetValues( w, GLwNvisualInfo, &pVI, NULL );
hRC = glXCreateContext( XtDisplay( w ), pVI, 0, True );
// レンダリングコンテキストをカレントにする
glXMakeCurrent( XtDisplay( w ), XtWindow( w ), hRC );
見ての通り、レンダリングコンテキストを構築しカレントにしています。
そして、サイズ変更部分はもう通常のOpenGLのコードですからあえて記述しません。
視野錐台とビューポートの設定を行ってください。
たぶんこれで後はOpenGLの関数を呼び出し描画するだけでいいと思います。
とりあえず私が作ったのはこんな感じです。
sop.jpg 22KB
(色がおかしくなってしまっています。もう少しまともなソフトでキャプチャしたかったのですが。)
9 コンパイル
作ったプログラムはコンパイルする必要があります。
ForteC++の場合、まず、プロジェクトの型は「複合アプリケーション」です。標準ライブラリとしてMotifのライブラリが必要となります。
また、ユーザのライブラリとして以下のものを追加します。
- /usr/lib/sparcv9/libGL.so
- /usr/lib/sparcv9/libGLU.so
- /usr/lib/sparcv9/libGLw.so
- /usr/lib/sparcv9/libXext.so
なお、私は64ビットでコンパイルしているため「/usr/lib/sparcv9」となっていますが、32ビットでコンパイルする場合は、「/usr/lib」のものを使用することなるはずです。
また、ヘッダファイルは以下のものをインクルードする必要があります。
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glx.h>
- #include <Xm/XmAll.h>
- #include <X11/GLw/GLwMDrawA.h>
- #include <X11/Xmu/StdCmap.h>
10 ディスプレイの設定
最後になりましたが、ディスプレイの設定方法を紹介しておきます。
Blade100の一番安いやつでは、「PGX64」というグラフィックチップが使われているようです。
ディスプレイを設定するには「m64config」というコマンドを使用します。
デフォルトでは「8ビットカラー」に設定されているため、OpenGLを使用したソフトを「作る」または「使う」ことはままなりませんが、 このコマンドを用いれば、24ビットカラーに設定できます。
詳しい設定方法はmanコマンドで確認して下さい。
|