jit.gl.pix を使ったパーティクルシステム: #max6 #jitter #cycling74

スクリーンショット 2014-07-12 17.53.52

先日、jit.p.shiva や jit.p.vishunを使ったパーティクルシステムを紹介しました。パーティクルの数が1000程度で30fpsと、あまり性能が振るわなかったので、改善点を検討しました。例えばGPUなんかを駆使して・・・

そこで今回は、jit.p.shiva パーティクル生成システムをjit.gl.pixで代用してみます。

スクリーンショット 2014-07-12 18.01.12

パッチでは、jit.gl.pixに超簡略化したjit.p.shivaの代わりをさせています。たんにjit.gl.pixで生成したRGBの値を、XYZに見立ててパーティクルを描画してみようというだけですね。これでGPU上でパーティクルを生成する事ができます。ただし、jit.gl.multipleを用いて描画する関係で、GPU上で計算したパーティクルの位置を保存しているテクスチャ(jit_gl_texture)を一旦CPU側(jit_matrix)に変換かける必要があります。

描画した結果は、1000パーティクルで20fps程度とこちらも結果がふるいませんでした。jit.p.shivaやjit.p.vishnuを使った時よりもパフォーマンスがでてないですね。どうやら、GPU→CPUへテクスチャを戻す処理が重たいようです。CPU処理ですがjit.genでパーティクルを生成した方が良さそうです。

もう1つ以前からの問題ですが、Maxのテクスチャ付きパーティクルを使う際に必須であるjit.gl.multipleがボトルネックになってるようです。jit.gen + jit.gl.render によるOpenGLプリミティブの描画(LineやPoint)では10万パーティクルの描画できるので、jit.gl.multipleを改善しなければ・・・

改善案として、例えばjit.gl.pixでjit.gl.multipleに相当する処理を書ければ、大幅なパフォーマンスアップするのでは?と思いました。テクスチャとパーティクルのポジションだけ貰って、そんなに上手くシェーダーをかけるのか・・・?今後の課題として取り組もうと思います。

おまけ


