東京工業大学
デジタル創作同好会

2015年12月2日 | メンバーブログ

D言語でOpenGL†入門†

sobaya007

タイトルの通りOpenGLの入門記事をぼちぼち書いていきます。準備に関しては前の記事を参照。

GLFWでとにかくウインドウを表示

D言語ですので引数のない関数の()は取れますし、型名をいちいち書くのが面倒ならautoでいいんですが、説明にならないのでここでは省略をなるべくしない形で書いていきます。

import derelict.opengl3.gl;
import derelict.glfw3.glfw3;
 
void main() {
	//======Derelict側の初期化=====
	DerelictGL.load();
	DerelictGLFW3.load();
 
	//=====GLFWの初期化=====
	glfwInit();
 
	//=====ウインドウの初期化=====
	const int window_width  = 800;
	const int window_height = 600;
	//末尾のnullはそれぞれフルスクリーン、ウインドウの共有をするときに使う(らしい?)
	GLFWwindow *window = glfwCreateWindow(window_width, window_height, "Hello, D World!", null, null);
 
	//=====メインループ=====
	while (!glfwWindowShouldClose(window)) {
	}
 
	//=====おわり=====
	glfwTerminate();
}

これで一応GLFWからウインドウを表示することはできます。しかしやってみるとわかりますが、この状態ではウインドウにマウスを乗せただけでグルグルしてしまいます。

これは、GLFWでマウスイベントを処理していないために起きています。これを直すには*glfwPollEvents()*という関数を使います。

import derelict.opengl3.gl;
import derelict.glfw3.glfw3;

void main() {
	//======Derelict側の初期化=====
	DerelictGL.load();
	DerelictGLFW3.load();

	//=====GLFWの初期化=====
	glfwInit();

	//=====ウインドウの初期化=====
	const int window_width  = 800;
	const int window_height = 600;
	//末尾のnullはそれぞれフルスクリーン、ウインドウの共有をするときに使う(らしい?)
	GLFWwindow *window = glfwCreateWindow(window_width, window_height, "Hello, D World!", null, null);
	
	glfwMakeContextCurrent(window);

	//=====メインループ=====
	while (!glfwWindowShouldClose(window)) {
		glfwPollEvents();
	}

	//=====おわり=====
	glfwTerminate();
}

これでとりあえずウインドウがまともに出せました。続いては何か書いてみましょう。

三角形の表示

すべては三角形に始まり三角形に終わります。三角形は三次元上で使え、凸性を保証された優れた図形です。まずはこれを画面に描いてみましょう。

import derelict.opengl3.gl;
import derelict.glfw3.glfw3;

void main() {
	//======Derelict側の初期化=====
	DerelictGL.load();
	DerelictGLFW3.load();

	//=====GLFWの初期化=====
	glfwInit();

	//=====ウインドウの初期化=====
	const int window_width  = 800;
	const int window_height = 600;
	//末尾のnullはそれぞれフルスクリーン、ウインドウの共有をするときに使う(らしい?)
	GLFWwindow *window = glfwCreateWindow(window_width, window_height, "Hello, D World!", null, null);

	//OpenGLでの描画対象をwindowに設定
	glfwMakeContextCurrent(window);

	//=====メインループ=====
	while (!glfwWindowShouldClose(window)) {
		
		//三角形を描画
		glClear(GL_COLOR_BUFFER_BIT);
		glBegin(GL_TRIANGLES);
		glVertex3d(-0.5, -0.5, 0.0);
		glVertex3d( 0.5, -0.5, 0.0);
		glVertex3d( 0.0,  0.5, 0.0);
		glEnd();
		
		//画面を更新
		glfwSwapBuffers(window);

		glfwPollEvents();
	}

	//=====おわり=====
	glfwTerminate();
}

Triangle

こんなかんじになったでしょうか。ここらへんから真面目に解説しようと思います。OpenGLでの図形の描画は上のコードの通り、glClearで画面をクリアし、glBegin始め、途中でglVertex3dをいくつかはさんで頂点の座標を指定し、最後にglEndで締めくくるという流れで行います。

OpenGLの座標系は、ウインドウの中心が原点、ウインドウの右上が(1,1),ウインドウの左下が(-1,-1)で、ウインドウの手前から奥へ行く向きにz軸正方向が取ってあります。遠近法はデフォルトでは働かないため、zを大きくしても図形が小さくなったりはしません。また、描画されるものは0 <= z <= 1のもののみです。適当に座標位置を変えながら色々と試してみてください。

色をつける

import derelict.opengl3.gl;
import derelict.glfw3.glfw3;

void main() {
	//======Derelict側の初期化=====
	DerelictGL.load();
	DerelictGLFW3.load();

	//=====GLFWの初期化=====
	glfwInit();

	//=====ウインドウの初期化=====
	const int window_width  = 800;
	const int window_height = 600;
	//末尾のnullはそれぞれフルスクリーン、ウインドウの共有をするときに使う(らしい?)
	GLFWwindow *window = glfwCreateWindow(window_width, window_height, "Hello, D World!", null, null);

	//OpenGLでの描画対象をwindowに設定
	glfwMakeContextCurrent(window);
	
	//=====メインループ=====
	while (!glfwWindowShouldClose(window)) {
		
		//三角形を描画
		glClear(GL_COLOR_BUFFER_BIT);
		glBegin(GL_TRIANGLES);
		glColor3b(byte.max, 0, 0);
		glVertex3d(-0.5, -0.5, 0.0);
		glColor3f(0, 1.0f, 0);
		glVertex3d( 0.5, -0.5, 0.0);
		glColor3i(0, 0, int.max);
		glVertex3d( 0.0,  0.5, 0.0);
		glEnd();
		
		//画面を更新
		glfwSwapBuffers(window);

		glfwPollEvents();
	}

	//=====おわり=====
	glfwTerminate();
}

キャプチャ

こんなかんじになります。各頂点の色をglColorで設定してやります。設定しない場合は最後に指定した色が使われ、デフォルト値は白です。頂点間の色は各頂点の色を線形補間したものになる(詳細は下の※参照)。

(※ 各頂点の位置ベクトルをp1,p2,p3\vec{p_1}, \vec{p_2}, \vec{p_3}とすると、三角形上の任意の点p\vec{p}は、実数t1,t2,t3(0t1,t2,t31,t1+t2+t3=1)t_1, t_2, t_3(0 \leq t_1, t_2, t_3 \leq 1, t_1 + t_2 + t_3 = 1)を用いて、

$\vec{p} = t_1\vec{p_1} + t_2\vec{p_2} + t_3\vec{p_3}$

と表される。この$t_1, t_2, t_3$は「$\vec{p}$が$\vec{p_1}, \vec{p_2}, \vec{p_3}$にどれだけ近いか」を表すパラメータとみてよい。よって、各頂点の色のRGBを3次元ベクトルとみて、$\vec{c_1}, \vec{c_2}, \vec{c_3}$としたときの$\vec{p}$における色$\vec{c}$は、

$\vec{c} = t_1\vec{c_1} + t_2\vec{c_2} + t_3\vec{c_3}$

と表せる。こうして頂点間の色をいいかんじに表現している。)

この記事を書いた人
sobaya007

東工大工学部の異端児

この記事をシェア

このエントリーをはてなブックマークに追加

関連する記事

2017年11月17日
そばやのワク☆ワク流体シミュレーション~MPS編~
sobaya007
2015年12月4日
D言語でOpenGL†入門†2
sobaya007
2015年12月2日
VisualDでOpenGL
sobaya007

活動の紹介

カテゴリ

タグ