OpenGLに関して
freeglut†
freeglutについて†
GLUTはversion3.7 (1998年) を最後として,それ以降開発されていません.
freeglutはGLUT(OpenGL Utility Toolkit)の代替となるオープンソースのOpenGLツールキットであり,GLUTの命令と完全に互換性を持っています.
GLUTからfreeglutに乗り換えるときは,単純にインクルードするファイルを変更するだけで済みます.
ダウンロードとインストール†
- ビルド
- ダウンロードしたファイルを解凍
- (2.8.1以前) 解凍したフォルダのVisualStudio/2012/freeglut.slnがVS2012用のソリューションファイル.freeglut.slnを開いてビルドする.スタティックビルドの場合はプロジェクト構成で*_Staticというのを選択する.
- (3.0.0以降) CMakeをインストールし,CMake(GUI)で"Where is the source code"にfreeglutを解凍したフォルダ(srcフォルダではないので注意),"Where to build the binaries"にプロジェクトを作成するフォルダへのパスを入力し,"Configure"→ビルドオプション指定→"Generate"でプロジェクトを作成,ソリューションファイルを開いてビルドする.
TIPS†
平面クリップ†
平面クリップを行うには,glClipPlaneを用いる.
void glClipPlane(GLenum plane, const GLdouble *equation);
planeにはクリップ平面番号(GL_CLIP_PLANE0, GL_CLIP_PLANE1など)を設定する.
最大数は,GL_MAX_CLIP_PLANESを参照することで調べられる.
equationには平面方程式(ax+by+cz+d=0)の係数(a,b,c,d)を格納した4要素配列を指定する.
ax+by+cz+d<0の範囲がクリップされる.
平面クリップのON/OFFは,
glEnable(GL_CLIP_PLANE0);
glDisable(GL_CLIP_PLANE0);
マルチサンプリングによるアンチエリアシング†
- 描画する前にマルチサンプリングをONにする
glEnable(GL_MULTISAMPLE);
- GLUTの場合,glutInitDisplayModeにGLUT_MULTISAMPLEを追加.例えば,
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
- サンプリングの対応状況を調べる
GLint buf, sbuf;
glGetIntegerv(GL_SAMPLE_BUFFERS, &buf);
cout << "number of sample buffers is " << buf << endl;
glGetIntegerv(GL_SAMPLES, &sbuf);
cout << "number of samples is " << sbuf << endl;
buf,sbufが0ならばGPUが対応していない or ビデオカードの設定が適切でない可能性がある.
NVIDIAのGPUの場合,
- NVIDIAコントロールパネルの3D設定の管理を開く.
- グローバル設定の「アンチエリアシング - モード」を「アプリケーション設定の変更」にする.
- 「アンチエリアシング - 設定」が選択できるようになっているので,2xや4xなどを設定する.
- サンプリング本数をアプリケーションから設定する場合は,
上記「アンチエリアシング - モード」を「アプリケーションによるコントロール」にして,
ピクセルフォーマットを手動で設定する必要がある.
wglChoosePixelFormatARBを用いると設定は可能だがGLUTでは使えない.
freeglutを用いている場合は,freeglutのソースコードをいじれば変更できる.
変更箇所は,
DualViewなどでのフルスクリーン(Windows Only)†
GLUT,freeglutではglutFullScreen関数で全画面表示できる.
標準ではマルチディスプレイの場合,スパン設定なら問題ないがDiualViewなどでは
メイン画面上でしかフルスクリーンにならない.
これは,DualViewではメインディスプレイのサイズがAPIが与える物理的な画面サイズとして用いられるためである.
DualViewでは仮想的なスパン画面が設定されているので,これをglutFullScreenから参照されるようにしなければならない.
freeglutのソースコードを変更する.freeglut_init.c の fghInitialize関数内の
fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN );
fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
の部分を
fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXVIRTUALSCREEN );
fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYVIRTUALSCREEN );
とすればよい.
glutFullScreen命令を呼んだときだけ変えたいときや別の関数を使ってやりたいときは,
freeglut_window.c内のglutFullScreen関数の,
1
2
3
4
| | rect.left = 0;
rect.top = 0;
rect.right = fgDisplay.ScreenWidth;
rect.bottom = fgDisplay.ScreenHeight;
|
を
1
2
3
4
| | rect.left = 0;
rect.top = 0;
rect.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
rect.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
などとする.
また,マルチディスプレイ用のフルスクリーン命令を新たに作りたい場合は,
この関数をコピーして名前を変えて,上記の変更をすればよい.
新しい関数を追加した場合(例えば,glutFullScreenMultiとする)は,
- freeglut_ext.hに関数宣言を追加
FGAPI void FGAPIENTRY glutFullScreenMulti( int left, int top, int right, int bottom );
- freeglut_ext.cの最初の方の #define CHECK_NAME(x) に追加
CHECK_NAME(glutFullScreenMulti);
- freeglutdll.defに関数名(glutFullScreenMulti)を追加
また,任意のマルチディスプレイに対応するために,
関数の宣言を
void FGAPIENTRY glutFullScreenMulti( int left, int top, int right, int bottom )
として,上記の変更点を以下のようにする.
1
2
3
4
5
6
7
8
9
10
11
12
| | if(!left && !right && !top && !bottom){
rect.left = 0;
rect.top = 0;
rect.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
rect.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
else{
rect.left = left;
rect.top = top;
rect.right = right;
rect.bottom = bottom;
}
|
関数を呼び出すときにフルスクリーンの範囲を指定する.
画像読み込み†
OpenCVを利用†
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| | #pragma comment(lib, "cv120.lib")
#pragma comment(lib, "cxcore120.lib")
#pragma comment(lib, "cvaux120.lib")
#pragma comment(lib, "highgui120.lib")
#include "cv.h"
#include "cxcore.h"
#include "highgui/highgui.h"
static int LoadGLTexture(const string &fn, GLuint &tex_name, bool mipmap, bool compress)
{
IplImage* img = cvLoadImage(fn.c_str(), CV_LOAD_IMAGE_COLOR);
if(!img){
return 0;
}
GLuint iformat, format;
int w, h, c;
w = img->width;
h = img->height;
c = img->nChannels;
format = GL_BGRA;
if(c == 1){
format = GL_LUMINANCE;
}
else if(c == 3){
format = GL_BGR;
}
if(compress){
iformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
if(c == 1){
iformat = GL_COMPRESSED_LUMINANCE_ARB;
}
else if(c == 3){
iformat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT ;
}
}
else{
iformat = GL_RGBA;
if(c == 1){
iformat = GL_LUMINANCE;
}
else if(c == 3){
iformat = GL_RGB;
}
}
if(tex_name == 0){
glGenTextures(1, &tex_name);
glBindTexture(GL_TEXTURE_2D, tex_name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
if(mipmap){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 6);
}
glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, GL_UNSIGNED_BYTE, img->imageData);
if(mipmap){
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
}
else{
glBindTexture(GL_TEXTURE_2D, tex_name);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, img->imageData);
if(mipmap){
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
}
glBindTexture(GL_TEXTURE_2D, 0);
return 1;
}
|
ミップマップ作成にglGenerateMipmapEXTを使っている.
これはもともとFBO拡張の一部であるが,FBOなしでも使え,
ハードウェアによるアクセラレーションにも対応しているので新しめのGPUなら高速かもしれない.
代わりに,
gluBuild2DMipmaps(GL_TEXTURE_2D, iformat, w, h, format, GL_UNSIGNED_BYTE, img->imageData);
を用いてもよい.
描画の画像保存†
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| | bool SaveFrameBuffer(const string &fn, int w, int h)
{
int c = 3;
vector<unsigned char> img_buf(w*h*c);
int format = GL_BGRA;
if(c == 3){
format = GL_BGR;
}
glRasterPos2i(0, h);
glReadPixels(0, 0, w, h, format, GL_UNSIGNED_BYTE, &img_buf[0]);
IplImage *cvimg;
cvimg = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3);
for(int i = 0; i < w; ++i){
for(int j = 0; j < h; ++j){
int idx = 3*(w*(h-j-1)+i);
int r, g, b;
r = img_buf[idx+0];
g = img_buf[idx+1];
b = img_buf[idx+2];
SetPixel(cvimg, i, j, r, g, b);
}
}
cvSaveImage(fn.c_str(), cvimg);
return true;
}
|
リンク集†
リファレンスなど†
GUIライブラリ†
拡張ライブラリ†
3Dモデルダウンロード†
- 3DXtras : 著作権フリーのさまざまな3Dモデルが多数投稿されている.ダウンロードするには要登録.max,3dsなど
- 3D CHAYA : 日本の城や刀など.OBJ,DXF,3DS.
- 3D Total : 様々なモデル.STUFF->modelsからダウンロードできる.MAX,3DS,LWOなど
- ホンダ ウェブプラモ : バイク,車メーカーのHondaが車やバイク,アシモのモデルを提供している.DXF形式.
|