hlslSm3FXShader.cpp

//-
// ==========================================================================
// Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+

#include <maya/MGlobal.h>

#include "Platform.h"
#include "hlslSm3FXShader.h"

#include "ResourceManager.h"

const char header[] =
"///////////////////////////////////////////////////////////////////////////////\n"
"//\n"
"// Copyright 2003, ATI Technologies, Inc., All rights reserved.\n"
"//\n"
"// Permission to use, copy, modify, and distribute this software and its \n"
"// documentation for any purpose and without fee is hereby granted,\n"
"// provided that the above copyright notice appear in all copies and derivative\n"
"// works and that both the copyright notice and this permission notice appear in\n"
"// support documentation, and that the name of ATI Technologies, Inc. not be used\n"
"// in advertising or publicity pertaining to distribution of the software without\n"
"// specific, written prior permission.\n"
"//\n"
"///////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// Ashli native operator -> GLSL\n"
"\n"
"float Add(float f0, float f1) { return f0 + f1; }\n"
"vec2 Add(float f, vec2 v) { return f + v; }\n"
"vec2 Add(vec2 v, float f) { return v + f; }\n"
"vec2 Add(vec2 v0,  vec2 v1) { return v0 + v1; }\n"
"vec3 Add(float f, vec3 v) { return f + v; }\n"
"vec3 Add(vec3 v, float f) { return v + f; }\n"
"vec3 Add(vec3 v0,  vec3 v1) { return v0 + v1; }\n"
"vec4 Add(float f, vec4 v) { return f + v; }\n"
"vec4 Add(vec4 v, float f) { return v + f; }\n"
"vec4 Add(vec4 v0,  vec4 v1) { return v0 + v1; }\n"
"mat2 Add(float f, mat2 m) { return m + f; }\n"
"mat2 Add(mat2 m, float f) { return m + f; }\n"
"mat2 Add(mat2 m0, mat2 m1) { return m0 + m1; }\n"
"\n"
"float Subtract(float f0, float f1) { return f0 - f1; }\n"
"vec2 Subtract(float f, vec2 v) { return f - v; }\n"
"vec2 Subtract(vec2 v, float f) { return v - f; }\n"
"vec2 Subtract(vec2 v0, vec2 v1) { return v0 - v1; }\n"
"vec3 Subtract(float f, vec3 v) { return f - v; }\n"
"vec3 Subtract(vec3 v, float f) { return v - f; }\n"
"vec3 Subtract(vec3 v0, vec3 v1) { return v0 - v1; }\n"
"vec4 Subtract(float f, vec4 v) { return f - v; }\n"
"vec4 Subtract(vec4 v, float f) { return v - f; }\n"
"vec4 Subtract(vec4 v0, vec4 v1) { return v0 - v1; }\n"
"mat2 Subtract(float f, mat2 m) { return f - m; }\n"
"mat2 Subtract(mat2 m, float f) { return m - f; }\n"
"mat2 Subtract(mat2 m0, mat2 m1) { return m0 - m1; }\n"
"\n"
"float Multiply(float f0, float f1) { return f0 * f1; }\n"
"vec2 Multiply(float f, vec2 v) { return f * v; }\n"
"vec2 Multiply(vec2 v, float f) { return v * f; }\n"
"vec2 Multiply(vec2 v0, vec2 v1) { return v0 * v1; }\n"
"vec3 Multiply(float f, vec3 v) { return f * v; }\n"
"vec3 Multiply(vec3 v, float f) { return v * f; }\n"
"vec3 Multiply(vec3 v0, vec3 v1) { return v0 * v1; }\n"
"vec4 Multiply(float f, vec4 v) { return f * v; }\n"
"vec4 Multiply(vec4 v, float f) { return v * f; }\n"
"vec4 Multiply(vec4 v0, vec4 v1) { return v0 * v1; }\n"
"mat2 Multiply(float f, mat2 m) { return f * m; }\n"
"mat2 Multiply(mat2 m, float f) { return m * f; }\n"
"vec2 Multiply(mat2 m, vec2 v) { return m * v; }\n"
"vec2 Multiply(vec2 v, mat2 m) { return v * m; }\n"
"mat2 Multiply(mat2 m0, mat2 m1) { return m0 * m1; }\n"
"mat3 Multiply(float f, mat3 m) { return f * m; }\n"
"mat3 Multiply(mat3 m, float f) { return m * f; }\n"
"vec3 Multiply(mat3 m, vec3 v) { return m * v; }\n"
"vec3 Multiply(vec3 v, mat3 m) { return v * m; }\n"
"mat3 Multiply(mat3 m0, mat3 m1) { return m0 * m1; }\n"
"mat4 Multiply(float f, mat4 m) { return f * m; }\n"
"mat4 Multiply(mat4 m, float f) { return m * f; }\n"
"vec4 Multiply(mat4 m, vec4 v) { return m * v; }\n"
"vec4 Multiply(vec4 v, mat4 m) { return v * m; }\n"
"mat4 Multiply(mat4 m0, mat4 m1) { return m0 * m1; }\n"
"\n"
"float Divide(float f0, float f1) { return f0 / f1; }\n"
"vec2 Divide(vec2 v, float f) { return v / f; }\n"
"vec2 Divide(float f, vec2 v) { return f / v; }\n"
"vec2 Divide(vec2 v0, vec2 v1) { return v0 / v1; }\n"
"vec3 Divide(vec3 v, float f) { return v / f; }\n"
"vec3 Divide(float f, vec3 v) { return f / v; }\n"
"vec3 Divide(vec3 v0, vec3 v1) { return v0 / v1; }\n"
"vec4 Divide(vec4 v, float f) { return v / f; }\n"
"vec4 Divide(float f, vec4 v) { return f / v; }\n"
"vec4 Divide(vec4 v0, vec4 v1) { return v0 / v1; }\n"
"mat2 Divide(mat2 m, float f) { return m / f; }\n"
"mat2 Divide(float f, mat2 m) { return f / m; }\n"
"mat2 Divide(mat2 m0, mat2 m1) { return m0 / m1; }\n"
"mat3 Divide(mat3 m, float f) { return m / f; }\n"
"mat3 Divide(float f, mat3 m) { return f / m; }\n"
"mat3 Divide(mat3 m0, mat3 m1) { return m0 / m1; }\n"
"mat4 Divide(mat4 m, float f) { return m / f; }\n"
"mat4 Divide(float f, mat4 m) { return f / m; }\n"
"mat4 Divide(mat4 m0, mat4 m1) { return m0 / m1; }\n"
"\n"
"float MultiplyAdd(float f0, float f1, float f2) { return f0 * f1 + f2; }\n"
"vec2 MultiplyAdd(float f0, vec2 v1, vec2 v2) { return f0 * v1 + v2; }\n"
"vec3 MultiplyAdd(float f0, vec3 v1, vec3 v2) { return f0 * v1 + v2; }\n"
"vec4 MultiplyAdd(float f0, vec4 v1, vec4 v2) { return f0 * v1 + v2; }\n"
"vec2 MultiplyAdd(vec2 v0, float f1, vec2 v2) { return v0 * f1 + v2; }\n"
"vec3 MultiplyAdd(vec3 v0, float f1, vec3 v2) { return v0 * f1 + v2; }\n"
"vec4 MultiplyAdd(vec4 v0, float f1, vec4 v2) { return v0 * f1 + v2; }\n"
"vec2 MultiplyAdd(vec2 v0, vec2 v1, float f2) { return v0 * v1 + f2; }\n"
"vec3 MultiplyAdd(vec3 v0, vec3 v1, float f2) { return v0 * v1 + f2; }\n"
"vec4 MultiplyAdd(vec4 v0, vec4 v1, float f2) { return v0 * v1 + f2; }\n"
"vec2 MultiplyAdd(vec2 v0, float f1, float f2) { return v0 * f1 + f2; }\n"
"vec3 MultiplyAdd(vec3 v0, float f1, float f2) { return v0 * f1 + f2; }\n"
"vec4 MultiplyAdd(vec4 v0, float f1, float f2) { return v0 * f1 + f2; }\n"
"vec2 MultiplyAdd(float f0, vec2 v1, float f2) { return f0 * v1 + f2; }\n"
"vec2 MultiplyAdd(float f0, float f1, vec2 v2) { return f0 * f1 + v2; }\n"
"vec3 MultiplyAdd(float f0, float f1, vec3 v2) { return f0 * f1 + v2; }\n"
"vec4 MultiplyAdd(float f0, float f1, vec4 v2) { return f0 * f1 + v2; }\n"
"vec2 MultiplyAdd(vec2 v0, vec2 v1, vec2 v2) { return v0 * v1 + v2; }\n"
"vec3 MultiplyAdd(vec3 v0, vec3 v1, vec3 v2) { return v0 * v1 + v2; }\n"
"vec4 MultiplyAdd(vec4 v0, vec4 v1, vec4 v2) { return v0 * v1 + v2; }\n"
"\n"
"float Negate(float f) { return -f; }\n"
"vec2 Negate(vec2 v) { return -v; }\n"
"vec3 Negate(vec3 v) { return -v; }\n"
"vec4 Negate(vec4 v) { return -v; }\n"
"mat2 Negate(mat2 m) { return -m; }\n"
"mat3 Negate(mat3 m) { return -m; }\n"
"mat4 Negate(mat4 m) { return -m; }\n"
"\n"
"float Reciprocal(float f) { return 1.0 / f; }\n"
"vec2 Reciprocal(vec2 v) { return 1.0 / v; }\n"
"vec3 Reciprocal(vec3 v) { return 1.0 / v; }\n"
"vec4 Reciprocal(vec4 v) { return 1.0 / v; }\n"
"mat2 Reciprocal(mat2 m) { return 1.0 / m; }\n"
"mat3 Reciprocal(mat3 m) { return 1.0 / m; }\n"
"mat4 Reciprocal(mat4 m) { return 1.0 / m; }\n"
"\n"
"float ReciprocalSquareRoot(float f) { return inversesqrt(f); }\n"
"vec2 ReciprocalSquareRoot(vec2 v) { return inversesqrt(v); }\n"
"vec3 ReciprocalSquareRoot(vec3 v) { return inversesqrt(v); }\n"
"vec4 ReciprocalSquareRoot(vec4 v) { return inversesqrt(v); }\n"
"mat2 ReciprocalSquareRoot(mat2 m) { return mat2(inversesqrt(m[0]), inversesqrt(m[1])); } \n"
"mat3 ReciprocalSquareRoot(mat3 m) { return mat3(inversesqrt(m[0]), inversesqrt(m[1]), inversesqrt(m[2])); }\n"
"mat4 ReciprocalSquareRoot(mat4 m) { return mat4(inversesqrt(m[0]), inversesqrt(m[1]), inversesqrt(m[2]), inversesqrt(m[3])); } \n"
"\n"
"float Absolute(float f) { return abs(f); }\n"
"vec2 Absolute(vec2 v) { return abs(v); }\n"
"vec3 Absolute(vec3 v) { return abs(v); }\n"
"vec4 Absolute(vec4 v) { return abs(v); }\n"
"mat2 Absolute(mat2 m) { return mat2(abs(m[0]), abs(m[1])); } \n"
"mat3 Absolute(mat3 m) { return mat3(abs(m[0]), abs(m[1]), abs(m[2])); } \n"
"mat4 Absolute(mat4 m) { return mat4(abs(m[0]), abs(m[1]), abs(m[2]), abs(m[3])); }\n"
"\n"
"float Modulus(float f0, float f1) { return mod(f0, f1); } \n"
"vec2 Modulus(float f, vec2 v) { return mod(vec2(f), v); } \n"
"vec2 Modulus(vec2 v, float f) { return mod(v, f); } \n"
"vec2 Modulus(vec2 v0, vec2 v1) { return mod(v0, v1); }  \n"
"vec3 Modulus(float f, vec3 v) { return mod(vec3(f), v); } \n"
"vec3 Modulus(vec3 v, float f) { return mod(v, f); } \n"
"vec3 Modulus(vec3 v0, vec3 v1) { return mod(v0, v1); } \n"
"vec4 Modulus(float f, vec4 v) { return mod(vec4(f), v); }\n"
"vec4 Modulus(vec4 v, float f) { return mod(v, f); } \n"
"vec4 Modulus(vec4 v0, vec4 v1) { return mod(v0, v1); }\n"
"mat2 Modulus(float f, mat2 m) { return mat2(mod(vec2(f), m[0]), mod(vec2(f), m[1])); }\n"
"mat2 Modulus(mat2 m, float f) { return mat2(mod(m[0], vec2(f)), mod(m[1], vec2(f))); }\n"
"mat2 Modulus(mat2 m0, mat2 m1) { return mat2(mod(m0[0], m1[0]), mod(m0[1], m1[1])); } \n"
"mat3 Modulus(float f, mat3 m) { return mat3(mod(vec3(f), m[0]), mod(vec3(f), m[1]), mod(vec3(f), m[2])); }\n"
"mat3 Modulus(mat3 m, float f) { return mat3(mod(m[0], vec3(f)), mod(m[1], vec3(f)), mod(m[2], vec3(f))); }\n"
"mat3 Modulus(mat3 m0, mat3 m1) { return mat3(mod(m0[0], m1[0]), mod(m0[1], m1[1]), mod(m0[2], m1[2])); }\n"
"mat4 Modulus(float f, mat4 m) { return mat4(mod(vec4(f), m[0]), mod(vec4(f), m[1]), mod(vec4(f), m[2]), mod(vec4(f), m[3])); } \n"
"mat4 Modulus(mat4 m, float f) { return mat4(mod(m[0], vec4(f)), mod(m[1], vec4(f)), mod(m[2], vec4(f)), mod(m[3], vec4(f))); } \n"
"mat4 Modulus(mat4 m0, mat4 m1) { return mat4(mod(m0[0], m1[0]), mod(m0[1], m1[1]), mod(m0[2], m1[2]), mod(m0[3], m1[3])); } \n"
"\n"
"float Fraction(float f) { return fract(f); }\n"
"vec2 Fraction(vec2 v) { return fract(v); }\n"
"vec3 Fraction(vec3 v) { return fract(v); }\n"
"vec4 Fraction(vec4 v) { return fract(v); }\n"
"mat2 Fraction(mat2 m) { return mat2(fract(m[0]), fract(m[1])); }\n"
"mat3 Fraction(mat3 m) { return mat3(fract(m[0]), fract(m[1]), fract(m[2])); } \n"
"mat4 Fraction(mat4 m) { return mat4(fract(m[0]), fract(m[1]), fract(m[2]), fract(m[3])); }\n"
"\n"
"float Exponent(float f) { return exp2(f); }\n"
"vec2 Exponent(vec2 v) { return exp2(v); }\n"
"vec3 Exponent(vec3 v) { return exp2(v); }\n"
"vec4 Exponent(vec4 v) { return exp2(v); }\n"
"mat2 Exponent(mat2 m) { return mat2(exp2(m[0]), exp2(m[1])); } \n"
"mat3 Exponent(mat3 m) { return mat3(exp2(m[0]), exp2(m[1]), exp2(m[2])); }\n"
"mat4 Exponent(mat4 m) { return mat4(exp2(m[0]), exp2(m[1]), exp2(m[2]), exp2(m[3])); }\n"
"\n"
"float Power(float f0, float f1) { return pow(f0, f1); }  \n"
"vec2 Power(vec2 v, float f) { return pow(v, vec2(f)); }\n"
"vec2 Power(float f, vec2 v) { return pow(vec2(f), v); }\n"
"vec2 Power(vec2 v0, vec2 v1) { return pow(v0, v1); }\n"
"vec3 Power(vec3 v, float f) { return pow(v, vec3(f)); }\n"
"vec3 Power(float f, vec3 v) { return pow(vec3(f), v); }\n"
"vec3 Power(vec3 v0, vec3 v1) { return pow(v0, v1); }\n"
"vec4 Power(vec4 v, float f) { return pow(v, vec4(f)); }\n"
"vec4 Power(float f, vec4 v) { return pow(vec4(f), v); }\n"
"vec4 Power(vec4 v0, vec4 v1) { return pow(v0, v1); }\n"
"mat2 Power(mat2 m, float f) { return mat2(pow(m[0], vec2(f)), pow(m[1], vec2(f))); }\n"
"mat2 Power(float f, mat2 m) { return mat2(pow(vec2(f), m[0]), pow(vec2(f), m[1])); }\n"
"mat2 Power(mat2 m0, mat2 m1) { return mat2(pow(m0[0], m1[0]), pow(m0[1], m1[1])); }\n"
"mat3 Power(mat3 m, float f) { return mat3(pow(m[0], vec3(f)), pow(m[1], vec3(f)), pow(m[2], vec3(f))); }\n"
"mat3 Power(float f, mat3 m) { return mat3(pow(vec3(f), m[0]), pow(vec3(f), m[1]), pow(vec3(f), m[2])); }\n"
"mat3 Power(mat3 m0, mat3 m1) { return mat3(pow(m0[0], m1[0]), pow(m0[1], m1[1]), pow(m0[2], m1[2])); }\n"
"mat4 Power(mat4 m, float f) { return mat4(pow(m[0], vec4(f)), pow(m[1], vec4(f)), pow(m[2], vec4(f)), pow(m[3], vec4(f))); }\n"
"mat4 Power(float f, mat4 m) { return mat4(pow(vec4(f), m[0]), pow(vec4(f), m[1]), pow(vec4(f), m[2]), pow(vec4(f), m[3])); }\n"
"mat4 Power(mat4 m0, mat4 m1) { return mat4(pow(m0[0], m1[0]), pow(m0[1], m1[1]), pow(m0[2], m1[2]), pow(m0[3], m1[3])); }\n"
"\n"
"float Log(float f) { return log2(f); }\n"
"vec2 Log(vec2 v) { return log2(v); }\n"
"vec3 Log(vec3 v) { return log2(v); }\n"
"vec4 Log(vec4 v) { return log2(v); }\n"
"mat2 Log(mat2 m) { return mat2(log2(m[0]), log2(m[1])); } \n"
"mat3 Log(mat3 m) { return mat3(log2(m[0]), log2(m[1]), log2(m[2])); } \n"
"mat4 Log(mat4 m) { return mat4(log2(m[0]), log2(m[1]), log2(m[2]), log2(m[3])); } \n"
"\n"
"float Max(float f0, float f1) { return max(f0, f1); }\n"
"vec2 Max(float f, vec2 v) { return max(vec2(f), v); }\n"
"vec2 Max(vec2 v, float f) { return max(v, f); }\n"
"vec2 Max(vec2 v0, vec2 v1) { return max(v0, v1); }\n"
"vec3 Max(float f, vec3 v) { return max(vec3(f), v); }\n"
"vec3 Max(vec3 v, float f) { return max(v, f); }\n"
"vec3 Max(vec3 v0, vec3 v1) { return max(v0, v1); }\n"
"vec4 Max(float f, vec4 v) { return max(vec4(f), v); }\n"
"vec4 Max(vec4 v, float f) { return max(v, f); }\n"
"vec4 Max(vec4 v0, vec4 v1) { return max(v0, v1); }\n"
"mat2 Max(float f, mat2 m) { return mat2(max(vec2(f), m[0]), max(vec2(f), m[1])); } \n"
"mat2 Max(mat2 m, float f) { return mat2(max(m[0], f),max(m[1], f)); } \n"
"mat2 Max(mat2 m0, mat2 m1) { return mat2(max(m0[0], m1[0]), max(m0[1], m1[1])); } \n"
"mat3 Max(float f, mat3 m) { return mat3(max(vec3(f), m[0]), max(vec3(f), m[1]), max(vec3(f), m[2])); } \n"
"mat3 Max(mat3 m, float f) { return mat3(max(m[0], f), max(m[1], f), max(m[2], f)); } \n"
"mat3 Max(mat3 m0, mat3 m1) { return mat3(max(m0[0], m1[0]), max(m0[1], m1[1]), max(m0[2], m1[2])); } \n"
"mat4 Max(float f, mat4 m) { return mat4(max(vec4(f), m[0]), max(vec4(f), m[1]), max(vec4(f), m[2]), max(vec4(f), m[3])); } \n"
"mat4 Max(mat4 m, float f) { return mat4(max(m[0], f), max(m[1], f), max(m[2], f), max(m[3], f)); } \n"
"mat4 Max(mat4 m0, mat4 m1) { return mat4(max(m0[0], m1[0]), max(m0[1], m1[1]), max(m0[2], m1[2]), max(m0[3], m1[3])); } \n"
"\n"
"float Min(float f0, float f1) { return min(f0, f1); }\n"
"vec2 Min(float f, vec2 v) { return min(vec2(f), v); }\n"
"vec2 Min(vec2 v, float f) { return min(v, f); }\n"
"vec2 Min(vec2 v0, vec2 v1) { return min(v0, v1); }\n"
"vec3 Min(float f, vec3 v) { return min(vec3(f), v); }\n"
"vec3 Min(vec3 v, float f) { return min(v, f); }\n"
"vec3 Min(vec3 v0, vec3 v1) { return min(v0, v1); }\n"
"vec4 Min(float f, vec4 v) { return min(vec4(f), v); }\n"
"vec4 Min(vec4 v, float f) { return min(v, f); }\n"
"vec4 Min(vec4 v0, vec4 v1) { return min(v0, v1); }\n"
"mat2 Min(float f, mat2 m) { return mat2(min(vec2(f), m[0]), min(vec2(f), m[1])); } \n"
"mat2 Min(mat2 m, float f) { return mat2(min(m[0], f), min(m[1], f)); } \n"
"mat2 Min(mat2 m0, mat2 m1) { return mat2(min(m0[0], m1[0]), min(m0[1], m1[1])); } \n"
"mat3 Min(float f, mat3 m) { return mat3(min(vec3(f), m[0]), min(vec3(f), m[1]), min(vec3(f), m[2])); } \n"
"mat3 Min(mat3 m, float f) { return mat3(min(m[0], f), min(m[1], f), min(m[2], f)); } \n"
"mat3 Min(mat3 m0, mat3 m1) { return mat3(min(m0[0], m1[0]), min(m0[1], m1[1]), min(m0[2], m1[2])); } \n"
"mat4 Min(float f, mat4 m) { return mat4(min(vec4(f), m[0]), min(vec4(f), m[1]), min(vec4(f), m[2]), min(vec4(f), m[3])); } \n"
"mat4 Min(mat4 m, float f) { return mat4(min(m[0],f),min(m[1], f),min(m[2], f),min(m[3], f)); }\n"
"mat4 Min(mat4 m0, mat4 m1) { return mat4(min(m0[0], m1[0]), min(m0[1], m1[1]), min(m0[2], m1[2]), min(m0[3], m1[3])); }\n"
"\n"
"float Clamp(float f) { return clamp(f, 0.0, 1.0); }\n"
"vec2 Clamp(vec2 v) { return clamp(v, 0.0, 1.0); }\n"
"vec3 Clamp(vec3 v) { return clamp(v, 0.0, 1.0); }\n"
"vec4 Clamp(vec4 v) { return clamp(v, 0.0, 1.0); }\n"
"mat2 Clamp(mat2 m) { return mat2(clamp( m[0], 0.0, 1.0), clamp(m[1], 0.0, 1.0)); }\n"
"mat3 Clamp(mat3 m) { return mat3(clamp( m[0], 0.0, 1.0), clamp(m[1], 0.0, 1.0), clamp(m[2], 0.0, 1.0)); } \n"
"mat4 Clamp(mat4 m) { return mat4(clamp( m[0], 0.0, 1.0), clamp(m[1], 0.0, 1.0), clamp(m[2], 0.0, 1.0), clamp(m[3], 0.0, 1.0 )); } \n"
"\n"
"vec2 Normalize(vec2 v) { return normalize(v); }\n"
"vec3 Normalize(vec3 v) { return normalize(v); }\n"
"vec4 Normalize(vec4 v) { return normalize(v); }\n"
"\n"
"float DotProduct(vec2 v0, vec2 v1) { return dot(v0, v1); }\n"
"float DotProduct(vec3 v0, vec3 v1) { return dot(v0, v1); }\n"
"float DotProduct(vec4 v0, vec4 v1) { return dot(v0, v1); }\n"
"\n"
"vec3 CrossProduct(vec3 v0, vec3 v1) { return cross(v0, v1); }\n"
"\n"
"float LinearInterpolate(float a, float f0, float f1) { return mix(f0, f1, a); }\n"
"vec2 LinearInterpolate(float a, vec2 v0, vec2 v1) { return mix(v0, v1, a); }\n"
"vec3 LinearInterpolate(float a, vec3 v0, vec3 v1) { return mix(v0, v1, a); }\n"
"vec4 LinearInterpolate(float a, vec4 v0, vec4 v1) { return mix(v0, v1, a); }\n"
"vec2 LinearInterpolate(vec2 a, vec2 v0, vec2 v1) { return mix(v0, v1, a); }\n"
"vec3 LinearInterpolate(vec3 a, vec3 v0, vec3 v1) { return mix(v0, v1, a); }\n"
"vec4 LinearInterpolate(vec4 a, vec4 v0, vec4 v1) { return mix(v0, v1, a); }\n"
"mat2 LinearInterpolate(mat2 a, mat2 m0, mat2 m1) { return mat2(mix(m0[0], m1[0], a[0]), mix(m0[1], m1[1], a[1])); }\n"
"mat3 LinearInterpolate(mat3 a, mat3 m0, mat3 m1) { return mat3(mix(m0[0], m1[0], a[0]), mix(m0[1], m1[1], a[1]), mix(m0[2], m1[2], a[2])); }\n"
"mat4 LinearInterpolate(mat4 a, mat4 m0, mat4 m1) { return mat4(mix(m0[0], m1[0], a[0]), mix(m0[1], m1[1], a[1]), mix(m0[2], m1[2], a[2]), mix(m0[3], m1[3], a[3])); }\n"
"\n"
"float Sine(float f) { return sin(f); }\n"
"vec2 Sine(vec2 v) { return sin(v); }\n"
"vec3 Sine(vec3 v) { return sin(v); }\n"
"vec4 Sine(vec4 v) { return sin(v); }\n"
"mat2 Sine(mat2 m) { return mat2(sin(m[0]), sin(m[1])); }\n"
"mat3 Sine(mat3 m) { return mat3(sin(m[0]), sin(m[1]), sin(m[2])); }\n"
"mat4 Sine(mat4 m) { return mat4(sin(m[0]), sin(m[1]), sin(m[2]), sin(m[3])); }\n"
"float Cosine(float f) { return cos(f); }\n"
"vec2 Cosine(vec2 v) { return cos(v); }\n"
"vec3 Cosine(vec3 v) { return cos(v); }\n"
"vec4 Cosine(vec4 v) { return cos(v); }\n"
"mat2 Cosine(mat2 m) { return mat2(cos(m[0]), cos(m[1])); }\n"
"mat3 Cosine(mat3 m) { return mat3(cos(m[0]), cos(m[1]), cos(m[2])); }\n"
"mat4 Cosine(mat4 m) { return mat4(cos(m[0]), cos(m[1]), cos(m[2]), cos(m[3])); }\n"
"                       \n"
"bool GreaterThan(float f0, float f1) { return f0 > f1; }\n"
"bvec2 GreaterThan(vec2 v0, vec2 v1) { return greaterThan( v0, v1 ); }\n"
"bvec3 GreaterThan(vec3 v0, vec3 v1) { return greaterThan( v0, v1 ); }\n"
"bvec4 GreaterThan(vec4 v0, vec4 v1) { return greaterThan( v0, v1 ); }\n"
"bool GreaterThanOrEqual(float f0, float f1) { return f0 >= f1; }\n"
"bvec2 GreaterThanOrEqual(vec2 v0, vec2 v1) { return greaterThanEqual( v0, v1 ); } \n"
"bvec3 GreaterThanOrEqual(vec3 v0, vec3 v1) { return greaterThanEqual( v0, v1 ); } \n"
"bvec4 GreaterThanOrEqual(vec4 v0, vec4 v1) { return greaterThanEqual( v0, v1 ); }\n"
"bool LessThan(float f0, float f1) { return f0 < f1; }\n"
"bvec2 LessThan(vec2 v0, vec2 v1) { return lessThan( v0, v1 ); } \n"
"bvec3 LessThan(vec3 v0, vec3 v1) { return lessThan( v0, v1 ); } \n"
"bvec4 LessThan(vec4 v0, vec4 v1) { return lessThan( v0, v1 ); }\n"
"bool LessThanOrEqual(float f0, float f1) { return f0 <= f1; }\n"
"bvec2 LessThanOrEqual(vec2 v0, vec2 v1) { return lessThanEqual( v0, v1 ); } \n"
"bvec3 LessThanOrEqual(vec3 v0, vec3 v1) { return lessThanEqual( v0, v1 ); } \n"
"bvec4 LessThanOrEqual(vec4 v0, vec4 v1) { return lessThanEqual( v0, v1 ); }\n"
"bool Equal(float f0, float f1) { return f0 == f1; }\n"
"bvec2 Equal(vec2 v0, vec2 v1) { return equal( v0, v1 ); } \n"
"bvec3 Equal(vec3 v0, vec3 v1) { return equal( v0, v1 ); } \n"
"bvec4 Equal(vec4 v0, vec4 v1) { return equal( v0, v1 ); }\n"
"bool NotEqual(float f0, float f1) { return f0 != f1; }\n"
"bvec2 NotEqual(vec2 v0, vec2 v1) { return notEqual( v0, v1 ); } \n"
"bvec3 NotEqual(vec3 v0, vec3 v1) { return notEqual( v0, v1 ); } \n"
"bvec4 NotEqual(vec4 v0, vec4 v1) { return notEqual( v0, v1 ); }\n"
"\n"
"bool LogicalNot(float f) { return !bool(f); }\n"
"#define NOT2(v) v.x = !v.x; v.y = !v.y\n"
"bvec2 LogicalNot(vec2 v) { bvec2 t = bvec2(v); NOT2(t); return t; }\n"
"#define NOT3(v) v.x = !v.x; v.y = !v.y; v.x = !v.z\n"
"bvec3 LogicalNot(vec3 v) { bvec3 t = bvec3(v); NOT3(t); return t; }\n"
"#define NOT4(v) v.x = !v.x; v.y = !v.y; v.x = !v.z; v.w = !v.w\n"
"bvec4 LogicalNot(vec4 v) { bvec4 t = bvec4(v); NOT4(t); return t; }\n"
"bool LogicalAnd(float f0, float f1) { return bool(f0) && bool(f1); }\n"
"#define AND2(v0, v1) v0.x = v0.x && v1.x; v0.y = v0.y && v1.y\n"
"bvec2 LogicalAnd(vec2 v0, vec2 v1) { bvec2 t0 = bvec2(v0); bvec2 t1 = bvec2(v1); AND2(t0, t1); return t0; }\n"
"#define AND3(v0, v1) v0.x = v0.x && v1.x; v0.y = v0.y && v1.y; v0.z = v0.z && v1.z\n"
"bvec3 LogicalAnd(vec3 v0, vec3 v1) { bvec3 t0 = bvec3(v0); bvec3 t1 = bvec3(v1); AND3(t0, t1); return t0; }\n"
"#define AND4(v0, v1) v0.x = v0.x && v1.x; v0.y = v0.y && v1.y; v0.z = v0.z && v1.z; v0.w = v0.w && v1.w\n"
"bvec4 LogicalAnd(vec4 v0, vec4 v1) { bvec4 t0 = bvec4(v0); bvec4 t1 = bvec4(v1); AND4(t0, t1); return t0; }\n"
"bool LogicalOr(float f0, float f1) { return bool(f0) || bool(f1); }\n"
"#define OR2(v0, v1) v0.x = v0.x || v1.x; v0.y = v0.y || v1.y \n"
"bvec2  LogicalOr(vec2 v0, vec2 v1) { bvec2 t0 = bvec2(v0); bvec2 t1 = bvec2(v1); OR2(t0, t1); return t0; }\n"
"#define OR3(v0, v1) v0.x = v0.x || v1.x; v0.y = v0.y || v1.y; v0.z = v0.z || v1.z\n"
"bvec3  LogicalOr(vec3 v0, vec3 v1) { bvec3 t0 = bvec3(v0); bvec3 t1 = bvec3(v1); OR3(t0, t1); return t0; }\n"
"#define OR4(v0, v1) v0.x = v0.x || v1.x; v0.y = v0.y || v1.y; v0.z = v0.z || v1.z; v0.w = v0.w || v1.w\n"
"bvec4  LogicalOr(vec4 v0, vec4 v1) { bvec4 t0 = bvec4(v0); bvec4 t1 = bvec4(v1); OR4(t0, t1); return t0; }\n"
"\n"
"float MultiChoice(bool cond, float f0, float f1) { return (cond ? f0 : f1); }\n"
"vec2 MultiChoice(bool cond, vec2 v0, vec2 v1) { return (cond ? v0 : v1); }\n"
"vec3 MultiChoice(bool cond, vec3 v0, vec3 v1) { return (cond ? v0 : v1); }\n"
"vec4 MultiChoice(bool cond, vec4 v0, vec4 v1) { return (cond ? v0 : v1); }\n"
"mat2 MultiChoice(bool cond, mat2 m0, mat2 m1) { return (cond ? m0 : m1); }\n"
"mat3 MultiChoice(bool cond, mat3 m0, mat3 m1) { return (cond ? m0 : m1); }\n"
"mat4 MultiChoice(bool cond, mat4 m0, mat4 m1) { return (cond ? m0 : m1); }\n"
"\n"
"float TypeCast(int i) { return float(i); }\n"
"int TypeCast(float f) { return int(f); }\n"
"vec2 TypeCast(vec3 v) { return vec2(v); }\n"
"vec2 TypeCast(vec4 v) { return vec2(v); }\n"
"//vec3 TypeCast(vec4 v) { return vec3(v); }\n"
"//mat2 TypeCast(mat3 m) { return mat2(m); }\n"
"//mat2 TypeCast(mat4 m) { return mat2(m); }\n"
"//mat3 TypeCast(mat4 m) { return mat3(m); }\n"
"\n";

