shadow[PV3D]
セルフシャドウ
ほんとは影をグルグルまわしたかったけど生成が重い。
/**
* Copyright kuma360 ( http://wonderfl.net/user/kuma360 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/uShh
*/
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.media.*;
import flash.net.*;
import flash.system.*;
import flash.utils.*;
import org.papervision3d.core.geom.renderables.*;
import org.papervision3d.core.math.*;
import org.papervision3d.materials.*;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.view.*;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")]
public class Main extends BasicView {
private var BD:BitmapData = new BitmapData ( 200 , 200 , false , 0 ) ;
private var TEX:BitmapData = new BitmapData ( 200 , 200 , false , 0 ) ;
private var P:Plane ;
public function Main() {
//地面
var M:BitmapMaterial = new BitmapMaterial ( TEX , true ) ;
P = new Plane ( M , 100 , 100 , MAX , MAX ) ;
scene.addChild ( P ) ;
P.rotationX = 90 ;
Create( ) ;
camera.x = 30 ;
camera.y = 70 ;
camera.z = - 40 ;
startRendering() ;
stage.addEventListener (
MouseEvent.CLICK ,
function ( ) :void {
Create ( ) ;
}
);
}
public function Create ( ) :void {
//ポリゴンに凹凸を作る
var TF:Triangle3D ;
var TV:Vertex3D ;
var NNN:Number = 20 ;
for each ( TV in P.geometry.vertices ) {
TV.z = 40 ;
}
for ( var II:int = 0 ; II < 10 ; ++ II ) {
TV = P.geometry.vertices [ Math.floor ( Math.random ( ) * MAX * MAX ) ] ;
TV.z = Math.random ( ) * 35 ;
}
for each ( TF in P.geometry.faces ) {
TF.createNormal () ;
}
for each ( TV in P.geometry.vertices ) {
TV.calculateNormal () ;
}
//テクスチャに凹凸の高さを書き込む
for ( var X:int = 0 ; X < BD.width ; ++ X ) {
for ( var Y:int = 0 ; Y < BD.height ; ++ Y ) {
var TX:int = ( X ) * MAX / BD.width ;
var TY:int = ( BD.height - Y ) * MAX / BD.height ;
TY *= 2 ;
if ( X % ( BD.width / MAX ) >= Y % ( BD.height / MAX ) ) {
TY += 1 ;
}
var I:int = TX * ( MAX * 2 ) + TY ;
TF = P.geometry.faces[ I ] as Triangle3D ;
if ( TF ) {
var N:Number3D = TF.faceNormal ;
var P0:Vertex3D = TF.v0 ;
var RX:Number = X * 100 / BD.width - 50 ;
var RY:Number = ( BD.height - Y ) * 100 / BD.height - 50 ;
var Z:Number = - ( N.x * ( RX - P0.x ) + N.y * ( RY - P0.y ) ) / N.z + P0.z ;
if ( 0 < Z ) {
BD.setPixel ( X , Y , 255 - Z ) ;
} else {
BD.setPixel ( X , Y , 0 ) ;
}
}
}
}
//影を作る
for ( X = 0 ; X < TEX.width ; ++ X ) {
for ( Y = 0 ; Y < TEX.height ; ++ Y ) {
TX = X * BD.width / TEX.width ;
TY = Y * BD.width / TEX.width ;
var D1:uint = BD.getPixel ( TX , TY ) ;
//ライト方向をチェック ( 簡易 )
var LCHK:Boolean = true ;
for ( var LX:int = TX ; LX < BD.width ; LX ++ ) {
var D2:uint = BD.getPixel ( LX , TY ) ;
if ( D1 + 1/3 * ( LX - TX ) < D2 ) {
LCHK = false ;
break ;
}
}
if ( LCHK ) {
TEX.setPixel32 ( X , Y , 0xFFFF6050 ) ;
} else {
TEX.setPixel32 ( X , Y , 0xFF403020 ) ;
}
}
}
//ごまかし & ソフトシャドウ
TEX.applyFilter ( TEX , TEX.rect , new Point , new BlurFilter ( 8, 8 , 2 ) ) ;
}
override protected function onRenderTick(event:Event = null):void
{
super.onRenderTick ( event ) ;
camera.x = Math.cos ( getTimer() * 0.001 ) * 100 ;
camera.z = Math.sin ( getTimer() * 0.001 ) * 100 ;
}
}
}
const MAX:int = 15 ;