キー検知とシェーダーによる画面制御

こちらの記事はMinecraft Command Advent Calendar 2024への参加記事になっています

hi こんにちは
巷では最近、スナップショットにてキー検知が追加された事で盛り上がりを見せていましたが
今回はそんなキー検知を活用して、シェーダーを制御する方法についての紹介をしていきたいと思います

リソパシェーダーについて

リソパシェーダーについては過去の記事にてこれまでに紹介をしていきましたが
改めて端的に言い表すと画面の表示をすきに変えることができる機能となっています
もともとこのリソパシェーダーの制御には、スコアから値を読み取り、その値によって表示の決定をしていました
このスコアの値をキー入力によって変更することで、プレイヤーの操作を直接画面表示へと反映することが可能になります。

キー検知について

現在キー入力はプレイヤーのpredicateを参照する形で検知できます
具体的にはforward、backward、left、right、sprint、jump、sneakの7つの状態を取ることができます
デフォルトのキー操作で言うとWASD、Ctrl、Space、Shift 計7つのキー入力に対応しています
これらのキー操作を、スコアを通して最終的にシェーダーへと渡すことで、画面の制御を行っていこうと思います。

キー検知によるcoreシェーダーの制御

まずは先ほどのキー検知を用いて、シェーダーへ数値を渡すためのスコアの設定を行っていきます
今回は6つのキー入力を、それぞれXYZ軸のプラス、マイナス方向に見立ててみようと思います
具体的に言うと、WSで上下、ADで左右、CtrlSpaceで奥手前といった操作をシェーダーへ反映していきます
リソパシェーダーへ数値を受け渡すために、TextColorR、TextColorG、TextColorBというスコアを用意していますが
今回はTextColorRにX方向、TextColorGにY方向、TextColorBにZ方向を割り当てる形で、これら3つのスコアの増減を操作できるようにコマンドを組んでいきます
まずはAdvancementにて、predicateからプレイヤーのキー入力を検知します

{
  "criteria": {
    "w": {
      "conditions": {
        "player": [
          {
            "condition":"entity_properties",
            "entity": "this",
            "predicate": {
              "type_specific": {
                "type": "minecraft:player",
                "input": {
                  "forward":true
                }
              }
            }
          }
        ]
      },
      "trigger": "minecraft:tick"
    }
  },

...

}

△predicateのinputからキー検知を設定

これをトリガーにfunctionを実行させ、キー入力に対応したスコアを増減させます

{

...

  "rewards": {
    "function": "ktos:key/w"
  }
}
...
scoreboard players add @s TextColorG 1
...

これら一連の処理をまとめたデータパックとリソースパックが以下のものになります
TitleShader
https://github.com/midorikuma/TitleShader
ScoreToColor
https://github.com/midorikuma/DP_Libraries
以前の記事と同様、リンク先のTitleShaderDPScoreToColorDPをワールドデータのdatapacksへ配置し、
TitleShaderRPをresourcepacksへ配置し、導入を行います
導入後、試しに以下のコマンドを実行することでシェーダーをテストすることができます

/function ktos:startcore {id:0}

停止する際には以下のコマンドを使用します

/function ktos:stop

次に以前の記事と同じシェーダーを、次の手順で新たに追加してみます
まずは以下のtest.glslファイルをTitleShader\assets\minecraft\shaders\include\coreに配置します

#ifndef fsh
const vec4 vertexColor = vec4(vec3(255,0,0)/255.0 ,1.0);
#endif

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 nCoord;
    //座標正規化(0~1)
    // nCoord = fragCoord/iResolution.xy;

    //座標正規化(-1~1)
    nCoord = (fragCoord-iMouse.xy) * 2.0;
    // nCoord /= iResolution.xy;
    nCoord /= min( iResolution.x, iResolution.y );

    vec3 color;
    //色設定(単色)
    color = vec3( 0.0, 0.0, 0.0 );
    //色設定(座標)
    // color.r = nCoord.x;
    // color.g = nCoord.y;

    //色設定(円形)
    // color = vec3( length(nCoord) );
    float alpha = float( vertexColor.b < length(nCoord) );

    fragColor = vec4( vec3(0), alpha );
}

