jit.gl.shader multi textureの書き方 & vertex shader で波形表示サンプル #jitter #maxmsp #glsl

本日はjit.gl.shaderに2つ目のテクスチャを突っ込んで波形表示するサンプルを作ってみました。1つはカラフルな色のシェーダーを、もう一つはjit.catch~ で作った波形のテクスチャです。

波形のテクスチャ生成

ほとんどjit.catch~のhelpを流用してるだけなので簡単です。

続いてシェーダーですが、JXSの仕様通りにつくればいけると思いきや、罠がありました。

state = “TEXTURE0” とか書けってdocumentに書いてあったのでハマった・・・

結果

vertex shaderは0中心に振動するとか戻ってくる処理(サンプルのように)ウネウネさせるくらいじゃないと、CPUが管理している本来のモデルの位置からズレちゃうので使いにくそうだなと思いました。

本で読んだ感じだと、PBOとテッセレーションシェーダーと組み合わせたりしてパーティクル作ったりとかそのような使い方が良さそうな。

また今回書いた程度の処理ならぶっちゃけjit.gen使ってCPU上で書いちゃうのもありかもしれません。activity monitor と睨めっこしてCPU / GPU 比較的余裕ありそうなな方に担当してもらうと。

jit.gl.shader色々調べてみましたが、まだまだGLSL4.1の勉強という感じですね。

code

<jittershader name="fill-flat-quads">
	<description>Default Shader </description>
    <!-- JXS Document https://docs.cycling74.com/max8/tutorials/jitterchapter99_appendixc -->
    <!-- Vertex -->
	<param name="position" type="vec3" state="POSITION" />
	<param name="modelViewProjectionMatrix" type="mat4" state="MODELVIEW_PROJECTION_MATRIX" />
	<param name="color" type="vec4" state="COLOR" />
    <!-- Texture -->
    <param name="texcoord" type="vec2" state="TEXCOORD" />
    <!-- Texture1 -->
	<param name="tex0" type="int" default="0" />
    <param name="textureMatrix0" type="mat4" state="TEXTURE0_MATRIX" />
    <param name="texdim0" type="vec2" state="TEXDIM0" />
    <!-- Texture2 -->
 	<param name="tex1" type="int" default="1" />
    <param name="textureMatrix1" type="mat4" state="TEXTURE1_MATRIX" />
    <param name="texdim1" type="vec2" state="TEXDIM1" />
    <!-- my uniform -->
    <param name="u_time" type="float" />
	<param name="k" type="float" default="4" />
	<param name="velocity" type="float" default="1" />
	<param name="amp" type="float" default="1" />
	<language name="glsl" version="4.1">
		<bind param="position" program="vp" />
		<bind param="modelViewProjectionMatrix" program="vp" />
		<bind param="textureMatrix0" program="vp" />
        <bind param="tex0" program="fp" />
        <bind param="texdim0" program="fp" />
		<bind param="textureMatrix1" program="vp" />
        <bind param="tex1" program="vp" />
        <bind param="texdim1" program="vp" />
		<bind param="color" program="vp" />
		<bind param="texcoord" program="vp" />
		<bind param="u_time" program="fp"/>
		<bind param="k" program="vp" />
		<bind param="velocity" program="vp" />
		<bind param="amp" program="vp" />
		<program name="vp" type="vertex">
<![CDATA[
#version 410

//in : Each instance can have different values
in vec2 texcoord;
in vec3 position;
in vec4 color;

//Textures are placed in GPU memory.
uniform sampler2DRect tex1;
uniform vec2 texdim1;

//uniform : Keeps the same value for all instances
uniform mat4 modelViewProjectionMatrix;
uniform mat4 textureMatrix0;

uniform float k; //wave count
uniform float velocity;
uniform float amp;
uniform float u_time;

//out : Structural input to next shader stage
out jit_PerVertex {
	vec4 color;
    vec2 texcoord;	
} jit_out;

void main() {

	vec4 pos = vec4(position, 1.);

	/*
	// sin wave
	float u = k * (pos.x - velocity * u_time);
	pos.y += amp * sin(u);
	vec3 n = vec3(0);
	n.xy = normalize(vec2(-k * amp * cos(u),1));
	*/	

	float temp = (pos.x + 1)/2;
	pos.y += texture(tex1,vec2(temp*texdim1.x,0)).r * 2;
	//pos.z += texture(tex1,vec2(temp*texdim1.x,0)).r * 2;

    //Convert vertex vectors to view positions
	gl_Position = modelViewProjectionMatrix * pos;
	jit_out.color = color;

    //Determine the reference coordinates of the texture for each vertex (by creating them in the vertex shader, linear completion can be applied).
    jit_out.texcoord = vec2(textureMatrix0*vec4(texcoord, 0, 1.));
}
]]>
		</program>
<!--		
<program name="gp" type="geometry">
<![CDATA[
#version 410

layout (triangles) in;

layout (triangle_strip, max_vertices=15) out;

in jit_PerVertex {
	vec4 color;	
    vec2 texcoord;	
} jit_in[];

out jit_PerVertex {
	vec4 color;	
    vec2 texcoord;	
} jit_out;

float offset = 10.0;
vec4 offsets[4] = vec4[](vec4(-offset, offset, 0, 0), vec4(offset, offset, 0, 0), vec4(-offset, -offset, 0, 0), vec4(offset, -offset, 0, 0));

void main() {

    // Drawing of original primitives
	for(int i = 0; i < 3; i++) {
		jit_out.color = jit_in[i].color;
		jit_out.texcoord = jit_in[i].texcoord;
		gl_Position = gl_in[i].gl_Position;
		EmitVertex();
	}
	EndPrimitive();

    // Drawing of primitives to be replicated
	for(int j = 0; j < 4; j++) {
		for(int i = 0; i < 3; i++) {
			jit_out.color = jit_in[i].color;
			jit_out.texcoord = jit_in[i].texcoord;
			gl_Position = gl_in[i].gl_Position + offsets[j];
			EmitVertex();
		}
		EndPrimitive();
	}
}


]]>
</program>
-->
		<program name="fp" type="fragment">
<![CDATA[
#version 410

//Textures are placed in GPU memory.
uniform sampler2DRect tex0;

//in : Receiving structure from previous stage.
in jit_PerVertex {
	vec4 color;
    vec2 texcoord;	
} jit_in;

//Color output of this pixel for video output
out vec4 fragColor;

void main() {

    //Refer to the appropriate texture position for each pixel
	fragColor = texture(tex0,jit_in.texcoord.xy);
}	
]]>
		</program>
	</language>
</jittershader>