Papervision3D 2.0(GreateWhite)で反射を比較する

前回の記事に続いてPV3D 2.0の勉強2回目。今日は様々な反射(シェーディング)を比較して試してみます(比較キャプチャを載せてます)。

Papervision3D 2.0 GreateWhite ライト機能

サンプルは10×10の二次元配列を3Dグラフ状に表示したものです。

ライト機能は「GouraudMaterial」を使いました。この「GouraudMaterial」はグーローシェーディングの照明機能です。他にも 「FlatShadeMaterial」「CellMaterial」「PhongMaterial」などラシェーディングの種類が選べます。ものによってレンダリング結果と処理負荷が変わってくるので、どれを選ぶかは要検討といったところでしょうか。

shadematerialsの比較

以下はorg.papervision3d.materials.shadematerialsパッケージにある複数のマテリアルに切り替えてレンダリングしたものです。

FlatShadeMaterial(フラットシェーディング)
べったりと面に照明を単一に当てるマテリアルです。簡易ながらもっとも高速でした。
3次元コンピュータグラフィックス – Wikipediaによると「単純なアルゴリズムなので計算速度が高速であるが、ポリゴンの継ぎ目ごとに不連続的に色が変化するため、滑らかには見えない。」とのことです。

EnvMapMaterial
BitmapDataを照明に割り合えてることができます。

CellMaterial
照明の当たり具合を段々畑状に設定するマテリアル。段々畑の回数は設定できます。

GouraudMaterial(グーローシェーディング)
グラデーション風に適用されるマテリアル。
これは3次元コンピュータグラフィックス – Wikipediaによると「頂点間は一次補間してピクセルの色を算出する。ピクセル間の継ぎ目は目立たなくなる。」とのことです。なるほど。

PhongMaterial(フォンシェーディング)
GouraudMaterialと似てますが、グラデーション風にかかってます。
これは3次元コンピュータグラフィックス – Wikipediaによると「グーローシェーディングにおける光沢の不自然さを改善する。」とのこと。確かに周囲のオブジェクトに対して照明が計算されてる気がしますね。

シェーディングの種類ははじめて知りました。う〜ん、3Dは奥が深いですね。

検証用のソースは以下に掲載します。

package
{
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;

	import org.papervision3d.cameras.*;
	import org.papervision3d.render.BasicRenderEngine;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.Viewport3D;
	import org.papervision3d.materials.*;
	import org.papervision3d.objects.*;
	import org.papervision3d.objects.primitives.*
	import org.papervision3d.materials.utils.*;
	import org.papervision3d.materials.shadematerials.*;

	import org.papervision3d.lights.*;

	[SWF(width = "450", height = "300", frameRate = "60", backgroundColor = "#000000")]

	public class Main extends MovieClip
	{
		// const vars
		static private const GRAPH_CUBE_LENGTH :int = 100;
		static private const GRAPH_CUBE_MARGIN :int = 25;
		static private const CAMERA_Z_POINT    :int = -1500;
		static private const CAMERA_Z_DEG      :int = 750;

		// plot data

		static private const PLOT_2x2_DATA :Array =
		[
			[0, 20, 40, 60, 80, 100, 120, 140, 160, 180],
			[10, 50, 100, 200, 300, 400, 300, 200, 100, 50],
			[20, 100, 200, 300, 400, 500, 400, 300, 200, 100],
			[40, 50, 100, 200, 400, 600, 400, 200, 100, 50],
			[10, 120, 200, 860, 880, 800, 700, 200, 100, 10],
			[80, 220, 450, 500, 900, 1000,800, 600, 400, 200],
			[30, 20, 40, 350, 600, 800, 600, 400, 200, 100],
			[20, 100, 200, 300, 400, 500, 400, 300, 200, 100],
			[10, 50, 100, 200, 300, 400, 300, 200, 100, 50],
			[30, 120, 140, 160, 180, 200, 220, 240, 260, 280],
			[10, 20, 40, 60, 80, 0, 20, 40, 60, 80],
		];

		// 3d vars
		private var camera   :Camera3D;
		private var viewport :Viewport3D;
		private var render   :BasicRenderEngine
		private var scene    :Scene3D;
		private var light    :PointLight3D;
		private var wrap     :DisplayObject3D;

		// for test EnvMapMaterial
		//[Embed(source = 'Dock.jpg')] private var MyBitmap:Class;

		/**
		 * Constructor
		 */
		public function Main()
		{
			// init swf
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align     = StageAlign.TOP_LEFT;
			stage.quality   = StageQuality.HIGH;

			// init 3d
			scene    = new Scene3D()
			camera   = new Camera3D();
			render   = new BasicRenderEngine();
			viewport = new Viewport3D(0, 0, true, false);
			addChild(viewport);

			//camera
			camera.focus     = 500;
			camera.zoom      = 1;
			camera.x         = 0;
			camera.y         = 750;
			camera.z         = CAMERA_Z_POINT;
			camera.rotationX = 20;

			// light
			light = new PointLight3D(false);
			light.z = 0;
			light.x = 1000;
			light.y = 1000;

			// wrap
			wrap = new DisplayObject3D();
			scene.addChild(wrap);

			// cell length
			var cellLength:Number = GRAPH_CUBE_LENGTH + GRAPH_CUBE_MARGIN;

			// 2x2 loop
			for (var i:int = 0; i < PLOT_2x2_DATA.length; i++)
			{
				var color:uint = Math.random() * 0x335533 + 0x0000AA;

				for (var j:int = 0; j < PLOT_2x2_DATA[i].length; j++ )
				{
					var cube:Cube = new Cube(
						//new MaterialsList( { all:new CellMaterial(light, 0xFFFFFF, 0x666666, 10) } ), // heavey...
						//new MaterialsList( { all:new EnvMapMaterial(light, new MyBitmap().bitmapData ) } ), // most light...
						//new MaterialsList( { all:new FlatShadeMaterial(light, 0xFFFFFF, 0x666666) } ), // most light...
						//new MaterialsList( { all:new GouraudMaterial(light, 0xFFFFFF, 0x666666) } ), // heavey...
						//new MaterialsList( { all:new PhongMaterial(light, 0xFFFFFF, 0x666666, 10) } ), // heavey...

						new MaterialsList( { all:new GouraudMaterial(light, 0xFFFFFF, color) } ), // heavey...
						GRAPH_CUBE_LENGTH,
						GRAPH_CUBE_LENGTH,
						PLOT_2x2_DATA[i][j],
						1,
						1,
						1);
					cube.x = i * cellLength - PLOT_2x2_DATA.length * cellLength / 2;
					cube.y = PLOT_2x2_DATA[i][j] / 2;
					cube.z = j * cellLength - PLOT_2x2_DATA[i].length * cellLength / 2;
					wrap.addChild(cube);
				}
			}

			this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}

		/**
		* Render
		* @param	event
		*/
		private function enterFrameHandler(event:Event):void
		{
			wrap.yaw(-2);
			camera.z = Math.sin(getTimer() / 1000) * CAMERA_Z_DEG + CAMERA_Z_POINT;
			render.renderScene(scene, camera, viewport);
		}
	}
}

このブログ内の関連記事

Papervision3D 2.0(GreateWhite)の習作

投稿者 : 池田 泰延

BookMark

ブックマークはこちらからどうぞ。

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

Comment/Trackback 3件