forked from: Pixel Bender Tutorial - modularGradient
PixelBenderで再現
/**
* Copyright zahir ( http://wonderfl.net/user/zahir )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/s0Sr
*/
// forked from hika's Pixel Bender Tutorial - modularGradient
// PixelBenderで再現
package {
import flash.display.*;
import flash.events.*;
import flash.ui.*;
[SWF(backgroundColor="#ffffff", frameRate="60", width="465", height="465")]
public class Main extends Sprite{
public function Main() {
var g:Graphics = this.graphics;
var shader:CmodularGradientShader = new CmodularGradientShader();
shader.size = 48;
g.beginShaderFill( shader );
g.drawRect(0,0, 465, 465);
g.endFill();
//addEventListener( Event.ADDED_TO_STAGE, ADDED_TO_STAGE );
}
public function ADDED_TO_STAGE( $e:Event ): void {
removeEventListener( Event.ADDED_TO_STAGE, ADDED_TO_STAGE );
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var shader:CabstractShader = new CmodularGradient( new BitmapData( 300, 300, true, 0 ) );
addChild( new Bitmap( shader.run( {size:50} ) ) );
}
}
}
import flash.display.BitmapData;
import flash.display.Shader;
import mx.utils.Base64Decoder;
class CmodularGradientShader extends Shader
{
public function CmodularGradientShader()
{
var dec:Base64Decoder = new Base64Decoder();
dec.decode( "pQEAAACkEABDbW9kdWxhckdyYWRpZW50oAxuYW1lc3BhY2UAemFoaXIxOTI5AKAMdmVuZG9yAHphaGlyAKAIdmVyc2lvbgABAKAMZGVzY3JpcHRpb24AQ21vZHVsYXJHcmFkaWVudAChAQIAAAxfT3V0Q29vcmQAoQIEAQAPZHN0AKEBAQAAAnNpemUAogFtYXhWYWx1ZQBDgAAAogFtaW5WYWx1ZQBBgAAAogFkZWZhdWx0VmFsdWUAQoAAAB0CAMEAABAAMgAAED+AAAAdAgAgAACAAAICACAAAMAAHQAAEAIAgAAdAgAgAgAAAAgCACAAAIAAHQIAEAAAwAACAgAQAgCAAAQCACAAAMAAAwIAIAIAwAAdAgAQAgCAAB0CACACAEAACAIAIAAAgAAdAwCAAADAAAIDAIACAIAABAIAIAAAwAADAgAgAwAAAB0DAIACAIAAMgIAID+AAAAyAwBAPwAAAB0DACACAMAAAwMAIAMAQAAyAwBAPwAAAB0DABADAAAAAwMAEAMAQAAdAwBAAwCAAAEDAEADAMAAHQMAIAIAgAACAwAgAwBAAB0CACADAIAABAMAQAAAgAADAwBAAgAAABoDACADAEAAHQMAQAMAgAAEAwAgAACAAAMDACACAEAAGgMAEAMAgAAdAwAgAwDAADIDABBAAAAAHQQAgAMAQAAIBACAAwDAADIDABAAAAAAKAQAgAMAwAAdAYCAAIAAADQAAAABgAAAMgMAEEAAAAAdBACAAwCAAAgEAIADAMAAMgMAEAAAAAAoBACAAwDAAB0BgEAAgAAANAAAAAGAQAAdBACAAgDAAB0EAEADAAAAMgMAEAAAAAAdBAAgAwDAADIDABA/gAAAHQQAEAMAwAAdAQDzBAAbADUAAAAAAAAAHQQAgAIAwAAyAwAQAAAAAB0EAEADAMAAHQQAIAMAAAAyAwAQP4AAAB0EABADAMAAHQEA8wQAGwA2AAAAAAAAADUAAAAAAAAAMgMAEEAAAAAdBACAAwCAAAgEAIADAMAAMgMAEAAAAAAoBACAAwDAAB0BgEAAgAAANAAAAAGAQAAyAwAQAAAAAB0EAIADAMAAHQQAQAIAwAAdBAAgAwAAADIDABA/gAAAHQQAEAMAwAAdAQDzBAAbADUAAAAAAAAAHQQAgAIAgAAdBABAAgCAAB0EACACAIAAMgMAED+AAAAdBAAQAwDAAB0BAPMEABsANgAAAAAAAAA2AAAAAAAAAA==" );
this.byteCode = dec.toByteArray();
dec = null;
}
public function get size():int{
return this.data.size.value[0];
}
public function set size( value:int ):void{
this.data.size.value = [ value ];
}
}
class CabstractShader{
// 초기 비트맵데이터
private var _src:BitmapData;
private var _width:uint;
private var _height:uint;
// 알고리즘 전체가 공유할 값 - 현재 위치 및 결과용 컬러배열
protected var _outCoord:Vector.<Number> = new Vector.<Number>( 2, true ); // [ x, y ]
protected var _color:Vector.<Number> = new Vector.<Number>( 4, true ); // [ r, g, b, a ] 0~1사이의 소수값
public function CabstractShader( $src:BitmapData ){
// 기본이 되는 비트맵데이터를 초기화한다.
_src = $src;
_width = _src.width;
_height = _src.height;
}
final public function run( $param:Object = null ):BitmapData {
// 반환용 비트맵데이터
var result:BitmapData;
// 루프용
var cx:uint, cy:uint;
// 색상변환용
var r:uint, g:uint, b:uint, a:uint;
// 반환용 비트맵데이터 초기화
result = new BitmapData( _width, _height );
// 모든 픽셀에 대한 루프 시작
for( cy = 0 ; cy < _height ; ++cy ){
for( cx = 0 ; cx < _width ; ++cx ){
// 현재 위치를 설정한다.
_outCoord[0] = cx;
_outCoord[1] = cy;
// 실제 색상계산용 알고리즘-자식객체가 구상한다.
calc( $param );
// RGBA로 반환한다.
r = _color[0] * 0xff;
g = _color[1] * 0xff;
b = _color[2] * 0xff;
a = _color[3] * 0xff;
// 반환 비트맵데이터에 기록한다.
result.setPixel32( cx, cy, a * 0x1000000 + r * 0x10000 + g * 0x100 + b );
}
}
//완성된 비트맵
return result;
}
final protected function sampleNearest( $x:uint, $y:uint, $src:BitmapData = null ):Vector.<Number>{
// x,y 위치의 점으로부터 색상을 읽어들일 비트맵데이터
var src:BitmapData;
// null로 주어지는 경우 _src를 참조한다.
if( $src === null ){
src = _src;
}else{
src = $src;
}
// 결과보고용 벡터 - [ r, g, b, a ] 0~1사이의 값 으로 보고한다.
var result:Vector.<Number>;
// getPixel32로부터 값을 받을 임시변수
var color:uint;
if( $x > src.width -1 || $y > src.height -1 ){
throw new Error( '$x 또는 $y의 값이 이미지의 크기보다 더 큽니다.' );
}else{
result = new Vector.<Number>( 4, true );
color = src.getPixel32( $x, $y );
result[0] = (color >> 16) & 0xFF; //r
result[1] = (color >> 8) & 0xFF; //g
result[2] = color & 0xFF; //b
result[3] = (color >> 24) & 0xFF; //a
return result;
}
}
//자식이 구상해야하는 알고리즘 메쏘드
protected function calc( $param:Object = null ):void {
throw new Error( '반드시 상속 구상해야합니다.' );
}
}
import flash.display.BitmapData;
class CmodularGradient extends CabstractShader{
public function CmodularGradient( $src:BitmapData ){
super( $src );
}
override protected function calc( $param:Object = null ):void {
var dx:Number, dy:Number, brightness:Number, cx:uint, cy:uint;
dx = ( ( $param.size - 1 ) - _outCoord[0] % $param.size ) / ( $param.size - 1 );
dy = ( ( $param.size - 1 ) - _outCoord[1] % $param.size ) / ( $param.size - 1 );
brightness = 1- (dx * 0.5 + dy * 0.5);
cx = _outCoord[0] / $param.size;
cy = _outCoord[1] / $param.size;
if( cx % 2 === 0 ){
if( cy % 2 === 0 ){
_color[0] = dx;
_color[1] = dy;
_color[2] = 0;
_color[3] = 1;
}else{
_color[0] = dx;
_color[1] = 0;
_color[2] = dy;
_color[3] = 1;
}
}else{
if( cy % 2 === 0 ){
_color[0] = 0;
_color[1] = dx;
_color[2] = dy;
_color[3] = 1;
}else{
_color[0] = brightness;
_color[1] = brightness;
_color[2] = brightness;
_color[3] = 1;
}
}
}
}