----------begin_max5_patcher----------
3073.3oc6c0zaiiaF9ryuBUidnXZFuheoOJ5gza8XuOXQfhMsilQVRURNIyt
XOLygh1doKJ588vde+Crsn+WZVzdr+EJ+PxQxVJl1hVCUyLAvZLkkzKe3Ke+
3gTje8ESldSxCz7oV+Jq2XMYxWewjIhh3ELo76SltN3g4QA4he1z4IqWSiKl
do7bEzGJDk+u9Ce6uKHqHbdD8+729t+8e7as9EuMrXV5r7aCuK3wO7C+zO98
O9w+xie7O+e+6+opqNdy5jMEQzBw81trzkYqtQ78YUkDtP7LRt4suFaWcwKS
hKhCVSEm52jEFDUclzfh42FFu55L57BYkC5CY2MKnmq3.fHNvdBVe4SxRXbk
n.p8LxC+Jwy.vtC7R+lKtf+wkJBX2HjFZV604pGjrnh2mRkx6TF3c85fhrP1
89K2GFP3moxRb8mQ3UOGQsDwARl3S5p1VAyaQyEz0I2EtflLiUUXOfomP8Nl
dOSP2SOgqTrhF2NZ.U.MtzZZqHBDeRJFXODGcPtX9AL5zzKpe+YM0RToDVX+
5vH5czr7vj3Z2jISCRSqU7jZWBGKeah3F4b41hBikEA1VTF8tvpq2caoAYrZ
YAqJtISBBO34LUdRV62EUW5S8M3UZG4m1BkELoFDvZoWMOIR9reCqao+k09.
z7GFkL+czE0zpXsloz3v3zLZNyvQPQo3t8zKnKC1DUbc6XZyyuLXNsyKt017
ISWkEtHIlKDMtRdwUOt2XIMH.H0qLheQbPZKWbNqdrI+lfLN7eSDslxKSWOI
Ip4o11hy5xDDGxzjoEgRgEZu8lFtNMKLtnwChFGvtG2lOOKIJpwsRdl6Z4LK
XJEyo2Gtn31FlQ4mg8yCSqZBltEiVDthlWzrrhfU4MKogyh5Zq0sEzn7mylP
S6BLojT+DsZlrciCaMGrqIgF2vt0P5vx.vUX9DgEpFn87XzoczN8bLoxJZYO
Q8ihLrwBzMLZ2NNg0ANgAdRCoGFm.GGN8TOxnv3tT.EBF+7sCf4IaxlWovTp
aX0TDYcNJBi2Ze5Mawlc9c2FtXQSyAxdP479iRKesVIt3oRzmqzMwoAyemEz
5pjkKyorVe1eW81MqSsPVn18xhTyKqB9bANmVvXHnrmkPWA36NXAiwgrko4q
1DdjAfzMDPNMHPZawWDugmckElyN.7LpRUs05NvL.5DURjAlIMqPFt.1et.W
ilIBKNMJHlZcEutXU9+C1Tjv.hv4LqEWkuNIo31qyuMXAqRwKIJb0sE7Jnzs
MuH1g3EUem0ocAMkcMUmu54yMoMOYiLr.r9abfmTiSYFFHWfLCCjL1wAn0YM
MOOXEculm04GYBVsCG18QWEfj8pgbrgq21NZ.O65p7fKYgntNUGXRu59Bbjp
FNCV22tHnnr+aZ3CVO9w+5O8O9mO9gu+wO7c6PZQOXl.B5gm.nqL3IYLTHUv
opbgPsfcP74w6.KnhkQIAEHnEv11darl5LO99ntAI9x737GL8stLHsbSTDKa
KJM15mCzQ+PXehzffsmAIHeaGV3FkgccT1mPmD3TjrZUD8Hq8hbfaC.bNb0z
9opIzVMcfzfLFVVPyJ88tMBd8z4I0hkz8Qh.2DDupcHv8DI4h6QpN3fkzgBN
Dkf6pCLtI5hTinKrjnKO6Oye0m4uRQlWjcTOZ9U7N.CJPOA4yPn7.o5S0XPo
JfGQUcXnYJmFYs0TT29+eFiaW9Lz1A6EcTkfIPRD09D52o+tOgz18N566FLw
OGXx6ucYaG5BbAZAbABimjxgYRibhdV35CnHWePMw02k8VhgJJwd5lcxR+64
A2QWbM6IvZ4uNnfEv9MaJjMG0822WWaG104QXuuUg3Yd3c8PYg.bSPTYDNau
1VbqbVHz89v3EI2aUd3pk4La6aXdiEzJwjVdfKVHGN+QIYKnYbliVlGDHOV+
G+934Gc9Y6YatgoCu9j.hKbavmD.ZvROiq71EauUOF9uQNV8BHc5QkVF9z3.
G.JyK6IXAPrMDRNWy5TFlFQ2pFVDjshVzAemZiJcbeFMArsWM9h6FDgCEHld
RjouJ5Z9MhmPSW3jeuXHQl8OA7BbhN3BpMbKNNBHv2G+4Y5vmyTT2YJ1jE5l
1GhSByopkD4dDNK68USA65co2P5Wwt7iNmZDd8KO.XkRTqts58P9e4HB1Qxo
YmzbxAwc2dg6HaxSCmhIA7OSxsor.HX1O09j6gnCjDSjgggFCHIT6XXOm4Od
BpT8jtUA9igYHU97.wvuCrds8LH+C8qYBzglYIAV.HYLvf0SvJGUOGfpsFbX
45Ohfz6n74RBSAEPrr0Mbh86WOeeYOeOfz.vgwSzmb77WpcLrewPAj4s5Ksa
JmzHltN4qNGcswt5.GcjlMQ3wfm7WwRlT6dy2xD0IZhj4FmLxvweMSeDocbD
qC8QW4zZE4MFvw76CY0CsCjHc.jdxoIL1YL3jgmri96X2yQDU9N83JQP7nHU
Gs6rF4qkN0N3wiyZttH3Kzt1Hpmg8vBB2k6mwUnH5hFEjG8aoAYE8g7n5.nV
h2gTle33fDne1q0tZHQKFEsGQQey7R+UVuW6.IVGgMRjSqtwg2kyhWZjVh1w
AMh7RKTHeP6.ITK1GGSJjuR6XHPCzkgcgiGiiwIYq0NJZqElbskqs.ih2f3k
YAyKzBN14vkI4WPphcnwKCh0xn7HeW.FKbCgQtDuYDrimKY.ZJJmRHGroPKC
3FzS3eymLJ7uEFOD3OwVI72QK3OVNLcNiA7mODHrmlumumkq2LHBYaCOqsHx
gx.HGnnC1hzyAyu5g4U6kGcTjCxCue.5VnZifmV7Q61wqYtI1sXQxP3gFBvJ
g+9ZwrjbNDLNB0bdRttizD1u30wRZI8kA33+Rx2ZcPTGyQfJPzYbDqXw8Iog
5FHA95.HIxzdbGKQZXyLyo+YZA.oiLwkSdaW6wvXfouTHaagJ4DIERNO+7cF
Q4ApcHTGbBAjqljiCG0egkCgfbzNPZqCcQ4j3k.GEDlyWiDrVq8vd.5.HkKM
eN3w.8ZmCVJ0gyZ45AgJSVE6++z+hNdeHPPvKZZFqAmtZ.NeQRUXMLzQGX3m
o6ahNWTX88dYSYWKqKb8JZxWhztouk5D3ni5rOIKPwkSzdh6nZAJV0UnX9P8
aALhksD9jrTsUUYrwrTqzhnzgLiLmkGFUk4VTh9joa.NFbVE840gKRSBiKJ6
vg.bCfdk61ERWJhu07Yd1qnjiRgBZDMNp1uk+V3YJ5S1pJy.iQlIJuRT4YNx
rp3LvbvYfxxr4rjeoppAvb5BhU1cumwDhRKdweFY1PvYuAdypPCVmUcEri+x
eZJvrqpQbaNQBhTNXCGyAmcTEmIlSlMpZ1.YNlMPdGCNaHxrx6KOlimarp15
DoGO1zm8GeYPhviPY1fhDEcLLOYHLhnpuan4zGDppsNn4nOCU02Mzb7o.UMM
En4DiDz6XzmMDYV4TXQFSePfx5FFjsN6iAmMCYVU0Yf4nNqtpg4vHCP4vMLm
HjFcKN+.3wvHJXTsgBXNd.UMPCyg+H2AdSa3xAaSvEpI83yzlf6pnYYzX9lg
P05UuXyOvVma9A8YuOn7ErEr+TTcnWe+KrtQ7GMKHuiskM7gfmcOJuWsgYt8
Ayjqpxttepgre+ZZQVhkmt1B2v8.T.x4LtCYv1hCz5F3G4vUP31tHFvV2WTR
vBoVtdZ56yFDpzDhisYtwo7ztuqh6ytfdsox520BOuYfFKBWebvAxoWaoGku
vm39aqTbgMmEaRzY2HKJwnCLyj5JtXb83I1OVh8iiXuVKUkGfipxi8fHOtMp
4mn3ryDehfm4gX+CxeANjuAGXwbgR7smdXZqRfTATgCJlB6ozrCj5hmw7053
f4XY4DoWN+Z4e6L.oPEPT+ACQQJ0Kd3ZgE8hOT2F3v0KtIwZcgONCl7zjr8t
jGuASdvNlk73oh3PFTCVnCHNdGmAKewhvHb6KDY0WNClpbU.LGtlVUz7GNCC
pX2zcvjFeUT6QCmWEUDGvvYDGXT9bUIJlly8yiKLFTYNSdyDwJ50ZQfRxWjA
6H91YvBxNUCEFghyqhfBRyv4b.pTv0Cn7nh8d3oFqiLgyc1eH4hxN6Kj6rmP
t+9AYW6Ejrmy2bw+CbP7J8C
-----------end_max5_patcher-----------

