• 締切済み

ウインドウ描画のタイミングの制御について

OpenGLで描画した結果を,自分で指定した時間だけ遅らせて ウインドウに提示したいと考えております. ※たとえば,入力して,10msec経過してから,ディスプレイを描画するなど ご助言を頂けますと幸いです. [現在試している環境]: C++,GLUT GLUTで指定する描画関数 glutDisplayFunc(display);  待機命令: Sleep関数 [試したこと] GLUTで指定した描画関数displyの中で,待機命令を与えました. 処理時間を計測した結果,待機命令分,必ずしも遅れていないことがわかりました. ※例えば,Sleep(10)という記述をdisplay関数内に書いても,10msec遅れない,1,2msec程度しか遅れが発生しない.しかし,Sleep(50)というように待機時間を増やすと,大体49msec程度遅れる. GLUTはdisplay関数は,必ずしも描画される保証はないと,友人に言われましたが, どのようにすれば,任意に画面描画タイミングを決められるのでしょうか? OpenGLを使用して,画面描画タイミングを任意に設定できないものなのでしょうか? ゲームやグラフィックカード等では,やっているような気がしますので方法はありそうなのですが 検討がついていない状態です. 不勉強で申し訳ありませんが,ご助言を頂けませんでしょうか? どうぞよろしくお願いいたします.

みんなの回答

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

今気づきましたが、もしかして赤と緑を交互に表示して1秒間に28枚と32枚を表示したいと言うことでしょうか? それだとテレシネ変換に近い力技が必要です。 http://www.mediajoy.com/mjc/movie_club/film2video/1.html 場合によりコマ数の多いフレームを増やすわけです。 例のとおりなら4コマ多いわけですから14コマ目と15コマ目とその倍数は同じ色を表示してやればご希望通り1秒間に28枚と32枚となります。

全文を見る
すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

基本的にディスプレイに同期すると思ってもらって良いと思います。 同期を切れないわけじゃないですが、どっちにしろディスプレイの周期を無視してもちゃんと表示されないので同期したほうが無難です。 こういう場合は、Sleep等でタイミングを調整するのではなく同じ画像を何周期も描画して調整するのが普通でしょう。 赤色28枚 緑色32枚ならdisplay関数で赤色を28周期、緑色を32周期描画すれば目的は達せられます。

全文を見る
すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

そもそも液晶ディスプレイが1/60秒周期(16.666・・・ms)でしか更新されないので10msなどの微妙なタイミング調整に意味はありません。

hhsato
質問者

補足

