jit.gl.pix における2次元平面のアンチエイリアス処理 #maxmsp #jitter

jit.gl.pixでトランジションエフェクト

あのタグの次期バージョンに入れるトランジションエフェクトを開発しています。例えば、中央から丸が出てきて画面全体に広がるようなエフェクトをつくろうとすると、丸を書いて2つのテクスチャを割当るだけで簡単そうです。しかし、単純につくるとエッジがギザギザしてしまいます。そこでjit.gl.pix(フラグメントシェーダ)におけるアンチエイリアスを実装してみます。

アンチエイリアス処理有り

スクリーンショット 2014-08-10 03.08.23

アンチエイリアス処理無し

スクリーンショット 2014-08-10 03.13.37中央の円のエッジがギザギザしており、VJなどで大画面に表示するともっと気になるかなと思います。

円トランジションjit.gl.pix

スクリーンショット 2014-08-10 03.25.40現在のピクセルの半径rと、トランジションする円の半径rとの距離をとって、その距離が短い場合に(0~0.005の距離)smoothstepで補間をしています。補完した値でmixする事でエッジをなだらかに繋ぐ事が可能です。ここを単純に書くと大なり小なりで比較して、0 or 1ピクセルの色を指定して、switchやif文でピクセル値を切り替えて出力したくなりますが、それではエッジがギザギザになってしまいます。

jit.gl.shader / GLSL アルファテスト&デプステストを使った透過テクスチャの描画 #maxmsp #jitter #glsl

OpenGLの透過&深度

スクリーンショット 2014-08-06 22.15.08
JitterのOpenGLにおいて、透過テクスチャを使う場合は、@blendenable 1 @depthenable 0 と設定します。ただし、その方法では奥行き(Z軸)も使ったポイントスプライト等の描画(@depathenable 1)をしたい場合に、上記画像のようにテクスチャの枠が出てしまう問題があります。描画するメッシュのZ座標が「画家のアルゴリズム」で想定される順番と逆方向に並んでいるために、手前の画像を描く方が先だと、後ろの画像がdepth testで描画されなくなっちゃうんですね。Zソートが出来れば良いですが、Jitterには実装されていないようです。

GLSLを使ったAlpha Test(アルファテスト)

スクリーンショット 2014-08-06 22.14.55
上記問題を解決するために、Alpha Testという方法があります。OpenGLのWikiに載っていたのですが、フラグメントシェーダで透過値が0なら描画をキャンセルすればOKという簡単な手法です。ただし、この方法は透過がbinaryつまり0か1のどちらかしか無い場合にしか使えないようです。

上記画像はポイントスプライトのGLSLに追加で実装してみた結果です。綺麗に描画されましたね。

GLSL / Fragment Shader

#version 120
uniform sampler2DRect tex0;

void main (void)
{
	vec4 texel = texture2DRect(tex0, gl_TexCoord[0].st);
	
        //Alpha Test
	if(texel.a < 1.0)
		discard;
	
	gl_FragColor = texel;
}

半透明ポリゴンは・・・?

Wikiに書いてあるように、Depth Sort(Z軸でメッシュの並べ替え)が必要です。Sortの方法にはBSP Tree Sorting(バイナリ空間分割)やDepth peelingという手法があるそうです。そのうち必要になったら実装してみたいと思います。

おぱんちゅ

スクリーンショット 2014-08-06 22.36.30
ぱんつつくった by 貞子♂様 ありがとうございます!

jit.gl.shader / GLSL でマルチテクスチャ #maxmsp #jitter #glsl

スクリーンショット 2014-08-06 19.09.09

マルチテクスチャ

jit.gl.shaderの中で複数のテクスチャを利用する方法を調べました。Tutorial 43: A Slab of Your Very Own こちらで紹介されている方法です。jit.gl.slabで使うことを想定して紹介されていますが、jit.gl.shaderでも利用できるように少しコードを変更しています。

JXS / GLSLコード

<jittershader name="mrr.mixer.4ch.jxs">
	<description>
	</description>
		
	<param name="a" type="vec4" default="0.25 0.25 0.25 0.25"/>	
	<param name="b" type="vec4" default="0.25 0.25 0.25 0.25"/>	
	<param name="c" type="vec4" default="0.25 0.25 0.25 0.25"/>	
	<param name="d" type="vec4" default="0.25 0.25 0.25 0.25"/>	
<!-- 4つのテクスチャを使う場合にはparam要素の指定と、default値の指定が必須 -->
	<param name="tex0" type="int" default="0" />
	<param name="tex1" type="int" default="1" />
	<param name="tex2" type="int" default="2" />
	<param name="tex3" type="int" default="3" />
	<language name="glsl" version="1.2">
	<bind param="a" program="fp" />
	<bind param="b" program="fp" />
	<bind param="c" program="fp" />
	<bind param="d" program="fp" />
	<bind param="tex0" program="fp" />
	<bind param="tex1" program="fp" />
	<bind param="tex2" program="fp" />
	<bind param="tex3" program="fp" />

		<program name="vp" type="vertex">
<!-- GLSL内部で日本語コメントすると即落ちする -->
<!-- varying 次のシェーダーへ受け渡す / 前のシェーダから受け取る変数 -->
<!-- uniform Maxから直接受け取れる変数。param指定 -->
<![CDATA[

#version 120 

varying vec2 texcoord0;
varying vec2 texcoord1;
varying vec2 texcoord2;
varying vec2 texcoord3;

void main(void)
{
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;	
	
	texcoord0 = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);
	texcoord1 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord1);
	texcoord2 = vec2(gl_TextureMatrix[2] * gl_MultiTexCoord2);
	texcoord3 = vec2(gl_TextureMatrix[3] * gl_MultiTexCoord3);
}
]]>
		</program>
		<program name="fp" type="fragment">
<![CDATA[

#version 120
		 
uniform vec4 a;
uniform vec4 b;
uniform vec4 c;
uniform vec4 d;

varying vec2 texcoord0;
varying vec2 texcoord1;
varying vec2 texcoord2;
varying vec2 texcoord3;
		 
uniform sampler2DRect tex0;
uniform sampler2DRect tex1;
uniform sampler2DRect tex2;
uniform sampler2DRect tex3;

void main()
{
	vec4 input0 = texture2DRect(tex0,texcoord0);
	vec4 input1 = texture2DRect(tex1,texcoord1);
	vec4 input2 = texture2DRect(tex2,texcoord2);
	vec4 input3 = texture2DRect(tex3,texcoord3);
	
	gl_FragColor = a * input0 + b*input1 + c*input2 + d*input3;
	
}
]]>
		</program>
	</language>
</jittershader>

jit.gl.pixと比較

上記のサンプルであれば、jit.gl.pixで出力した結果をjit.gl.*系のオブジェクトへバインドすれば同様の事ができるのでjit.gl.pixで書いた方が良いと思われます。Vertex ShaderやGeometry ShaderでのVertexの操作やテクスチャの細かいバインディングする場合に必要になる処理ですね。