//
//
//
hlslSm3FXShader::hlslSm3FXShader() :  m_techniqueCount(0), m_valid(false), m_stale(false), m_color(true), m_activePass(0), m_activeTechnique(0), m_normal(true),
m_tangent(true), m_binormal(true), m_texMask(0x1), m_error("") {

  
}

//
//
//
hlslSm3FXShader::~hlslSm3FXShader() {
  for (std::vector<passState*>::iterator it=m_stateList.begin(); it<m_stateList.end(); it++) {
    delete *it;
  }

  deleteShaders();
}

//
//
//
void hlslSm3FXShader::deleteShaders() {

        //these assume destroying object 0 is OK

        //schedule all the programs for delete
        {
                for (std::vector<GLuint>::iterator it=m_programList.begin(); it<m_programList.end(); it++) {
                        ResourceManager::destroyProgram( *it);
                }
        }
        m_programList.clear();

        //schedule all the vertex shaders for delete
        {
                for (std::vector<GLuint>::iterator it=m_vShaderList.begin(); it<m_vShaderList.end(); it++) {
                        ResourceManager::destroyProgram( *it);
                }
        }
        m_vShaderList.clear();

        //schedule all the fragment shaders for delete
        {
                for (std::vector<GLuint>::iterator it=m_fShaderList.begin(); it<m_fShaderList.end(); it++) {
                        ResourceManager::destroyProgram( *it);
                }
        }
        m_fShaderList.clear();
}

