PaperVision3Dでトゥーンレンダリング

記事を見つけてから前々からやってみたかったPaperVision3Dでトゥーンレンダリングをやってみました。
こんな感じ
http://moeten.info/flex/20081205_papervision3Dtoonshader/bin-release/main.html

簡単な説明

アイドルマスターみたいにセル画塗り風にレンダリングするには、CellMaterialやCellShaderっというクラスを使用します。
シェードってことなのでライトが必要なので作っておきます。

//ポイントライトの作成
light = new PointLight3D(true);
scene.addChild(light);
//マテリアル作成
//var cellMaterial:CellMaterial = new CellMaterial( light , 0xFFFFFF, 0x000000,5);
var cellShader:CellShader = new CellShader( light , 0xffffff,0x333333,5);
var movieMat:MovieMaterial = new MovieMaterial(new Tex1() );
var cellShaderMat:ShadedMaterial = new ShadedMaterial( movieMat , cellShader);
//球作成
sphere = new Sphere( cellShaderMat , 100 , 16 ,16);
scene.addChild(sphere);

メタセコイアなどのオブジェクトでもできるといいなぁ。
参考リンク

ソースはこちら

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute" creationComplete="init3D()" width="640" height="480"
    backgroundGradientColors="[0x999999,0x000000]"
     viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
/* **********************************
            PV3D
********************************** */
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.materials.shaders.ShadedMaterial;
import org.papervision3d.materials.shadematerials.CellMaterial;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.shaders.CellShader;
private var scene    : Scene3D;
private var viewport : Viewport3D;
private var renderer : BasicRenderEngine;
private var camera   : Camera3D;
private var cameraTarget : DisplayObject3D;
//初期化
private function init3D():void{
    setupScene();
    setupCamera();
    setupBox();
    setupListeners();
}
//シーンの作成
private function setupScene():void{
    viewport = new Viewport3D( myUI.width , myUI.height , true , false , true , true );
    myUI.addChildAt(viewport , 0);
    renderer = new BasicRenderEngine();
    scene    = new Scene3D();
}
//カメラ設定
private function setupCamera():void{
    cameraTarget = new DisplayObject3D();
    camera = new Camera3D();
    camera.z = - 300;
    camera.y = 10;
}
//イベントリスナー設定
private function setupListeners():void{
    this.addEventListener(Event.ENTER_FRAME , onRenderTick );
}
//メイン部分
[Embed (source="05.gif")]private var Tex1:Class;
private var sphere:Sphere;
private var light:PointLight3D;
private function setupBox():void{
    //ポイントライトの作成
    light = new PointLight3D(true);
    scene.addChild(light);
    //マテリアル作成
    //var cellMaterial:CellMaterial = new CellMaterial( light , 0xFFFFFF, 0x000000,5);
    var cellShader:CellShader = new CellShader( light , 0xffffff,0x333333,5);
    var movieMat:MovieMaterial = new MovieMaterial(new Tex1() );
    var cellShaderMat:ShadedMaterial = new ShadedMaterial( movieMat , cellShader);
    //球作成
    sphere = new Sphere( cellShaderMat , 100 , 16 ,16);
    scene.addChild(sphere);
}
//レンダリング+マウス操作
private var theta:Number = 0;
protected function onRenderTick(e:Event):void {
    var reach:Number = 0.01;
    var ease:Number = 0.1;
    var cameraDistance:Number = 100;
    camera.x += (Math.sin(mouseX * reach) *   cameraDistance - camera.x) * ease;
    camera.y += (Math.sin(mouseY * reach) *   cameraDistance - camera.y) * ease;
    sphere.rotationY -=1;
    theta+=0.03;
    light.x = Math.sin(theta)*200;
    light.z = Math.cos(theta)*200;
    myLog.text = "x=>" + light.x + "\nz=>" + light.z ;
    renderer.renderScene(scene , camera , viewport );
}
//リサイズイベント
private function onResize(e : Event) : void {
}
]]>
</mx:Script>
<mx:UIComponent id="myUI" width="100%" height="100%" />
<mx:TextArea id="myLog" width="204" height="55" x="10" y="10"/>
</mx:Application>