jit.genでglTexSubImage2D的なもの

Genがかなり強力そうなので、5,6年ぶりにMaxを再開してみる。
練習がてらいくつか簡単なパッチを作ってアップするのを始めてみる。
一日ひとつとはいかないまでも、続いたらいいな…。

最近個人的には音より映像の方をよく触るので、まずはjitterからはじめていこうと思う。

とりあえずテクスチャの矩形切り出しをやってみた。
video_uv
UV分割数と使用インデックスで指定する方法と、
UVオフセットと幅で指定する方法とを用意した。(サブパッチみてね)

入力がビデオでも静止画でも同じように書けることに地味に感動しつつ。

昔と勝手が違うところがいろいろあって最初は手間取ったけど、
ちょっと触ればやっぱり簡単に作れてすごいソフトだなーと改めて思う。

プログラマな僕としてはGenの導入がかなりMaxをパワーアップさせてくれた感があるので
作品制作に使えるレベルまで継続したい。と今は思っている。

ポイントスプライトでテクスチャアニメーション

前回ジオメトリシェーダでポイントスプライトを実装しましたが、

このへんを見ると当然、テクスチャ座標を自分で設定したくなりますよね。

gl_TexCoord[0].st = vec2(0,0);
gl_TexCoord[0].st = vec2(0,1);
gl_TexCoord[0].st = vec2(1,0);
gl_TexCoord[0].st = vec2(1,1);

やることは至って単純で、右辺の0と1にあたる数値をCPUから設定してやるだけです。

0がUV位置、1がUV範囲と思えばわかりやすいかと思います。

両方をuniform変数で渡しても良いのですが、汎用性を考えてUV位置は頂点ごとに設定できるようにしました。

  • バーテックスシェーダ

    前回に加えて、glTexCoord2dでCPUから渡されたテクスチャ座標をジオメトリシェーダに渡してます。

    #version 120
    void main()
    {
     gl_Position = gl_Vertex;
     gl_TexCoord[0] = gl_MultiTexCoord0;
    }
    
  • ジオメトリシェーダ

    前回に加えて、テクスチャ座標の計算が入ってます。

    #version 120
    #extension GL_EXT_geometry_shader4 : enable
    uniform vec2 size; // 描画サイズ(CPUからglUniform2fで渡す)
    uniform vec2 size_uv; // UV範囲(CPUからglUniform2fで渡す)
    void main() {
     gl_Position = gl_ModelViewProjectionMatrix * gl_PositionIn[0];
     gl_Position.x -= size.x/2;
     gl_Position.y += size.y/2;
     gl_TexCoord[0] = gl_TexCoordIn[0][0];
     EmitVertex();
     gl_Position.y -= size.y;
     gl_TexCoord[0].t += size_uv.t;
     EmitVertex();
     gl_Position.x += size.x;
     gl_Position.y += size.y;
     gl_TexCoord[0].s += size_uv.s;
     gl_TexCoord[0].t -= size_uv.t;
     EmitVertex();
     gl_Position.y -= size.y;
     gl_TexCoord[0].t += size_uv.t;
     EmitVertex();
    }
    
  • フラグメントシェーダ

    そのまんまです。

    #version 120
    uniform sampler2D tex0;
    void main (void)
    {
     gl_FragColor = texture2D(tex0, gl_TexCoord[0].st);
    }
    

CPU側では、表示したいテクスチャをglBindTextureしてglUniform1iした上でこんな感じで描画しましょう。

glBegin(GL_POINTS)
glTexCoord2d(s,t);
glVertex3d(x,y,z);
glEnd();

これで、頂点に渡すテクスチャ座標を時間変化させるだけでテクスチャアニメーションができますね。

ジオメトリシェーダでポイントスプライト

OpenGLに、ポイントスプライトという機能があります。

点(Vertex)に対してテクスチャを貼り付けて表示するもので、パーティクルの表示等によく使われるみたいです。

もうちょっと自由度ほしいなーというのと、シェーダのお勉強のために、同等の機能をシェーダを使って実装してみました。

  • バーテックスシェーダ

    CPUから渡された座標をそのままジオメトリシェーダに渡します。

    #version 120
    void main()
    {
     gl_Position = gl_Vertex;
    }
    
  • ジオメトリシェーダ

    四角形ポリゴンを作ってテクスチャ座標を指定します。

    ※GL_GEOMETRY_INPUT_TYPE_EXTにはGL_POINTSを、GL_GEOMETRY_OUTPUT_TYPE_EXTにはGL_TRIANGLE_STRIPを指定しておきます。

    #version 120
    #extension GL_EXT_geometry_shader4 : enable
    uniform vec2 size; // 描画サイズ(CPUからglUniform2fで渡す)
    void main() {
     gl_Position = gl_ModelViewProjectionMatrix * gl_PositionIn[0];
     gl_Position.x -= size.x/2;
     gl_Position.y += size.y/2;
     gl_TexCoord[0].st = vec2(0,0);
     EmitVertex();
     gl_Position.y -= size.y;
     gl_TexCoord[0].st = vec2(0,1);
     EmitVertex();
     gl_Position.x += size.x;
     gl_Position.y += size.y;
     gl_TexCoord[0].st = vec2(1,0);
     EmitVertex();
     gl_Position.y -= size.y;
     gl_TexCoord[0].st = vec2(1,1);
     EmitVertex();
    }
    
  • フラグメントシェーダ

    テクスチャを参照して色を設定します。

    #version 120
    uniform sampler2D tex0;
    void main (void)
    {
     gl_FragColor = texture2D(tex0, gl_TexCoord[0].st);
    }
    

CPU側では、表示したいテクスチャをglBindTextureしてglUniform1iした上でこんな感じで描画しましょう。

glBegin(GL_POINTS)
glVertex3d(x,y,z);
glEnd();