three.js で ShaderToy シェーダーを実装するにはどうすればいいですか? 質問する

three.js で ShaderToy シェーダーを実装するにはどうすればいいですか? 質問する

threejs 内で ShaderToy パラメータ iGlobalTime、iChannel などを再作成する方法に関する情報を探しています。iGlobalTime は Shader が開始してから経過した時間であることは知っています。また、iChannel はテクスチャから RGB を取り出すためのものだと思いますが、これらを設定する方法についての情報があれば幸いです。

編集: three.js の例に付属するすべてのシェーダーを調べてきましたが、答えはすべてどこかにあると思います。たとえば、iChannel1 = テクスチャ入力などに相当するものを見つけるだけです。

ベストアンサー1

あなたの質問に答えたかどうかはわかりませんが、shadertoys を THREEJS に統合する手順を他の人に知ってもらうのは良いことかもしれません。

まず、shadertoys はフラグメント シェーダーであることを知っておく必要があります。つまり、すべての shadertoys (フラグメント シェーダー) で動作する「汎用」頂点シェーダーを設定する必要があります。

ステップ1「汎用」頂点シェーダーを作成する

varying vec2 vUv; 
void main()
{
    vUv = uv;

    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
}

この頂点シェーダーは非常に基本的なものです。テクスチャ マッピングがどこにあるかをフラグメント シェーダーに伝えるために、可変変数 vUv を定義したことに注目してください。これは、iResolution基本レンダリングに画面解像度 ( ) を使用しないため重要です。代わりにテクスチャ座標を使用します。これは、同じ THREEJS シーン内の異なるオブジェクトに複数のシェーダートイを統合するために行いました。

ステップ2必要なシェーダートイを選択し、フラグメント シェーダーを作成します。(パフォーマンスの良いシンプルなトイを選択しました。niklashuss によるシンプルなトンネル 2D)。

このおもちゃに与えられたコードは次のとおりです:

void main(void)
{
    vec2 p = gl_FragCoord.xy / iResolution.xy;
    vec2 q = p - vec2(0.5, 0.5);

    q.x += sin(iGlobalTime* 0.6) * 0.2;
    q.y += cos(iGlobalTime* 0.4) * 0.3;

    float len = length(q);

    float a = atan(q.y, q.x) + iGlobalTime * 0.3;
    float b = atan(q.y, q.x) + iGlobalTime * 0.3;
    float r1 = 0.3 / len + iGlobalTime * 0.5;
    float r2 = 0.2 / len + iGlobalTime * 0.5;

    float m = (1.0 + sin(iGlobalTime * 0.5)) / 2.0;
    vec4 tex1 = texture2D(iChannel0, vec2(a + 0.1 / len, r1 ));
    vec4 tex2 = texture2D(iChannel1, vec2(b + 0.1 / len, r2 ));
    vec3 col = vec3(mix(tex1, tex2, m));
    gl_FragColor = vec4(col * len * 1.5, 1.0);
}

ステップ3シェーダートイの生のコードをカスタマイズして、完全な GLSL フラグメント シェーダーを作成します。コードで最初に欠けているのは、uniforms と varyings の宣言です。これらをフラグメント シェーダー ファイルの先頭に追加します (次のコードをコピーして貼り付けるだけです)。

uniform float iGlobalTime;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;

varying vec2 vUv;

このサンプルに使用される shadertoys 変数のみが宣言され、さらに頂点シェーダーで以前に宣言された可変 vUv も宣言されていることに注意してください。

最後に調整する必要があるのは、画面解像度を使用しないことにしたので、適切な UV マッピングです。これを行うには、IResolution ユニフォームを使用する行を次のように置き換えます。

vec2 p = gl_FragCoord.xy / iResolution.xy;

と:

vec2 p = -1.0 + 2.0 *vUv;

これで、シェーダーを THREEJS シーンで使用できるようになりました。

ステップ4THREEJS コード:

ユニフォームをセットアップする:

var tuniform = {
        iGlobalTime:    { type: 'f', value: 0.1 },
        iChannel0:  { type: 't', value: THREE.ImageUtils.loadTexture( 'textures/tex07.jpg') },
        iChannel1:  { type: 't', value: THREE.ImageUtils.loadTexture( 'textures/infi.jpg' ) },
    };

テクスチャがラップされていることを確認します。

tuniform.iChannel0.value.wrapS = tuniform.iChannel0.value.wrapT = THREE.RepeatWrapping;
tuniform.iChannel1.value.wrapS = tuniform.iChannel1.value.wrapT = THREE.RepeatWrapping;

シェーダーを使用してマテリアルを作成し、それを平面ジオメトリに追加します。平面ジオメトリ() は、shadertoys 700x394 の画面解像度をシミュレートします。つまり、アーティストが共有しようとした作品を最適に転送します。

var mat = new THREE.ShaderMaterial( {
            uniforms: tuniform,
            vertexShader: vshader,
            fragmentShader: fshader,            
            side:THREE.DoubleSide
        } );

var tobject = new THREE.Mesh( new THREE.PlaneGeometry(700, 394,1,1), mat);

THREE.Clock()最後に、更新関数の合計時間ではなく、iGlobalTime 値にデルタを追加します。

tuniform.iGlobalTime.value += clock.getDelta();

これで、この設定でほとんどのシェーダートイを実行できるようになりました...

おすすめ記事