回答をありがとうございます. 回答について質問させてください. 例えば,ディスプレイ(60fps)に交互に赤色,緑色を出力するとします. そうすると,一秒間に,赤色 30枚,緑色30枚の絵を観察することができると思います. 人間は,30回の緑赤の切り替えを観察できます. 私は,緑赤が切り替わるまでの時間を伸ばしたいと考えています. 例えば,一秒間に,赤色28枚 緑色32枚 にして, 人間に,28回の緑赤の切り替えを提示したいです. 描画関数に遅れを与えることができれば,私のしたいことが実現可能だと考えているのですが,難しいのでしょうか? 描画関数内で待機命令をしても,特に影響がありません. OpenGLの描画命令が,ディスプレイの周波数と同期するように,調整しているのでしょうか?(待機命令を与えても,ディスプレイの周波数と合わせるので,10msec待機させても,ディスプレイの周期16msec待たされてしまう?) 長々と質問してしまい,申し訳ありません. どうぞよろしくお願いいたします.

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • OpenGLでの描画のタイミング

     OpenGLの使い方について疑問があったので質問しました.  OpenGLを用いて3Dのゲームを作っています.しかし, どうも処理が遅くカクカクした動きになってしまいます. 描画の量が多くなるにつれて遅くなっているので,原因は 描画の時に原因があるようです.ダブルバッファリング を用いて描画しているのですが,描画のときは… 1「描画関数の実行」(glVertex3f()などの実行) 2「裏に描画」(見えていないバッファに描画) 3「裏表入れ替え」(2つのバッファを交換) 0「一定時間待機して自分自身を呼び出す」            (60FPSなら1/60秒程度) を繰り返すものと考えています.  「1230」と繰り返せば通常通り動くのですが, 「1」に計算がかかりすぎると,「2」と「3」が遅れてしまい, カクカクしてしまうのだろうと考えました. (↑これがそもそも間違っていたらすいません><)  そこで,対策を2つ考えたのですが,これでいいでしょうか? それとも,もっと良い方法はないでしょうか?(「1」を 速くするしか方法はないでしょうか?) 【1】一定時間待機する秒数を可変的にする  現在のところ,「0」では,1/60秒待機させています.  しかし,1に1/30秒かかったとすると,「1230」を 1回繰り返すのに,3/60秒かかってしまうことになり, 結局FPSは20止まりです.  そこで,「123」でかかった時間を記録し,その秒数 を1/60から引いた分だけ「0」で待機すれば,1/60秒になる だろう,という方法です. 【2】描画のタイミングを変える  現在のところ,「1230」の順番で繰り返しています. しかし,これでは描画の関数を呼び出した時,「1」に 1/30秒かかったとすると,実際に表示できるのは1/30秒後 ということになります.よって,プログラムの始めに 「1232」を実行しておき,描画の関数の中身は 「3120」とする,という方法です. (そもそも,「2」と「3」のタイミングを   離せるのかどうかもよくわかりません><)  もちろん【1】と【2】の方法は併用もできると思っています. 「2」はOpenGLに入っているglFlush() 「3」はOpenGLに入っているglutSwapBuffers() 「0」はOpenGLに入っているglutTimerFunc() を用いています. 質問が長くなってしまいましたが,よろしくお願いします. 参考までに… 【OS】Mac OS10.7(Lion) 【開発環境】Xcode3 【言語】c++ 【プログラミング歴】6年(c++2年,OpenGL1年) 【CPU】2.66 GHz Intel Core 2 Duo 【メモリ】4 GB 1067 MHz DDR3

  • OpenGLで登録したコールバック関数の引数

    OpenGLで画面を描画をする際に, 以下のソースのように,glutDisplayFuncに関数を登録しています. main関数で,定義した定数や,そのポインタを display_funcに渡したいと思うのですが, どのような方法があるのでしょうか? 現在,私は,グローバル変数を定義して,それをmain関数とdisplay関数で いじっています. ソースコードの整理,関数化のため,できれば,ポインタや引数を渡したいです. どうぞよろしくお願いします. --------------------------------------------- #include <GL/glut.h> void display_func(void) { 描画内容を記述 } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutCreateWindow(argv[0]); glutDisplayFunc(display_func); glutMainLoop(); return 0; } ---------------------------------------------

  • ROP2での描画について

    WinAPI(C言語)でペイントのようなアプリを作成しているのですが、 例えば、写真のような画像の上に任意の色で塗りつぶした四角形を描画し、 それを元の画像に戻す場合は、SetROP2関数は使用できないのでしょうか? 当初R2_NOTを指定すればいいと思っていたのですが、 これはR2_NOTで描画した画像の上にR2_NOTで描画すれば以前の画像に戻りますが、 白や黒の任意のブラシで塗りつぶした場合にそれを元の画像に戻す方法はありますか? ご教示願います。

  • Opengl+jpeglibでC3867エラー

    お世話になります visual studio 2010 c++/cliのプロジェクトで Opengl+jpeglibで画像を表示しようとしているのですが このエラーが出てしまい、ビルドが通りません 何が悪いのか教えていただけないでしょうか error C3867: 'プロジェクト名::display': 関数呼び出しには引数リストがありません。メンバーへのポインターを作成するために '&プロジェクト名::display' を使用してください ここを参考に作成しております http://www21.atwiki.jp/opengl/pages/68.html ここを参考に以下の様にしたのですが 今度はC2275,C2227エラーになってしまいダメでした http://forum.programuj.com/viewtopic.php?t=5410&sid=97e82ad2762362899fad2dd331532bc7 glutDisplayFunc(&display); glutDisplayFunc(&プロジェクト名::display); glutDisplayFunc(&this->display); C2275,C2227

  • プログラミングのopenglで困っています.

    OpenGlの超初心者です. openglで,円を一つ作ってあるsampleプログラムを拾ってきたのですが, 円をもう一つ,別の座標で作りたいのですが,以下のプログラムをどのように編集すればいいですか? 誰か助けてください. ========================================== #include <GLUT/glut.h> #include "glut.h" #include <math.h> //--初期化処理------------------------------------------------------------------ void myinit(void){ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//背景色の設定(R,G,B,ALPHA) 0.0-1.0の範囲で } //--描画内容-------------------------------------------------------------------- void display(void){ float x1,y1,x2,y2; float th1,th2; float th1_rad, th2_rad; float hankei = 0.1; glClear(GL_COLOR_BUFFER_BIT);//画面全体を背景色で塗りつぶす glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //単位行列を行列スタックに読み込む glColor3f(0.0f, 0.0f, 0.0f);//頂点カラーの指定( R, G, B すべてが1.0fなら白) for (th1 = 0.0; th1 <= 360.0; th1 = th1 + 10.0){ th2 = th1 + 10.0; th1_rad = th1 / 180.0 * 3.1415926; // 「度」を「ラジアン」に直す th2_rad = th2 / 180.0 * 3.1415926; x1 = hankei * cos(th1_rad); y1 = hankei * sin(th1_rad); x2 = hankei * cos(th2_rad); y2 = hankei * sin(th2_rad); glBegin(GL_LINES);//glBegin(GL_LINES)とglEnd()の間に glVertex2f( x1, y1 ); //描画したい直線の頂点を並べる glVertex2f( x2, y2 ); glEnd(); //ここまでで,ひとつのオブジェクトの宣言がおわる } glFlush();//OpenGLで実際に描画を行う } //--再描画---------------------------------------------------------------------- void myReshape(GLsizei w, GLsizei h){ glViewport(0,0,w,h); //ウィンドウ全体をビューポートにする glMatrixMode(GL_PROJECTION); glLoadIdentity();//単位行列を行列スタックに読み込む glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); } //--メイン関数------------------------------------------------------------------ int main(int argc, char **argv){ glutInitWindowPosition(100, 100); //(図形が描画される)ウィンドウ位置の設定 glutInitWindowSize(600, 600); //(図形が描画される)ウィンドウサイズの設定 glutInit(&argc, argv);//環境の初期化 glutInitDisplayMode(GLUT_RGBA|GLUT_SINGLE); //表示モードの設定 glutCreateWindow("kadai"); //ウィンドウを開く glutDisplayFunc(display); //図形表示関数の指定 myinit(); glutReshapeFunc(myReshape); //座標軸・ビューポート設定関数の指定 glutMainLoop();//無限ループ return 0; } ==========================================

  • openGLについて

    最近プログラムを学んでいる初心者の者です。 私は床井研究室の”GLUTによる「手抜き」OpenGL入門”というサイトを使い学んでいるのですが、最初の段階でつまずいてしまいました。 最初のウィンドウを開く段階で #include <GL/glut.h> void display(void) { } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutCreateWindow(argv[0]); glutDisplayFunc(display); glutMainLoop(); return 0; } とすると書いてあるのですが、 最初の#includeのところがペーストしてもエラーが出ます。 あと他のサイトを見ると#includeが複数書かれているようです。 何か解決する方法はありますでしょうか。 ちなみに 私が使っているのはwindows7です。 どうかお願いします。

  • OpenGLで描画するテクスチャのアルファ値(透明度)を変更したい

    初めて質問させていただきます、tri-oと申します。 現在OpenGLでの2D描画プログラムを書いています。 ある画像を描画する時、その画像全体のアルファ値に、任意の値を乗算して、全体の透明度を変更したいのですが、やり方がわかりません。 例えば、キャラクターが書いてある画像があって、時間が経つ毎に透明度が変わり、徐々に出現するようなプログラムを書きたいのです。 色々と検索してみたのですが、目的のページにたどり着けませんでした。 ご存知の方いらっしゃいましたら、ご回答よろしくお願いします。

  • 右上の×を押したときに行う処理を意図的に書きたい

    今、OpenCVとOpenGLの両方を用いたプログラムを書いています。 OpenCVで物体を追跡したとおりにOpenGLで絵を動かそうとしており、 そのためには glutDisplayFunc(display); で呼び出しているdisplay()関数内で OpenCVを用いた画像処理プログラムを書く必要があると思っています。 しかし、cvCapture *captureなどとした場合、 cvReleaseCapture(&capture); などをプログラムの最後に行わなければなりません。 キーボードの「q」を打つことでメモリ解放および プログラムの終了をさせることができるのですが、 ウィンドウの右上の×を押しても同様の処理をさせたいと 考えています。 ウィンドウの右上の×を押してもcvReleaseCapture(&capture) などを行わせるにはどのように書けばよいのでしょうか?

  • Windows8+OpenGLで未処理の例外エラー

    Windows8 Pro のマシンで OpenGL を使うため、glut をインストールし、 簡単なサンプルをコンパイルして実行したところ、 「ユーザーコールバック中に未処理の例外エラーが発生しました」 というエラーを吐いて止まってしまいました。 統合環境は Visual C++2010 Express を利用しています。 サンプルプログラムは、以下の通りです。 #include <GL/glut.h> void display(void) { glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFlush(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA); glutInitWindowSize(640,480); glutCreateWindow(”window”); glutDisplayFunc(display); glutMainLoop(); return 0; } glut は様々なサイトで紹介されている方法通りに、 公式ページにて必要なファイル (32bit版) をダウンロードし、 glut.h を C:\Program Files (x86)\Microsoft Visual Stdio 10.0\VC\include\GL\ に、 glut32.lib を C:\Progma Files (x86)\Microsoft Visual Stdio 10.0\VC\lib\ に glut32.dll を C:\Windows\SysWOW64\ にコピーしました。 glut の代わりに freeglut も試してみたのですが、同様のエラーで止まってしまいました。 使用しているマシンは Surface Pro で ディスプレイアダプターは、 Intel(R) HD Graphics 4000 です。 ネットでいろいろ調べて Windows8 にインストールしている事例もちらほら見かけたので、 Windows8 でも動くとは思うんですが、どうにもうまくいきません。 dll が Windows8 に対応していないのか、Surface だから駄目なのか、検討がつきません。 原因をご存知の方がいましたら、どうか詳しく教えていただけないでしょうか? よろしくお願いします。

  • Windows 10の設定について(ノートパソコン

    Windows 10の「電源とスリープ」で「画面」にある 「次の時間が経過後、ディスプレイの電源を切る」(バッテリー駆動時)と(電源に接続時)を設定すると電源が切れてしまいます。(シャットダウン状態) 仕様でしょうか。不具合でしょうか。 「次の時間が経過後、ディスプレイの電源を切る」の設定を「なし」(バッテリー駆動時)と(電源に接続時)両方設定し、「スリープ」を設定するとちゃんとスリープモードで待機してくれます。