Pixel Bender Tutorial - seroGradient

by hika
♥0 | Line 88 | Modified 2009-08-18 10:13:40 | MIT License
play

ActionScript3 source code

/**
 * Copyright hika ( http://wonderfl.net/user/hika )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/7OTp
 */

package {
    
	import flash.display.*;
	import flash.events.*;
	import flash.ui.*;
	
	[SWF(backgroundColor="#ffffff", frameRate="60", width="700", height="500")]

	public class Main extends Sprite{
		

		public function Main()	{
			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 CseroGradient( new BitmapData( 300, 300, true, 0 ) );
			
			addChild( new Bitmap( shader.run( {height:300} ) ) );

		}
	}

	
}

import flash.display.BitmapData;

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 CseroGradient extends CabstractShader{

	public function CseroGradient( $src:BitmapData ){
		super( $src );
	}
	override protected function calc( $param:Object = null ):void {
		var brightness:Number; 
		
		//상단에서 멀어질수록 어두워진다.
		brightness = ( $param.height - _outCoord[1] ) / (  $param.height );
		
		//컬러를 설정한다.
		_color[0] = brightness; //r
		_color[1] = brightness; //g
		_color[2] = brightness; //b
		_color[3] = 1; //a
	}
}