次にcore\main\fsh.glslにて追加したシェーダーを登録します

#undef mainImage
#define mainImage test
#moj_import <core/test.glsl>
...
        switch(flag){
            default: defaultmain();
            break;
            
            // Add shaders here
            shader(0, debug)
            shader(1, test)

△moj_importにてファイルを指定、shader()からシェーダーid:1を新たにcoreへ登録

最後に以下のコマンドを実行することで、新たに追加したシェーダーを反映できます

/function ktos:startcore {id:1}

こうして、プレイヤーの操作をシェーダーへ反映できるようになりました
まずはcoreシェーダーへ導入を行ってきましたが、次にpostシェーダーについても導入をしてみようと思います。

postシェーダーへの応用

今まで、postシェーダーをグラフィック設定に依存しない形で実行するには、スペクテイターによるモブへの憑依が必要でした
そのため、一方的に画面の表示を変えることはできても、プレイヤーからの入力によって画面を変えることはできない状態でした
しかし、今回導入したキー検知ではスペクテイター状態でもキー入力の取得が可能です、
そのためpostシェーダー表示中にもプレイヤーの入力を反映した画面の表示を可能となったのです
試しに以下のコマンドを実行することでシェーダーをテストすることができます

/function ktos:startpost {id:0}

またpostシェーダーの強みとして、現在の画面表示をバッファとして保存し操作することが可能です
試しに保存した画面表示を、プレイヤーのキー入力に合わせて操作できるようにしてみます
今回は先ほどのシェーダーとバッファを使用して、円の内側と外側とで色が変化する画面効果を適用してみます
まずは以下のtest.glslファイルをTitleShader\assets\minecraft\shaders\include\postに配置します

#ifndef fsh
const vec4 vertexColor = vec4(vec3(128,128,128)/255.0 ,1.0);
const vec4 mainColor = vec4(1.0, 0.0, 0.0, 1.0);
#endif

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 nCoord;
    //座標正規化(0~1)
    // nCoord = fragCoord/iResolution.xy;

    //座標正規化(-1~1)
    nCoord = (fragCoord-iMouse.xy) * 2.0;
    // nCoord /= iResolution.xy;
    nCoord /= min( iResolution.x, iResolution.y );

    vec3 color;
    //色設定(単色)
    color = vec3( 0.0, 0.0, 0.0 );
    //色設定(座標)
    // color.r = nCoord.x;
    // color.g = nCoord.y;

    //色設定(円形)
    // color = vec3( length(nCoord) );
    float alpha = float( vertexColor.b < length(nCoord) );

    fragColor.rgb = mix(mainColor.rgb, vec3((mainColor.r+mainColor.g+mainColor.b)/3.0), alpha);
    fragColor.a = 1.0;
}

次にpost\main\fsh.glslにて追加したシェーダーを登録します

#undef mainImage
#define mainImage test
#moj_import <post/test.glsl>
...
        switch(flag){
            default: defaultmain();
            break;
            
            // Add shaders here
            shader(0, debug)
            shader(1, test)

△moj_importにてファイルを指定、shader()からシェーダーid:1を新たにpostへ登録

最後に以下のコマンドを実行することで、新たに追加したシェーダーを反映できます

/function ktos:startpost {id:1}

このように、postシェーダーについてもプレイヤーからの操作によって制御できるようになりました。

終わりに

ここまで書いた内容は、predicateでのキー検知機能が追加された当時のアイディアを元に作成していますが、
最新版においては今回とは別の新機能を使うことであらゆるキー操作をリソースパックへと反映可能になっています
あらゆる操作なので、本当にすべてのキーにおいて検知が可能です
こうなってしまえば実質やりたい放題になったと言っても過言ではないかもしれません
なので次回はモデルから直接キー検知が可能な方法を用いたシェーダーの制御について紹介をしていきたいと思います。

おわり

コメントを残す