jit.gl.pix を使ったnoise生成:#max6 #jitter #cycling74

スクリーンショット 2014-07-12 15.47.44

jit.gl.pixではnoiseオブジェクトが利用できないので、こちらを参考に実装してみました。

jit.genコード

スクリーンショット 2014-07-12 16.11.36


----------begin_max5_patcher----------
1602.3oc6Z1riahCG.+bxSABsmVkFgMX9XO084npJxAbX7TBlEblYZq5883d
Xuuuc69Zr9CfARfIDBglJ0VofFaC9u+4+eZ3qKWXtk8Bovz32L9fwhEec4hE
pljMrn7uWXtG+RXBtPMLyP198jTt4JcebxKbU6OR4qiSVmQewHkQKH+2e+O+
6e9WUCaGKkmh2STC82yo3jpdROrmcfmP3pGuUYqYXd3Czz3M4jPtV7ftqsVY
.8T+5.kWrsWaY7wpoHOdq5Qr1pwjtCGplT6FsUP+hpMnS8PERAMsRH.kMRiT
hKa6iuCBLks8skKk+rZfrJk7r3l6DU6w7bApbL1kvvbanA.5aYD3ZcoDC1Ow
.tn0HAr7ULCfBTnypIyZPC.rlF5GO+yYD8CRJwazRr4JCSy56+rXaLTaOon.
GSNAa6NjjTDlSHoF+B3RwD3bJVNBXAQ1AVtqLJAVPejxteR0CafcvFzXfCmE
GmPF6ZD95ZTpGbj1PFNWPRNIeCIEuMgzzf7jEJU3CX35AtSn4SlAoHbB2+c7
kVIMYi16BDLh8+s3z3d3hUGbwyrobQxKoQINDSKMg7DIufxRarJVXhyxZz7h
F2hjgOxTOH2U0MQS0MApaJm7Ds598paEmKnCWflC4Zj9hudqSsusr5VqUqPR
P4pbr35nznb7anRI1giSXgehD0..BpkQRooY4jBQjDLuTJp6NhrCeHguoauS
s6ux+dmc1ohwBy3bZDKUJDstSYyUSmv4IR6zr4hQMhTbVG2bgXcbnXKNWR0R
aGXUmbFKocW0ajBK.bJU3akvoZgEZU+Po6yxU1YMlHso4CBGgrjjVOJcOO0Q
OQh85PxyzH9CshPJ6QLbZV0VfYMihnwjBd61333h1szJ6glJgMMsa09Ql3Z6
mpmWu4CzqaMeGkkJTeAU8a8VVeNmN1PzuoHTkhiZoV0rx2UocvHWrs7m01mV
AIwn1Yva6Xq+b.NCk.1pvZN1G63+MRE3Mbx0LQfdC30cBA2dd9IxmGKLcFFL
AJuchbpPWILkF3q55R+v0pa3B5Btu58Jgl1mwpZcJ6uapWvNjGVIu5swUFsW
wBGIbZZsu7OTaVcz3dfFE010o1aSgz2kNJwfzPtTIFLPIFNQRrwGW1LnoYA9
IRzFwLHTj1f4hTo2dfq2NZFu+ZCsc9PmWf+9NEh2Xx6aREo.rEmTlgS881QX
kkuBwoqRqmooQrmMJu79cEBe6GDQiEayuWJsxDWLrcE+0VVdDI2.HGDFquVO
3pmsTmKjcPGd.NcEqUlgdfWcVn1nNJxcfErchG5ylhNveLonK0jOPGax3x6V
MVM4MeiRYAkEo8Jd.HqQWO6vwhi6DW3ebx5mnQDVVBNkTqUhOvYhj.ogRsRd
NNsXGKe+FYFxbC3zel.1tpnX1kINMmmI.vY5IZlTHlbFAUYJg.WEhhS1HkVY
8TWDlB9AuxPakAKBppMzVa9Za4zt1vPVhd1+fnnjfUM9A7yhH+YQjSPcUBs6
8isR.vYpDPGdVGXBc0EUc446GLSESsKGGxuoPDV5ev4VRwdK8edn3uJp71C4
uF4356gto3D3qhYEf9NfSu45DSno2VF5nUFc+NvP2YhgOQBkRefefugm+Zns
skE7FQ0.eIH8r0mD0Mkp8b1Sn4Ry7Y5WLd4y2TsSMGcB9NnbZOSXLhcai4.r
70k.c0mf286wfJDUCvXon0fhbizTz6R0DGhplyrcflAC73AsuaNPSzEbflf6
BI1efRrycCi89g6XtcGnD6c2Hw1y7AyuZ1d4GtS8qRXxO1rbRp7.u0GBo4Te
V1Ue2Q.6Qe.ZW9wX6OgGtH2Xq5+jbbA4RwiyYwik5hm2USmiupk2AiLuIDY+
wdBOmY.bm7uOKfq5hK55v0f+7rbl8uNKvqGF+r8gYglv89DFNRqBNwa8Z+Ht
V2hc9tdAEMYh5tZmooFQGG0nDTuczhdhTzJ6ySiRbZDhS1vFpzHi6COiz.mM
oIX.rA3Lqv4bhi+rJM12URC3Z2p1SixXB+SklRHm091h+AkufHctBdH8qKxq
gU9zsHPCXCd9T2bbGh5+7sE6L.wwa1jF3PrFgtym7LjcKHZ9jGz8k1CX.hyX
oiNH7QuYaofbzaz9n2l8ouI69dK1h44aK+e.LmYwH
-----------end_max5_patcher-----------