//
//
//
bool hlslSm3FXShader::createFromFile( const char *filename) {
  /*
  m_error = ""; 
  m_fx = new IAshliFX;
  m_fx->init();
  m_fx->setBinding( IAshliFX::DXSL);
  m_fx->setFX( filename);  //may need to do some path searching here
  m_stale = true;

  m_observer = new stateObserver;
  m_fx->attach( (IObserveFX*)m_observer);

  if (!m_fx->parse()) {
    //should store a string describing the failure for query
    m_error = "Unable to load FX file\n  ";
    m_error += m_fx->getError();
    delete m_fx;
    m_fx = NULL;
    return false;
  }

  m_ashli = new IAshli;
  m_ashli->setNative(IAshli::DXSL);
  m_ashli->setFlag( IAshli::UnpackedScalars, true);
  m_ashli->setFlag( IAshli::ContiguousMatrix, true);
  m_ashli->setFlag( IAshli::ContiguousArray, true);
  m_ashli->setFlag( IAshli::MultiPass, false);
  m_ashli->init( IAshli::Stream, IAshli::GL, IAshli::Stream);

  if ( !m_fx->isVertexNull( 0, 0)) {
    m_ashli->addShaderItem( m_fx->getVertexShader( 0, 0));
    m_ashli->addShaderInstance( m_ashli->addShader( IAshli::Vertex, m_fx->getVertexEntry( 0, 0)));
  }
  if ( !m_fx->isPixelNull( 0, 0)) {
    m_ashli->addShaderItem( m_fx->getPixelShader( 0, 0));
    m_ashli->addShaderInstance( m_ashli->addShader( IAshli::Pixel, m_fx->getPixelEntry( 0, 0)));
  }
  if ( m_ashli->invoke("")) {
    //compile succeeded 
    m_fx->setMetadata( 0, 0, m_ashli->getFormals());
    m_fx->setVertexAssembly( 0, 0, m_ashli->getVertexShader());
    m_fx->setPixelAssembly( 0, 0, m_ashli->getPixelShader());
    
  }
  else {
    //compile failed
    m_error = "Shader failed to compile\n";
    m_error += m_ashli->getError();
  }

  if ( (m_fx->getNumTechniques()) && (m_fx->getNumPasses(0) == 1)) {
  }
  else {
    //message about no valid first technique/incorrect number of passes
    delete m_fx;
    m_fx = NULL;
    m_error = "FX file lacked a valid shader";
    return false;
  }
  
  //this will move to bind time
  //if (!buildShaders())
  //  return false;

  if (!parseParameters())
    return false;
*/
  return true;

}

