Пример #1
0
depthShaderOverride::depthShaderOverride(const MObject& obj)
: MPxSurfaceShadingNodeOverride(obj)
, fFragmentName("")
{
	// Define fragments needed for VP2 version of shader, this could also be
	// defined in a separate XML file
	//
	// Define the input and output parameter names to match the input and
	// output attribute names so that the values are automatically populated
	// on the shader.
	//
	// Define a separate fragment for computing the camera space position so
	// that the operation can be done in the vertex shader rather than the
	// pixel shader. Then connect the two fragments together in a graph.
	static const MString sFragmentName("depthShaderPluginFragment");
	static const char* sFragmentBody =
		"<fragment uiName=\"depthShaderPluginFragment\" name=\"depthShaderPluginFragment\" type=\"plumbing\" class=\"ShadeFragment\" version=\"1.0\">"
		"	<description><![CDATA[Depth shader fragment]]></description>"
		"	<properties>"
		"		<float name=\"depthValue\" />"
		"		<float3 name=\"color\" />"
		"		<float3 name=\"colorFar\" />"
		"		<float name=\"near\" />"
		"		<float name=\"far\" />"
		"	</properties>"
		"	<values>"
		"		<float name=\"depthValue\" value=\"0.0\" />"
		"		<float3 name=\"color\" value=\"0.0,1.0,0.0\" />"
		"		<float3 name=\"colorFar\" value=\"0.0,0.0,1.0\" />"
		"		<float name=\"near\" value=\"0.0\" />"
		"		<float name=\"far\" value=\"2.0\" />"
		"	</values>"
		"	<outputs>"
		"		<float3 name=\"outColor\" />"
		"	</outputs>"
		"	<implementation>"
		"	<implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\">"
		"		<function_name val=\"depthShaderPluginFragment\" />"
		"		<source><![CDATA["
		"float3 depthShaderPluginFragment(float depthValue, float3 cNear, float3 cFar, float nearClip, float farClip) \n"
		"{ \n"
		"	float ratio = (farClip + depthValue)/(farClip - nearClip); \n"
		"	return cNear*ratio + cFar*(1.0f - ratio); \n"
		"} \n]]>"
		"		</source>"
		"	</implementation>"
		"	<implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\">"
		"		<function_name val=\"depthShaderPluginFragment\" />"
		"		<source><![CDATA["
		"float3 depthShaderPluginFragment(float depthValue, float3 cNear, float3 cFar, float nearClip, float farClip) \n"
		"{ \n"
		"	float ratio = (farClip + depthValue)/(farClip - nearClip); \n"
		"	return cNear*ratio + cFar*(1.0f - ratio); \n"
		"} \n]]>"
		"		</source>"
		"	</implementation>"
		"	<implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\">"
		"		<function_name val=\"depthShaderPluginFragment\" />"
		"		<source><![CDATA["
		"vec3 depthShaderPluginFragment(float depthValue, vec3 cNear, vec3 cFar, float nearClip, float farClip) \n"
		"{ \n"
		"	float ratio = (farClip + depthValue)/(farClip - nearClip); \n"
		"	return cNear*ratio + cFar*(1.0f - ratio); \n"
		"} \n]]>"
		"		</source>"
		"	</implementation>"
		"	</implementation>"
		"</fragment>";

	static const MString sVertexFragmentName("depthShaderPluginInterpolantFragment");
	static const char* sVertexFragmentBody =
		"<fragment uiName=\"depthShaderPluginInterpolantFragment\" name=\"depthShaderPluginInterpolantFragment\" type=\"interpolant\" class=\"ShadeFragment\" version=\"1.0\">"
		"	<description><![CDATA[Depth shader vertex fragment]]></description>"
		"	<properties>"
		"		<float3 name=\"Pm\" semantic=\"Pm\" flags=\"varyingInputParam\" />"
		"		<float4x4 name=\"worldViewProj\" semantic=\"worldviewprojection\" />"
		"	</properties>"
		"	<values>"
		"	</values>"
		"	<outputs>"
		"		<float name=\"outDepthValue\" ^1s/>"
		"	</outputs>"
		"	<implementation>"
		"	<implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\">"
		"		<function_name val=\"depthShaderPluginInterpolantFragment\" />"
		"		<source><![CDATA["
		"float depthShaderPluginInterpolantFragment(float depthValue) \n"
		"{ \n"
		"	return depthValue; \n"
		"} \n]]>"
		"		</source>"
		"		<vertex_source><![CDATA["
		"float idepthShaderPluginInterpolantFragment(float3 Pm, float4x4 worldViewProj) \n"
		"{ \n"
		"	float4 pCamera = mul(worldViewProj, float4(Pm, 1.0f)); \n"
		"	return (pCamera.z - pCamera.w*2.0f); \n"
		"} \n]]>"
		"		</vertex_source>"
		"	</implementation>"
		"	<implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\">"
		"		<function_name val=\"depthShaderPluginInterpolantFragment\" />"
		"		<source><![CDATA["
		"float depthShaderPluginInterpolantFragment(float depthValue) \n"
		"{ \n"
		"	return depthValue; \n"
		"} \n]]>"
		"		</source>"
		"		<vertex_source><![CDATA["
		"float idepthShaderPluginInterpolantFragment(float3 Pm, float4x4 worldViewProj) \n"
		"{ \n"
		"	float4 pCamera = mul(float4(Pm, 1.0f), worldViewProj); \n"
		"	return (pCamera.z - pCamera.w*2.0f); \n"
		"} \n]]>"
		"		</vertex_source>"
		"	</implementation>"
		"	<implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\">"
		"		<function_name val=\"depthShaderPluginInterpolantFragment\" />"
		"		<source><![CDATA["
		"float depthShaderPluginInterpolantFragment(float depthValue) \n"
		"{ \n"
		"	return depthValue; \n"
		"} \n]]>"
		"		</source>"
		"		<vertex_source><![CDATA["
		"float idepthShaderPluginInterpolantFragment(vec3 Pm, mat4 worldViewProj) \n"
		"{ \n"
		"	vec4 pCamera = worldViewProj * vec4(Pm, 1.0f); \n"
		"	return (pCamera.z - pCamera.w*2.0f); \n"
		"} \n]]>"
		"		</vertex_source>"
		"	</implementation>"
		"	</implementation>"
		"</fragment>";

	static const MString sFragmentGraphName("depthShaderPluginGraph");
	static const char* sFragmentGraphBody =
		"<fragment_graph name=\"depthShaderPluginGraph\" ref=\"depthShaderPluginGraph\" class=\"FragmentGraph\" version=\"1.0\">"
		"	<fragments>"
		"			<fragment_ref name=\"depthShaderPluginFragment\" ref=\"depthShaderPluginFragment\" />"
		"			<fragment_ref name=\"depthShaderPluginInterpolantFragment\" ref=\"depthShaderPluginInterpolantFragment\" />"
		"	</fragments>"
		"	<connections>"
		"		<connect from=\"depthShaderPluginInterpolantFragment.outDepthValue\" to=\"depthShaderPluginFragment.depthValue\" />"
		"	</connections>"
		"	<properties>"
        "		<float3 name=\"Pm\" ref=\"depthShaderPluginInterpolantFragment.Pm\" semantic=\"Pm\" flags=\"varyingInputParam\" />"
        "		<float4x4 name=\"worldViewProj\" ref=\"depthShaderPluginInterpolantFragment.worldViewProj\" semantic=\"worldviewprojection\" />"
		"		<float3 name=\"color\" ref=\"depthShaderPluginFragment.color\" />"
		"		<float3 name=\"colorFar\" ref=\"depthShaderPluginFragment.colorFar\" />"
		"		<float name=\"near\" ref=\"depthShaderPluginFragment.near\" />"
		"		<float name=\"far\" ref=\"depthShaderPluginFragment.far\" />"
		"	</properties>"
		"	<values>"
		"		<float3 name=\"color\" value=\"0.0,1.0,0.0\" />"
		"		<float3 name=\"colorFar\" value=\"0.0,0.0,1.0\" />"
		"		<float name=\"near\" value=\"0.0\" />"
		"		<float name=\"far\" value=\"2.0\" />"
		"	</values>"
		"	<outputs>"
		"		<float3 name=\"outColor\" ref=\"depthShaderPluginFragment.outColor\" />"
		"	</outputs>"
		"</fragment_graph>";

	// Register fragments with the manager if needed
	MHWRender::MRenderer* theRenderer = MHWRender::MRenderer::theRenderer();
	if (theRenderer)
	{
		MHWRender::MFragmentManager* fragmentMgr =
			theRenderer->getFragmentManager();
		if (fragmentMgr)
		{
			// Add fragments if needed
			bool fragAdded = fragmentMgr->hasFragment(sFragmentName);
			bool vertFragAdded = fragmentMgr->hasFragment(sVertexFragmentName);
			bool graphAdded = fragmentMgr->hasFragment(sFragmentGraphName);
			if (!fragAdded)
			{
				fragAdded = (sFragmentName == fragmentMgr->addShadeFragmentFromBuffer(sFragmentBody, false));
			}
			if (!vertFragAdded)
			{
				// In DirectX, need to specify a semantic for the output of the vertex shader
				MString vertBody;
				if (theRenderer->drawAPI() == MHWRender::kDirectX11)
				{
					vertBody.format(MString(sVertexFragmentBody), MString("semantic=\"extraDepth\" "));
				}
				else
				{
					vertBody.format(MString(sVertexFragmentBody), MString(" "));
				}
				vertFragAdded = (sVertexFragmentName == fragmentMgr->addShadeFragmentFromBuffer(vertBody.asChar(), false));
			}
			if (!graphAdded)
			{
				graphAdded = (sFragmentGraphName == fragmentMgr->addFragmentGraphFromBuffer(sFragmentGraphBody));
			}

			// If we have them all, use the final graph for the override
			if (fragAdded && vertFragAdded && graphAdded)
			{
				fFragmentName = sFragmentGraphName;
			}
		}
	}
}
// Static fragment registration/deregistration methods called from plugin
// init/unint functions. Only need to be called once.
MStatus simpleNoiseShaderOverride::registerFragments()
{
	// Get fragment manager for registration
	MHWRender::MFragmentManager* fragmentMgr =
		MHWRender::MRenderer::theRenderer()
			? MHWRender::MRenderer::theRenderer()->getFragmentManager()
			: NULL;
	// No fragment manager, fail
	if (!fragmentMgr) return MS::kFailure;
	// Fragments are already registered, return success
	if (fragmentMgr->hasFragment(sFinalFragmentGraphName)) return MS::kSuccess;

	MString fragmentName;
	char* fragmentBody = NULL;

	// ------------------------------------------------------------------------
	// Struct declaration fragment. This fragment provides the declaration of
	// the output structure of the simple noise fragment graph giving support
	// for multiple outputs. The struct fragment must be a part of the final
	// fragment graph in order to ensure that the fragment system includes
	// the declaration of the struct in the final effect.
	//
	fragmentName = "simpleNoiseOutput";
	fragmentBody =
		"<fragment uiName=\"simpleNoiseOutput\" name=\"simpleNoiseOutput\" type=\"structure\" class=\"ShadeFragment\" version=\"1.0\"> \r\n"
		"	<description><![CDATA[Struct output for simple noise shader]]></description> \r\n"
		"	<properties> \r\n"
		"		<struct name=\"simpleNoiseOutput\" struct_name=\"simpleNoiseOutput\" /> \r\n"
		"	</properties> \r\n"
		"	<values> \r\n"
		"	</values> \r\n"
		"	<outputs> \r\n"
		"		<alias name=\"simpleNoiseOutput\" struct_name=\"simpleNoiseOutput\" /> \r\n"
		"		<float3 name=\"outColor\" /> \r\n"
		"		<float name=\"outAlpha\" /> \r\n"
		"	</outputs> \r\n"
		"	<implementation> \r\n"
		"	<implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\"> \r\n"
		"		<function_name val=\"\" /> \r\n"
		"		<declaration name=\"simpleNoiseOutput\"><![CDATA[ \r\n"
		"struct simpleNoiseOutput \r\n"
		"{ \r\n"
		"	float3 outColor; \r\n"
		"	float outAlpha; \r\n"
		"}; \r\n"
		"		]]></declaration> \r\n"
		"	</implementation> \r\n"
		"	<implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\"> \r\n"
		"		<function_name val=\"\" /> \r\n"
		"		<declaration name=\"simpleNoiseOutput\"><![CDATA[ \r\n"
		"struct simpleNoiseOutput \r\n"
		"{ \r\n"
		"	float3 outColor; \r\n"
		"	float outAlpha; \r\n"
		"}; \r\n"
		"		]]></declaration> \r\n"
		"	</implementation> \r\n"
		"	<implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\"> \r\n"
		"		<function_name val=\"\" /> \r\n"
		"		<declaration name=\"simpleNoiseOutput\"><![CDATA[ \r\n"
		"struct simpleNoiseOutput \r\n"
		"{ \r\n"
		"	vec3 outColor; \r\n"
		"	float outAlpha; \r\n"
		"}; \r\n"
		"		]]></declaration> \r\n"
		"	</implementation> \r\n"
		"	</implementation> \r\n"
		"</fragment> \r\n";
	if (fragmentName != fragmentMgr->addShadeFragmentFromBuffer(fragmentBody, false)) return MS::kFailure;

	// ------------------------------------------------------------------------
	// Actual noise computation fragment. Based on Maya's "wave" noise type
	// from the 2d procedural noise texture node. Computes a struct output
	// containing both color and alpha to match the outputs of the DG node.
	// Uses a 3D texture loaded with the entire Maya noise table for generating
	// results consistent with the compute() method of the associated node.
	//
	fragmentName = "simpleNoiseBase";
	fragmentBody =
		"<fragment uiName=\"simpleNoiseBase\" name=\"simpleNoiseBase\" type=\"plumbing\" class=\"ShadeFragment\" version=\"1.0\"> \r\n"
		"	<description><![CDATA[Computes simple 2D procedural noise]]></description> \r\n"
		"	<properties> \r\n"
		"		<float2 name=\"uvCoord\" semantic=\"mayaUvCoordSemantic\" flags=\"varyingInputParam\" /> \r\n"
		"		<texture3 name=\"noiseLookupMap\" /> \r\n"
		"		<sampler name=\"noiseLookupMapSampler\" /> \r\n"
		"		<float name=\"amplitude\" /> \r\n"
		"		<float name=\"ratio\" /> \r\n"
		"		<int name=\"depthMax\" /> \r\n"
		"		<float name=\"frequency\" /> \r\n"
		"		<float name=\"frequencyRatio\" /> \r\n"
		"		<float name=\"time\" /> \r\n"
		"		<int name=\"numWaves\" /> \r\n"
		"	</properties> \r\n"
		"	<values> \r\n"
		"		<float name=\"amplitude\" value=\"1.0\" /> \r\n"
		"		<float name=\"ratio\" value=\"0.707000\" /> \r\n"
		"		<int name=\"depthMax\" value=\"3\" /> \r\n"
		"		<float name=\"frequency\" value=\"8.0\" /> \r\n"
		"		<float name=\"frequencyRatio\" value=\"2.0\" /> \r\n"
		"		<float name=\"time\" value=\"0.0\" /> \r\n"
		"		<int name=\"numWaves\" value=\"5\" /> \r\n"
		"	</values> \r\n"
		"	<outputs> \r\n"
		"		<struct name=\"simpleNoiseBase\" struct_name=\"simpleNoiseOutput\" /> \r\n"
		"	</outputs> \r\n"
		"	<implementation> \r\n"
		"	<implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\"> \r\n"
		"		<function_name val=\"simpleNoise\" /> \r\n"
		"		<source><![CDATA[ \r\n"
		"float simpleNoise_RawNoiseLookup( \r\n"
		"	int index, \r\n"
		"	texture3D noiseLookupMap, \r\n"
		"	sampler3D noiseLookupMapSampler) \r\n"
		"{ \r\n"
		"	int3 index3; \r\n"
		"	index3.x = index; \r\n"
		"	index3.y = (index>> 5); \r\n"
		"	index3.z = (index>> 10); \r\n"
		"	index3 &= 31; \r\n"
		"	float3 uvw = float3(index3) / 32.0f; \r\n"
		"	return (tex3D(noiseLookupMapSampler, uvw).r * 2.0f) - 1.0f; \r\n"
		"} \r\n"
		"simpleNoiseOutput simpleNoise( \r\n"
		"	float2 uv, \r\n"
		"	texture3D noiseLookupMap, \r\n"
		"	sampler3D noiseLookupMapSampler, \r\n"
		"	float amplitude, \r\n"
		"	float ratio, \r\n"
		"	int depthMax, \r\n"
		"	float frequency, \r\n"
		"	float frequencyRatio, \r\n"
		"	float time, \r\n"
		"	int numWaves) \r\n"
		"{ \r\n"
		"	const float M_PI = 3.1415926535897f; \r\n"
		"	const float M_2PI = 2.0f*M_PI; \r\n"
		"	simpleNoiseOutput finalResult; \r\n"
		"	float timeRatio = sqrt(frequencyRatio); \r\n"
		"	uv *= frequency; \r\n"
		"	float cosine = 0.0f; \r\n"
		"	float noise = 0.0f; \r\n"
		"	int depthId = 0; \r\n"
		"	int waveId = 0; \r\n"
		"	int seedOffset = 0; \r\n"
		"	while (depthId<depthMax && waveId<numWaves) { \r\n"
		"		int step = depthId; \r\n"
		"		int seed = 50*step; \r\n"
		"		float2 dir = float2( \r\n"
		"			simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMap, noiseLookupMapSampler), \r\n"
		"			simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMap, noiseLookupMapSampler)); \r\n"
		"		float norm = length(dir); \r\n"
		"		if (norm <= 0.0f) continue; \r\n"
		"		dir /= norm; \r\n"
		"		noise += cos(dir.x*uv.x*M_2PI + dir.y*uv.y*M_2PI + M_PI*simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMap, noiseLookupMapSampler) + time*M_PI); \r\n"
		"		++waveId; \r\n"
		"		if (waveId < numWaves) continue; \r\n"
		"		noise /= float(numWaves); \r\n"
		"		uv *= frequencyRatio; \r\n"
		"		time *= timeRatio; \r\n"
		"		cosine += amplitude * noise; \r\n"
		"		amplitude *= ratio; \r\n"
		"		noise = 0.0f; \r\n"
		"		waveId = 0; \r\n"
		"		seedOffset = 0; \r\n"
		"		++depthId; \r\n"
		"	} \r\n"
		"	cosine = 0.5f*cosine + 0.5f; \r\n"
		"	float noiseVal = (cosine> 1.0f) ? 1.0f : cosine; \r\n"
		"	finalResult.outColor = float3(noiseVal, noiseVal, noiseVal); \r\n"
		"	finalResult.outAlpha = noiseVal; \r\n"
		"	return finalResult; \r\n"
		"} \r\n"
		"		]]></source> \r\n"
		"	</implementation> \r\n"
		"	<implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\"> \r\n"
		"		<function_name val=\"simpleNoise\" /> \r\n"
		"		<source><![CDATA[ \r\n"
		"float simpleNoise_RawNoiseLookup( \r\n"
		"	int index, \r\n"
		"	Texture3D noiseLookupMap, \r\n"
		"	sampler noiseLookupMapSampler) \r\n"
		"{ \r\n"
		"	int3 index3; \r\n"
		"	index3.x = index; \r\n"
		"	index3.y = (index>> 5); \r\n"
		"	index3.z = (index>> 10); \r\n"
		"	index3 &= 31; \r\n"
		"	float3 uvw = float3(index3) / 32.0f; \r\n"
		"	return (noiseLookupMap.SampleLevel(noiseLookupMapSampler, uvw, 0).r * 2.0f) - 1.0f; \r\n"
		"} \r\n"
		"simpleNoiseOutput simpleNoise( \r\n"
		"	float2 uv, \r\n"
		"	Texture3D noiseLookupMap, \r\n"
		"	sampler noiseLookupMapSampler, \r\n"
		"	float amplitude, \r\n"
		"	float ratio, \r\n"
		"	int depthMax, \r\n"
		"	float frequency, \r\n"
		"	float frequencyRatio, \r\n"
		"	float time, \r\n"
		"	int numWaves) \r\n"
		"{ \r\n"
		"	const float M_PI = 3.1415926535897f; \r\n"
		"	const float M_2PI = 2.0f*M_PI; \r\n"
		"	simpleNoiseOutput finalResult; \r\n"
		"	float timeRatio = sqrt(frequencyRatio); \r\n"
		"	uv *= frequency; \r\n"
		"	float cosine = 0.0f; \r\n"
		"	float noise = 0.0f; \r\n"
		"	int depthId = 0; \r\n"
		"	int waveId = 0; \r\n"
		"	int seedOffset = 0; \r\n"
		"	while (depthId<depthMax && waveId<numWaves) { \r\n"
		"		int step = depthId; \r\n"
		"		int seed = 50*step; \r\n"
		"		float2 dir = float2( \r\n"
		"			simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMap, noiseLookupMapSampler), \r\n"
		"			simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMap, noiseLookupMapSampler)); \r\n"
		"		float norm = length(dir); \r\n"
		"		if (norm <= 0.0f) continue; \r\n"
		"		dir /= norm; \r\n"
		"		noise += cos(dir.x*uv.x*M_2PI + dir.y*uv.y*M_2PI + M_PI*simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMap, noiseLookupMapSampler) + time*M_PI); \r\n"
		"		++waveId; \r\n"
		"		if (waveId < numWaves) continue; \r\n"
		"		noise /= float(numWaves); \r\n"
		"		uv *= frequencyRatio; \r\n"
		"		time *= timeRatio; \r\n"
		"		cosine += amplitude * noise; \r\n"
		"		amplitude *= ratio; \r\n"
		"		noise = 0.0f; \r\n"
		"		waveId = 0; \r\n"
		"		seedOffset = 0; \r\n"
		"		++depthId; \r\n"
		"	} \r\n"
		"	cosine = 0.5f*cosine + 0.5f; \r\n"
		"	float noiseVal = (cosine> 1.0f) ? 1.0f : cosine; \r\n"
		"	finalResult.outColor = float3(noiseVal, noiseVal, noiseVal); \r\n"
		"	finalResult.outAlpha = noiseVal; \r\n"
		"	return finalResult; \r\n"
		"} \r\n"
		"		]]></source> \r\n"
		"	</implementation> \r\n"
		"	<implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\"> \r\n"
		"		<function_name val=\"simpleNoise\" /> \r\n"
		"		<source><![CDATA[ \r\n"
		"float simpleNoise_RawNoiseLookup( \r\n"
		"	int index, \r\n"
		"	sampler3D noiseLookupMapSampler) \r\n"
		"{ \r\n"
		"	ivec3 index3; \r\n"
		"	index3.x = index; \r\n"
		"	index3.y = (index >> 5); \r\n"
		"	index3.z = (index >> 10); \r\n"
		"	index3 &= 31; \r\n"
		"	vec3 uvw = vec3(index3) / 32.0f; \r\n"
		"	return (texture(noiseLookupMapSampler, uvw).r * 2.0f) - 1.0f; \r\n"
		"} \r\n"
		"simpleNoiseOutput simpleNoise( \r\n"
		"	vec2 uv, \r\n"
		"	sampler3D noiseLookupMapSampler, \r\n"
		"	float amplitude, \r\n"
		"	float ratio, \r\n"
		"	int depthMax, \r\n"
		"	float frequency, \r\n"
		"	float frequencyRatio, \r\n"
		"	float time, \r\n"
		"	int numWaves) \r\n"
		"{ \r\n"
		"	const float M_PI = 3.1415926535897f; \r\n"
		"	const float M_2PI = 2.0f*M_PI; \r\n"
		"	simpleNoiseOutput finalResult; \r\n"
		"	float timeRatio = sqrt(frequencyRatio); \r\n"
		"	uv *= frequency; \r\n"
		"	float cosine = 0.0f; \r\n"
		"	float noise = 0.0f; \r\n"
		"	int depthId = 0; \r\n"
		"	int waveId = 0; \r\n"
		"	int seedOffset = 0; \r\n"
		"	while (depthId<depthMax && waveId<numWaves) { \r\n"
		"		int step = depthId; \r\n"
		"		int seed = 50*step; \r\n"
		"		vec2 dir = vec2( \r\n"
		"			simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMapSampler), \r\n"
		"			simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMapSampler)); \r\n"
		"		float norm = length(dir); \r\n"
		"		if (norm <= 0.0f) continue; \r\n"
		"		dir /= norm; \r\n"
		"		noise += cos(dir.x*uv.x*M_2PI + dir.y*uv.y*M_2PI + M_PI*simpleNoise_RawNoiseLookup(seed + seedOffset++, noiseLookupMapSampler) + time*M_PI); \r\n"
		"		++waveId; \r\n"
		"		if (waveId < numWaves) continue; \r\n"
		"		noise /= float(numWaves); \r\n"
		"		uv *= frequencyRatio; \r\n"
		"		time *= timeRatio; \r\n"
		"		cosine += amplitude * noise; \r\n"
		"		amplitude *= ratio; \r\n"
		"		noise = 0.0f; \r\n"
		"		waveId = 0; \r\n"
		"		seedOffset = 0; \r\n"
		"		++depthId; \r\n"
		"	} \r\n"
		"	cosine = 0.5f*cosine + 0.5f; \r\n"
		"	float noiseVal = (cosine > 1.0f) ? 1.0f : cosine; \r\n"
		"	finalResult.outColor = vec3(noiseVal, noiseVal, noiseVal); \r\n"
		"	finalResult.outAlpha = noiseVal; \r\n"
		"	return finalResult; \r\n"
		"} \r\n"
		"		]]></source> \r\n"
		"	</implementation> \r\n"
		"	</implementation> \r\n"
		"</fragment> \r\n";
	if (fragmentName != fragmentMgr->addShadeFragmentFromBuffer(fragmentBody, false)) return MS::kFailure;

	// ------------------------------------------------------------------------
	// Full, final graph made up of previously registered fragments. A picture
	// which flows from top to bottom.
	//
	//                         simpleNoiseBase
	//                                |
	//                        simpleNoiseOutput
	//                                |
	//                          <FINAL RESULT>
	//
	// Maya's shader translation system will take this graph and connect UV
	// information where appropriate.
	//
	// From Maya's point of view, this graph is fully representative of the
	// associated shading node in the DG. All inputs and outputs on this graph
	// are matched to inputs and outputs on the DG node. Connections to other
	// nodes (input or output) will be mirrored by connections to other
	// fragments using the matching parameters.
	//
	fragmentName = sFinalFragmentGraphName;
	fragmentBody =
		"<fragment_graph name=\"simpleNoise\" ref=\"simpleNoise\" class=\"FragmentGraph\" version=\"1.0\"> \r\n"
		"	<fragments> \r\n"
		"		<fragment_ref name=\"simpleNoiseBase\" ref=\"simpleNoiseBase\" /> \r\n"
		"		<fragment_ref name=\"simpleNoiseOutput\" ref=\"simpleNoiseOutput\" /> \r\n"
		"	</fragments> \r\n"
		"	<connections> \r\n"
		"		<connect from=\"simpleNoiseBase.simpleNoiseBase\" to=\"simpleNoiseOutput.simpleNoiseOutput\" name=\"simpleNoiseOutput\" /> \r\n"
		"	</connections> \r\n"
		"	<properties> \r\n"
		"		<float2 name=\"uvCoord\" ref=\"simpleNoiseBase.uvCoord\" semantic=\"mayaUvCoordSemantic\" flags=\"varyingInputParam\" /> \r\n"
		"		<texture3 name=\"noiseLookupMap\" ref=\"simpleNoiseBase.noiseLookupMap\" /> \r\n"
		"		<sampler name=\"noiseLookupMapSampler\" ref=\"simpleNoiseBase.noiseLookupMapSampler\" /> \r\n"
		"		<float name=\"amplitude\" ref=\"simpleNoiseBase.amplitude\" /> \r\n"
		"		<float name=\"ratio\" ref=\"simpleNoiseBase.ratio\" /> \r\n"
		"		<int name=\"depthMax\" ref=\"simpleNoiseBase.depthMax\" /> \r\n"
		"		<float name=\"frequency\" ref=\"simpleNoiseBase.frequency\" /> \r\n"
		"		<float name=\"frequencyRatio\" ref=\"simpleNoiseBase.frequencyRatio\" /> \r\n"
		"		<float name=\"time\" ref=\"simpleNoiseBase.time\" /> \r\n"
		"		<int name=\"numWaves\" ref=\"simpleNoiseBase.numWaves\" /> \r\n"
		"	</properties> \r\n"
		"	<values> \r\n"
		"		<float name=\"amplitude\" value=\"1.0\" /> \r\n"
		"		<float name=\"ratio\" value=\"0.707000\" /> \r\n"
		"		<int name=\"depthMax\" value=\"3\" /> \r\n"
		"		<float name=\"frequency\" value=\"8.0\" /> \r\n"
		"		<float name=\"frequencyRatio\" value=\"2.0\" /> \r\n"
		"		<float name=\"time\" value=\"0.0\" /> \r\n"
		"		<int name=\"numWaves\" value=\"5\" /> \r\n"
		"	</values> \r\n"
		"	<outputs> \r\n"
		"		<struct name=\"simpleNoiseOutput\" ref=\"simpleNoiseOutput.simpleNoiseOutput\" /> \r\n"
		"	</outputs> \r\n"
		"</fragment_graph> \r\n";
	if (fragmentName != fragmentMgr->addFragmentGraphFromBuffer(fragmentBody)) return MS::kFailure;

	return MS::kSuccess;
}