OpenGL関数で陰影付け
最初に、MinimalisticOpenGLDemo を見たことがない方は、先にそちらをご覧ください。
ここでは、GLUTによる「手抜き」OpenGL入門「陰影付け」で解説されている内容をPTBのプログラムの中で行う方法について解説します。またPTBとどのように連動させるのかに重きを置いているので、OpenGLに関する詳細な説明はリンク元をご覧ください。
実行するとアニメーションが開始されます。左矢印キーを押すたびに、アニメーションの有効と無効が切り替わります。アニメーションが無効な状態で右矢印キーを押すと、立方体が1度だけ回転します。エスケープキーで終了します。
clear all;
AssertOpenGL;
ListenChar(2);
screenNumber=max(Screen('Screens'));
InitializeMatlabOpenGL;
% 頂点の情報
vertex = [
0, 0, 0 % A (1)
1, 0, 0 % B (2)
1, 1, 0 % C (3)
0, 1, 0 % D (4)
0, 0, 1 % E (5)
1, 0, 1 % F (6)
1, 1, 1 % G (7)
0, 1, 1 % H (8)
];
face = [
1, 2, 3, 4
2, 6, 7, 3
6, 5, 8, 7
5, 1, 4, 8
5, 6, 2, 1
4, 3, 7, 8
];
normal = [
0 0 -1
1 0 0
0 0 1
-1 0 0
0 -1 0
0 1 0
];
light0pos = [0 3 5 1];
light1pos = [5 3 0 1];
green = [0 1 0 1];
red = [0.8 0.2 0.2 1];
try
[windowPtr, windowRect] = Screen('OpenWindow', screenNumber);
% スクリーンの中心座標
[centerPos(1), centerPos(2)] = RectCenter(windowRect);
% OpenGL関数を使い始めるという宣言
Screen('BeginOpenGL', windowPtr);
glEnable(GL.DEPTH_TEST);
glEnable(GL.CULL_FACE);
glCullFace(GL.FRONT);
glEnable(GL.LIGHTING);
glEnable(GL.LIGHT0);
glEnable(GL.LIGHT1);
glLightfv(GL.LIGHT1, GL.DIFFUSE, green);
glLightfv(GL.LIGHT1, GL.SPECULAR, green);
glMatrixMode(GL.PROJECTION); % アンダーバーがドットになっていることに注意。
glLoadIdentity;
gluPerspective(30.0, windowRect(3)/windowRect(4), 1.0, 100.0);
glMatrixMode(GL.MODELVIEW);
r = 0; % 回転角の初期値
flag = 1; % flagが1のときrが自動的に加算される。(アニメーション)
while KbCheck; end; % いずれのキーも押していないことを確認
while 1 % while 文の中をぐるぐる回ります。
[ keyIsDown, keyTime, keyCode ] = KbCheck; % キーが押されたか、そのときの時間、どのキーか、の情報を取得する
if keyIsDown
if keyCode(KbName('ESCAPE')) % エスケープキーでプログラムを終了
break;
end
if keyCode(KbName('LeftArrow'))
flag = 1-flag; % アニメーションを有効にしたり、無効にしたり。
end;
if keyCode(KbName('RightArrow'))
r = r + 1; % 手動で回転角度を増やす。
if r >= 360
r = 0;
end;
end;
while KbCheck; end;
end;
glClearColor(1,1,1,1); % 背景色
glClear(GL.COLOR_BUFFER_BIT);
glClear(GL.DEPTH_BUFFER_BIT);
glLoadIdentity;
gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); % 視点位置と視線方向
% 光源の設定
glLightfv(GL.LIGHT0, GL.POSITION, light0pos);
glLightfv(GL.LIGHT1, GL.POSITION, light1pos);
glRotated(r, 0, 1, 0); % 図形の回転
% 図形の色
glMaterialfv(GL.FRONT_AND_BACK, GL.AMBIENT_AND_DIFFUSE, red);
% 図形の描画
glBegin(GL.QUADS); % アンダーバーがドットになっていることに注意。
for j = 1:6
glNormal3dv(normal(j,:));
for i = 1:4
glVertex3dv(vertex(face(j,i),:));
end;
end;
glEnd();
% OpenGL関数の使用を終わります。
Screen('EndOpenGL', windowPtr);
% この段階で、PTBの機能を使って図形を描画することも可能です。
Screen('FillRect', windowPtr, [255 0 0], [200 300 400 400]);
Screen('Flip', windowPtr);
% 次の繰り返しのために
Screen('BeginOpenGL', windowPtr);
if flag % flagが1のときはアニメーション
r = r + 1;
if r >= 360
r = 0;
end;
end;
end;
% OpenGL関数の使用を終わります。
Screen('EndOpenGL', windowPtr);
Screen('CloseAll');
ShowCursor;
ListenChar(0);
catch
Screen('CloseAll');
ShowCursor;
ListenChar(0);
psychrethrow(psychlasterror);
end