//
//
//
bool hlslSm3FXShader::createFromFX( IAshliFX *fx) {
        m_error = ""; 
        m_stale = true;
  m_valid = false;

  if ( fx->getNumTechniques()) {
                //handle any per-technique processing, none presently required
        }
        else {
                //the effect lacks any technique, consider it invalid
                m_error = "FX file lacked a valid shader";
                return false;
        }

  if (!parseParameters(fx))
                return false;

  //need to extract all shader data from the fx file here 
  //these are to hold the ASHLIFX data
  m_techniqueCount = fx->getNumTechniques();
  m_techniqueNames.clear();
  m_passCount.clear();
  m_techniqueOffset.clear();
  m_vertexShaders.clear();
  m_fragmentShaders.clear();
  for (std::vector<passState*>::iterator it=m_stateList.begin(); it<m_stateList.end(); it++) {
    delete *it;
  }
  m_stateList.clear();
  int totalPasses =0;

  stateObserver *observer = new stateObserver;

  fx->attach( (IObserveFX*)observer);

  for (int ii=0; ii<m_techniqueCount; ii++) {
    int passCount = fx->getNumPasses(ii);
    m_techniqueOffset.push_back(totalPasses);
    ITechniqueFX tech;
    fx->getTechnique(ii, tech);
    m_techniqueNames.push_back(tech.getId());
    m_passCount.push_back(passCount);
    for (int jj=0; jj<passCount; jj++) {
      std::string vString;
      std::string fString;
      std::string orgVString;
      std::string orgFString;

      //allocate an ashli for this pass
      IAshli *ashli = new IAshli;
      ashli->setNative(IAshli::DXSL);
      ashli->setFlag( IAshli::UnpackedScalars, true);
      ashli->setFlag( IAshli::ContiguousMatrix, true);
      ashli->setFlag( IAshli::ContiguousArray, true);
      ashli->setFlag( IAshli::MultiPass, false);
      ashli->init( IAshli::Stream, IAshli::GL_SL10, IAshli::Stream);
      if ( !fx->isVertexNull( ii, jj)) {
        orgVString = fx->getVertexShader( ii, jj);
        ashli->addShaderItem( orgVString.c_str());
        ashli->addShaderInstance( ashli->addShader( IAshli::Vertex, fx->getVertexEntry( ii, jj)));
      }
      if ( !fx->isPixelNull( ii, jj)) {
        orgFString = fx->getPixelShader( ii, jj);
        ashli->addShaderItem( orgFString.c_str());
        ashli->addShaderInstance( ashli->addShader( IAshli::Pixel, fx->getPixelEntry( ii, jj)));
      }
      if ( ashli->invoke("")) {
        //compile succeeded 
        fx->setMetadata( ii, jj, ashli->getFormals());
        fx->setVertexAssembly( ii, jj, ashli->getVertexShader());
        fx->setPixelAssembly( ii, jj, ashli->getPixelShader());
        if (fx->getVertexAssembly( ii, jj))
          vString = fx->getVertexAssembly( ii, jj);
        if (fx->getPixelAssembly( ii, jj))
          fString = fx->getPixelAssembly( ii, jj);
      }
      else {
        //compile failed
        const char* error = ashli->getError();
        m_error = "Shader failed to compile\n";
        m_error += error;
        m_error += std::string("\n");
        // would like to print the offending text, but the parsing seems to difficult
      }

      m_vertexShaders.push_back(vString);
      m_fragmentShaders.push_back(fString);

      m_orgVertexShaders.push_back(orgVString);
      m_orgFragmentShaders.push_back(orgFString);

      //accumulate the state data
      m_stateList.push_back(new passState);
      observer->setPassMonitor(m_stateList.back());
      for (int kk=0; kk<fx->getNumStates( ii,jj); kk++) {
        fx->getStateItem( ii, jj, kk);
      }
      observer->finalizePassMonitor();
    }
    totalPasses += passCount;
  }
    
  fx->attach(NULL);
  delete observer;

  m_valid = true;

        return true;
}

