さて、前回(何も原理を理解していないのに、三次元描画をしたかったので見よう見まねで取り敢えず作った)GLSamplerで二次元サンプル、三次元サンプルをウィンドウに描画し、三次元サンプルは動かしても見ました。しかし、この段階ではまだ何がどうなっているのかを知らず、またそれほど興味もなかったのでスルーしました。

 

が、

 

今回の企画で「矢張り少しは3Dグラフィックスを学習し、GLUTが何をやっているか理解しよう」ということで、ウェブに転がっている(無料の有難い)参考書を(最初は訳も分からず)読んでは実験してみました。(

:数少ない私の良い資質の一つは「必ず実験する」ということだと思います。文字よりも画像、座学よりも実際に動かしてみ(実験)ことで、抽象概念が観念として定着するのでしょう。

 

1.三次元空間

三次元空間を知っているか?と訊かれたら、「そんなの知ってるよ。現実に今暮らしているこの縦(y)、横(x)高さ(z)のある空間がそれでしょ?」と答えるでしょう。それは正しいのですが、OpenGLで3Dグラフィックプログラミングを行う場合にはより詳細で具体的な決め事があることを知りました。

(1)三次元空間内の位置決めは座標(x, y, z)で行いますが、横のxは左から右へ、縦のyは下から上へ(PCのスクリーン座標と逆ですね)、深さのzは前から後ろへ値が増してゆきます。このような空間を右手系空間(右手の法則や右手法等)というようです。

(2)(私は単純に絶対空間が一つあるだけかと思っていましたが)OpenGLの扱う三次元空間にはワールド座標系空間の他、三次元空間の描画対象物(以降OpenGLの「プリミティブ」と呼びましょうか)が規定される(プリミティブの中心を原点とする)ローカル座標系空間が存在します。この空間でプリミティブを移動、回転、縮小・拡大させたりします。これを(座標の)モデル変換というようです。

 

2.3Dグラフィックス

昔、私は3Dグラフィックスを漠然と「二次元グラフィックは平面に(x, y)座標で位置指定して描画していたものを、立体空間に(x, y, z)座標で位置指定して描画」しているんだろうな、と思っていました。しかしPCのスクリーンに描画するには、プリィミティブを平面へ投射する際、三角関数を使って変換する、ということは分かっていてもなんだか面倒くさいな、ということで敬遠していたのも事実です。

:投影ともいわれますが、"project(ion)"の訳語でしょう。

 

OpenGLでは、先ずこのプリミティブの存在するローカル空間の座標を、プリミティブを配置するワールド空間内の座標に置き換えることから始ります。これをビュー変換というそうです。従って、プリミティブをワールド空間に配置するまでを一貫させてモデル・ビュー変換と呼ぶようです。

 

しかし、プリミティブをワールド空間に配置するだけでは3Dグラフィックスは完成できません。何故なら普段は余り気にしていない「見る主体(ユーザー)」の視点とそこから広がる「視野空間(注)」によってワールド空間内のプリミティブの画像が変化するからです。

注:参考文献では抽象的に"field of view"とか、三次元空間としての視野を"viewing volume"と呼んでいるようですが、訳語が「視体積」とか「視錐台」とかにするので、いたずらに難しくしているように感じます。要すれば「視点」からプリミティブまでの四角垂(またはその一部)のことです。

 

プリミティブがどのように視点に映る(写る)かは、投射(投影)の仕方で異なります。視点からの四角垂の場合は遠近の相違が反映されますが、視点にそのまま映す(視野空間が直方体の場合)は遠近感が失われます。OpenGLでは前者を透視投影(投射)"perspective projection"、後者を平行投影(投射)"pararelle projection"というようです。

 

勿論、プリミティブ(の全部乃至一部)が視野空間から外れれば、それは見えなくなりますし、視野空間が変化すれば、プリミティブの画像も変化します。

 

このようなモデル・ビュー変換でワールド空間に配置されたプリミティブが、視点と視野空間により「どのように見えるか」迄規定することをプロジェクション変換と呼ぶようです。

 

最後にモデル・ビュー変換プロジェクション変換を受けたプリミティブの座標データをPCのスクリーンに表示する為に、投影面に投影された2次元映像をPCのスクリーン座標の指定領域内に表示するためのビューポート変換を受けて3Dグラフィックスが出来上がります。

 

さらに、

 

ここまでで出来上がったプリミティブに対して光源による照光を行い、様々な特定の光線を受けたプリミティブの表面の反射特性から質感を表現して3Dグラフィックが完成します。(

:私はプリミティブの描画までで息切れして、照光や質感は(元来、絵心がないこともあり)手に余るので、出来て先達の模倣程度であることをご承知おきください。

 

3.OpenGLとGLUT

では、OpenGLとGLUTがこのようなプロセスで行う3Dグラフィックスをどのようにおこなっているのか(具体的にはC++でどのようにコーディングするのか)は、次回以降実際のコードと画像をもとに説明しましょう。

 

4.その他補足事項

(1)↑ではサラッと「座標変換」とか書いていますが、実際には3次元座標を行列としてとらえ、行列の積により回転、縮小・拡大を行いますが、更に平行移動を計算する為に4次元座標として計算しています。しかし実際にユーザーが座標計算する訳ではないので、「TVを観るのにTVの原理を知る必要はない」という考え方からこの座標変換部分はスキップしています。それでも「高校時代の数学は忘れてしまった」ので詳しく知りたいという方はウェブで「行列 積」でググってください。

(2)行列の積だけではなく、その三次元画像への応用を知りたい方は↓を参考にしてください。(頭が痛くなること請け合いです。

関数・写像の定義
ベクトル空間の定義
ベクトル空間の基底と次元の定義
基底の変換行列の定義
(3)ただ私としては、最終目的が3DグラフィックスのPCプログラミングなので、単にこれをしっかりお読みいただければ十分かと思います。(私が見た中で簡潔に全体を網羅しているように思えましたので。)

 

では次回からは、GLUTを(その本来の使い方で)使って、↑に掛かれていることを実際に確かめてゆこうと思います。

 

ps. 本ブログ中で「...というようです。」と伝聞形で記述しているところは、現在学習中の私が間違いを犯しても一切責任はとれないことを示唆する為です。又、如何に偉大なる大阪人が使う絶対免責文言を付加します。

 

知らんけど...