jit.gl.pix でモルフォロジー処理を実装してみた : #max6 #jitter #cycling74

Before

スクリーンショット 2014-07-11 16.12.13

After

スクリーンショット 2014-07-11 16.12.10

モルフォロジー処理は、コバルト爆弾αΩのΔに教えてもらいました。ノイズを消すにはメディアンフィルターより良いとの事。エッジ抽出などにも使えるようです。アルゴリズムや使い道は、こちらが参考になりました。10個とか重ねて書けてもあまりfps落ちないので、シェーダー凄いっぽい。

CodeBox(モルフォロジー処理(収縮))


delta = 1/(dim+1);

outPix = in1;

for( i = 0 ; i < 9 ; i += 1) { x = ((i%3)-1) * delta.x; y = (floor(i/3) -1) * delta.y; pix = nearest(in1,vec( x,y ) + norm,boundmode="clamp"); outPix = switch(pix < 0.5, pix,outPix); } out1 = outPix;

pix < 0.5 を pix > 0.5 にすると膨張処理に変わります。

Max Patch

スクリーンショット 2014-07-11 16.22.09

続きを読む jit.gl.pix でモルフォロジー処理を実装してみた : #max6 #jitter #cycling74

jit.gl.pix でラプラシアンフィルターを実装してみた:#max6 #jitter #cycling74