//
//
//
//new method, parsing parameters from AshliFX
bool hlslSm3FXShader::parseParameters(const IAshliFX *fx) {

  int passCount =0, ii;
  
  for (ii=0; ii<fx->getNumTechniques(); ii++) {
    passCount = std::max<int>( fx->getNumPasses(ii), passCount);
  }

  //process the exposed shader parameters
  for (ii=0; ii<fx->getNumParameters(); ii++) {
    IParameterFX parm;
    fx->getParameter( "", ii, parm);
    const char *usage = parm.getUsage();
    const char *type = parm.getType();
    const char *name = parm.getId();
    const char *semantic = parm.getSemantic();
    const char *expression = parm.getExpression();
    if (strcmp( "const", usage)) {
      if (strncmp( "sampler", type, 7)) {
        // this is a regular uniform (not a sampler)

        //should verify the compatibility of the following pieces of data
        shader::DataType dt = parseUniformType( type);
        shader::Semantic sm = parseUniformSemantic( semantic);
        uniform u;
        u.type = dt;
        u.handle.resize( passCount, -1);
        u.usage = sm;
        u.name = name;
        //parse the expression to extract a default value
        parseExpression( u, expression);

        //skip adding strings for now, maybe add them somewhere else later
        if (dt != shader::dtString)
          m_uniformList.push_back(u);
      }
      else {
        // this is a sampler uniform
        shader::SamplerType st = parseSamplerType( type);
        sampler s;
        s.texUnit.resize( passCount, -1);
        s.handle.resize( passCount, -1);
        s.type = st;
        s.name = name;
        m_samplerList.push_back(s);
      }
    }
    else {
      //don't know what else we could encounter, might want to create warnings
    }
  }

  return true;
}

