Skip to content

3D描画

Reputeless edited this page Mar 14, 2017 · 5 revisions

ボックスを描く

# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		Box(4).draw();
	}
}

3D 空間を自由に移動する

Graphics3D::FreeCamera() を毎フレーム呼ぶと、W, A, S, D, E, X, アローキーを使って 3D 空間を移動できるようになります。

# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		Graphics3D::FreeCamera();

		Box(4).draw();
	}
}

いろいろな 3D 形状を描く

# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		Graphics3D::FreeCamera();

		Plane(Vec3(-5, 0, -10), 4).draw();

		Disc(Vec3(5, 0, -10), 2).draw();

		Sphere(Vec3(-10, 2, 0), 2).draw();

		Box(Vec3(0, 2, 0), 4).draw();

		Cone(Vec3(10, 0, 0), 2, 4).draw();

		Cylinder(Vec3(0, 2, 10), 2, 4).draw();
	}
}

3D 形状に色を付ける

ColorHSV に加え、RGBA の各成分を 0.0~1.0 で表す ColorF 型が使えます。

# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		Graphics3D::FreeCamera();

		Plane(Vec3(-5, 0, -10), 4).draw(ColorF(1.0, 0.5, 0.0));

		Disc(Vec3(5, 0, -10), 2).draw(ColorF(0.0, 0.5, 1.0));

		Sphere(Vec3(-10, 2, 0), 2).draw(Palette::Orange);

		Box(Vec3(0, 2, 0), 4).draw(Color(127, 127, 127));

		Cone(Vec3(10, 0, 0), 2, 4).draw(HSV(180, 0.9, 1.0));

		Cylinder(Vec3(0, 2, 10), 2, 4).draw(ColorF(0.2, 0.8, 1.0));
	}
}

3D 形状にテクスチャを貼る

3D 描画に用いる Texture を作成する際は、TextureDesc::For3D を指定します。
この指定により、エンジン内部で sRGB フォーマットの設定とミップマップが作成され、3D 描画に適した Texture が作成されます。

# include <Siv3D.hpp>

void Main()
{
	const Texture textureGrass(L"Example/Grass.jpg", TextureDesc::For3D);
	const Texture textureEarth(L"Example/Earth.jpg", TextureDesc::For3D);
	const Texture textureBrick(L"Example/Brick.jpg", TextureDesc::For3D);

	while (System::Update())
	{
		Graphics3D::FreeCamera();

		Plane(Vec3(0, 0, 0), 20).draw(textureGrass);

		Sphere(Vec3(-2, 2, 0), 2).draw(textureEarth);

		Box(Vec3(2, 1, 0), 2).draw(textureBrick);
	}
}

座標変換をする

asMesh() を使うと 3D 形状を Mesh として扱えます。
Meshtranslated()rotated(), scaled() で移動や回転、拡大縮小などの座標変換が柔軟にできます。

# include <Siv3D.hpp>

void Main()
{
	const Texture textureEarth(L"Example/Earth.jpg", TextureDesc::For3D);
	const Texture textureBrick(L"Example/Brick.jpg", TextureDesc::For3D);

	Stopwatch stopwatch(true);

	while (System::Update())
	{
		const double t = stopwatch.ms() / 1000.0;

		Graphics3D::FreeCamera();

		Box(5).asMesh()
			.rotated(Quaternion::Roll(t))
			.draw(textureBrick);

		Sphere(5).asMesh()
			.rotated(Quaternion::Yaw(-t))
			.translated(15, 0, 0)
			.rotated(Quaternion::Yaw(t * -0.2))
			.draw(textureEarth);	
	}
}

3D 形状を作る

MeshData を使うと、独自に用意した頂点とインデックスデータから Mesh を作成できます。
また、MeshData にはいくつかの基本形状を作る関数が用意されています。
以下のプログラムは、その関数を使用して基本形状を作るサンプルです。

# include <Siv3D.hpp>