Before-特大ゆっくり魔理沙(ニコニ・コモンズより)

スクリーンショット 2014-07-09 19.54.20

After ラプラシアンフィルターによるエッジ抽出

スクリーンショット 2014-07-09 19.54.12

メディアンフィルターに引き続き、ラプラシアンフィルターによるエッジ抽出をjit.gl.pix実装してみました。

jit.gl.pix – Codebox

[javascript]

//laplacian
filter = vec(0,1,0,1,-4,1,0,1,0);

//sharp
//filter = vec(0,-1,0,-1,5,-1,0,-1,0);

//mean
//filter = vec(1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9);

//mean2
//filter = vec(1/16,2/16,1/16,2/16,4/16,2/16,1/16,2/16,1/16);

//mean3
//filter = vec(1/3,0,0,0,1/3,0,0,0,1/3);

//sobel
//filter = vec(-1,0,1,-2,0,2,-1,0,1);

step = 1/(dim+1);

d = (vec( 0 % 3 , floor( 0 /3)) – 1) * step;
p0 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 1 % 3 , floor( 1 /3)) – 1) * step;
p1 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 2 % 3 , floor( 2 /3)) – 1) * step;
p2 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 3 % 3 , floor( 3 /3)) – 1)* step;
p3 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 4 % 3 , floor( 4 /3)) – 1) * step;
p4 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 5 % 3 , floor( 5 /3)) – 1) * step;
p5 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 6 % 3 , floor( 6 /3)) – 1)* step;
p6 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 7 % 3 , floor( 7 /3)) – 1)* step;
p7 = sample(in1,norm + d,boundmode="clamp");

d = (vec( 8 % 3 , floor( 8 /3)) – 1)* step;
p8 = sample(in1,norm + d,boundmode="clamp");

sum = p0 * swiz(filter,0)
+ p1 * swiz(filter,1)
+ p2 * swiz(filter,2)
+ p3 * swiz(filter,3)
+ p4 * swiz(filter,4)
+ p5 * swiz(filter,5)
+ p6 * swiz(filter,6)
+ p7 * swiz(filter,7)
+ p8 * swiz(filter,8);

out1 = sum;
[/javascript]

一番上のfilterの初期値を変える事で、いくつかのフィルターを試せるようにしてあります。

おまけ – jit.gl.pix の困ってるポイント

  • sample / nearest を function や for 文で、取得する位置を変更しながら繰り返し利用するとコンパイル通らない。
  • sample / nearest から取得した pixcel から swizしようとすると(例 : swiz(vec,0) ) コンパイルが通らない。
  • function と Param を同時に定義するとコンパイル出来ない事がある。

jit.gl.pix でメディアンフィルターを実装してみた:#max6 #jitter #cycling74

Before

lena noise

After – 3×3 メディアンフィルターで処理

lena median