//
//
//
shader::DataType hlslSm3FXShader::parseUniformType( const char *type) {
  if (!strcmp( "float", type)) {
    return shader::dtFloat;
  }
  else if (!strcmp( "float1", type)) {
    return shader::dtFloat;
  }
  else if (!strcmp( "float2", type)) {
    return shader::dtVec2;
  }
  else if (!strcmp( "float3", type)) {
    return shader::dtVec3;
  }
  else if (!strcmp( "float4", type)) {
    return shader::dtVec4;
  }
  else if (!strcmp( "int", type)) {
    return shader::dtInt;
  }
  else if (!strcmp( "int1", type)) {
    return shader::dtInt;
  }
  else if (!strcmp( "int2", type)) {
    return shader::dtIVec2;
  }
  else if (!strcmp( "int3", type)) {
    return shader::dtIVec3;
  }
  else if (!strcmp( "int4", type)) {
    return shader::dtIVec4;
  }
  else if (!strcmp( "bool", type)) {
    return shader::dtBool;
  }
  else if (!strcmp( "bool1", type)) {
    return shader::dtBVec2;
  }
  else if (!strcmp( "bool2", type)) {
    return shader::dtBVec2;
  }
  else if (!strcmp( "bool3", type)) {
    return shader::dtBVec3;
  }
  else if (!strcmp( "bool4", type)) {
    return shader::dtBVec4;
  }
  else if (!strcmp( "float2x2", type)) {
    return shader::dtMat2;
  }
  else if (!strcmp( "float3x3", type)) {
    return shader::dtMat3;
  }
  else if (!strcmp( "float4x4", type)) {
    return shader::dtMat4;
  }
  
  return shader::dtUnknown;
}

//
//
//
void hlslSm3FXShader::parseExpression( hlslSm3FXShader::uniform &u, const char *exp) {
  //this function should call a real parser, until then only handle a subset of types

  for (int ii=0; ii<16; ii++)
    u.fDefault[ii] = 0.0f;

  switch ( u.type) {
    case shader::dtInt:
      if ( 1 == sscanf( exp, " int ( %f )", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " int1 ( %f )", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " %f ", &u.fDefault[0])) {
      }
      else {
        u.fDefault[0] = 0.0f;
      }
      break;
    case shader::dtFloat:
      if ( 1 == sscanf( exp, " float ( %f )", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " float1 ( %f )", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " %f ", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " float ( %ff )", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " float1 ( %ff )", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " %ff ", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " { %f } ", &u.fDefault[0])) {
      }
      else if ( 1 == sscanf( exp, " { %ff } ", &u.fDefault[0])) {
      }
      else {
        u.fDefault[0] = 0.0f;
      }
      break;
    case shader::dtVec2:
      if ( 2 == sscanf( exp, " float2 ( %f , %f )", &u.fDefault[0], &u.fDefault[1])) {
      }
      else if ( 2 == sscanf( exp, " { %f , %f }", &u.fDefault[0], &u.fDefault[1])) {
      }
      else if ( 2 == sscanf( exp, " float2 ( %ff , %ff )", &u.fDefault[0], &u.fDefault[1])) {
      }
      else if ( 2 == sscanf( exp, " { %ff , %ff }", &u.fDefault[0], &u.fDefault[1])) {
      }
      else {
        u.fDefault[0] = 0.0f;
        u.fDefault[1] = 0.0f;
      }
      break;
    case shader::dtVec3:
      if ( 3 == sscanf( exp, " float3 ( %f , %f , %f )", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2])) {
      }
      else if ( 3 == sscanf( exp, " { %f , %f , %f }", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2])) {
      }
      else if ( 3 == sscanf( exp, " float3 ( %ff , %ff , %ff )", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2])) {
      }
      else if ( 3 == sscanf( exp, " { %ff , %ff , %ff }", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2])) {
      }
      else {
        u.fDefault[0] = 0.0f;
        u.fDefault[1] = 0.0f;
        u.fDefault[2] = 0.0f;
      }
      break;
    case shader::dtVec4:
      if ( 4 == sscanf( exp, " float4 ( %f , %f , %f , %f )", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2], &u.fDefault[3])) {
      }
      else if ( 4 == sscanf( exp, " float4 ( %ff , %ff , %ff , %ff )", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2], &u.fDefault[3])) {
      }
      else if ( 4 == sscanf( exp, " { %f , %f , %f , %f }", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2], &u.fDefault[3])) {
      }
      else if ( 4 == sscanf( exp, " { %ff , %ff , %ff , %ff }", &u.fDefault[0], &u.fDefault[1], &u.fDefault[2], &u.fDefault[3])) {
      }
      else {
        u.fDefault[0] = 0.0f;
        u.fDefault[1] = 0.0f;
        u.fDefault[2] = 0.0f;
        u.fDefault[3] = 0.0f;
      }
      break;
    default:
      //make gcc happy
      break;
  };
}

