Posted at

OpenGL最小入門

More than 3 years have passed since last update.


OpenGL最小入門

この記事では以下の視点からOpenGLについて理解を深めていきます。


  • 頂点と描画例

  • 透視投影とは

  • シェーダーとは

また以下の事は扱いません。

- UVと画像表示

- ファイル読み込み

- 様々な最適化


頂点と描画例

頂点とは3D空間の中にある1つの座標をx, y, zの3つの小数で表します。

これから点、線、三角形、四角形といった簡単な図形の描画例を見ていきます。


まずは頂点を1つ表示

座標情報と点の大きさを指定します。大きさを指定しないと点が小さすぎて見つけにくいので、大きめを指定します。

model.SetVertices({

0., 0, 0,
});
model.DrawLines(100.0f);

描画するとこんな感じ。座標0が真ん中を表します。

dot.png


次に頂点を2つ表示

もう一つ座標を追加し2つの頂点を指定します。

model.SetVertices({

0.5f, 0, 0,
0.7f, 0.5f, 0
});
model.SetDrawLines(100.0f);

右上に点が追加されました。x座標が正だと右、y座標が正だと上に移動します。負の場合はそれぞれ逆方向に移動します。

two_dot.png


線を表示

座標を2つと「線を引く」命令で線となります。

model.SetVertices({

0.5f, 0, 0,
-0.5f, 0, 0,
});
model.DrawLines(100.0f);

line.png

次に線を2本引いてみます。

model.SetVertices({

0.5f, 0, 0,
-0.5f, 0, 0,
0.5f, 0.5f, 0,
-0.5f, 0.5f, 0,
});
model.DrawLines(100.0f);

two_line.png


そして三角形を表示

三角形はこれまでと少し違います。頂点3つに加え、どの順番で頂点を描画するか順序を指定しないといけません。この順序は頂点インデックスと呼ばれています。

model.SetVertices({

0.5f, -0.5f, 0,![index.png]
0, 0.5f, 0,
-0.5f, -0.5f, 0,
});
model.DrawTriangles({
0, 1, 2
});

triangle.png

index.png

描画順はこんな感じです。


最後に四角形を表示

四角形は2つの三角形を合わせて描画します。ここでは4つの頂点と頂点インデックスの組み合わせで、2つの三角形を表現しています。

model.SetVertices({

0.5, -0.5, 0,
0.5, 0.5, 0,
-0.5, 0.5, 0,
-0.5, -0.5, 0,
});
model.DrawTriangles({
0, 1, 2,
0, 2, 3,
});

quadrangle.PNG


透視投影とは

透視投影(perspective projection)という図法を使えば3Dっぽく見せることができます。近くのものはより大きく、遠くのものはより小さく写す事で遠近感を表現できます。

透視投影のイメージ図。zが0に近い程に大きく、zが大きくなるに連れ小さく描画されます。


透視投影法のイメージ画像

ゲームつくろー!の「② 視錐台を描画空間に変換する」より

引用元サイトで透視投影の理論と計算方法の紹介もあります


これまでと比べて少し複雑ですが、透視投影を使い右斜上からの視点で正方形を描画してみます。

// 正方形の頂点は8点、各頂点はx y zの3つを持つ

model.SetVertices({
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
-1.0, -1.0, -1.0,

1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
});
// 正方形の面は6つ、それぞれの面を2つの三角形で表現
model.DrawTriangles({
1, 3, 0,
7, 5, 4,

4, 1, 0,
5, 2, 1,

2, 7, 3,
0, 7, 4,

1, 2, 3,
7, 6, 5,

4, 5, 1,
5, 6, 2,

2, 6, 7,
0, 3, 7
});

// カメラの座標(4, 2, 6)から、正方形の座標(0, 0, 0)を見る射影行列を求める
glm::mat4 mvp = camera.LookAt(glm::vec3(4, 2, 6), glm::vec3(0, 0, 0));
model.SetMVP(mvp);

cube.PNG


シェーダーとは

大きく2つの種類があります。「頂点シェーダー」と「フラグメントシェーダー」です。フラグメントシェーダはOpenGLの用語でDirectXでは「ピクセルシェーダー」と呼ばれています。

頂点シェーダーの例。

全ての頂点に同じ処理を行えます。

positionにプログラムで指定した(-1.0, 0.0, -0.5)とかの座標が、mvpには透視投影を行うための行列情報が格納されます。

#version 450

layout (location = 0) in vec3 position;
uniform mat4 mvp;
void main()
{
gl_Position = mvp * vec4(position, 1.0);
}

フラグメントシェーダーの例。

描画対象のピクセルの色を決めています。

vec4(赤, 緑, 青, 透明度)を表し、赤緑青の場合は全て1.0で白、全て0.0で黒を表しその中間で様々な色を表現します。透明度は1.0で不透明、0.0で透明(見えない)、その中間で半透明を表しています。

#version 450

out vec4 out_color;
void main()
{
out_color = vec4(1.0, 1.0, 1.0, 1.0);
}


終わりに

記事で用いたサンプルプログラムと、更に進んだ内容を勉強するための参考URLを記載しておきます。


参考URL


サンプルプログラムの構成

githubのサンプルコード

git clone https://github.com/hythof/opengl_tutorial.git

動作確認環境

- Windows 7 (64 bit)

- Microsoft Visual Studio 2015 Pro

- GLFW 3.2. (zlib/libpng license)

- GLEW 2.0 (license link)

- glm 0.9.8.0 (MIT license)

パス
説明

src/gldemo/gldemo.sln
VS2015のソリューション

src/gldemo/gldemo/main.cpp
サンプルプログラムのmain関数

src/gldemo/vendors/
一般公開されているライブラリ