- 2008年07月23日 (水)

- Tweet
Papervision3D 2.0(GreateWhite)で反射を比較する
前回の記事に続いてPV3D 2.0の勉強2回目。今日は様々な反射(シェーディング)を比較して試してみます(比較キャプチャを載せてます)。
サンプルは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);
}
}
}




















2009年05月16日(土) 09:38
[…] それらのマテリアルの種類については Papervision3D 2.0(GreateWhite)で反射を比較する が非常に詳しい。ありがとうございます。 […]
2010年09月03日(金) 09:41
グーローシェーディングは頂点単位でライティングを、
フォンシェーディングはピクセル単位でライティングを行うことですよ。
フォンシェーディングの方がポリゴンのつなぎ目が目立たないです。
2011年02月21日(月) 00:18
[…] 参考: http://clockmaker.jp/blog/2008/07/papervision3d_shading/ http://blog.yaimo.net/2009/06/06/505/ […]