void Main()
{
	Graphics::SetBackground(Color(80, 160, 230));

	const Texture textureEarth(L"Example/Earth.jpg", TextureDesc::For3D);

	const Mesh meshSphere5(MeshData::Sphere(2.0, 5));

	const Mesh meshFloor(MeshData::Plane(20, { 5, 5 }));

	const Mesh meshBipyramid(MeshData::Bipyramid(1.0, 2.0));

	while (System::Update())
	{
		Graphics3D::FreeCamera();

		meshFloor.draw(textureEarth);

		meshSphere5.translated(-3, 2, 0).draw();

		meshBipyramid.translated(3, 3, 0).draw(Palette::Yellowgreen);
	}
}

3D モデルデータを読み込む

現在のバージョンで対応している 3D モデルファイルの形式は Wavefront OBJ (.obj) のみです。
OBJ 以外の形式のローダーを独自に実装する場合は、MeshData を使って Mesh の集合を作成してください。

# include <Siv3D.hpp>

void Main()
{
	Graphics::SetBackground(Color(80, 160, 230));

	const Texture textureGround(L"Example/ground.jpg", TextureDesc::For3D);
	const Mesh meshGround(MeshData::Plane(30, 30, { 6, 6 }));

	const Model model(L"Example/Well/Well.wavefrontobj");

	while (System::Update())
	{
		Graphics3D::FreeCamera();

		meshGround.draw(textureGround);

		model.draw();
	}
}

環境光を設定する

デフォルトの環境光は ColorF(0.1, 0.1, 0.1) に設定されています。

# include <Siv3D.hpp>

void Main()
{
	GUI gui(GUIStyle::Default);
	gui.add(L"ambient", GUIToggleSwitch::Create(L"環境光なし", L"環境光あり", false));

	Graphics::SetBackground(Color(80, 160, 230));

	const Texture textureGround(L"Example/ground.jpg", TextureDesc::For3D);
	const Mesh meshGround(MeshData::Plane(30, 30, { 6, 6 }));

	const Model model(L"Example/Well/Well.wavefrontobj");

	while (System::Update())
	{
		Graphics3D::FreeCamera();

		meshGround.draw(textureGround);

		model.draw();

		if (gui.toggleSwitch(L"ambient").isRight)
		{
			Graphics3D::SetAmbientLight(ColorF(0.4, 0.2, 0.1));
		}
		else
		{
			Graphics3D::SetAmbientLight(ColorF(0.0, 0.0, 0.0));
		}
	}
}

ライティングを設定する

光源の種類は Light::None() (なし), Light::Directional() (平行光源), Light::Point() (点光源) の 3 種類です。
デフォルトでは インデックス 0 に Light::Directional({ 0.1, 0.5, -0.9 }, { 1.0, 1.0, 1.0 }) が設定されています。
光源の上限数は Graphics3D::MaxLight で定義されている 128 個です。後述する Forward Rendering の光源の上限数は Graphics3D::MaxLightForward で定義されている 4 個です。

# include <Siv3D.hpp>

void Main()
{
	GUI gui(GUIStyle::Default);
	gui.add(L"light", GUICheckBox::Create({ L"ライト 0", L"ライト 1", L"ライト 2" }, { 0 }));

	while (System::Update())
	{
		Graphics3D::FreeCamera();

		if (gui.checkBox(L"light").checked(0))
		{
			Graphics3D::SetLight(0, Light::Directional(Vec3(0.1, 0.5, -0.9), ColorF(0.5, 0.5, 0.5)));
		}
		else
		{
			Graphics3D::SetLight(0, Light::None());
		}

		if (gui.checkBox(L"light").checked(1))
		{
			Graphics3D::SetLight(1, Light::Point(Vec3(-4, 4, -4), 10, ColorF(1.0, 0.0, 0.0)));
		}
		else
		{
			Graphics3D::SetLight(1, Light::None());
		}

		if (gui.checkBox(L"light").checked(2))
		{
			Graphics3D::SetLight(2, Light::Point(Vec3(4, 4, -4), 10, ColorF(0.0, 1.0, 0.0)));
		}
		else
		{
			Graphics3D::SetLight(2, Light::None());
		}

		Plane(Vec3(0, 0, 0), 20).draw();

		Sphere(Vec3(-2, 2, 0), 2).draw();

		Box(Vec3(2, 1, 0), 2).draw();
	}
}

カメラの状態を変更する

# include <Siv3D.hpp>

