此示例演示了如何获取现有的着色器代码并在 Maya 中为 GLSL/CgFX 环境对其进行自定义,以便可以在 OpenGL 模式下将它与 ShaderFX 一起使用。然后,该示例演示了如何为 HLSL 环境自定义代码,以便也可以在 Maya 中在 DirectX 11 模式下使用。
本例中所用的着色器代码取自 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 ); }
若要修改此代码,使其与 SFX_GLSL_*/SFX_CGFX_3 兼容,以便可以在 Maya 中在 OpenGL 模式下与 ShaderFX 一起使用,请执行以下操作:
gl_FragCoord.xy 是 GLSL 中所用的一个全局变量,用于获得纹理坐标。在 Maya 中,您使用 UV 集来获得纹理坐标。
将 main (void) 更改为函数定义,使其与“自定义代码”(Custom Code)节点默认提供的函数定义类似:
CustomCode1178Output CustomCode1178Func( float2 UV )
struct CustomCode1178Output { float3 color; };
将 iGlobalTime 替换为 time。
将 float time 作为输入参数添加到函数定义中。
将 float time 作为输入参数添加到 voronoi 函数定义中。
添加 time 作为名为 voronoi 的输入参数。
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 编辑器中和 Viewport 2.0 OpenGL 模式下证明其动画。
如果在 DirectX 11 模式下创建相同的 ShaderFX 网络,然后尝试执行样例渲染,则无法编译着色器样例。为帮助调试,请选择“设置 > 显示样例编译错误”(Settings > Show Swatch Compile Errors)并检查出现的错误。
若要修改此代码,使其与 SFX_HLSL_3/SFX_HLSL_5 兼容,以便可以在 Maya 中在 DirectX 11 模式下与 ShaderFX 一起使用,请执行以下操作:
#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 集。
观看以下形象地演示上述工作流示例的视频: