オフスクリーンウィンドウ
複雑な刺激(例えば幾何学的な模様が入り乱れているような)を使う場合、各試行で呈示する直前で描画を行っていると、そこで時間のロスが生じる可能性があります。それを防止するため、使用する刺激をあらかじめオフスクリーンウィンドウ(テクスチャ)に描画しておく方法があります。試行が始まると、事前に描画しておいたオフスクリーンウィンドウを画面に呈示するだけなので、時間のロスを抑えることができます。
Screen('OpenOffscreenWindow') も参照してください。
またデモのMullerLyerIllusionのなかにも、
% %an example of preparing an offScreenwindow (for repeated use and fast drawing)
% [fixcross,rect2]=Screen('OpenOffscreenWindow',screenNumber,[],[0 0 20 20]);
% Screen('drawline',fixcross,[0 0 0],10,0,10,20,2);%mx-10,my,mx+10,my
% Screen('drawline',fixcross,[0 0 0],0,10,20,10,2);%mx,my-10,mx,my+10
のように、オフスクリーンウィンドウの使用方法について記載があります。
Screen('MakeTexture') を使用してもよいのですが、刺激によっては行列を作るのが難しい場合があると思います(例えば円を描画するときなど)。もしくはアンチエイリアシングを行いたい場合も(おそらく)MakeTextureを使うのは難しいと思います。
少し話がそれますが描画速度に興味のあるかたは、/Applications/Psychtoolbox/PsychTests/ にある DrawingSpeedTest もご覧ください。
私の環境だとprimitivetypeとmodeの組み合わせによって、最適な描画方法が異なりますが、基本的にはmode=1(複数の座標を事前に指定しておき、for文などの繰り返しを使わない方法)で問題のない速度で描画ができています。
かなり複雑な刺激の描画でない限りは、mode=1 の方法でよさそうです。オフスクリーンウィンドウを使う場合より、シンプルなコードになります。
以下にオフスクリーンウィンドウを使ったサンプルプログラムを記します。
3秒ごとにオフスクリーンウィンドウを切り替えています。
最後の刺激はアンチエイリアシングの動作確認です。
function offscreenTest
% 刺激を呈示する前にオフスクリーン(テクスチャ)に刺激を描画しておくことにより
% 時間のロスをなくす方法
%
ListenChar(2);
AssertOpenGL;
WaitSecs(0.1);
%OSで共通のキー配置にする
KbName('UnifyKeyNames');
%手作りfunction。必要に応じてコメントアウトしてください。
%myKeyCheck;
try
bgColor = [128 128 128]; % 画面全体の背景色
bgColor2 = [0 0 0]; % 四角形領域の背景色
screenNumber=max(Screen('Screens'))
%ウィンドウでの呈示
%[windowPtr, windowRect]=Screen('OpenWindow', screenNumber, bgColor, [100, 200, 800, 600]);
%フルスクリーンでの呈示
[windowPtr, windowRect]=Screen('OpenWindow', screenNumber, bgColor);
OvalColor = [255 255 255]; % 円の色
StimRect = [0 0 200 200]; % Stimulus Rect 円を描画する四角形領域
[centerX centerY] = RectCenter(StimRect); % 四角形の中心座標
radius = 20; % 円の半径
dist = 50; % 円と円のあいだの距離
%-----------------------------------
% オフスクリーン(テクスチャ)の作成 (このサンプルでは4つのオフスクリーンを作成しています)
% オフスクリーン1:中心に1つの円
OvalTex1 = Screen('OpenOffscreenWindow', screenNumber, bgColor2, StimRect);
Screen('FillOval', OvalTex1, OvalColor, [centerX - radius, centerY - radius, centerX + radius, centerY + radius]);
% オフスクリーン2:水平に並んだ2つの円
OvalTex2 = Screen('OpenOffscreenWindow', screenNumber, bgColor2, StimRect);
Screen('FillOval', OvalTex2, OvalColor, [centerX - radius, centerY - radius, centerX + radius, centerY + radius]);
Screen('FillOval', OvalTex2, OvalColor, [centerX - radius - dist, centerY - radius, centerX + radius - dist, centerY + radius]);
% オフスクリーン3:水平に並んだ3つの円
OvalTex3 = Screen('OpenOffscreenWindow', screenNumber, bgColor2, StimRect);
Screen('FillOval', OvalTex3, OvalColor, [centerX - radius, centerY - radius, centerX + radius, centerY + radius]);
Screen('FillOval', OvalTex3, OvalColor, [centerX - radius - dist, centerY - radius, centerX + radius - dist, centerY + radius]);
Screen('FillOval', OvalTex3, OvalColor, [centerX - radius + dist, centerY - radius, centerX + radius + dist, centerY + radius]);
% オフスクリーン4:斜めの2本の線分
% アンチエイリアシングの確認
LineTex = Screen('OpenOffscreenWindow', screenNumber, bgColor2, StimRect);
Screen(LineTex,'BlendFunction',GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); % アンチエイリアシングを有効に
Screen('DrawLines', LineTex, [20, 150; 20, 40], 2, OvalColor, [], 0); % アンチエイリアシングなしの線分
Screen('DrawLines', LineTex, [20, 150; 60, 80], 2, OvalColor, [], 1); % アンチエイリアシングありの線分
% 呈示の開始
Screen('DrawTexture', windowPtr, OvalTex1);
Screen('Flip', windowPtr);
WaitSecs(3);
Screen('DrawTexture', windowPtr, OvalTex2);
Screen('Flip', windowPtr);
WaitSecs(3);
Screen('DrawTexture', windowPtr, OvalTex3);
Screen('Flip', windowPtr);
WaitSecs(3);
Screen('DrawTexture', windowPtr, LineTex);
Screen('Flip', windowPtr);
KbWait;
%終了処理
Screen('CloseAll');
ShowCursor;
ListenChar(0);
catch
Screen('CloseAll');
ShowCursor;
ListenChar(0);
psychrethrow(psychlasterror);
end