この例では、既存のシェーダ コードを取得し、これを 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 ); }
Maya の OpenGL モードで ShaderFX とともに使用できるようにコードを修正して SFX_GLSL_*/SFX_CGFX_3 との互換性を確保するには、次の手順を実行します。
gl_FragCoord.xy は、テクスチャ座標を取得するために GLSL で使用されるグローバル変数です。Maya では、テクスチャ座標を取得するために UV セットを使用します。
既定で Custom Code ノードに用意されているものと同様に、main (void) を関数定義に変更します。
CustomCode1178Output CustomCode1178Func( float2 UV )
struct CustomCode1178Output { float3 color; };
iGlobalTime を time に置き換えます。
入力パラメータとして関数定義に float time を追加します。
入力パラメータとして voronoi 関数定義に float time を追加します。
voronoi がコールされる入力パラメータとして time を追加します。
CustomCode1178Output OUT; OUT.color = col; return OUT;
修正されたコードは次のようになります。
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 モードで同じ ShaderFX ネットワークを作成してからスウォッチ レンダリングを実行しようとすると、シェーダ スウォッチをコンパイルすることができません。デバッグを支援するには、設定 > スウォッチ コンパイル エラーを表示(Settings > Show Swatch Compile Errors)を選択し、表示されるエラーを検証します。
Maya の DirectX 11 モードで ShaderFX とともに使用できるようにコードを修正して SFX_HLSL_3/SFX_HLSL_5 との互換性を確保するには、次の手順を実行します。
#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 ノードを作成したら、以下のようなネットワークを作成することができます。
グループの作成と Default Value ノードの使用の詳細については、「グループ ノードに代替入力値を指定しグループ ノードのポートにラベルを付ける」を参照してください。
この例には既定の UV セットと既定のタイム ノードが用意されていますが、ユーザは別の UV セットを指定することもできます。
上記のワークフロー例の視覚的なデモンストレーションについては、次のビデオをご覧ください。