//
//
//
shader::Semantic hlslSm3FXShader::parseUniformSemantic( const char *semantic) {

  if (semantic == NULL)
    return shader::smNone;

  //this would be more efficient as a map
  if (!strcmp( "World", semantic)) {
    return shader::smWorld;
  }
  else if (!strcmp( "View", semantic)) {
    return shader::smView;
  }
  else if (!strcmp( "Projection", semantic)) {
    return shader::smProjection;
  }
  else if (!strcmp( "WorldView", semantic)) {
    return shader::smWorldView;
  }
  else if (!strcmp( "ViewProjection", semantic)) {
    return shader::smViewProjection;
  }
  else if (!strcmp( "WorldViewProjection", semantic)) {
    return shader::smWorldViewProjection;
  }
  else if ( (!strcmp( "WorldI", semantic)) || (!strcmp( "WorldInverse", semantic))) {
    return shader::smWorldI;
  }
  else if ( (!strcmp( "ViewI", semantic)) || (!strcmp( "ViewInverse", semantic)) ) {
    return shader::smViewI;
  }
  else if ( (!strcmp( "ProjectionI", semantic)) || (!strcmp( "ProjectionInverse", semantic)) ) {
    return shader::smProjectionI;
  }
  else if ( (!strcmp( "WorldViewI", semantic)) || (!strcmp( "WorldViewInverse", semantic)) ) {
    return shader::smWorldViewI;
  }
  else if ( (!strcmp( "ViewProjectionI", semantic)) || (!strcmp( "ViewProjectionInverse", semantic)) ) {
    return shader::smViewProjectionI;
  }
  else if ( (!strcmp( "WorldViewProjectionI", semantic)) || (!strcmp( "WorldViewProjectionInverse", semantic)) ) {
    return shader::smWorldViewProjectionI;
  }
  else if ( (!strcmp( "WorldT", semantic)) || (!strcmp( "WorldTranspose", semantic)) ) {
    return shader::smWorldT;
  }
  else if ( (!strcmp( "ViewT", semantic)) || (!strcmp( "ViewTranspose", semantic)) ) {
    return shader::smViewT;
  }
  else if ( (!strcmp( "ProjectionT", semantic)) || (!strcmp( "ProjectionTranspose", semantic)) ) {
    return shader::smProjectionT;
  }
  else if ( (!strcmp( "WorldViewT", semantic)) || (!strcmp( "WorldViewTranspose", semantic)) ) {
    return shader::smWorldViewT;
  }
  else if ( (!strcmp( "ViewProjectionT", semantic)) || (!strcmp( "ViewProjectionTranspose", semantic)) ) {
    return shader::smViewProjectionT;
  }
  else if ( (!strcmp( "WorldViewProjectionT", semantic)) || (!strcmp( "WorldViewProjectionTranspose", semantic)) ) {
    return shader::smWorldViewProjectionT;
  }
  else if ( (!strcmp( "WorldIT", semantic)) || (!strcmp( "WorldInverseTranspose", semantic)) ) {
    return shader::smWorldIT;
  }
  else if ( (!strcmp( "ViewIT", semantic)) || (!strcmp( "ViewInverseTranspose", semantic)) ) {
    return shader::smViewIT;
  }
  else if ( (!strcmp( "ProjectionIT", semantic)) || (!strcmp( "ProjectionInverseTranspose", semantic)) ) {
    return shader::smProjectionIT;
  }
  else if ( (!strcmp( "WorldViewIT", semantic)) || (!strcmp( "WorldViewInverseTranspose", semantic)) ) {
    return shader::smWorldViewIT;
  }
  else if ( (!strcmp( "ViewProjectionIT", semantic)) || (!strcmp( "ViewProjectionInverseTranspose", semantic)) ) {
    return shader::smViewProjectionIT;
  }
  else if ( (!strcmp( "WorldViewProjectionIT", semantic)) || (!strcmp( "WorldViewProjectionInverseTranspose", semantic)) ) {
    return shader::smWorldViewProjectionIT;
  }

  return shader::smUnknown;
}

//
//
//
shader::SamplerType hlslSm3FXShader::parseSamplerType( const char *type) {
  if (!strcmp( "sampler1D", type)) {
    return shader::st1D;
  }
  else if (!strcmp( "sampler2D", type)) {
    return shader::st2D;
  }
  else if (!strcmp( "sampler3D", type)) {
    return shader::st3D;
  }
  else if (!strcmp( "samplerCUBE", type)) {
    return shader::stCube;
  }

  //add sampler RECT stuff here

  return shader::stUnknown;
}

//
//
//
void hlslSm3FXShader::updateHandles() {
  passState ps;
/*
  //attach a pass state to th observer here and iterate the list
  m_observer->setPassMonitor( &ps);
  for (int ii=0; ii<m_fx->getNumStates( 0, 0); ii++) {
    m_fx->getStateItem( 0, 0, ii);
  }


  MGlobal::displayInfo( MString("Vertex uniforms: ") + ps.m_vRegMap.size());
  MGlobal::displayInfo( MString("Fragment uniforms: ") + ps.m_fRegMap.size());

  //now apply the information
  for (std::vector<uniform>::iterator it = m_uniformList.begin(); it < m_uniformList.end(); it++) {
    std::map< std::string, int>::const_iterator it2 = ps.m_vRegMap.find(it->name);
    if ( it2 != ps.m_vRegMap.end()) 
      it->vReg = it2->second;
    else
      it->vReg = -1;

    it2 = ps.m_fRegMap.find(it->name);
    if ( it2 != ps.m_fRegMap.end()) 
      it->fReg = it2->second;
    else
      it->fReg = -1;

    //need to use observer to get the register value grrrrr
    it->dirty = true; //need to mark it dirty, don't know the old state
  }

  for (std::vector<sampler>::iterator it = m_samplerList.begin(); it < m_samplerList.end(); it++) {
    std::map< std::string, int>::const_iterator it2 = ps.m_fRegMap.find(it->name);

    if ( it2 != ps.m_fRegMap.end()) 
      it->texUnit = it2->second;
    else
      it->texUnit = -1;

    //this should only happen once per compile, we never remap samplers
    it->dirty = true;
  }

  for (std::vector<attribute>::iterator it = m_attributeList.begin(); it < m_attributeList.end(); it++) {
    //it->handle = glGetAttribLocation( m_program, it->name);
    //nothing to mark dirty
  }

  m_observer->setPassMonitor( NULL);
  */
}


//
// buildShaders
//
//  This is doen when the shader is marked dirty to rebuild the shaders. It
// requires a current context.
bool hlslSm3FXShader::buildShaders() {

        //clean up any old shaders
        deleteShaders();

        //create all the passes up front
  m_programList.resize( m_passCount[m_activeTechnique], 0);
  m_vShaderList.resize( m_passCount[m_activeTechnique], 0);
  m_fShaderList.resize( m_passCount[m_activeTechnique], 0);
  

  int offset = m_techniqueOffset[m_activeTechnique];

  for (int ii=0; ii<m_passCount[m_activeTechnique]; ii++) {
    //build the programs
    GLuint program = glCreateProgramObject();
    m_programList[ii] = program;
    bool fail = false;

    GL_CHECK;

    if (m_vertexShaders[offset+ii].length() > 0) {
      const char* temp[2];
      GLuint vShader = glCreateShaderObject( GL_VERTEX_SHADER);
      m_vShaderList[ii] = vShader;
      glAttachObject( program, vShader);
      temp[0] = header;
      temp[1] = m_vertexShaders[offset+ii].c_str();
      glShaderSource( vShader, 2, temp, NULL);
      glCompileShader(vShader);
      //need to check for success here
      GLint success;
      glGetObjectParameteriv( vShader, GL_COMPILE_STATUS, &success);
      if (!success) {
        char log[256];
        glGetInfoLog( vShader, 256, NULL, log);
        fail = true; //allow fragment shader errors to occur
        m_error = "Vertex shader failed compile:\n";
        m_error += log;
        m_error += "\n";
      }
    }
    GL_CHECK;

    if (m_fragmentShaders[offset+ii].length() > 0) {
      const char* temp[2];
      GLuint fShader = glCreateShaderObject( GL_FRAGMENT_SHADER);
      m_fShaderList[ii] = fShader;
      glAttachObject( program, fShader);
      temp[0] = header;
      temp[1] = m_fragmentShaders[offset+ii].c_str();
      glShaderSource( fShader, 2, temp, NULL);
      glCompileShader(fShader);
      //need to check for success here
      GLint success;
      glGetObjectParameteriv( fShader, GL_COMPILE_STATUS, &success);
      if (!success) {
        char log[256];
        glGetInfoLog( fShader, 256, NULL, log);
        fail = true; //allow fragment shader errors to occur
        m_error += "Fragment shader failed compile:\n";
        m_error += log;
      }
    }
    GL_CHECK;

    if (fail) {
      glDeleteObject( m_programList[ii]);
      m_programList[ii] = 0;
      if (m_fShaderList[ii]) {
        glDeleteObject( m_fShaderList[ii]);
        m_fShaderList[ii] = 0;
      }
      if (m_vShaderList[ii]) {
        glDeleteObject( m_vShaderList[ii]);
        m_vShaderList[ii] = 0;
      }
      return false;
    }

    glLinkProgram(program);
    GLint success;
    glGetObjectParameteriv( program, GL_LINK_STATUS, &success);
    if (!success) {
      char log[256];
      glGetInfoLog( program, 256, NULL, log);
      m_error = "Link failed:\n";
      m_error += log;
      glDeleteObject( m_programList[ii]);
      m_programList[ii] = 0;
      if (m_fShaderList[ii]) {
        glDeleteObject( m_fShaderList[ii]);
        m_fShaderList[ii] = 0;
      }
      if (m_vShaderList[ii]) {
        glDeleteObject( m_vShaderList[ii]);
        m_vShaderList[ii] = 0;
      }
      GL_CHECK;
      return false;
    }

    GL_CHECK;
  }

  return true;
}

