Dancing Metaballs
Shamelessly based on: https://www.shadertoy.com/view/XdfGRH
Music from 23skidoo
@author Devon O.
/**
* Copyright devon_o ( http://wonderfl.net/user/devon_o )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/fCRv
*/
package
{
import com.adobe.utils.AGALMiniAssembler;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display3D.Context3D;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
import flash.display3D.VertexBuffer3D;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundLoaderContext;
import flash.media.SoundMixer;
import flash.net.URLRequest;
import flash.system.Security;
import flash.utils.ByteArray;
/**
* Shamelessly based on: https://www.shadertoy.com/view/XdfGRH
*
* Music from 23skidoo
*
* @author Devon O.
*/
[SWF(width="465", height="465", frameRate="60", backgroundColor="#000000")]
public class DancingBalls extends Sprite
{
private static const FRAGMENT_SHADER:String =
<![CDATA[
mov ft0.xy, v0.xy
mul ft0.xy, ft0.xy, fc1.yy
sub ft0.xy, ft0.xy, fc0.ww
pow ft2.x, ft0.x, fc1.y
pow ft2.y, ft0.y, fc1.y
add ft2.z, ft2.x, ft2.y
abs ft2.z, ft2.z
mul ft2.z, ft2.z, fc1.y
sub ft2.w, ft2.x, ft2.y
abs ft2.w, ft2.w
add ft2.w, ft2.z, ft2.w
pow ft2.x, ft2.w, fc1.z
mov ft1.xyz, ft2.xxx
max ft1.xyz, ft1.xyz, fc0.www
mov ft2.x, fc0.x
mul ft2.x, ft2.x, fc1.y
add ft2.x, ft2.x, fc0.y
mul ft2.y, ft2.x, fc1.y
mul ft2.z, ft2.x, fc1.w
sin ft3.x, ft2.y
sin ft3.y, ft2.z
mul ft3.z, ft2.x, fc0.z
sin ft3.z, ft3.z
cos ft3.w, ft2.y
cos ft4.x, ft2.z
mul ft4.y, fc2.x, ft3.z
mul ft4.z, fc2.y, ft4.x
add ft5.x, ft4.y, ft4.z
mul ft4.y, fc2.y, ft3.x
mul ft4.z, fc3.y, ft4.x
add ft5.y, ft4.y, ft4.z
mul ft4.y, fc3.x, ft3.y
mul ft4.z, fc2.z, ft3.w
add ft6.x, ft4.y, ft4.z
neg ft4.y, ft3.z
mul ft4.y, ft4.y, fc2.x
mul ft4.z, fc2.z, ft4.x
add ft6.y, ft4.y, ft4.z
mul ft4.y, fc2.x, ft3.y
mul ft4.z, fc2.w, ft4.x
add ft7.x, ft4.y, ft4.z
neg ft4.y, ft3.z
mul ft4.y, ft4.y, fc2.x
mul ft4.z, fc2.w, ft3.w
add ft7.y, ft4.y, ft4.z
sub ft2, ft5.xy, ft0.xy
dp3 ft2, ft2, ft2
sqt ft2.x, ft2
mul ft1.x, ft1.x, ft2.x
sub ft2, ft6.xy, ft0.xy
dp3 ft2, ft2, ft2
sqt ft2.x, ft2
mul ft1.y, ft1.y, ft2.x
sub ft2, ft7.xy, ft0.xy
dp3 ft2, ft2, ft2
sqt ft2.x, ft2
mul ft1.z, ft1.z, ft2.x
mov ft3.x, fc0.x
add ft3.x, ft3.x, fc1.x
sub ft3.y, ft5.x, ft0.x
pow ft3.y, ft3.y, fc1.y
sub ft3.z, ft5.y, ft0.y
pow ft3.z, ft3.z, fc1.y
add ft2.x, ft3.y, ft3.z
div ft2.x, ft3.x, ft2.x
sub ft3.y, ft6.x, ft0.x
pow ft3.y, ft3.y, fc1.y
sub ft3.z, ft6.y, ft0.y
pow ft3.z, ft3.z, fc1.y
add ft2.y, ft3.y, ft3.z
div ft2.y, ft3.x, ft2.y
sub ft3.y, ft7.x, ft0.x
pow ft3.y, ft3.y, fc1.y
sub ft3.z, ft7.y, ft0.y
pow ft3.z, ft3.z, fc1.y
add ft2.z, ft3.y, ft3.z
div ft2.z, ft3.x, ft2.z
add ft2.x, ft2.x, ft2.y
add ft2.x, ft2.x, ft2.z
pow ft2.x, ft2.x, fc3.z
mul ft1.xyz, ft1.xyz, ft2.xxx
mov ft1.w, fc0.w
mov oc, ft1
]]>
private static const POLICY:String = "http://www.onebyonedesign.com/crossdomain.xml";
private static const SOUND:String = "http://www.onebyonedesign.com/flash/djscratch/sound1.mp3";
private var mContext3d:Context3D;
private var mVertBuffer:VertexBuffer3D;
private var mIndexBuffer:IndexBuffer3D;
private var mProgram:Program3D;
private var mSound:Sound;
private var mMatrix:Matrix3D = new Matrix3D();
public function DancingBalls()
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(event:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
Security.loadPolicyFile(POLICY);
initStage();
setS3d();
loadSound();
addEventListener(Event.ENTER_FRAME, onTick);
}
private function setS3d():void
{
stage.stage3Ds[0].addEventListener( Event.CONTEXT3D_CREATE, initStage3d );
stage.stage3Ds[0].requestContext3D();
}
private function initStage():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
}
private function initStage3d(event:Event):void
{
mContext3d = stage.stage3Ds[0].context3D;
mContext3d.configureBackBuffer(stage.stageWidth, stage.stageHeight, 1, true);
var vertices:Vector.<Number> = Vector.<Number>([
// x y z u v
-1.0, -1.0, 0, 0, 0,
-1.0, 1.0, 0, 0, 1,
1.0, 1.0, 0, 1, 1,
1.0, -1.0, 0, 1, 0 ]);
mVertBuffer = mContext3d.createVertexBuffer(4, 5);
mVertBuffer.uploadFromVector(vertices, 0, 4);
mIndexBuffer = mContext3d.createIndexBuffer(6);
mIndexBuffer.uploadFromVector (Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);
mContext3d.setVertexBufferAt(0, mVertBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
mContext3d.setVertexBufferAt(1, mVertBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
generateProgram();
}
private function generateProgram():void
{
var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler();
vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
"m44 op, va0, vc0 \n" +
"mov v0, va1 "
);
var fragmentShaderAssembler:AGALMiniAssembler= new AGALMiniAssembler();
fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT, FRAGMENT_SHADER);
mProgram = mContext3d.createProgram();
mProgram.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
}
private var mChannel:SoundChannel;
private function loadSound():void
{
mSound = new Sound();
mSound.load(new URLRequest(SOUND), new SoundLoaderContext(5000, true));
mChannel = mSound.play(0, 100);
}
private var mSoundBytes:ByteArray = new ByteArray();
private var mBeat:Number = .0;
private var mTime:Number = Math.random() * 10000;
private var mTimeInc:Number = 0.0;
private var fc0:Vector.<Number> = new <Number>[ 0, 0, 4.0, 1.0 ];
private var fc1:Vector.<Number> = new <Number>[ .015, 2.0, 5.0, 3.0 ];
private var fc2:Vector.<Number> = new <Number>[ .1, .4, .3, .5 ];
private var fc3:Vector.<Number> = new <Number>[ .15, .2, 1.75, 1];
private function onTick(event:Event):void
{
if ( !mContext3d )
return;
mContext3d.clear ( 0, 0, 0, 1 );
mContext3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mMatrix, true);
mContext3d.setProgram(mProgram);
// fc0 = [beat, time, 4.0, 1]
// fc1 = [.015, 2.0, 5.0, 3.0]
// fc2 = [.1, .4, .3, .5]
// fc3 = [.15, .2, 1.75, 1]
var t:Number;
mSoundBytes.clear();
SoundMixer.computeSpectrum(mSoundBytes, true);
mTime += .005;
t = mSoundBytes.readFloat() / 7;
mTimeInc += (t - mTimeInc) / 8;
mTime += mTimeInc;
mSoundBytes.position = 512;
t = mSoundBytes.readFloat();
mBeat += (t - mBeat) / 4;
fc0[0] = mBeat;
fc0[1] = mTime;
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, fc0 );
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, fc1 );
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, fc2 );
mContext3d.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 3, fc3 );
mContext3d.drawTriangles(mIndexBuffer);
mContext3d.present();
}
}
}