void Main()
{
	Camera camera;

	// カメラの注視点
	camera.lookat = Vec3(0, 2, 0);

	// カメラの位置
	camera.pos = Vec3(0, 4, -8);

	while (System::Update())
	{
		if (Input::KeyLeft.pressed)
		{
			camera.pos.x -= 0.1;
		}

		if (Input::KeyRight.pressed)
		{
			camera.pos.x += 0.1;
		}

		Plane(Vec3(0, 0, 0), 20).draw();

		Sphere(Vec3(-2, 2, 0), 2).draw();

		Box(Vec3(2, 1, 0), 2).draw();

		Graphics3D::SetCamera(camera);

		ClearPrint();
		Println(1_dp, L"lookat: ", camera.lookat);
		Println(1_dp, L"pos: ", camera.pos);
	}
}

フォグを設定する

フォグは Fog::None() (なし), Fog::Linear() (線形フォグ), Fog::Exponential() (指数フォグ), Fog::SquaredExponential() (平方指数フォグ), Fog::Height() (高さフォグ) の 5 種類が用意されています。

# include <Siv3D.hpp>

void Main()
{
	Graphics::SetBackground(ColorF(0.6, 0.8, 1.0));

	GUI gui(GUIStyle::Default);
	gui.setTitle(L"Fog density");
	gui.add(L"density", GUISlider::Create(0.0, 0.02, 0.005, 100));

	const Texture textureGrass(L"Example/Grass.jpg", TextureDesc::For3D);
	const Mesh meshGround(MeshData::Plane(250, { 10, 10 }));

	while (System::Update())
	{
		Graphics3D::FreeCamera();

		const double density = gui.slider(L"density").value;
		Graphics3D::SetFog(Fog::SquaredExponential(ColorF(0.6, 0.8, 1.0), density));

		meshGround.draw(textureGrass);

		for (int32 x = -5; x <= 5; ++x)
		{
			for (int32 z = -5; z <= 5; ++z)
			{
				Box(Vec3(x * 20, 2.5, z * 20), 5).draw();
			}
		}
	}
}

透過する 3D 形状を描く

通常の draw() は Deferred Rendering のため透過は扱えません。
3D 描画で透過色を使用したい場合は drawForward() を用いて Forward Rendering で描画します。
ライトやフォグなどは、Deferred, Forward で個別に設定する必要があります。

# include <Siv3D.hpp>

void Main()
{
	Graphics::SetBackground(Color(80, 160, 230));

	const Texture textureGrass(L"Example/Grass.jpg", TextureDesc::For3D);

	// Forward Rendering 用の設定
	Graphics3D::SetAmbientLightForward(ColorF(0.4, 0.4, 0.4));

	while (System::Update())
	{
		Graphics3D::FreeCamera();

		Plane(40).draw(textureGrass);

		for (int32 i = 0; i < 12; ++i)
		{
			const Vec2 v = Circular(8, Radians(i * 30));
			
			Cylinder(Vec3(v.x, 2, v.y), 1, 4).drawForward(HSV(i*30).toColorF(0.5));
		}
	}
}

← 前の章へ戻る | - 目次 - | 次の章へ進む →

Siv3D について

  1. Siv3D の基本
  2. 図形を描く
  3. テクスチャを描く
  4. テキストを描く
  5. 文字列と数値の変換
  6. キーボード入力
  7. マウス入力
  8. サウンドの再生
  9. MIDI の再生
  10. ウィンドウと背景
  11. 図形のあたり判定
  12. 乱数
  13. ダイアログ
  14. ドラッグ & ドロップ
  15. アプリの状態
  16. テキストファイル
  17. INI, CSV, JSON
  18. バイナリファイル
  19. GUI
  20. アセット管理
  21. 画像編集
  22. Web カメラ
  23. マイク入力
  24. 経過時間の測定
  25. HSV カラー
  26. ファイルダウンロード
  27. 3D 描画
  28. 2D のレンダーステート
  29. 3D のレンダーステート
  30. パーティクル
  31. スクリーンショット
  32. アプリケーションの公開
  33. さらに学ぶには

表現テクニック集

入出力デバイス

開発のヒント

Clone this wiki locally