ノイズが載った画像を綺麗にする必要が出てきたので、jit.gl.pix のシェーダーを使ってメディアンフィルター(Median Filter)を実装してみました。下の画像は、上記のノイズ画像をメディアンフィルターで処理した結果です。結構凄い!

jit.gl.pix で実装する上でのポイント

メディアンフィルターのアルゴリズムは、こちらにある通り、近傍の画素値を拾ってきて、並び替えた上で中央値を採用するという単純なものです。例えば、3×3で行うと中央のピクセルに対して周辺と自分を含めた9つの画素値を、明るさで並べ替えて、4番目の値を出力すればOK。

しかしjit.gl.pixでは実装に問題がありました。for文を使って近傍画素を取得し配列へ保存したいのですが、配列が使えないです。そのため変数(m0 ~ m8)を9つ用意し、愚直にベタ書きをしました。また並べ替えに関しても同様の問題がありバブルソートをベタ書きしています。

この問題点は、jit.gl.pixの仕様なのか、シェーダーの仕様なのかはわからないですが、非線形な処理を書こうとすると苦労しそうです。もし、簡単・軽量・カッコよく実装する方法があれば、是非教えてください!

jit.gl.pix Codebox – 3×3 Median Filter

[javascript]

sort(x,y){

return min(x,y),max(x,y);
};

xmin = 1/(dim.x – 1);
ymin = 1/(dim.y – 1);

//近傍画素の取得
//0
x = (-1) * xmin;
y = (-1) * ymin;
m0 = sample(in1,norm + vec(x,y),boundmode="clamp");

//1
x = (0) * xmin;
y = (-1) * ymin;
m1 = sample(in1,norm + vec(x,y),boundmode="clamp");

//2
x = (1) * xmin;
y = (-1) * ymin;
m2 = sample(in1,norm + vec(x,y),boundmode="clamp");

//3
x = (-1) * xmin;
y = (0) * ymin;
m3 = sample(in1,norm + vec(x,y),boundmode="clamp");

//4
x = (0) * xmin;
y = (0) * ymin;
m4 = sample(in1,norm + vec(x,y),boundmode="clamp");

//5
x = (1) * xmin;
y = (0) * ymin;
m5 = sample(in1,norm + vec(x,y),boundmode="clamp");

//6
x = (-1) * xmin;
y = (1) * ymin;
m6 = sample(in1,norm + vec(x,y),boundmode="clamp");

//7
x = (0) * xmin;
y = (1) * ymin;
m7 = sample(in1,norm + vec(x,y),boundmode="clamp");

//8
x = (1) * xmin;
y = (1) * ymin;
m8 = sample(in1,norm + vec(x,y),boundmode="clamp");

//バブルソート
m0,m1 = sort(m0,m1);
m0,m2 = sort(m0,m2);
m0,m3 = sort(m0,m3);
m0,m4 = sort(m0,m4);
m0,m5 = sort(m0,m5);
m0,m6 = sort(m0,m6);
m0,m7 = sort(m0,m7);
m0,m8 = sort(m0,m8);

m1,m2 = sort(m1,m2);
m1,m3 = sort(m1,m3);
m1,m4 = sort(m1,m4);
m1,m5 = sort(m1,m5);
m1,m6 = sort(m1,m6);
m1,m7 = sort(m1,m7);
m1,m8 = sort(m1,m8);

m2,m3 = sort(m2,m3);
m2,m4 = sort(m2,m4);
m2,m5 = sort(m2,m5);
m2,m6 = sort(m2,m6);
m2,m7 = sort(m2,m7);
m2,m8 = sort(m2,m8);

m3,m4 = sort(m3,m4);
m3,m5 = sort(m3,m5);
m3,m6 = sort(m3,m6);
m3,m7 = sort(m3,m7);
m3,m8 = sort(m3,m8);

m4,m5 = sort(m4,m5);
m4,m6 = sort(m4,m6);
m4,m7 = sort(m4,m7);
m4,m8 = sort(m4,m8);

m5,m6 = sort(m5,m6);
m5,m7 = sort(m5,m7);
m5,m8 = sort(m5,m8);

m6,m7 = sort(m6,m7);
m6,m8 = sort(m6,m8);

m7,m8 = sort(m7,m8);

//中央値の出力
out1 = m4;

[/javascript]

参考

上記画像は、画像処理の分野で良く使われているLenaという女性の画像です。