ShaderFX カスタム コードの高度な例

この例では、既存のシェーダ コードを取得し、これを OpenGL モードで ShaderFX とともに使用できるように、Maya で GLSL/CGFX 環境用にカスタマイズする方法を示します。次に、Maya の DirectX 11 モードで使用できるように、HLSL 環境用にコードをカスタマイズする方法を示します。

この例で使用しているシェーダ コードは、https://www.shadertoy.com/view/ldB3zc の Iñigo Quilez 氏の厚意により提供されています。このサイトにアクセスすると、次のサンプル コードを取得し、Maya で使用するために修正することができます。

次のワークフローのビデオ デモンストレーションが利用できます。詳細については、下記の「ビデオ チュートリアル」を参照してください。

float hash1( float n ) { return fract(sin(n)*43758.5453); }
vec2  hash2( vec2  p ) { p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) ); return fract(sin(p)*43758.5453); }

vec4 voronoi( in vec2 x, float w )
{
    vec2 n = floor( x );
    vec2 f = fract( x );

    vec4 m = vec4( 8.0, 0.0, 0.0, 0.0 );
    for( int j=-2; j<=2; j++ )
    for( int i=-2; i<=2; i++ )
    {
        vec2 g = vec2( float(i),float(j) );
        vec2 o = hash2( n + g );
        // animate
        o = 0.5 + 0.5*sin( iGlobalTime + 6.2831*o );

        // distance to cell
        float d = length(g - f + o);

        // do the smooth min for colors and distances
 
        vec3 col = 0.5 + 0.5*sin( hash1(dot(n+g,vec2(7.0,113.0)))*2.5 + 3.5 + vec3(2.0,3.0,0.0));
        float h = smoothstep( 0.0, 1.0, 0.5 + 0.5*(m.x-d)/w );
        m.x   = mix( m.x,     d, h ) - h*(1.0-h)*w/(1.0+3.0*w); // distance
        m.yzw = mix( m.yzw, col, h ) - h*(1.0-h)*w/(1.0+3.0*w); // cioloe
    }
    return m;
}

void main( void )
{
    vec2 p = gl_FragCoord.xy/iResolution.yy;
    float k = 2.0 + 70.0 * pow( 0.5 + 0.5*sin(0.25*6.2831*iGlobalTime), 4.0 );
    k = 0.5 - 0.5*cos(0.25*6.2831*iGlobalTime);
    vec4 c = voronoi( 6.0*p, k );

    vec3 col = c.yzw;
    col *= 1.0 - 0.8*c.x*step(p.y,0.33);
    col *= mix(c.x,1.0,step(p.y,0.66));
    col *= smoothstep( 0.005, 0.007, abs(p.y-0.33) );
    col *= smoothstep( 0.005, 0.007, abs(p.y-0.66) );
    gl_FragColor = vec4( col, 1.0 );
}

GLSL/CGFX モードで作業する

