テクスチャ生成実験2
Perlin noizeを変調してテクスチャを生成
クリックで別パターンを生成
/**
* Copyright Nao_u ( http://wonderfl.net/user/Nao_u )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ym6j
*/
//
// Perlin noizeを変調してテクスチャを生成
//
// クリックで別パターンを生成
//
//
package {
import flash.display.Sprite;
import flash.events.*;
[SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="30")]
public class FlashTest extends Sprite {
public function FlashTest() {
Main = this;
initialize();
stage.addEventListener(Event.ENTER_FRAME,update);
stage.addEventListener(MouseEvent.MOUSE_DOWN, function (event:MouseEvent):void{ Text.text = "生成中..."; Cnt=0 });
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.*
import flash.text.TextField;
import flash.geom.*;
import flash.utils.getTimer;
var Main:Sprite;
var SCREEN_W:Number = 465;
var SCREEN_H:Number = 465;
var Text:TextField
var View: Bitmap;
var BmpData: BitmapData;
var BITMAP_W:int = SCREEN_W/2;
var BITMAP_H:int = SCREEN_H/2;
var Cnt:int;
var Frequency:Number = 32;
var Base:Number = 0;
var Type:int = 0;
var bAbs:Boolean = true;
function initialize():void{
BmpData = new BitmapData(BITMAP_W, BITMAP_H, false, 0xffffff);
View = new Bitmap(BmpData);
View.scaleX = 2.0;
View.scaleY = 2.0;
Main.addChild(View);
Text = new TextField();
Text.text = "生成中...";
Text.autoSize = "left";
Main.addChild(Text);
}
function resetTexture():void{
BmpData.lock();
for( var x:int=0; x<BITMAP_W; x++ ){
for( var y:int=0; y<BITMAP_H; y++ ){
var col:int = 0xffffff;
BmpData.setPixel(x, y, col);
}
}
BmpData.unlock();
}
function createTexture(Type:int, frequency:Number, base:Number, bAbs:Boolean):void{
var func:Function;
switch( Type ){
case 0: func = Noise0; break;
case 1: func = Noise1; break;
case 2: func = Noise2; break;
case 3: func = Noise3; break;
}
var cont:Number = 64;
var mul:Number = 128 + cont;
BmpData.lock();
for( var x:int=0; x<BITMAP_W; x++ ){
for( var y:int=0; y<BITMAP_H; y++ ){
var col:int;
col = func( x, y, frequency, 0.4, 4, bAbs, base) * mul;
if( bAbs ) col = col + 32;
else col = col + 128;
col = col + (col<<8) + (col<<16);
BmpData.setPixel(x, y, col);
}
}
BmpData.unlock();
}
function update(e :Event):void{
Cnt++;
if( Cnt == 1 ){
resetTexture();
}
if( Cnt == 2 ){
var time:int = getTimer();
createTexture(Type%4,Frequency, Base, bAbs);
var endTime:int = getTimer() - time;
Text.text = "生成時間:" + endTime + "[ms]";
Type++;
Frequency = 16 + 64 * Math.abs(rnd( Type*13, Type*27 ));
Base = 16 + 240 * Math.abs(rnd( (Frequency+Type)*27, Type*13 ));
if( Type%5 && ((Type-3)%7) ) bAbs = true;
else bAbs = false;
}
}
// Noiseを生成(ランダムで変調)
function Noise0( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number ):Number{
var total:Number = 0;
var amplitude:Number = presistence;
var n:Number;
for( var i:int=0; i<octave; i++ ){
var sx:Number = x;
var sy:Number = y;
x += 48*makeNoise( sx, sy, frequency, amplitude, bAbs );
y += 48*makeNoise( sx, sy, frequency, amplitude, bAbs );
n = makeNoise( base+x, base+y, frequency, amplitude, bAbs );
if( bAbs ) n *= 1.9;
total += n;
amplitude *= presistence;
frequency *= 0.50;
}
return total;
}
// Noiseを生成(sin変調)
function Noise1( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number ):Number{
var total:Number = 0;
var amplitude:Number = presistence;
var n:Number;
for( var i:int=0; i<octave; i++ ){
var sx:Number = 0.5 + x / BITMAP_W * 3.14 *4;
var sy:Number = y / BITMAP_H * 3.14 *3;
sx = sx + Math.sin(sy) ;
n = makeNoise( base+x+5.5*Math.sin(sy), base+y+17.5*Math.sin(sx), frequency, amplitude, bAbs );
if( bAbs ) n *= 1.9;
total += n;
amplitude *= presistence;
frequency *= 0.5;
}
return total;
}
// PerlinNoiseを生成(通常)
function Noise2( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number ):Number{
var total:Number = 0;
var amplitude:Number = presistence;
for( var i:int=0; i<octave; i++ ){
total += makeNoise( base+x, base+y, frequency, amplitude, bAbs );
amplitude *= presistence;
frequency *= 0.5;
}
return total;
}
// Noiseを生成(回転)
function Noise3( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number ):Number{
var total:Number = 0;
var amplitude:Number = presistence;
frequency *= 2;
presistence *= 2;
base += 1000;
for( var i:int=0; i<octave; i++ ){
var sx:Number = x;
var sy:Number = y;
x = sx * 1.5 + sy * -1.1;
y = sx * 1.1 + sy * 1.5;
total += 0.85*(makeNoise( 4000+x, 4000+y, frequency, amplitude, bAbs ));
amplitude *= presistence;
frequency *= 1.00;
}
return (total);
}
// 周波数に対応したノイズを生成
function makeNoise( x:Number, y:Number, frequency:Number, amplitude:Number, bAbs:Boolean ):Number{
if( bAbs ) return Math.abs(rndSmooth(x/frequency,y/frequency) * amplitude);
else return (rndSmooth(x/frequency,y/frequency) * amplitude);
}
// 入力値( x, y ) に対応した、滑らかな擬似乱数を生成 (補間の結果-1.0を下回ったり、1.0を超えることがある)
function rndSmooth( x:Number, y:Number ):Number{
var tx:Number = (x - Math.floor(x));
var txInv:Number = 1.0 - tx;
var ty:Number = (y - Math.floor(y));
var tyInv:Number = 1.0 - ty;
var ix:int = x;
var iy:int = y;
// cos補間
var x0:Number = interpolate( rnd(ix, iy), rnd(ix+1, iy), tx );
var x1:Number = interpolate( rnd(ix, iy+1), rnd(ix+1, iy+1), tx );
return interpolate( x0, x1, ty );
}
// a から b をcosでなめらかに補間
function interpolate( a:Number, b:Number, t:Number ):Number{
var ft:Number = t * Math.PI;
var f:Number = (1.0 - Math.cos( ft )) * 0.5;
return a * (1.0 - f) + b * f;
}
// 入力値( x, y ) に対応した、-1.0 ~ 1.0 の擬似乱数を生成
function rnd( x:int, y:int ):Number{
x += y * 465 + 789221; // 465=2次元での横幅に対応
x = (x>>10) ^ x;
var ret:int = (( (x * (x * x * 15731 + 789221) + 1376312589) ) / 1000000);
return ((((ret & 0xff) + ((ret & 0xff00)>>8)+ ((ret & 0xff0000)>>16))&0x1ff) / 256) - 1.0;
}