#region OpenTK

OpenTKがGitHubで更新されるようになりました。NuGetから手に入れることができるようになりました。
現在は.NET Coreに対応する機運があるようです。

フォグ(霧)

フォグの効果-霧の表現だけではない

今回は霧のエフェクトを扱います。下の写真をご覧ください。

FoggyMountain
遠い山は霧の影響を強く受けるので色が白っぽい

ご覧の通り、霧で空の色に近づいている効果で山の距離感がよく出ていると思います。

フォグは3Dゲームの中に自然の距離感を与えてくれます。ただ、距離に応じて濃くなるため、煙などの表現には向かないでしょう。

フォグの数式

現実世界の霧は、遠くにあるものを白っぽくみせる効果があります。OpenGLでは、距離によるフォグの効果の変化を表す数式がいくつか定義されており、その中から一つ選ぶことになります。

Linear
f=dend-zdend-dstart
Exp
f=-density×z
Exp2
f=-density×z2

この数式のfは"percent of original color"で、0.0~1.0の値を取るようにclampされます。fが0.0に近いほど色が霞んでいきます。

遠いものを描画するときに重宝

Fog
赤い球が霞んでいる

ソースコードは、フォグのパラメータの指定以外に見どころはありません。

		//ウィンドウの起動時に実行される。
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			GL.ClearColor(Color4.Gray);
			GL.Enable(EnableCap.DepthTest);

			//裏面削除、反時計回りが表でカリング
			GL.Enable(EnableCap.CullFace);
			GL.CullFace(CullFaceMode.Back);
			GL.FrontFace(FrontFaceDirection.Ccw);

			//ライティングON Light0を有効化
			GL.Enable(EnableCap.Lighting);
			GL.Enable(EnableCap.Light0);

			//法線の正規化
			GL.Enable(EnableCap.Normalize);

			//色を材質に変換
			GL.Enable(EnableCap.ColorMaterial);
			GL.ColorMaterial(MaterialFace.Front, ColorMaterialParameter.Diffuse);

			//フォグの設定
			GL.Enable(EnableCap.Fog);
			GL.Fog(FogParameter.FogColor, fogColor);
			GL.Fog(FogParameter.FogMode, (int)FogMode.Linear);
			GL.Hint(HintTarget.FogHint, HintMode.Nicest);
			GL.Fog(FogParameter.FogStart, 3.0f);
			GL.Fog(FogParameter.FogEnd, 30.0f);

			torus.CreateBuffers();
			sphere.CreateBuffers();
			plate.CreateBuffers();
		}

まずは起動時に、フォグを許可(182行目)します。また、フォグの色を指定(183行目)しますが、これは背景の色と同じにするのが無難でしょう。

さらに、フォグの計算の精度を指定することができます。今回は最高品質としました。(185行目)

他のパラメータの指定は次のコードと共に載せます。

			//ZキーでFogMode.Linear
			if (Keyboard[Key.Z])
			{
				this.Title = "1-10:Fog(FogMode.Linear)";

				GL.Fog(FogParameter.FogMode, (int)FogMode.Linear);
				GL.Fog(FogParameter.FogStart, 3.0f);
				GL.Fog(FogParameter.FogEnd, 30.0f);
			}

			//XキーでFogMode.Exp
			if (Keyboard[Key.X])
			{
				this.Title = "1-10:Fog(FogMode.Exp)";

				GL.Fog(FogParameter.FogMode, (int)FogMode.Exp);
				GL.Fog(FogParameter.FogDensity, 0.1f);
			}

			//CキーでFogMode.Exp2
			if (Keyboard[Key.C])
			{
				this.Title = "1-10:Fog(FogMode.Exp2)";

				GL.Fog(FogParameter.FogMode, (int)FogMode.Exp2);
				GL.Fog(FogParameter.FogDensity, 0.1f);
			}

Linearの計算式で霧を描画する場合、モードの指定と、どの距離から霧がかかり始めるか(フォグの始まり)、どの距離になると霧で物体が見えなくなるか(フォグの終わり)というパラメータの指定が必要になります。そのため、234行目でモードの指定、235行目でフォグの始まる距離の指定、236行目でフォグの終わる距離の指定をしています。

ExpやExp2の計算式で霧を描画する場合、モードの指定と、フォグの濃度のパラメータの指定が必要になります。そのため、244行目や253行目でモードの指定、245行目や254行目で濃度の指定をしています。

それぞれの計算式によるフォグの効果は下のようになります。

Fog1Fog2Fog3

記事

外部リンク

Thanks