void TranslateMatrices(HlslStructure.ShaderStatement[] elements, int callDepth, ShaderExtension extension)
		{
			bool isInstancing = extension == ShaderExtension.Instancing;
			List<int> skipFinalRemappingIndices = new List<int>();

			int processingMul = 0, depth = 0, arg = 0;
			int argStart = 0, argEnd = 0;
			int remapArg = -1;
			int remapIndex = 0;
			MatrixMapping remapping = new MatrixMapping();

			Stack<int> mulStart = new Stack<int>();
			Stack<int> mulDepth = new Stack<int>();
			Stack<int> mulArg = new Stack<int>();
			Stack<int> mulArgStart = new Stack<int>();
			Stack<int> mulArgEnd = new Stack<int>();
			Stack<int> mulRemap = new Stack<int>();
			Stack<int> mulRemapIdx = new Stack<int>();
			Stack<MatrixMapping> mulRemapping = new Stack<MatrixMapping>();

			for (int i = 0; i < elements.Length; i++)
			{
				string line = elements[i].Statement;

				if (line == "mul")
				{
					processingMul++;
					mulStart.Push(i);
					mulDepth.Push(depth);
					mulArg.Push(arg);
					mulArgEnd.Push(argEnd);
					mulArgStart.Push(argStart);
					mulRemap.Push(remapArg);
					mulRemapping.Push(remapping);
					mulRemapIdx.Push(remapIndex);

					depth = 0;
					arg = 0;
					argStart = 0;
					argEnd = 0;
					remapArg = -1;
					remapIndex = 0;
					remapping = new MatrixMapping();
				}

				MatrixMapping mapping;
				if (processingMul > 0 && depth == 1 && matrixRemap.TryGetValue(line, out mapping) && (mapping.BaseName != null || !isInstancing))
				{
					remapArg = arg;
					remapping = mapping;
					remapIndex = i;
				}

				if (processingMul > 0 && line == "(")
				{
					if (depth == 0)
						argStart = i;
					depth++;
				}

				if (processingMul > 0 && depth == 1 && line == ",")
				{
					if (depth == 1)
						argEnd = i;
					arg++;
				}

				if (processingMul > 0 && line == ")")
				{
					depth--;
					if (depth == 0)
					{
						string baseMatrix = remapping.Name;
						if (isInstancing)
							baseMatrix = remapping.BaseName;

						string prefix = "";
						int startPrefix = -1;
						if (remapArg == 1)
							startPrefix = argEnd;
						if (remapArg == 0)
							startPrefix = argStart;

						if (remapIndex > startPrefix && startPrefix != -1)
						{
							for (int p = startPrefix + 1; p < remapIndex; p++)
								prefix += elements[p].Statement + " ";
						}

						//right, see if the args need modifying.
						if (remapArg == 1)
						{
							//a known remapping matrix was used.
							var element = elements[remapIndex];
							elements[remapIndex] = new HlslStructure.ShaderStatement(baseMatrix, element.Line);

							element = elements[argStart];
							elements[argStart] = new HlslStructure.ShaderStatement("(mul(", element.Line);

							element = elements[argEnd];
							elements[argEnd] = new HlslStructure.ShaderStatement("," + prefix + worldMatrixName + "),", element.Line);

							if (!isInstancing)
								skipFinalRemappingIndices.Add(remapIndex);
						}

						if (remapArg == 0) // transpose
						{
							//a known remapping matrix was used.
							var element = elements[remapIndex];
							elements[remapIndex] = new HlslStructure.ShaderStatement(baseMatrix, element.Line);

							element = elements[argEnd];
							elements[argEnd] = new HlslStructure.ShaderStatement(",mul(" + prefix + worldMatrixName + ",", element.Line);

							element = elements[i];
							elements[i] = new HlslStructure.ShaderStatement("))", element.Line);

							if (!isInstancing)
								skipFinalRemappingIndices.Add(remapIndex);
						}


						processingMul--;
						mulStart.Pop();
						depth = mulDepth.Pop();
						arg = mulArg.Pop();
						argEnd = mulArgEnd.Pop();
						argStart = mulArgStart.Pop();
						remapArg = mulRemap.Pop();
						remapping = mulRemapping.Pop();
						remapIndex = mulRemapIdx.Pop();
					}
				}
			}

			//find unremapped matrices
			if (callDepth > 0)
			{
				for (int i = 0; i < elements.Length; i++)
				{
					//it is intended that this matrix reference is not modified.
					if (!isInstancing && skipFinalRemappingIndices.Contains(i))
						continue;

					MatrixMapping mapping;
					if (matrixRemap.TryGetValue(elements[i].Statement, out mapping))
						elements[i] = new HlslStructure.ShaderStatement(mapping.RemapTo, elements[i].Line);
				}
			}
		}
		void TranslateMethodNames(HlslStructure.ShaderStatement[] elements, int callDepth, ShaderExtension extension)
		{
			for (int i = 0; i < elements.Length; i++)
			{
				string methodName = elements[i].Statement;

				bool multArg;
				if (methodNames.TryGetValue(methodName, out multArg))
				{
					BuildMethod(methodName, extension);

					//find the method start
					for (int n = i+1; n < elements.Length; n++)
					{
						if (elements[n] == "(")
						{
							string argAppend = multArg ? ", " : "";
							//append the method signatures
							if (callDepth == 0)
								elements[n] = new HlslStructure.ShaderStatement("(" + this.methodSignatureAppend + argAppend, elements[n].Line);
							else
								elements[n] = new HlslStructure.ShaderStatement("(" + this.methodCallAppend + argAppend, elements[n].Line);

							elements[i] = new HlslStructure.ShaderStatement(ToInternalMethodName(methodName,extension), elements[i].Line);
							break;
						}
					}
				}
			}
		}