Maya の OpenGL モードで ShaderFX とともに使用できるようにコードを修正して SFX_GLSL_*/SFX_CGFX_3 との互換性を確保するには、次の手順を実行します。

  1. vec2vec3vec4 をそれぞれ float2float3float4 に変更します。
  2. gl_FragCoord.xyUV に変更します。

    gl_FragCoord.xy は、テクスチャ座標を取得するために GLSL で使用されるグローバル変数です。Maya では、テクスチャ座標を取得するために UV セットを使用します。

  3. ビューポートの解像度を定義する iResolution を削除します。Maya では必要ありません。
  4. main を定義する代わりに関数定義を使用します。

    既定で Custom Code ノードに用意されているものと同様に、main (void) を関数定義に変更します。

    CustomCode1178Output CustomCode1178Func( float2 UV )
  5. struct を追加してノードの出力を提供します。
    struct CustomCode1178Output 
    { 
        float3 color; 
    };
  6. iGlobalTime の代わりに、入力として Maya の Time ノードを使用します。

    iGlobalTimetime に置き換えます。

    入力パラメータとして関数定義に float time を追加します。

    入力パラメータとして voronoi 関数定義に float time を追加します。

    voronoi がコールされる入力パラメータとして time を追加します。

  7. 元のコードの gl_FragColor は、シェーダの最終出力を定義しています。OUT.color に変更し、次の出力を返します。
    CustomCode1178Output OUT; 
    OUT.color = col;
    return OUT; 
  8. (オプション)別のノードとの競合を回避するために、次の操作を実行して関数名をカスタマイズすることもできます。
    1. この関数を一般名 CustomCodexxxx の代わりに VoronoiSmooth と名付けます。
      注: すべての関数には一意の名前を付ける必要があります。同じ関数名を持つ Custom Code ノードが 2 つあることがないように注意してください。
    2. VoronoiSmooth_ を hash1 や hash2 などのその他の関数にプリフィックスとして追加し、関数 voronoi の名前を VoronoiSmooth に変更します。
    3. アトリビュート エディタ(Attribute Editor)関数名(Function Name)VoronoiSmooth に変更します。
  9. 注: 既定では、TraditionalGameSurfaceShader拡散カラー(Diffuse Color)ポートは float3 入力を受け入れます。たとえば代わりに Custom Code ノードから float4 を出力することにした場合、(Hw Shader Nodes > Values > Vector Component)ノードを使用して float4 からの出力を float3 に変換することができます。

修正されたコードは次のようになります。

float VoronoiSmooth_hash1( float n ) { return fract(sin(n)*43758.5453); }
float2 VoronoiSmooth_hash2( float2 p ) { p = float2( dot(p,float2(127.1,311.7)), dot(p,float2(269.5,183.3)) ); return fract(sin(p)*43758.5453); }

float4 VoronoiSmooth( in float2 x, float w, float time )
{
	   float2 n = floor( x );
	   float2 f = fract( x );

	   float4 m = float4( 8.0, 0.0, 0.0, 0.0 );
	   for( int j=-2; j<=2; j++ )
	   for( int i=-2; i<=2; i++ )
	   {
		     float2 g = float2( float(i),float(j) );
		     float2 o = VoronoiSmooth_hash2( n + g );
		     // animate
		     o = 0.5 + 0.5*sin( time + 6.2831*o );

		    // distance to cell 
		    float d = length(g - f + o);

		    // do the smooth min for colors and distances 
		    float3 col = 0.5 + 0.5*sin( VoronoiSmooth_hash1(dot(n+g,float2(7.0,113.0)))*2.5 + 3.5 + float3(2.0,3.0,0.0));
		    float h = smoothstep( 0.0, 1.0, 0.5 + 0.5*(m.x-d)/w );
		    m.x = mix( m.x, d, h ) - h*(1.0-h)*w/(1.0+3.0*w); // distanec
		    m.yzw = mix( m.yzw, col, h ) - h*(1.0-h)*w/(1.0+3.0*w); // cioloe
	   }
	   return m;
 }

struct VoronoiSmoothOutput 
{ 
	   float3 color; 
}; 

VoronoiSmoothOutput VoronoiSmoothFunc( float2 UV, float time ) 
{ 
	   float2 p = UV;
	   float k = 2.0 + 70.0 * pow( 0.5 + 0.5*sin(0.25*6.2831*time), 4.0 );
	   k = 0.5 - 0.5*cos(0.25*6.2831*time);
	   float4 c = VoronoiSmooth( 6.0*p, k, time );

	   float3 col = c.yzw;
	   col *= 1.0 - 0.8*c.x*step(p.y,0.33);
	   col *= mix(c.x,1.0,step(p.y,0.66));
	   col *= smoothstep( 0.005, 0.007, abs(p.y-0.33) );
	   col *= smoothstep( 0.005, 0.007, abs(p.y-0.66) );

	   VoronoiSmoothOutput OUT; 
	   OUT.color = col;
	   return OUT; 
} 

これで、カスタム コード ノードにこのコードを使用できるようになりました。次のように接続すると、ShaderFX エディタとビューポート 2.0(Viewport 2.0)OpenGL モードの両方でアニメーションを見ることができます。