//
//
//
bool hlslSm3FXShader::valid() {
  return m_valid;
}

//
//
//
int hlslSm3FXShader::passCount() {
  //forcing single pass for now
  return 1;
}

//
//
//
int hlslSm3FXShader::techniqueCount() {
  //ignoring techniques for now
  return 1;
}

//
//
//
const char* hlslSm3FXShader::techniqueName( int n) {
  //ignoring all but technique zero for now
  return NULL;
}

//
//
//
bool hlslSm3FXShader::build() {

  //need to try to compile the shaders here if they don't exist yet

  if (m_stale) {
    m_stale = false;
    if (!buildShaders())
      return false;
    updateHandles();
  }

  return true;
}

//
// bind
//
//  This function is used to bind in the active program and set all of
// the associated shape independent state. Please note that only dirty 
// program state is sent to the shader. 
void hlslSm3FXShader::bind() {
        glUseProgramObject( m_programList[m_activePass]);
        GL_CHECK;

        GLenum targets[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D, GL_TEXTURE_2D};

        //update dirty samplers
        for (std::vector<sampler>::iterator it2 = m_samplerList.begin(); it2<m_samplerList.end(); it2++) {
                if ( it2->handle[m_activePass] != -1) {
                        if (it2->dirty) {
                                glUniform1i( it2->handle[m_activePass], it2->texUnit[m_activePass]);
                                //it->dirty = false;
                        }
                        glActiveTexture( GL_TEXTURE0_ARB + it2->texUnit[m_activePass]);
                        glBindTexture( targets[it2->type], it2->texObject);
                }
        }
        glActiveTexture( GL_TEXTURE0_ARB);

        GL_CHECK;

        //set up the render states
  m_stateList[m_techniqueOffset[m_activeTechnique]+m_activePass]->setState();

        GL_CHECK;

        return;
}

//
// setShapeDependentState
//
//  This function is used to setup any shape dependent data
void hlslSm3FXShader::setShapeDependentState() {
        //update dirty values
        for (std::vector<uniform>::iterator it = m_uniformList.begin(); it<m_uniformList.end(); it++) {
                if ( it->dirty) {

                        //only mark it clean on the last pass
      if ( m_activePass == m_passCount[m_activeTechnique]-1)
                                it->dirty = false;

                        if ( it->handle[m_activePass] == -1)
                                continue; // avoid causing a GL error, by submitting a uniform with a -1 (does not exist) handle

                        switch (it->type) {
                case shader::dtBool:
                        glUniform1i( it->handle[m_activePass], it->iVal[0]);
                        break;
                case shader::dtBVec2:
                        glUniform2iv( it->handle[m_activePass], 1, it->iVal);
                        break;
                case shader::dtBVec3:
                        glUniform3iv( it->handle[m_activePass], 1, it->iVal);
                        break;
                case shader::dtBVec4:
                        glUniform4iv( it->handle[m_activePass], 1, it->iVal);
                        break;
                case shader::dtInt:
                        glUniform1i( it->handle[m_activePass], it->iVal[0]);
                        break;
                case shader::dtIVec2:
                        glUniform2iv( it->handle[m_activePass], 1, it->iVal);
                        break;
                case shader::dtIVec3:
                        glUniform3iv( it->handle[m_activePass], 1, it->iVal);
                        break;
                case shader::dtIVec4:
                        glUniform4iv( it->handle[m_activePass], 1, it->iVal);
                        break;
                case shader::dtFloat:
                        glUniform1f( it->handle[m_activePass], it->fVal[0]);
                        break;
                case shader::dtVec2:
                        glUniform2fv( it->handle[m_activePass], 1, it->fVal);
                        break;
                case shader::dtVec3:
                        glUniform3fv( it->handle[m_activePass], 1, it->fVal);
                        break;
                case shader::dtVec4:
                        glUniform4fv( it->handle[m_activePass], 1, it->fVal);
                        break;
                case shader::dtMat2:
                        glUniformMatrix2fv( it->handle[m_activePass], 1, false, it->fVal);
                        break;
                case shader::dtMat3:
                        glUniformMatrix3fv( it->handle[m_activePass], 1, false, it->fVal);
                        break;
                case shader::dtMat4:
                        glUniformMatrix4fv( it->handle[m_activePass], 1, false, it->fVal);
                        break;
                default:
                        break;
                        };
                        GL_CHECK;
                }
        }
        return;
}

//
//
//
void hlslSm3FXShader::unbind() {
  glDisable( GL_FRAGMENT_PROGRAM_ARB);
  glDisable( GL_VERTEX_PROGRAM_ARB);
}

//
//
//
void hlslSm3FXShader::setTechnique( int t) {
  m_activeTechnique = t;
}

//
//
//
void hlslSm3FXShader::setPass( int p) {
  m_activePass = p;
}

//
//
//
int hlslSm3FXShader::uniformCount() {
  return (int)m_uniformList.size();
}

//
//
//
int hlslSm3FXShader::samplerCount() {
  return (int)m_samplerList.size();
}

//
//
//
int hlslSm3FXShader::attributeCount() {
  return (int)m_attributeList.size();
}

//
//
//
const char* hlslSm3FXShader::uniformName(int i) {
  //should check for array bounds
  return m_uniformList[i].name.c_str();
}

//
//
//
shader::DataType hlslSm3FXShader::uniformType(int i) {
  //should check for array bounds
  return m_uniformList[i].type;
}

//
//
//
shader::Semantic hlslSm3FXShader::uniformSemantic(int i) {
  //might want to check array bounds
  return m_uniformList[i].usage;
}

//
//
//
const char* hlslSm3FXShader::samplerName(int i) {
  //should check for array bounds
  return m_samplerList[i].name.c_str();
}

//
//
//
shader::SamplerType hlslSm3FXShader::samplerType(int i) {
  //should check for array bounds
  return m_samplerList[i].type;
}

//
//
//
const char* hlslSm3FXShader::attributeName(int i) {
  //should check for array bounds
  return m_attributeList[i].name.c_str();
}

//
//
//
shader::DataType hlslSm3FXShader::attributeType(int i) {
  return m_attributeList[i].type;
}

//
//
//
void hlslSm3FXShader::updateUniformBool( int i, bool val) {
  m_uniformList[i].fVal[0] = val ? 1.0f : 0.0f;
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateUniformInt( int i, int val) {
  m_uniformList[i].fVal[0] = (float)val;
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateUniformFloat( int i, float val) {
  m_uniformList[i].fVal[0] = val;
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateUniformBVec( int i, const bool* val) {
  for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
    m_uniformList[i].fVal[ii] = val[ii] ? 0.0f : 1.0f;
  }
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateUniformIVec( int i, const int* val) {
  for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
    m_uniformList[i].fVal[ii] = (float)val[ii];
  }
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateUniformVec( int i, const float* val) {
  for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
    m_uniformList[i].fVal[ii] = val[ii];
  }
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateUniformMat( int i, const float* val) {
  for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
    m_uniformList[i].fVal[ii] = val[ii];
  }
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateUniformMat( int i, const double* val) {
  for (int ii=0; ii<size(m_uniformList[i].type); ii++) {
    m_uniformList[i].fVal[ii] = (float)val[ii];
  }
  m_uniformList[i].dirty = true;
}

//
//
//
void hlslSm3FXShader::updateSampler( int i, unsigned int val) {
  m_samplerList[i].texObject = val;
  //m_samplerList[i].dirty = true;
}

//
//
//
bool hlslSm3FXShader::usesColor() {
  return m_color;
}

//
//
//
bool hlslSm3FXShader::usesNormal() {
  return m_normal;
}

//
//
//
bool hlslSm3FXShader::usesTexCoord( int set) {
  return ((m_texMask>>set) & 0x1) == 1;
}

//
//
//
bool hlslSm3FXShader::usesTangent() {
  return m_tangent;
}

//
//
//
bool hlslSm3FXShader::usesBinormal() {
  return m_binormal;
}

//
//
//
int hlslSm3FXShader::tangentSlot() {
  return m_tangentSlot;
}

//
//
//
int hlslSm3FXShader::binormalSlot() {
  return m_binormalSlot;
}

//
//
//
const char* hlslSm3FXShader::errorString() {
  return m_error.c_str();
}


Autodesk® Maya® 2009 © 1997-2008 Autodesk, Inc. All rights reserved. Generated with doxygen 1.5.6