LearnOpenGL

Translation in progress of learnopengl.com.
git clone https://git.mtkn.jp/LearnOpenGL
Log | Files | Refs

OpenGL.html (14136B)


      1     <h1 id="content-title">OpenGL</h1>
      2 <h1 id="content-url" style='display:none;'>Getting-started/OpenGL</h1>
      3 <p>学習をはじめる前にOpenGLとは何かを確認しておきましょう。OpenGLとはグラフィックや画像を操作するための関数を多数提供するAPI(<def>アプリケーションプログラミングインターフェース</def>)だと考えられています。しかしOpenGLそのものはAPIではなく、<a href="http://www.khronos.org/" target="_blank">Khronos Group</a>により開発及びメンテナンスされている仕様です。</p>
      4 
      5 <img src="/img/getting-started/opengl.jpg" class="right" alt="Image of OpenGL's logo"/>
      6 
      7 <p>
      8 OpenGLの仕様は各関数がどのようにふるまい、どのような結果を残し、あるいどんな出力を返すのかを正確に規定しています。これらの関数をどのようにして仕様どおりに機能させるかは、開発者の<em>実装</em>に任されています。OpenGLの仕様は実装についての詳細を規定していないので、得られる結果が仕様通りである(つまりユーザーから見て同じである)限り、様々な実装が可能です。
      9 </p>
     10 
     11 <p>
     12 OpenGLのライブラリを開発しているのは、おもにグラフィックカードの製造者です。あなたが購入したグラフィックカードはその製品(あるいはそのシリーズ)に特化したOpenGLのバージョンをサポートしています。AppleのシステムではOpenGLのライブラリはApple自身によりメンテナンスされており、Linuxにおいてはグラフィックカードの製造者によるライブラリや、趣味の開発者によるものもあります。つまりOpenGLがおかしな挙動をする場合はたいていグラフィックカードの製造者(またはライブラリの開発に関わった誰か)のミスです。
     13 </p>
     14 
     15 <note>
     16 ほとんどの実装はグラフィックカードの製造者によるものなので、バグが見付かった場合はビデオカードのドライバをアップデートすることでたいてい解決します。最新のドライバにはそのグラフィックカードがサポートする最新のOpenGLが含まれているからです。グラフィックドライバをときどきアップデートするべき理由のひとつです。
     17 </note>
     18 
     19 <p>
     20 KhronosはすべてのOpenGLのバージョンの仕様に関するドキュメントを公開しています。興味がある読者はこれからみなさんが利用するバージョン3.3の仕様を<a href="https://www.opengl.org/registry/doc/glspec33.core.20100311.withchanges.pdf" target="_blank">ここ</a>で確認できます。このページはOpenGLの詳細を理解するのに非常に役立ちます(実装ではなく結果ばかりが記述されていることを確認してください)。OpenGLの仕様は関数の<strong>正確な</strong>ふるまいを確認する文献としても重要です。
     21 </p>
     22 
     23 
     24 <h2>Core-profileと即席モード</h2>
     25 <p>
     26 もともと、OpenGLを利用するとは<def>即席モード</def>(<def>固定関数パイプライン</def>とも)で開発するということでした。即席モードはグラフィックを描写する簡易な方法です。OpenGLのほとんどの機能はライブラリのなかに隠され、開発者は演算の方法にまで深くは踏み込めませんでした。開発者はしだいに柔軟性を求めるようになり、それに伴い仕様のほうも柔軟になりました。開発者がグラフィックの描画方法にに関してより多くのことを操作できるようになったのです。即席モードは理解し使用するのは非常に簡単ですが、効率はかなり悪いです。そのため仕様はバージョン3.2から即席モードの廃止に向かい、<def>core-profile</def>モードを推奨しはじめました。core-profileモードでは廃止された古い機能がすべて取り除かれています。
     27 </p>
     28 
     29 <p>
     30 Core-profileを使うには新しい方法に従う必要があります。廃止された関数を使おうとするとOpenGLがエラーを出して描画を停止します。新しい方法の利点は柔軟性の高さと効率のよさです。ただしその分習得するのが難しいです。即席モードはOpenGLがおこなっている<strong>実際の</strong>操作の多くを抽象化しているので習得するのが簡単な一方、OpenGLが実際になにをおこなっているかを把握するのは難しいです。新しい方法ではOpenGLやグラフィックスプログラミングについての深い理解が必要であるのですこし難解ではあるものの、柔軟性や効率のよさ、そして一番重要なことですが、グラフィックスプログラミングに関するよりよい理解が得られます。
     31 </p>
     32 
     33 <p>
     34 そのためこの本ではOpenGLバージョン3.3のcore-profileについて重点的に解説します。理解するのは大変ですが、努力する価値は十分にあります。
     35 </p>
     36 
     37 <p>
     38 今日、OpenGLのもっと新しいバージョンが利用できます(執筆時点での最新は4.6)。にも関わらずバージョン3.3を学習する意味があるのかと疑問に思うかもしれませんが、その答えは比較的簡単です。バージョン3.3より新しいものはすべて、このバージョンに便利な機能を追加したものであり、OpenGLの核となる部分は変更されません。新しいバージョンのものは以前と同じことをするうえでより効率がいい、あるいはより使いやすい方法を導入しただけです。考え方ややり方はバージョン3.3以降変わらないので、このバージョンを学ぶことが有効なのです。バージョン3.3でOpenGLに慣れ親しめば、より新しいバージョンの機能を利用することは簡単です。
     39 </p>
     40 
     41 <warning>
     42 最新のOpenGLを使って開発したアプリケーションは、最新のグラフィックカード以外では動作しません。そのためほとんどの開発者は古いバージョンのOpenGLで開発し、新しいバージョンの機能は対応するグラフィックカードへのオプションとして組込みます。
     43 </warning>
     44 
     45 <p>
     46 一部の章ではことわったうえで新しい機能を利用することがあります。
     47 </p>
     48 
     49 <h2>拡張機能</h2>
     50 <p>
     51 OpenGLの大きな特徴に、拡張機能があります。グラフィックカードの製造者が新しい技術を導入したり、描画を大幅に最適化した場合、それらの機能はドライバに実装される<def>拡張機能</def>によって提供されることが多いです。アプリケーションが動作しているハードウェアがそういった拡張機能をサポートしていれば、開発者はそれらを利用し先進的な、あるいは効率のいい方法でグラフィックを描画することができます。このような最新の機能は、グラフィックカードによりサポートされているかどうかを確認するだけで利用できるので、開発者はOpenGLにその機能が組込まれるのを待つ必要がありません。ある拡張機能が人気になり、あるいは便利であれば将来のOpenGLのバージョンに組込まれることになります。
     52 </p>
     53 
     54 <p>
     55 上記のようなグラフィックカードに特有の(あるいはOpenGL自身の)拡張機能を利用する前に、その機能が利用可能かどうかを確かめる必要があります。こうすることで、拡張機能が利用可能かどうかに応じてより効率のよいプログラムを書くことができます:
     56 </p>
     57 
     58 <pre><code>
     59 if(GL_ARB_extension_name)
     60 {
     61 	// 最新の機能を利用したクールなコード
     62 }
     63 else
     64 {
     65 	// 拡張機能がサポートされていない場合: 従来の方法を利用したコード
     66 }
     67 </code></pre>
     68 <p>
     69 OpenGLバージョン3.3において拡張機能はほとんど必要ありませんが、利用する場合は解説を付けます。
     70 </p>
     71 
     72 <h2>状態機械</h2>
     73 <p>
     74 OpenGLはひとつの大きな状態機械だといえます: 各時点におけるOpenGLの動作を規定する変数の集まりだという意味です。OpenGLの状態は<def>コンテクスト</def>と呼ばれます。OpenGLでは、オプションの設定やバッファの操作により状態を変化させ、その時点のコンテクストを利用して描画をおこないます。
     75 </p>
     76 
     77 <p>
     78 例えば描画するものを三角形から直線に変更するためには、コンテクストの変数のうち描画する図形を規定するものを変更することでOpenGLの状態を変化させることになります。そのようにコンテクストを変更すれば、以降の描画命令では三角形ではなく直線が描かれます。
     79 </p>
     80   
     81 <p>
     82 OpenGLでの開発において、コンテクストを変更する<def>状態変更</def>関数や、現在の状態にもとづいてなんらかの操作をおこなう<def>状態利用</def>関数を利用することになります。OpenGLが大きな状態機械であるということを頭にいれておけば、さまざまな機能を理解するのが楽になります。
     83 </p>
     84 
     85 <h2>オブジェクト</h2>
     86 <p>
     87 OpenGLのライブラリはC言語で記述されています。ほかの言語への派生も存在しますが、核となる部分はC言語のライブラリのままです。C言語の言語構造は他の高水準の言語にうまく翻訳できないので、OpenGLはいくつかの抽象的な概念を念頭に開発されました。<def>オブジェクト</def>の概念がそのひとつです。
     88 </p>
     89 
     90 <p>
     91 OpenGLにおいて<def>オブジェクト</def>とは、OpenGLの状態をあらわしたオプションのあつまりです。たとえばウィンドウの描画に係る設定をまとめたオブジェクトを作ることができます。このオブジェクトを通して、ウィンドウの大きさや表示できる色の数等を設定することができます。オブジェクトはC言語の構造体のようなものとしてとらえることができます:
     92 </p>
     93 
     94 <pre><code>
     95 struct object_name {
     96     float  option1;
     97     int    option2;
     98     char[] name;
     99 };
    100 </code></pre>
    101 
    102 <p>
    103 オブジェクトはたいてい以下のようなかたちで利用することになります(前半の部分はOpenGLのコンテクストを大きな構造体として記述したものです):
    104 </p>
    105 
    106 <pre><code>
    107 // OpenGLの状態
    108 struct OpenGL_Context {
    109   	...
    110   	object_name* object_Window_Target;
    111   	...  	
    112 };
    113 </code></pre>
    114   
    115 <pre><code>
    116 // オブジェクトの作成
    117 unsigned int objectId = 0;
    118 glGenObject(1, &amp;objectId);
    119 // コンテクストに対してオブジェクトを紐付け
    120 glBindObject(GL_WINDOW_TARGET, objectId);
    121 // 現在GL_WINDOW_TARGETに紐付いているオブジェクトのオプションを設定
    122 glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH,  800);
    123 glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600);
    124 // コンテクストの紐付けを解除
    125 glBindObject(GL_WINDOW_TARGET, 0);。
    126 </code></pre>
    127 
    128 <p>
    129 上のような記述はOpenGLで開発をしているとよくみかけます。まずオブジェクトを作成しそれを参照するためのIDを記憶しておきます(オブジェクトの実際のデータは開発者からは見えません)。つぎに記憶したIDによりオブジェクトをコンテクストのうち設定したいものに紐付けます(上の例では<var>GL_WINDOW_TARGET</var>に紐付けています)。そしてウィンドウのオプションを設定し、最後に<var>GL_WINDOW_TARGET</var>と紐付いたオブジェクトのIDを<code>0</code>にすることで、オブジェクトとコンテクストの紐付けを解除します。設定したオプションは<var>objectID</var>によって参照されるオブジェクトに保持され、オブジェクトを<var>GL_WINDOW_TARGET</var>と紐付けることでいつでも復元できます。
    130 </p>
    131 
    132 <warning>
    133 ここまでのサンプルコードはOpenGLの操作をおおまかに記述したものです。以降では実際に動作するサンプルコードを多く提供します。
    134 </warning>
    135 
    136 <p>
    137 オブジェクトを利用する大きな利点は、複数のオブジェクトを定義、設定しておけば、OpenGLの状態を利用してなにかするときにそれらのオブジェクトのなかから用途にあわせたものを選べることです。例えば家やキャラクター等の3Dモデルのデータを保持した複数のオブジェクトを定義しておけば、各オブジェクトを紐付けるだけで、そのオブジェクトが保持している3Dモデルが描画できます(最初に各3Dモデルに対してオブジェクトを作成し、必要なオプションを設定すればいいのです)。こうすることでたくさんのモデルを描画するときにいちいちオプションを設定しなおさなくてすみます。
    138 </p>
    139 
    140 <h2>さあ、始めましょう</h2>
    141 <p>
    142 ここまでOpenGLについてざっくりと学びました。OpenGLが仕様であり、ライブラリであること。OpenGLの内部がどのように機能するのか、またOpenGLをどのように扱うのか。すべてを理解できていなくても心配はいりません。この本では各段階においてOpenGLを理解するのに十分な例が提示されます。
    143 </p>
    144   
    145 <h2>参考</h2>
    146 <ul>
    147   <li><a href="https://www.opengl.org/" target="_blank">opengl.org</a>: OpenGLの公式ウェブサイト。</li>
    148   <li><a href="https://www.opengl.org/registry/" target="_blank">OpenGL registry</a>: OpenGLのすべてのバージョンの仕様と拡張機能が確認できるサイト。</li>
    149 </ul>
    150         
    151 
    152     </div>
    153 </body>
    154 </html>