DirectX 11 モードで作業する

DirectX 11 モードで同じ ShaderFX ネットワークを作成してからスウォッチ レンダリングを実行しようとすると、シェーダ スウォッチをコンパイルすることができません。デバッグを支援するには、設定 > スウォッチ コンパイル エラーを表示(Settings > Show Swatch Compile Errors)を選択し、表示されるエラーを検証します。

Maya の DirectX 11 モードで ShaderFX とともに使用できるようにコードを修正して SFX_HLSL_3/SFX_HLSL_5 との互換性を確保するには、次の手順を実行します。

  1. コードの最初に次の if/endif ステートメントを追加します。
    #if ( defined(SFX_HLSL_3) || defined( SFX_HLSL_5) )
    #define fract frac
    #define mix lerp
    #endif

修正されたコードは次のようになります。

#if ( defined(SFX_HLSL_3) || defined( SFX_HLSL_5) )
#define fract frac
#define mix lerp
#endif

float VoronoiSmooth_hash1( float n ) { return fract(sin(n)*43758.5453); }
float2 VoronoiSmooth_hash2( float2 p ) { p = float2( dot(p,float2(127.1,311.7)), dot(p,float2(269.5,183.3)) ); return fract(sin(p)*43758.5453); }

float4 VoronoiSmooth( in float2 x, float w, float time )
{
	   float2 n = floor( x );
	   float2 f = fract( x );

	   float4 m = float4( 8.0, 0.0, 0.0, 0.0 );
	   for( int j=-2; j<=2; j++ )
	   for( int i=-2; i<=2; i++ )
	   {
		     float2 g = float2( float(i),float(j) );
		     float2 o = VoronoiSmooth_hash2( n + g );
		     // animate
		     o = 0.5 + 0.5*sin( time + 6.2831*o );

		    // distance to cell 
		    float d = length(g - f + o);

		    // do the smooth min for colors and distances 
		    float3 col = 0.5 + 0.5*sin( VoronoiSmooth_hash1(dot(n+g,float2(7.0,113.0)))*2.5 + 3.5 + float3(2.0,3.0,0.0));
		    float h = smoothstep( 0.0, 1.0, 0.5 + 0.5*(m.x-d)/w );
		    m.x = mix( m.x, d, h ) - h*(1.0-h)*w/(1.0+3.0*w); // distanec
		    m.yzw = mix( m.yzw, col, h ) - h*(1.0-h)*w/(1.0+3.0*w); // cioloe
	   }
	   return m;
 }

struct VoronoiSmoothOutput 
{ 
	   float3 color; 
}; 

VoronoiSmoothOutput VoronoiSmoothFunc( float2 UV, float time ) 
{ 
	   float2 p = UV;
	   float k = 2.0 + 70.0 * pow( 0.5 + 0.5*sin(0.25*6.2831*time), 4.0 );
	   k = 0.5 - 0.5*cos(0.25*6.2831*time);
	   float4 c = VoronoiSmooth( 6.0*p, k, time );

	   float3 col = c.yzw;
	   col *= 1.0 - 0.8*c.x*step(p.y,0.33);
	   col *= mix(c.x,1.0,step(p.y,0.66));
	   col *= smoothstep( 0.005, 0.007, abs(p.y-0.33) );
	   col *= smoothstep( 0.005, 0.007, abs(p.y-0.66) );

	   VoronoiSmoothOutput OUT; 
	   OUT.color = col;
	   return OUT; 
} 

Custom Code ノードを使用して ShaderFX グラフを作成する

上記のコードを使用して Custom Code ノードを作成したら、以下のようなネットワークを作成することができます。

グループの作成と Default Value ノードの使用の詳細については、「グループ ノードに代替入力値を指定しグループ ノードのポートにラベルを付ける」を参照してください。

この例には既定の UV セットと既定のタイム ノードが用意されていますが、ユーザは別の UV セットを指定することもできます。

ビデオ チュートリアル

上記のワークフロー例の視覚的なデモンストレーションについては、次のビデオをご覧ください。