2009年10月12日月曜日

[Pv3D]Phong shadingとBump mapping[AS3.0]


久しぶりの更新です。
自転車で東京へ行くっていう馬鹿なことしてたので時間がありませんでした。

さて本題。
Papervision3DのPhongShaderを使ってバンプマッピングをしてみました。
バンプマッピングってのは白黒の画像で表面の凹凸を表現する方法のことらしいです。
こんな感じ。結構CPUに負荷かかるので気をつけてください。

クリックした場所のバンプマップを書き換えてます。
某アニメの最終話みたいに月に落書きします。
note.x | [PV3D2.0] BumpMapの動的書き換え
上の記事を参考に書きました。
月の画像はこちらのを使わせてもらいました。

あまりいい書き方ではないと思いますが、以下ソースコードです。
変数名とか関数名とかかなり適当。
package {
 import flash.display.Bitmap;
 import flash.events.Event;
 import flash.geom.Point;
 import flash.geom.Rectangle;

 import org.papervision3d.core.utils.InteractiveSceneManager;
 import org.papervision3d.core.utils.Mouse3D;
 import org.papervision3d.core.utils.virtualmouse.VirtualMouse;
 import org.papervision3d.lights.PointLight3D;
 import org.papervision3d.materials.BitmapMaterial;
 import org.papervision3d.materials.shaders.PhongShader;
 import org.papervision3d.materials.shaders.ShadedMaterial;
 import org.papervision3d.objects.primitives.Plane;
 import org.papervision3d.objects.primitives.Sphere;
 import org.papervision3d.view.BasicView;

 [SWF(backgroundColor="#ffffff")]
 public class sample_bump extends BasicView {
  // ヴァーチャルマウス
  private var vMouse:VirtualMouse;
  // 球(月)
  private var sphere:Sphere;
  // 月のバンプマップ埋め込み
  [Embed(source="moonbump1k.jpg")] private var bumpImage:Class;
  private var bumpMap:Bitmap = new bumpImage() as Bitmap;
  // シェーダー
  private var shader:PhongShader;

  /* constructor */
  public function sample_bump() {
   super(640, 480, true, true,"Target");

   // カメラ設定
   camera.x = 0;
   camera.y = 0;
   camera.z = 400;
   camera.focus = 1000;
   camera.zoom = 1;

   vMouse = viewport.interactiveSceneManager.virtualMouse;
   Mouse3D.enabled = true;

   /* 背景画像は画像を貼り付けたPlane(平面)を球(月)の奥に設置している */
   // 背景画像埋め込み
   [Embed(source="000191_m.jpg")] var wallpaper:Class;
   var wp:Bitmap = new wallpaper() as Bitmap;
   var star:BitmapMaterial = new BitmapMaterial(wp.bitmapData);
   star.doubleSided = true;
   star.smooth = true;
   var wall:Plane = new Plane(star, 1024, 681);
   wall.z = -200;
   scene.addChild(wall);

   // 月の画像埋め込み
   [Embed(source="moonmap1k.jpg")] var texture:Class;
   var tex:Bitmap = new texture() as Bitmap;
   // ライト設定
   var light:PointLight3D = new PointLight3D();
   light.x = 0;
   light.y = 200;
   light.z = 500;
   scene.addChild(light);

   var bmpMat:BitmapMaterial = new BitmapMaterial(tex.bitmapData);
   shader = new PhongShader(light, 0xFFFFFF, 0x666666, 50, bumpMap.bitmapData, tex.bitmapData);
   var material:ShadedMaterial = new ShadedMaterial(bmpMat, shader);
   material.smooth = true;
   material.interactive = true;

   sphere = new Sphere(material, 100, 16, 12);
   scene.addChild(sphere);

   startRendering();
  }

  // バンプマップ埋め込み
  [Embed(source="bump.png")] private var craterImage:Class;
  private var crater:Bitmap = new craterImage() as Bitmap;
  private function meteor():void {
   // バンプマップ合成
   bumpMap.bitmapData.merge(crater.bitmapData, new Rectangle(0, 0, crater.width, crater.height), new Point(vMouse.x*1000 - crater.width/2, vMouse.y*500 - crater.height/2), 128, 128, 128, 128);

   // バンプマップ更新
   shader.bumpmap = bumpMap.bitmapData;
  }

  override protected function onRenderTick(event:Event=null):void {
   // 回転
   sphere.yaw(0.25);
   if(InteractiveSceneManager.MOUSE_IS_DOWN) {
    meteor();
   }

   super.onRenderTick(event);
  }
 }
}

0 件のコメント:

コメントを投稿