conform to shader spec 1.10.59
authorMichal Krol <mjkrol@gmail.org>
Mon, 18 Oct 2004 12:18:33 +0000 (12:18 +0000)
committerMichal Krol <mjkrol@gmail.org>
Mon, 18 Oct 2004 12:18:33 +0000 (12:18 +0000)
src/mesa/shader/slang_common_builtin.gc
src/mesa/shader/slang_fragment_builtin.gc
src/mesa/shader/slang_vertex_builtin.gc

index 994e1a3..65c5c79 100755 (executable)
-\r
-// \r
-// TODO:\r
-// - implement sin, asin, acos, atan, pow, log2, floor, ceil,\r
-// - implement texture1D, texture2D, texture3D, textureCube,\r
-// - implement shadow1D, shadow2D,\r
-// - implement noise1, noise2, noise3, noise4,\r
-// \r
-\r
-// \r
-// From Shader Spec, ver. 1.051\r
-// \r
-// The following built-in constants are provided to vertex and fragment shaders.\r
-// \r
-\r
-// \r
-// Implementation dependent constants. The example values below\r
-// are the minimum values allowed for these maximums.\r
-// \r
-\r
-const int gl_MaxLights = 8;                             // GL 1.0\r
-const int gl_MaxClipPlanes = 6;                         // GL 1.0\r
-const int gl_MaxTextureUnits = 2;                       // GL 1.2\r
-const int gl_MaxTextureCoordsARB = 2;                   // ARB_fragment_program\r
-const int gl_MaxVertexAttributesGL2 = 16;               // GL2_vertex_shader\r
-const int gl_MaxVertexUniformFloatsGL2 = 512;           // GL2_vertex_shader\r
-const int gl_MaxVaryingFloatsGL2 = 32;                  // GL2_vertex_shader\r
-const int gl_MaxVertexTextureUnitsGL2 = 1;              // GL2_vertex_shader\r
-const int gl_MaxFragmentTextureUnitsGL2 = 2;            // GL2_fragment_shader\r
-const int gl_MaxFragmentUniformFloatsGL2 = 64;          // GL2_fragment_shader\r
-\r
-// \r
-// As an aid to accessing OpenGL processing state, the following uniform variables are built into\r
-// the OpenGL Shading Language. All page numbers and notations are references to the 1.4\r
-// specification.\r
-// \r
-\r
-// \r
-// Matrix state. p. 31, 32, 37, 39, 40.\r
-// \r
-\r
-uniform mat4 gl_ModelViewMatrix;\r
-uniform mat4 gl_ProjectionMatrix;\r
-uniform mat4 gl_ModelViewProjectionMatrix;\r
-uniform mat3 gl_NormalMatrix;                           // derived\r
-uniform mat4 gl_TextureMatrix[gl_MaxTextureCoordsARB];\r
-\r
-// \r
-// Normal scaling p. 39.\r
-// \r
-\r
-uniform float gl_NormalScale;\r
-\r
-// \r
-// Depth range in window coordinates, p. 33\r
-// \r
-\r
-struct gl_DepthRangeParameters {\r
-    float near;                                         // n\r
-    float far;                                          // f\r
-    float diff;                                         // f - n\r
-};\r
-\r
-uniform gl_DepthRangeParameters gl_DepthRange;\r
-\r
-// \r
-// Clip planes p. 42.\r
-// \r
-\r
-uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];\r
-\r
-// \r
-// Point Size, p. 66, 67.\r
-// \r
-\r
-struct gl_PointParameters {\r
-    float size;\r
-    float sizeMin;\r
-    float sizeMax;\r
-    float fadeThresholdSize;\r
-    float distanceConstantAttenuation;\r
-    float distanceLinearAttenuation;\r
-    float distanceQuadraticAttenuation;\r
-};\r
-\r
-uniform gl_PointParameters gl_Point;\r
-\r
-// \r
-// Material State p. 50, 55.\r
-// \r
-\r
-struct gl_MaterialParameters {\r
-    vec4 emission;                                      // Ecm\r
-    vec4 ambient;                                       // Acm\r
-    vec4 diffuse;                                       // Dcm\r
-    vec4 specular;                                      // Scm\r
-    float shininess;                                    // Srm\r
-};\r
-\r
-uniform gl_MaterialParameters gl_FrontMaterial;\r
-uniform gl_MaterialParameters gl_BackMaterial;\r
-\r
-// \r
-// Light State p 50, 53, 55.\r
-// \r
-\r
-struct gl_LightSourceParameters {\r
-    vec4 ambient;                                       // Acli\r
-    vec4 diffuse;                                       // Dcli\r
-    vec4 specular;                                      // Scli\r
-    vec4 position;                                      // Ppli\r
-    vec4 halfVector;                                    // Derived: Hi\r
-    vec3 spotDirection;                                 // Sdli\r
-    float spotExponent;                                 // Srli\r
-    float spotCutoff;                                   // Crli\r
-                                                        // (range: [0.0,90.0], 180.0)\r
-    float spotCosCutoff;                                // Derived: cos(Crli)\r
-                                                        // (range: [1.0,0.0],-1.0)\r
-    float constantAttenuation;                          // K0\r
-    float linearAttenuation;                            // K1\r
-    float quadraticAttenuation;                         // K2\r
-};\r
-\r
-uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];\r
-\r
-struct gl_LightModelParameters {\r
-    vec4 ambient;                                       // Acs\r
-};\r
-\r
-uniform gl_LightModelParameters gl_LightModel;\r
-\r
-// \r
-// Derived state from products of light and material.\r
-// \r
-\r
-struct gl_LightModelProducts {\r
-    vec4 sceneColor;                                    // Derived. Ecm + Acm * Acs\r
-};\r
-\r
-uniform gl_LightModelProducts gl_FrontLightModelProduct;\r
-uniform gl_LightModelProducts gl_BackLightModelProduct;\r
-\r
-struct gl_LightProducts {\r
-    vec4 ambient;                                       // Acm * Acli\r
-    vec4 diffuse;                                       // Dcm * Dcli\r
-    vec4 specular;                                      // Scm * Scli\r
-};\r
-\r
-uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];\r
-uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];\r
-\r
-// \r
-// Textureg Environment and Generation, p. 152, p. 40-42.\r
-// \r
-\r
-uniform vec4 gl_TextureEnvColor[gl_MaxFragmentTextureUnitsGL2];\r
-uniform vec4 gl_EyePlaneS[gl_MaxTextureCoordsARB];\r
-uniform vec4 gl_EyePlaneT[gl_MaxTextureCoordsARB];\r
-uniform vec4 gl_EyePlaneR[gl_MaxTextureCoordsARB];\r
-uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoordsARB];\r
-uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoordsARB];\r
-uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoordsARB];\r
-uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoordsARB];\r
-uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoordsARB];\r
-\r
-// \r
-// Fog p. 161\r
-// \r
-\r
-struct gl_FogParameters {\r
-    vec4 color;\r
-    float density;\r
-    float start;\r
-    float end;\r
-    float scale;                                        // 1 / (gl_FogEnd - gl_FogStart)\r
-};\r
-\r
-uniform gl_FogParameters gl_Fog;\r
-\r
-// \r
-// The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar\r
-// and vector operations. Many of these built-in functions can be used in more than one type\r
-// of shader, but some are intended to provide a direct mapping to hardware and so are available\r
-// only for a specific type of shader.\r
-// \r
-// The built-in functions basically fall into three categories:\r
-// \r
-// \95 They expose some necessary hardware functionality in a convenient way such as accessing\r
-//   a texture map. There is no way in the language for these functions to be emulated by a shader.\r
-// \r
-// \95 They represent a trivial operation (clamp, mix, etc.) that is very simple for the user\r
-//   to write, but they are very common and may have direct hardware support. It is a very hard\r
-//   problem for the compiler to map expressions to complex assembler instructions.\r
-// \r
-// \95 They represent an operation graphics hardware is likely to accelerate at some point. The\r
-//   trigonometry functions fall into this category.\r
-// \r
-// Many of the functions are similar to the same named ones in common C libraries, but they support\r
-// vector input as well as the more traditional scalar input.\r
-// \r
-// Applications should be encouraged to use the built-in functions rather than do the equivalent\r
-// computations in their own shader code since the built-in functions are assumed to be optimal\r
-// (e.g., perhaps supported directly in hardware).\r
-// \r
-// User code can replace built-in functions with their own if they choose, by simply re-declaring\r
-// and defining the same name and argument list.\r
-// \r
-\r
-// \r
-// Angle and Trigonometry Functions\r
-// \r
-// Function parameters specified as angle are assumed to be in units of radians. In no case will\r
-// any of these functions result in a divide by zero error. If the divisor of a ratio is 0, then\r
-// results will be undefined.\r
-// \r
-// These all operate component-wise.\r
-// \r
-\r
-// \r
-// Converts degrees to radians and returns the result, i.e., result = PI*deg/180.\r
-// \r
-\r
-float radians (float deg) {\r
-    return 3.141593 * deg / 180.0;\r
-}\r
-vec2 radians (vec2 deg) {\r
-    return vec2 (radians (deg.x), radians (deg.y));\r
-}\r
-vec3 radians (vec3 deg) {\r
-    return vec3 (radians (deg.x), radians (deg.y), radians (deg.z));\r
-}\r
-vec4 radians (vec4 deg) {\r
-    return vec4 (radians (deg.x), radians (deg.y), radians (deg.z), radians (deg.w));\r
-}\r
-\r
-// \r
-// Converts radians to degrees and returns the result, i.e., result = 180*rad/PI.\r
-// \r
-\r
-float degrees (float rad) {\r
-    return 180.0 * rad / 3.141593;\r
-}\r
-vec2 degrees (vec2 rad) {\r
-    return vec2 (degrees (rad.x), degrees (rad.y));\r
-}\r
-vec3 degrees (vec3 rad) {\r
-    return vec3 (degrees (rad.x), degrees (rad.y), degrees (rad.z));\r
-}\r
-vec4 degrees (vec4 rad) {\r
-    return vec4 (degrees (rad.x), degrees (rad.y), degrees (rad.z), degrees (rad.w));\r
-}\r
-\r
-// \r
-// The standard trigonometric sine function.\r
-// \r
-// XXX\r
-float sin (float angle) {\r
-    return 0.0;\r
-}\r
-vec2 sin (vec2 angle) {\r
-    return vec2 (sin (angle.x), sin (angle.y));\r
-}\r
-vec3 sin (vec3 angle) {\r
-    return vec3 (sin (angle.x), sin (angle.y), sin (angle.z));\r
-}\r
-vec4 sin (vec4 angle) {\r
-    return vec4 (sin (angle.x), sin (angle.y), sin (angle.z), sin (angle.w));\r
-}\r
-\r
-// \r
-// The standard trigonometric cosine function.\r
-// \r
-\r
-float cos (float angle) {\r
-    return sin (angle + 1.5708);\r
-}\r
-vec2 cos (vec2 angle) {\r
-    return vec2 (cos (angle.x), cos (angle.y));\r
-}\r
-vec3 cos (vec3 angle) {\r
-    return vec3 (cos (angle.x), cos (angle.y), cos (angle.z));\r
-}\r
-vec4 cos (vec4 angle) {\r
-    return vec4 (cos (angle.x), cos (angle.y), cos (angle.z), cos (angle.w));\r
-}\r
-\r
-// \r
-// The standard trigonometric tangent.\r
-// \r
-\r
-float tan (float angle) {\r
-    return sin (angle) / cos (angle);\r
-}\r
-vec2 tan (vec2 angle) {\r
-    return vec2 (tan (angle.x), tan (angle.y));\r
-}\r
-vec3 tan (vec3 angle) {\r
-    return vec3 (tan (angle.x), tan (angle.y), tan (angle.z));\r
-}\r
-vec4 tan (vec4 angle) {\r
-    return vec4 (tan (angle.x), tan (angle.y), tan (angle.z), tan (angle.w));\r
-}\r
-\r
-// \r
-// Arc sine. Returns an angle whose sine is x. The range of values returned by this function is\r
-// [\96PI/2, PI/2]. Results are undefined if |x| > 1.\r
-// \r
-// XXX\r
-float asin (float x) {\r
-    return 0.0;\r
-}\r
-vec2 asin (vec2 x) {\r
-    return vec2 (asin (x.x), asin (x.y));\r
-}\r
-vec3 asin (vec3 x) {\r
-    return vec3 (asin (x.x), asin (x.y), asin (x.z));\r
-}\r
-vec4 asin (vec4 x) {\r
-    return vec4 (asin (x.x), asin (x.y), asin (x.z), asin (x.w));\r
-}\r
-\r
-// \r
-// Arc cosine. Returns an angle whose cosine is x. The range of values returned by this function is\r
-// [0, PI]. Results are undefined if |x| > 1.\r
-// \r
-// XXX\r
-float acos (float x) {\r
-    return 0.0;\r
-}\r
-vec2 acos (vec2 x) {\r
-    return vec2 (acos (x.x), acos (x.y));\r
-}\r
-vec3 acos (vec3 x) {\r
-    return vec3 (acos (x.x), acos (x.y), acos (x.z));\r
-}\r
-vec4 acos (vec4 x) {\r
-    return vec4 (acos (x.x), acos (x.y), acos (x.z), acos (x.w));\r
-}\r
-\r
-// \r
-// Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine\r
-// what quadrant the angle is in. The range of values returned by this function is [\96PI, PI].\r
-// Results are undefined if x and y are both 0.\r
-// \r
-// XXX\r
-float atan (float x, float y) {\r
-    return 0.0;\r
-}\r
-vec2 atan (vec2 x, vec2 y) {\r
-    return vec2 (atan (x.x, y.x), atan (x.y, y.y));\r
-}\r
-vec3 atan (vec3 x, vec3 y) {\r
-    return vec3 (atan (x.x, y.x), atan (x.y, y.y), atan (x.z, y.z));\r
-}\r
-vec4 atan (vec4 x, vec4 y) {\r
-    return vec4 (atan (x.x, y.x), atan (x.y, y.y), atan (x.z, y.z), atan (x.w, y.w));\r
-}\r
-\r
-// \r
-// Arc tangent. Returns an angle whose tangent is y_over_x. The range of values returned by this\r
-// function is [\96PI/2, PI/2].\r
-// \r
-// XXX\r
-float atan (float y_over_x) {\r
-    return 0.0;\r
-}\r
-vec2 atan (vec2 y_over_x) {\r
-    return vec2 (atan (y_over_x.x), atan (y_over_x.y));\r
-}\r
-vec3 atan (vec3 y_over_x) {\r
-    return vec3 (atan (y_over_x.x), atan (y_over_x.y), atan (y_over_x.z));\r
-}\r
-vec4 atan (vec4 y_over_x) {\r
-    return vec4 (atan (y_over_x.x), atan (y_over_x.y), atan (y_over_x.z), atan (y_over_x.w));\r
-}\r
-\r
-// \r
-// Exponential Functions\r
-// \r
-// These all operate component-wise.\r
-// \r
-\r
-// \r
-// Returns x raised to the y power, i.e., x^y\r
-// \r
-// XXX\r
-float pow (float x, float y) {\r
-    return 0.0;\r
-}\r
-vec2 pow (vec2 x, vec2 y) {\r
-    return vec2 (pow (x.x, y.x), pow (x.y, y.y));\r
-}\r
-vec3 pow (vec3 x, vec3 y) {\r
-    return vec3 (pow (x.x, y.x), pow (x.y, y.y), pow (x.z, y.z));\r
-}\r
-vec4 pow (vec4 x, vec4 y) {\r
-    return vec4 (pow (x.x, y.x), pow (x.y, y.y), pow (x.z, y.z), pow (x.w, y.w));\r
-}\r
-\r
-// \r
-// Returns 2 raised to the x power, i.e., 2^x\r
-// \r
-\r
-float exp2 (float x) {\r
-    return pow (2.0, x);\r
-}\r
-vec2 exp2 (vec2 x) {\r
-    return vec2 (exp2 (x.x), exp2 (x.y));\r
-}\r
-vec3 exp2 (vec3 x) {\r
-    return vec3 (exp2 (x.x), exp2 (x.y), exp2 (x.z));\r
-}\r
-vec4 exp2 (vec4 x) {\r
-    return vec4 (exp2 (x.x), exp2 (x.y), exp2 (x.z), exp2 (x.w));\r
-}\r
-\r
-// \r
-// Returns the base 2 log of x, i.e., returns the value y which satisfies the equation x = 2^y\r
-// \r
-// XXX\r
-float log2 (float x) {\r
-    return 0.0;\r
-}\r
-vec2 log2 (vec2 x) {\r
-    return vec2 (log2 (x.x), log2 (x.y));\r
-}\r
-vec3 log2 (vec3 x) {\r
-    return vec3 (log2 (x.x), log2 (x.y), log2 (x.z));\r
-}\r
-vec4 log2 (vec4 x) {\r
-    return vec4 (log2 (x.x), log2 (x.y), log2 (x.z), log2 (x.w));\r
-}\r
-\r
-// \r
-// Returns the positive square root of x\r
-// \r
-\r
-float sqrt (float x) {\r
-    return pow (x, 0.5);\r
-}\r
-vec2 sqrt (vec2 x) {\r
-    return vec2 (sqrt (x.x), sqrt (x.y));\r
-}\r
-vec3 sqrt (vec3 x) {\r
-    return vec3 (sqrt (x.x), sqrt (x.y), sqrt (x.z));\r
-}\r
-vec4 sqrt (vec4 x) {\r
-    return vec4 (sqrt (x.x), sqrt (x.y), sqrt (x.z), sqrt (x.w));\r
-}\r
-\r
-// \r
-// Returns the reciprocal of the positive square root of x\r
-// \r
-\r
-float inversesqrt (float x) {\r
-    return 1.0 / sqrt (x);\r
-}\r
-vec2 inversesqrt (vec2 x) {\r
-    return vec2 (inversesqrt (x.x), inversesqrt (x.y));\r
-}\r
-vec3 inversesqrt (vec3 x) {\r
-    return vec3 (inversesqrt (x.x), inversesqrt (x.y), inversesqrt (x.z));\r
-}\r
-vec4 inversesqrt (vec4 x) {\r
-    return vec4 (inversesqrt (x.x), inversesqrt (x.y), inversesqrt (x.z), inversesqrt (x.w));\r
-}\r
-\r
-// \r
-// Common Functions\r
-// \r
-// These all operate component-wise.\r
-// \r
-\r
-// \r
-// Returns x if x >= 0, otherwise it returns \96x\r
-// \r
-\r
-float abs (float x) {\r
-    return x >= 0.0 ? x : -x;\r
-}\r
-vec2 abs (vec2 x) {\r
-    return vec2 (abs (x.x), abs (x.y));\r
-}\r
-vec3 abs (vec3 x) {\r
-    return vec3 (abs (x.x), abs (x.y), abs (x.z));\r
-}\r
-vec4 abs (vec4 x) {\r
-    return vec4 (abs (x.x), abs (x.y), abs (x.z), abs (x.w));\r
-}\r
-\r
-// \r
-// Returns 1.0 if x > 0, 0.0 if x = 0, or \961.0 if x < 0\r
-// \r
-\r
-float sign (float x) {\r
-    return x > 0.0 ? 1.0 : x < 0.0 ? -1.0 : 0.0;\r
-}\r
-vec2 sign (vec2 x) {\r
-    return vec2 (sign (x.x), sign (x.y));\r
-}\r
-vec3 sign (vec3 x) {\r
-    return vec3 (sign (x.x), sign (x.y), sign (x.z));\r
-}\r
-vec4 sign (vec4 x) {\r
-    return vec4 (sign (x.x), sign (x.y), sign (x.z), sign (x.w));\r
-}\r
-\r
-// \r
-// Returns a value equal to the nearest integer that is less than or equal to x\r
-// \r
-// XXX\r
-float floor (float x) {\r
-    return 0.0;\r
-}\r
-vec2 floor (vec2 x) {\r
-    return vec2 (floor (x.x), floor (x.y));\r
-}\r
-vec3 floor (vec3 x) {\r
-    return vec3 (floor (x.x), floor (x.y), floor (x.z));\r
-}\r
-vec4 floor (vec4 x) {\r
-    return vec4 (floor (x.x), floor (x.y), floor (x.z), floor (x.w));\r
-}\r
-\r
-// \r
-// Returns a value equal to the nearest integer that is greater than or equal to x\r
-// \r
-// XXX\r
-float ceil (float x) {\r
-    return 0.0;\r
-}\r
-vec2 ceil (vec2 x) {\r
-    return vec2 (ceil (x.x), ceil (x.y));\r
-}\r
-vec3 ceil (vec3 x) {\r
-    return vec3 (ceil (x.x), ceil (x.y), ceil (x.z));\r
-}\r
-vec4 ceil (vec4 x) {\r
-    return vec4 (ceil (x.x), ceil (x.y), ceil (x.z), ceil (x.w));\r
-}\r
-\r
-// \r
-// Returns x \96 floor (x)\r
-// \r
-\r
-float fract (float x) {\r
-    return x - floor (x);\r
-}\r
-vec2 fract (vec2 x) {\r
-    return vec2 (fract (x.x), fract (x.y));\r
-}\r
-vec3 fract (vec3 x) {\r
-    return vec3 (fract (x.x), fract (x.y), fract (x.z));\r
-}\r
-vec4 fract (vec4 x) {\r
-    return vec4 (fract (x.x), fract (x.y), fract (x.z), fract (x.w));\r
-}\r
-\r
-// \r
-// Modulus. Returns x \96 y * floor (x/y)\r
-// \r
-\r
-float mod (float x, float y) {\r
-    return x - y * floor (x / y);\r
-}\r
-vec2 mod (vec2 x, float y) {\r
-    return vec2 (mod (x.x, y), mod (x.y, y));\r
-}\r
-vec3 mod (vec3 x, float y) {\r
-    return vec3 (mod (x.x, y), mod (x.y, y), mod (x.z, y));\r
-}\r
-vec4 mod (vec4 x, float y) {\r
-    return vec4 (mod (x.x, y), mod (x.y, y), mod (x.z, y), mod (x.w, y));\r
-}\r
-vec2 mod (vec2 x, vec2 y) {\r
-    return vec2 (mod (x.x, y.x), mod (x.y, y.y));\r
-}\r
-vec3 mod (vec3 x, vec3 y) {\r
-    return vec3 (mod (x.x, y.x), mod (x.y, y.y), mod (x.z, y.z));\r
-}\r
-vec4 mod (vec4 x, vec4 y) {\r
-    return vec4 (mod (x.x, y.x), mod (x.y, y.y), mod (x.z, y.z), mod (x.w, y.w));\r
-}\r
-\r
-// \r
-// Returns y if y < x, otherwise it returns x\r
-// \r
-\r
-float min (float x, float y) {\r
-    return y < x ? y : x;\r
-}\r
-vec2 min (vec2 x, float y) {\r
-    return vec2 (min (x.x, y), min (x.y, y));\r
-}\r
-vec3 min (vec3 x, float y) {\r
-    return vec3 (min (x.x, y), min (x.y, y), min (x.z, y));\r
-}\r
-vec4 min (vec4 x, float y) {\r
-    return vec4 (min (x.x, y), min (x.y, y), min (x.z, y), min (x.w, y));\r
-}\r
-vec2 min (vec2 x, vec2 y) {\r
-    return vec2 (min (x.x, y.x), min (x.y, y.y));\r
-}\r
-vec3 min (vec3 x, vec3 y) {\r
-    return vec3 (min (x.x, y.x), min (x.y, y.y), min (x.z, y.z));\r
-}\r
-vec4 min (vec4 x, vec4 y) {\r
-    return vec4 (min (x.x, y.x), min (x.y, y.y), min (x.z, y.z), min (x.w, y.w));\r
-}\r
-\r
-// \r
-// Returns y if x < y, otherwise it returns x\r
-// \r
-\r
-float max (float x, float y) {\r
-    return min (y, x);\r
-}\r
-vec2 max (vec2 x, float y) {\r
-    return vec2 (max (x.x, y), max (x.y, y));\r
-}\r
-vec3 max (vec3 x, float y) {\r
-    return vec3 (max (x.x, y), max (x.y, y), max (x.z, y));\r
-}\r
-vec4 max (vec4 x, float y) {\r
-    return vec4 (max (x.x, y), max (x.y, y), max (x.z, y), max (x.w, y));\r
-}\r
-vec2 max (vec2 x, vec2 y) {\r
-    return vec2 (max (x.x, y.x), max (x.y, y.y));\r
-}\r
-vec3 max (vec3 x, vec3 y) {\r
-    return vec3 (max (x.x, y.x), max (x.y, y.y), max (x.z, y.z));\r
-}\r
-vec4 max (vec4 x, vec4 y) {\r
-    return vec4 (max (x.x, y.x), max (x.y, y.y), max (x.z, y.z), max (x.w, y.w));\r
-}\r
-\r
-// \r
-// Returns min (max (x, minVal), maxVal)\r
-// \r
-// Note that colors and depths written by fragment shaders will be clamped by the implementation\r
-// after the fragment shader runs.\r
-// \r
-\r
-float clamp (float x, float minVal, float maxVal) {\r
-    return min (max (x, minVal), maxVal);\r
-}\r
-vec2 clamp (vec2 x, float minVal, float maxVal) {\r
-    return vec2 (clamp (x.x, minVal, maxVal), clamp (x.y, minVal, maxVal));\r
-}\r
-vec3 clamp (vec3 x, float minVal, float maxVal) {\r
-    return vec3 (clamp (x.x, minVal, maxVal), clamp (x.y, minVal, maxVal),\r
-        clamp (x.z, minVal, maxVal));\r
-}\r
-vec4 clamp (vec4 x, float minVal, float maxVal) {\r
-    return vec4 (clamp (x.x, minVal, maxVal), clamp (x.y, minVal, maxVal),\r
-        clamp (x.z, minVal, maxVal), clamp (x.w, minVal, maxVal));\r
-}\r
-vec2 clamp (vec2 x, vec2 minVal, vec2 maxVal) {\r
-    return vec2 (clamp (x.x, minVal.x, maxVal.x), clamp (x.y, minVal.y, maxVal.y));\r
-}\r
-vec3 clamp (vec3 x, vec3 minVal, vec3 maxVal) {\r
-    return vec3 (clamp (x.x, minVal.x, maxVal.x), clamp (x.y, minVal.y, maxVal.y),\r
-        clamp (x.z, minVal.z, maxVal.z));\r
-}\r
-vec4 clamp (vec4 x, vec4 minVal, vec4 maxVal) {\r
-    return vec4 (clamp (x.x, minVal.x, maxVal.y), clamp (x.y, minVal.y, maxVal.y),\r
-        clamp (x.z, minVal.z, maxVal.z), clamp (x.w, minVal.w, maxVal.w));\r
-}\r
-\r
-// \r
-// Returns x * (1 \96 a) + y * a, i.e., the linear blend of x and y\r
-// \r
-\r
-float mix (float x, float y, float a) {\r
-    return x * (1.0 - a) + y * a;\r
-}\r
-vec2 mix (vec2 x, vec2 y, float a) {\r
-    return vec2 (mix (x.x, y.x, a), mix (x.y, y.y, a));\r
-}\r
-vec3 mix (vec3 x, vec3 y, float a) {\r
-    return vec3 (mix (x.x, y.x, a), mix (x.y, y.y, a), mix (x.z, y.z, a));\r
-}\r
-vec4 mix (vec4 x, vec4 y, float a) {\r
-    return vec4 (mix (x.x, y.x, a), mix (x.y, y.y, a), mix (x.z, y.z, a), mix (x.w, y.w, a));\r
-}\r
-vec2 mix (vec2 x, vec2 y, vec2 a) {\r
-    return vec2 (mix (x.x, y.x, a.x), mix (x.y, y.y, a.y));\r
-}\r
-vec3 mix (vec3 x, vec3 y, vec3 a) {\r
-    return vec3 (mix (x.x, y.x, a.x), mix (x.y, y.y, a.y), mix (x.z, y.z, a.z));\r
-}\r
-vec4 mix (vec4 x, vec4 y, vec4 a) {\r
-    return vec4 (mix (x.x, y.x, a.x), mix (x.y, y.y, a.y), mix (x.z, y.z, a.z),\r
-        mix (x.w, y.w, a.w));\r
-}\r
-\r
-// \r
-// Returns 0.0 if x <= edge, otherwise it returns 1.0\r
-// \r
-\r
-float step (float edge, float x) {\r
-    return x <= edge ? 0.0 : 1.0;\r
-}\r
-vec2 step (float edge, vec2 x) {\r
-    return vec2 (step (edge, x.x), step (edge, x.y));\r
-}\r
-vec3 step (float edge, vec3 x) {\r
-    return vec3 (step (edge, x.x), step (edge, x.y), step (edge, x.z));\r
-}\r
-vec4 step (float edge, vec4 x) {\r
-    return vec4 (step (edge, x.x), step (edge, x.y), step (edge, x.z), step (edge, x.w));\r
-}\r
-vec2 step (vec2 edge, vec2 x) {\r
-    return vec2 (step (edge.x, x.x), step (edge.y, x.y));\r
-}\r
-vec3 step (vec3 edge, vec3 x) {\r
-    return vec3 (step (edge.x, x.x), step (edge.y, x.y), step (edge.z, x.z));\r
-}\r
-vec4 step (vec4 edge, vec4 x) {\r
-    return vec4 (step (edge.x, x.x), step (edge.y, x.y), step (edge.z, x.z), step (edge.w, x.w));\r
-}\r
-\r
-// \r
-// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth Hermite interpolation\r
-// between 0 and 1 when edge0 < x < edge1. This is useful in cases where you would want a threshold\r
-// function with a smooth transition. This is equivalent to:\r
-// <type> t;\r
-// t = clamp ((x \96 edge0) / (edge1 \96 edge0), 0, 1);\r
-// return t * t * (3 \96 2 * t);\r
-// \r
-\r
-float smoothstep (float edge0, float edge1, float x) {\r
-    const float t = clamp ((x - edge0) / (edge1 - edge0), 0.0, 1.0);\r
-    return t * t * (3.0 - 2.0 * t);\r
-}\r
-vec2 smoothstep (float edge0, float edge1, vec2 x) {\r
-    return vec2 (smoothstep (edge0, edge1, x.x), smoothstep (edge0, edge1, x.y));\r
-}\r
-vec3 smoothstep (float edge0, float edge1, vec3 x) {\r
-    return vec3 (smoothstep (edge0, edge1, x.x), smoothstep (edge0, edge1, x.y),\r
-        smoothstep (edge0, edge1, x.z));\r
-}\r
-vec4 smoothstep (float edge0, float edge1, vec4 x) {\r
-    return vec4 (smoothstep (edge0, edge1, x.x), smoothstep (edge0, edge1, x.y),\r
-        smoothstep (edge0, edge1, x.z), smoothstep (edge0, edge1, x.w));\r
-}\r
-vec2 smoothstep (vec2 edge0, vec2 edge1, vec2 x) {\r
-    return vec2 (smoothstep (edge0.x, edge1.x, x.x), smoothstep (edge0.y, edge1.y, x.y));\r
-}\r
-vec3 smoothstep (vec3 edge0, vec3 edge1, vec3 x) {\r
-    return vec3 (smoothstep (edge0.x, edge1.x, x.x), smoothstep (edge0.y, edge1.y, x.y),\r
-        smoothstep (edge0.z, edge1.z, x.z));\r
-}\r
-vec4 smoothstep (vec4 edge0, vec4 edge1, vec4 x) {\r
-    return vec4 (smoothstep (edge0.x, edge1.x, x.x), smoothstep (edge0.y, edge1.y, x.y),\r
-        smoothstep (edge0.z, edge1.z, x.z), smoothstep (edge0.w, edge1.w, x.w));\r
-}\r
-\r
-// \r
-// Geometric Functions\r
-// \r
-// These operate on vectors as vectors, not component-wise.\r
-// \r
-\r
-// \r
-// Returns the dot product of x and y, i.e., result = x[0] * y[0] + x[1] * y[1] + ...\r
-// \r
-\r
-float dot (float x, float y) {\r
-    return x * y;\r
-}\r
-float dot (vec2 x, vec2 y) {\r
-    return dot (x.x, y.x) + dot (x.y, y.y);\r
-}\r
-float dot (vec3 x, vec3 y) {\r
-    return dot (x.x, y.x) + dot (x.y, y.y) + dot (x.z, y.z);\r
-}\r
-float dot (vec4 x, vec4 y) {\r
-    return dot (x.x, y.x) + dot (x.y, y.y) + dot (x.z, y.z) + dot (x.w, y.w);\r
-}\r
-\r
-// \r
-// Returns the length of vector x, i.e., sqrt (x[0] * x[0] + x[1] * x[1] + ...)\r
-// \r
-\r
-float length (float x) {\r
-    return sqrt (dot (x, x));\r
-}\r
-float length (vec2 x) {\r
-    return sqrt (dot (x, x));\r
-}\r
-float length (vec3 x) {\r
-    return sqrt (dot (x, x));\r
-}\r
-float length (vec4 x) {\r
-    return sqrt (dot (x, x));\r
-}\r
-\r
-// \r
-// Returns the distance between p0 and p1, i.e. length (p0 \96 p1)\r
-// \r
-\r
-float distance (float x, float y) {\r
-    return length (x - y);\r
-}\r
-float distance (vec2 x, vec2 y) {\r
-    return length (x - y);\r
-}\r
-float distance (vec3 x, vec3 y) {\r
-    return length (x - y);\r
-}\r
-float distance (vec4 x, vec4 y) {\r
-    return length (x - y);\r
-}\r
-\r
-// \r
-// Returns the cross product of x and y, i.e.\r
-// result.0 = x[1] * y[2] - y[1] * x[2]\r
-// result.1 = x[2] * y[0] - y[2] * x[0]\r
-// result.2 = x[0] * y[1] - y[0] * x[1]\r
-// \r
-\r
-vec3 cross (vec3 x, vec3 y) {\r
-    return vec3 (x.y * y.z - y.y * x.z, x.z * y.x - y.z * x.x, x.x * y.y - y.x * x.y);\r
-}\r
-\r
-// \r
-// Returns a vector in the same direction as x but with a length of 1.\r
-// \r
-\r
-float normalize (float x) {\r
-    return 1.0;\r
-}\r
-vec2 normalize (vec2 x) {\r
-    return x / length (x);\r
-}\r
-vec3 normalize (vec3 x) {\r
-    return x / length (x);\r
-}\r
-vec4 normalize (vec4 x) {\r
-    return x / length (x);\r
-}\r
-\r
-// \r
-// If dot (Nref, I) < 0 return N otherwise return \96N\r
-// \r
-\r
-float faceforward (float N, float I, float Nref) {\r
-    return dot (Nref, I) < 0.0 ? N : -N;\r
-}\r
-vec2 faceforward (vec2 N, vec2 I, vec2 Nref) {\r
-    return dot (Nref, I) < 0.0 ? N : -N;\r
-}\r
-vec3 faceforward (vec3 N, vec3 I, vec3 Nref) {\r
-    return dot (Nref, I) < 0.0 ? N : -N;\r
-}\r
-vec4 faceforward (vec4 N, vec4 I, vec4 Nref) {\r
-    return dot (Nref, I) < 0.0 ? N : -N;\r
-}\r
-\r
-// \r
-// For the incident vector I and surface orientation N, returns the reflection direction:\r
-// result = I \96 2 * dot (N, I) * N\r
-// N should be normalized in order to achieve the desired result.\r
-\r
-float reflect (float I, float N) {\r
-    return I - 2.0 * dot (N, I) * N;\r
-}\r
-vec2 reflect (vec2 I, vec2 N) {\r
-    return I - 2.0 * dot (N, I) * N;\r
-}\r
-vec3 reflect (vec3 I, vec3 N) {\r
-    return I - 2.0 * dot (N, I) * N;\r
-}\r
-vec4 reflect (vec4 I, vec4 N) {\r
-    return I - 2.0 * dot (N, I) * N;\r
-}\r
-\r
-// \r
-// Matrix Functions\r
-// \r
-\r
-// \r
-// Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product\r
-// of x[i][j] and y[i][j].\r
-// Note: to get linear algebraic matrix multiplication, use the multiply operator (*).\r
-// \r
-\r
-mat2 matrixCompMult (mat2 x, mat2 y) {\r
-    return mat2 (\r
-        x[0].x * y[0].x, x[0].y * y[0].y,\r
-        x[1].x * y[1].x, x[1].y * y[1].y\r
-    );\r
-}\r
-mat3 matrixCompMult (mat3 x, mat3 y) {\r
-    return mat4 (\r
-        x[0].x * y[0].x, x[0].y * y[0].y, x[0].z * y[0].z,\r
-        x[1].x * y[1].x, x[1].y * y[1].y, x[1].z * y[1].z,\r
-        x[2].x * y[2].x, x[2].y * y[2].y, x[2].z * y[2].z\r
-    );\r
-}\r
-mat4 matrixCompMult (mat4 x, mat4 y) {\r
-    return mat4 (\r
-        x[0].x * y[0].x, x[0].y * y[0].y, x[0].z * y[0].z + x[0].w * y[0].w,\r
-        x[1].x * y[1].x, x[1].y * y[1].y, x[1].z * y[1].z + x[1].w * y[1].w,\r
-        x[2].x * y[2].x, x[2].y * y[2].y, x[2].z * y[2].z + x[2].w * y[2].w,\r
-        x[3].x * y[3].x, x[3].y * y[3].y, x[3].z * y[3].z + x[3].w * y[3].w\r
-    );\r
-}\r
-\r
-// \r
-// Vector Relational Functions\r
-// \r
-// Relational and equality operators (<, <=, >, >=, ==, !=) are defined (or reserved) to produce\r
-// scalar Boolean results.\r
-// \r
-\r
-// \r
-// Returns the component-wise compare of x < y.\r
-// \r
-\r
-bvec2 lessThan (vec2 x, vec2 y) {\r
-    return bvec2 (x.x < y.x, x.y < y.y);\r
-}\r
-bvec3 lessThan (vec3 x, vec3 y) {\r
-    return bvec3 (x.x < y.x, x.y < y.y, x.z < y.z);\r
-}\r
-bvec4 lessThan (vec4 x, vec4 y) {\r
-    return bvec4 (x.x < y.x, x.y < y.y, x.z < y.z, x.w < y.w);\r
-}\r
-bvec2 lessThan (ivec2 x, ivec2 y) {\r
-    return bvec2 (x.x < y.x, x.y < y.y);\r
-}\r
-bvec3 lessThan (ivec3 x, ivec3 y) {\r
-    return bvec3 (x.x < y.x, x.y < y.y, x.z < y.z);\r
-}\r
-bvec4 lessThan (ivec4 x, ivec4 y) {\r
-    return bvec4 (x.x < y.x, x.y < y.y, x.z < y.z, x.w < y.w);\r
-}\r
-\r
-// \r
-// Returns the component-wise compare of x <= y.\r
-// \r
-\r
-bvec2 lessThanEqual (vec2 x, vec2 y) {\r
-    return bvec2 (x.x <= y.x, x.y <= y.y);\r
-}\r
-bvec3 lessThanEqual (vec3 x, vec3 y) {\r
-    return bvec3 (x.x <= y.x, x.y <= y.y, x.z <= y.z);\r
-}\r
-bvec4 lessThanEqual (vec4 x, vec4 y) {\r
-    return bvec4 (x.x <= y.x, x.y <= y.y, x.z <= y.z, x.w <= y.w);\r
-}\r
-bvec2 lessThanEqual (ivec2 x, ivec2 y) {\r
-    return bvec2 (x.x <= y.x, x.y <= y.y);\r
-}\r
-bvec3 lessThanEqual (ivec3 x, ivec3 y) {\r
-    return bvec3 (x.x <= y.x, x.y <= y.y, x.z <= y.z);\r
-}\r
-bvec4 lessThanEqual (ivec4 x, ivec4 y) {\r
-    return bvec4 (x.x <= y.x, x.y <= y.y, x.z <= y.z, x.w <= y.w);\r
-}\r
-\r
-// \r
-// Returns the component-wise compare of x > y.\r
-// \r
-\r
-bvec2 greaterThan (vec2 x, vec2 y) {\r
-    return bvec2 (x.x > y.x, x.y > y.y);\r
-}\r
-bvec3 greaterThan (vec3 x, vec3 y) {\r
-    return bvec3 (x.x > y.x, x.y > y.y, x.z > y.z);\r
-}\r
-bvec4 greaterThan (vec4 x, vec4 y) {\r
-    return bvec4 (x.x > y.x, x.y > y.y, x.z > y.z, x.w > y.w);\r
-}\r
-bvec2 greaterThan (ivec2 x, ivec2 y) {\r
-    return bvec2 (x.x > y.x, x.y > y.y);\r
-}\r
-bvec3 greaterThan (ivec3 x, ivec3 y) {\r
-    return bvec3 (x.x > y.x, x.y > y.y, x.z > y.z);\r
-}\r
-bvec4 greaterThan (ivec4 x, ivec4 y) {\r
-    return bvec4 (x.x > y.x, x.y > y.y, x.z > y.z, x.w > y.w);\r
-}\r
-\r
-// \r
-// Returns the component-wise compare of x >= y.\r
-// \r
-\r
-bvec2 greaterThanEqual (vec2 x, vec2 y) {\r
-    return bvec2 (x.x >= y.x, x.y >= y.y);\r
-}\r
-bvec3 greaterThanEqual (vec3 x, vec3 y) {\r
-    return bvec3 (x.x >= y.x, x.y >= y.y, x.z >= y.z);\r
-}\r
-bvec4 greaterThanEqual (vec4 x, vec4 y) {\r
-    return bvec4 (x.x >= y.x, x.y >= y.y, x.z >= y.z, x.w >= y.w);\r
-}\r
-bvec2 greaterThanEqual (ivec2 x, ivec2 y) {\r
-    return bvec2 (x.x >= y.x, x.y >= y.y);\r
-}\r
-bvec3 greaterThanEqual (ivec3 x, ivec3 y) {\r
-    return bvec3 (x.x >= y.x, x.y >= y.y, x.z >= y.z);\r
-}\r
-bvec4 greaterThanEqual (ivec4 x, ivec4 y) {\r
-    return bvec4 (x.x >= y.x, x.y >= y.y, x.z >= y.z, x.w >= y.w);\r
-}\r
-\r
-// \r
-// Returns the component-wise compare of x == y.\r
-// \r
-\r
-bvec2 equal (vec2 x, vec2 y) {\r
-    return bvec2 (x.x == y.x, x.y == y.y);\r
-}\r
-bvec3 equal (vec3 x, vec3 y) {\r
-    return bvec3 (x.x == y.x, x.y == y.y, x.z == y.z);\r
-}\r
-bvec4 equal (vec4 x, vec4 y) {\r
-    return bvec4 (x.x == y.x, x.y == y.y, x.z == y.z, x.w == y.w);\r
-}\r
-bvec2 equal (ivec2 x, ivec2 y) {\r
-    return bvec2 (x.x == y.x, x.y == y.y);\r
-}\r
-bvec3 equal (ivec3 x, ivec3 y) {\r
-    return bvec3 (x.x == y.x, x.y == y.y, x.z == y.z);\r
-}\r
-bvec4 equal (ivec4 x, ivec4 y) {\r
-    return bvec4 (x.x == y.x, x.y == y.y, x.z == y.z, x.w == y.w);\r
-}\r
-\r
-// \r
-// Returns the component-wise compare of x != y.\r
-// \r
-\r
-bvec2 notEqual (vec2 x, vec2 y) {\r
-    return bvec2 (x.x != y.x, x.y != y.y);\r
-}\r
-bvec3 notEqual (vec3 x, vec3 y) {\r
-    return bvec3 (x.x != y.x, x.y != y.y, x.z != y.z);\r
-}\r
-bvec4 notEqual (vec4 x, vec4 y) {\r
-    return (bvec4 (x.x != y.x, x.y != y.y, x.z != y.z, x.w != y.w);\r
-}\r
-bvec2 notEqual (ivec2 x, ivec2 y) {\r
-    return (bvec2 (x.x != y.x, x.y != y.y);\r
-}\r
-bvec3 notEqual (ivec3 x, ivec3 y) {\r
-    return (bvec3 (x.x != y.x, x.y != y.y, x.z != y.z);\r
-}\r
-bvec4 notEqual (ivec4 x, ivec4 y) {\r
-    return (bvec4 (x.x != y.x, x.y != y.y, x.z != y.z, x.w != y.w);\r
-}\r
-\r
-// \r
-// Returns true if any component of x is true.\r
-// \r
-\r
-bool any (bvec2 x) {\r
-    return x.x || x.y;\r
-}\r
-bool any (bvec3 x) {\r
-    return x.x || x.y || x.z;\r
-}\r
-bool any (bvec4 x) {\r
-    return x.x || x.y || x.z || x.w;\r
-}\r
-\r
-// \r
-// Returns true only if all components of x are true.\r
-// \r
-\r
-bool all (bvec2 x) {\r
-    return x.x && x.y;\r
-}\r
-bool all (bvec3 x) {\r
-    return x.x && x.y && x.z;\r
-}\r
-bool all (bvec4 x) {\r
-    return x.x && x.y && x.z && x.w;\r
-}\r
-\r
-// \r
-// Returns the component-wise logical complement of x.\r
-// \r
-\r
-bvec2 not (bvec2 x) {\r
-    return bvec2 (!x.x, !x.y);\r
-}\r
-bvec3 not (bvec3 x) {\r
-    return bvec3 (!x.x, !x.y, !x.z);\r
-}\r
-bvec4 not (bvec4 x) {\r
-    return bvec4 (!x.x, !x.y, !x.z, !x.w);\r
-}\r
-\r
-// \r
-// Texture Lookup Functions\r
-// \r
-// Texture lookup functions are available to both vertex and fragment shaders. However, level\r
-// of detail is not computed by fixed functionality for vertex shaders, so there are some\r
-// differences in operation between vertex and fragment texture lookups. The functions in the table\r
-// below provide access to textures through samplers, as set up through the OpenGL API. Texture\r
-// properties such as size, pixel format, number of dimensions, filtering method, number of mip-map\r
-// levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are\r
-// taken into account as the texture is accessed via the built-in functions defined below.\r
-// \r
-// If a non-shadow texture call is made to a sampler whose texture has depth comparisons enabled,\r
-// then results are undefined. If a shadow texture call is made to a sampler whose texture does not\r
-// have depth comparisions enabled, the results are also undefined.\r
-// \r
-// In all functions below, the bias parameter is optional for fragment shaders. The bias parameter\r
-// is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to\r
-// the calculated level of detail prior to performing the texture access operation. If the bias\r
-// parameter is not provided, then the implementation automatically selects level of detail:\r
-// For a texture that is not mip-mapped, the texture is used directly. If it is mip-mapped and\r
-// running in a fragment shader, the LOD computed by the implementation is used to do the texture\r
-// lookup. If it is mip-mapped and running on the vertex shader, then the base texture is used.\r
-// \r
-// The built-ins suffixed with \93Lod\94 are allowed only in a vertex shader. For the \93Lod\94 functions,\r
-// lod is directly used as the level of detail.\r
-// \r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 1D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate coord.s is divided by\r
-// the last component of coord.\r
-// \r
-// XXX\r
-vec4 texture1D (sampler1D sampler, float coord) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture1DProj (sampler1D sampler, vec2 coord) {\r
-    return texture1D (sampler, coord.s / coord.t);\r
-}\r
-vec4 texture1DProj (sampler1D sampler, vec4 coord) {\r
-    return texture1D (sampler, coord.s / coord.q);\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 2D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate (coord.s, coord.t) is\r
-// divided by the last component of coord. The third component of coord is ignored for the vec4\r
-// coord variant.\r
-// \r
-// XXX\r
-vec4 texture2D (sampler2D sampler, vec2 coord) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture2DProj (sampler2D sampler, vec3 coord) {\r
-    return texture2D (sampler, vec2 (coord.s / coord.p, coord.t / coord.p));\r
-}\r
-vec4 texture2DProj (sampler2D sampler, vec4 coord) {\r
-    return texture2D (sampler, vec2 (coord.s / coord.q, coord.t / coord.q));\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 3D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate is divided by coord.q.\r
-// \r
-// XXX\r
-vec4 texture3D (sampler3D sampler, vec3 coord) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture3DProj (sampler3D sampler, vec4 coord) {\r
-    return texture3D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q));\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the cube map texture currently bound\r
-// to sampler. The direction of coord is used to select which face to do a 2-dimensional texture\r
-// lookup in, as described in section 3.8.6 in version 1.4 of the OpenGL specification.\r
-// \r
-// XXX\r
-vec4 textureCube (samplerCube sampler, vec3 coord) {\r
-    return vec4 (0.0);\r
-}\r
-\r
-// \r
-// Use texture coordinate coord to do a depth comparison lookup on the depth texture bound\r
-// to sampler, as described in section 3.8.14 of version 1.4 of the OpenGL specification. The 3rd\r
-// component of coord (coord.p) is used as the R value. The texture bound to sampler must be a\r
-// depth texture, or results are undefined. For the projective (\93Proj\94) version of each built-in,\r
-// the texture coordinate is divide by coord.q, giving a depth value R of coord.p/coord.q. The\r
-// second component of coord is ignored for the \931D\94 variants.\r
-// \r
-// XXX\r
-vec4 shadow1D (sampler1DShadow sampler, vec3 coord) {\r
-    return vec4 (0.0);\r
-}\r
-// XXX\r
-vec4 shadow2D (sampler2DShadow sampler, vec3 coord) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord) {\r
-    return shadow1D (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q));\r
-}\r
-vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord) {\r
-    return shadow2D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q));\r
-}\r
-\r
-// \r
-// Noise Functions\r
-// \r
-// Noise functions are available to both fragment and vertex shaders. They are stochastic functions\r
-// that can be used to increase visual complexity. Values returned by the following noise functions\r
-// give the appearance of randomness, but are not truly random. The noise functions below are\r
-// defined to have the following characteristics:\r
-// \r
-// \95 The return value(s) are always in the range [-1,1]\r
-// \95 The return value(s) have an overall average of 0.0\r
-// \95 They are repeatable, in that a particular input value will always produce the same return value\r
-// \95 They are statistically invariant under rotation (i.e., no matter how the domain is rotated, it\r
-//   has the same statistical character)\r
-// \95 They have a statistical invariance under translation (i.e., no matter how the domain is\r
-//   translated, it has the same statistical character)\r
-// \95 They typically give different results under translation.\r
-// \95 They have a narrow bandpass limit in frequency (i.e., it has no visible features larger or\r
-//   smaller than a certain narrow size range)\r
-// \r
-\r
-// \r
-// Returns a 1D noise value based on the input value x.\r
-// \r
-// XXX\r
-float noise1 (float x) {\r
-    return 0.0;\r
-}\r
-// XXX\r
-float noise1 (vec2 x) {\r
-    return 0.0;\r
-}\r
-// XXX\r
-float noise1 (vec3 x) {\r
-    return 0.0;\r
-}\r
-// XXX\r
-float noise1 (vec4 x) {\r
-    return 0.0;\r
-}\r
-\r
-// \r
-// Returns a 2D noise value based on the input value x.\r
-// \r
-// XXX\r
-vec2 noise2 (float x) {\r
-    return vec2 (0.0);\r
-}\r
-// XXX\r
-vec2 noise2 (vec2 x) {\r
-    return vec2 (0.0);\r
-}\r
-// XXX\r
-vec2 noise2 (vec3 x) {\r
-    return vec2 (0.0);\r
-}\r
-// XXX\r
-vec2 noise2 (vec4 x) {\r
-    return vec2 (0.0);\r
-}\r
-\r
-// \r
-// Returns a 3D noise value based on the input value x.\r
-// \r
-// XXX\r
-vec3 noise3 (float x) {\r
-    return vec3 (0.0);\r
-}\r
-// XXX\r
-vec3 noise3 (vec2 x) {\r
-    return vec3 (0.0);\r
-}\r
-// XXX\r
-vec3 noise3 (vec3 x) {\r
-    return vec3 (0.0);\r
-}\r
-// XXX\r
-vec3 noise3 (vec4 x) {\r
-    return vec3 (0.0);\r
-}\r
-\r
-// \r
-// Returns a 4D noise value based on the input value x.\r
-// \r
-// XXX\r
-vec4 noise4 (float x) {\r
-    return vec4 (0.0);\r
-}\r
-// XXX\r
-vec4 noise4 (vec2 x) {\r
-    return vec4 (0.0);\r
-}\r
-// XXX\r
-vec4 noise4 (vec3 x) {\r
-    return vec4 (0.0);\r
-}\r
-// XXX\r
-vec4 noise4 (vec4 x) {\r
-    return vec4 (0.0);\r
-}\r
-\r
+
+// 
+// TODO:
+// - implement sin, asin, acos, atan, pow, log2, floor, ceil,
+// - implement texture1D, texture2D, texture3D, textureCube,
+// - implement shadow1D, shadow2D,
+// - implement noise1, noise2, noise3, noise4,
+// 
+
+// 
+// From Shader Spec, ver. 1.10, rev. 59
+// 
+// The following built-in constants are provided to vertex and fragment shaders.
+// 
+
+// 
+// Implementation dependent constants. The example values below
+// are the minimum values allowed for these maximums.
+// 
+
+const int gl_MaxLights = 8;                             // GL 1.0
+const int gl_MaxClipPlanes = 6;                         // GL 1.0
+const int gl_MaxTextureUnits = 2;                       // GL 1.3
+const int gl_MaxTextureCoords = 2;                      // ARB_fragment_program
+const int gl_MaxVertexAttribs = 16;                     // ARB_vertex_shader
+const int gl_MaxVertexUniformComponents = 512;          // ARB_vertex_shader
+const int gl_MaxVaryingFloats = 32;                     // ARB_vertex_shader
+const int gl_MaxVertexTextureImageUnits = 0;            // ARB_vertex_shader
+const int gl_MaxCombinedTextureImageUnits = 2;          // ARB_vertex_shader
+const int gl_MaxTextureImageUnits = 2;                  // ARB_fragment_shader
+const int gl_MaxFragmentUniformComponents = 64;         // ARB_fragment_shader
+const int gl_MaxDrawBuffers = 1;                        // proposed ARB_draw_buffers
+
+// 
+// As an aid to accessing OpenGL processing state, the following uniform variables are built into
+// the OpenGL Shading Language. All page numbers and notations are references to the 1.4
+// specification.
+// 
+
+// 
+// Matrix state. p. 31, 32, 37, 39, 40.
+// 
+
+uniform mat4 gl_ModelViewMatrix;
+uniform mat4 gl_ProjectionMatrix;
+uniform mat4 gl_ModelViewProjectionMatrix;
+uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];
+
+//
+// Derived matrix state that provides inverse and transposed versions
+// of the matrices above. Poorly conditioned matrices may result
+// in unpredictable values in their inverse forms.
+//
+uniform mat3 gl_NormalMatrix; // transpose of the inverse of the
+                              // upper leftmost 3x3 of gl_ModelViewMatrix
+
+uniform mat4 gl_ModelViewMatrixInverse;
+uniform mat4 gl_ProjectionMatrixInverse;
+uniform mat4 gl_ModelViewProjectionMatrixInverse;
+uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixTranspose;
+uniform mat4 gl_ProjectionMatrixTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixTranspose;
+uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];
+
+uniform mat4 gl_ModelViewMatrixInverseTranspose;
+uniform mat4 gl_ProjectionMatrixInverseTranspose;
+uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
+uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];
+
+// 
+// Normal scaling p. 39.
+// 
+
+uniform float gl_NormalScale;
+
+// 
+// Depth range in window coordinates, p. 33
+// 
+
+struct gl_DepthRangeParameters {
+    float near;                                         // n
+    float far;                                          // f
+    float diff;                                         // f - n
+};
+
+uniform gl_DepthRangeParameters gl_DepthRange;
+
+// 
+// Clip planes p. 42.
+// 
+
+uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];
+
+// 
+// Point Size, p. 66, 67.
+// 
+
+struct gl_PointParameters {
+    float size;
+    float sizeMin;
+    float sizeMax;
+    float fadeThresholdSize;
+    float distanceConstantAttenuation;
+    float distanceLinearAttenuation;
+    float distanceQuadraticAttenuation;
+};
+
+uniform gl_PointParameters gl_Point;
+
+// 
+// Material State p. 50, 55.
+// 
+
+struct gl_MaterialParameters {
+    vec4 emission;                                      // Ecm
+    vec4 ambient;                                       // Acm
+    vec4 diffuse;                                       // Dcm
+    vec4 specular;                                      // Scm
+    float shininess;                                    // Srm
+};
+
+uniform gl_MaterialParameters gl_FrontMaterial;
+uniform gl_MaterialParameters gl_BackMaterial;
+
+// 
+// Light State p 50, 53, 55.
+// 
+
+struct gl_LightSourceParameters {
+    vec4 ambient;                                       // Acli
+    vec4 diffuse;                                       // Dcli
+    vec4 specular;                                      // Scli
+    vec4 position;                                      // Ppli
+    vec4 halfVector;                                    // Derived: Hi
+    vec3 spotDirection;                                 // Sdli
+    float spotExponent;                                 // Srli
+    float spotCutoff;                                   // Crli
+                                                        // (range: [0.0,90.0], 180.0)
+    float spotCosCutoff;                                // Derived: cos(Crli)
+                                                        // (range: [1.0,0.0],-1.0)
+    float constantAttenuation;                          // K0
+    float linearAttenuation;                            // K1
+    float quadraticAttenuation;                         // K2
+};
+
+uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
+
+struct gl_LightModelParameters {
+    vec4 ambient;                                       // Acs
+};
+
+uniform gl_LightModelParameters gl_LightModel;
+
+// 
+// Derived state from products of light and material.
+// 
+
+struct gl_LightModelProducts {
+    vec4 sceneColor;                                    // Derived. Ecm + Acm * Acs
+};
+
+uniform gl_LightModelProducts gl_FrontLightModelProduct;
+uniform gl_LightModelProducts gl_BackLightModelProduct;
+
+struct gl_LightProducts {
+    vec4 ambient;                                       // Acm * Acli
+    vec4 diffuse;                                       // Dcm * Dcli
+    vec4 specular;                                      // Scm * Scli
+};
+
+uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
+uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
+
+// 
+// Texture Environment and Generation, p. 152, p. 40-42.
+// 
+
+uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];
+uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
+uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
+uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];
+
+// 
+// Fog p. 161
+// 
+
+struct gl_FogParameters {
+    vec4 color;
+    float density;
+    float start;
+    float end;
+    float scale;    // Derived:    1.0 / (end - start)
+};
+
+uniform gl_FogParameters gl_Fog;
+
+// 
+// The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar
+// and vector operations. Many of these built-in functions can be used in more than one type
+// of shader, but some are intended to provide a direct mapping to hardware and so are available
+// only for a specific type of shader.
+// 
+// The built-in functions basically fall into three categories:
+// 
+// \95 They expose some necessary hardware functionality in a convenient way such as accessing
+//   a texture map. There is no way in the language for these functions to be emulated by a shader.
+// 
+// \95 They represent a trivial operation (clamp, mix, etc.) that is very simple for the user
+//   to write, but they are very common and may have direct hardware support. It is a very hard
+//   problem for the compiler to map expressions to complex assembler instructions.
+// 
+// \95 They represent an operation graphics hardware is likely to accelerate at some point. The
+//   trigonometry functions fall into this category.
+// 
+// Many of the functions are similar to the same named ones in common C libraries, but they support
+// vector input as well as the more traditional scalar input.
+// 
+// Applications should be encouraged to use the built-in functions rather than do the equivalent
+// computations in their own shader code since the built-in functions are assumed to be optimal
+// (e.g., perhaps supported directly in hardware).
+// 
+// User code can replace built-in functions with their own if they choose, by simply re-declaring
+// and defining the same name and argument list.
+// 
+
+// 
+// 8.1 Angle and Trigonometry Functions
+// 
+// Function parameters specified as angle are assumed to be in units of radians. In no case will
+// any of these functions result in a divide by zero error. If the divisor of a ratio is 0, then
+// results will be undefined.
+// 
+// These all operate component-wise. The description is per component.
+// 
+
+// 
+// Converts degrees to radians and returns the result, i.e., result = PI*deg/180.
+// 
+
+float radians (float deg) {
+    return 3.141593 * deg / 180.0;
+}
+vec2 radians (vec2 deg) {
+    return vec2 (radians (deg.x), radians (deg.y));
+}
+vec3 radians (vec3 deg) {
+    return vec3 (radians (deg.x), radians (deg.y), radians (deg.z));
+}
+vec4 radians (vec4 deg) {
+    return vec4 (radians (deg.x), radians (deg.y), radians (deg.z), radians (deg.w));
+}
+
+// 
+// Converts radians to degrees and returns the result, i.e., result = 180*rad/PI.
+// 
+
+float degrees (float rad) {
+    return 180.0 * rad / 3.141593;
+}
+vec2 degrees (vec2 rad) {
+    return vec2 (degrees (rad.x), degrees (rad.y));
+}
+vec3 degrees (vec3 rad) {
+    return vec3 (degrees (rad.x), degrees (rad.y), degrees (rad.z));
+}
+vec4 degrees (vec4 rad) {
+    return vec4 (degrees (rad.x), degrees (rad.y), degrees (rad.z), degrees (rad.w));
+}
+
+// 
+// The standard trigonometric sine function.
+// 
+// XXX
+float sin (float angle) {
+    return 0.0;
+}
+vec2 sin (vec2 angle) {
+    return vec2 (sin (angle.x), sin (angle.y));
+}
+vec3 sin (vec3 angle) {
+    return vec3 (sin (angle.x), sin (angle.y), sin (angle.z));
+}
+vec4 sin (vec4 angle) {
+    return vec4 (sin (angle.x), sin (angle.y), sin (angle.z), sin (angle.w));
+}
+
+// 
+// The standard trigonometric cosine function.
+// 
+
+float cos (float angle) {
+    return sin (angle + 1.5708);
+}
+vec2 cos (vec2 angle) {
+    return vec2 (cos (angle.x), cos (angle.y));
+}
+vec3 cos (vec3 angle) {
+    return vec3 (cos (angle.x), cos (angle.y), cos (angle.z));
+}
+vec4 cos (vec4 angle) {
+    return vec4 (cos (angle.x), cos (angle.y), cos (angle.z), cos (angle.w));
+}
+
+// 
+// The standard trigonometric tangent.
+// 
+
+float tan (float angle) {
+    return sin (angle) / cos (angle);
+}
+vec2 tan (vec2 angle) {
+    return vec2 (tan (angle.x), tan (angle.y));
+}
+vec3 tan (vec3 angle) {
+    return vec3 (tan (angle.x), tan (angle.y), tan (angle.z));
+}
+vec4 tan (vec4 angle) {
+    return vec4 (tan (angle.x), tan (angle.y), tan (angle.z), tan (angle.w));
+}
+
+// 
+// Arc sine. Returns an angle whose sine is x. The range of values returned by this function is
+// [\96PI/2, PI/2]. Results are undefined if |x| > 1.
+// 
+// XXX
+float asin (float x) {
+    return 0.0;
+}
+vec2 asin (vec2 x) {
+    return vec2 (asin (x.x), asin (x.y));
+}
+vec3 asin (vec3 x) {
+    return vec3 (asin (x.x), asin (x.y), asin (x.z));
+}
+vec4 asin (vec4 x) {
+    return vec4 (asin (x.x), asin (x.y), asin (x.z), asin (x.w));
+}
+
+// 
+// Arc cosine. Returns an angle whose cosine is x. The range of values returned by this function is
+// [0, PI]. Results are undefined if |x| > 1.
+// 
+// XXX
+float acos (float x) {
+    return 0.0;
+}
+vec2 acos (vec2 x) {
+    return vec2 (acos (x.x), acos (x.y));
+}
+vec3 acos (vec3 x) {
+    return vec3 (acos (x.x), acos (x.y), acos (x.z));
+}
+vec4 acos (vec4 x) {
+    return vec4 (acos (x.x), acos (x.y), acos (x.z), acos (x.w));
+}
+
+// 
+// Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine
+// what quadrant the angle is in. The range of values returned by this function is [\96PI, PI].
+// Results are undefined if x and y are both 0.
+// 
+// XXX
+float atan (float x, float y) {
+    return 0.0;
+}
+vec2 atan (vec2 x, vec2 y) {
+    return vec2 (atan (x.x, y.x), atan (x.y, y.y));
+}
+vec3 atan (vec3 x, vec3 y) {
+    return vec3 (atan (x.x, y.x), atan (x.y, y.y), atan (x.z, y.z));
+}
+vec4 atan (vec4 x, vec4 y) {
+    return vec4 (atan (x.x, y.x), atan (x.y, y.y), atan (x.z, y.z), atan (x.w, y.w));
+}
+
+// 
+// Arc tangent. Returns an angle whose tangent is y_over_x. The range of values returned by this
+// function is [\96PI/2, PI/2].
+// 
+// XXX
+float atan (float y_over_x) {
+    return 0.0;
+}
+vec2 atan (vec2 y_over_x) {
+    return vec2 (atan (y_over_x.x), atan (y_over_x.y));
+}
+vec3 atan (vec3 y_over_x) {
+    return vec3 (atan (y_over_x.x), atan (y_over_x.y), atan (y_over_x.z));
+}
+vec4 atan (vec4 y_over_x) {
+    return vec4 (atan (y_over_x.x), atan (y_over_x.y), atan (y_over_x.z), atan (y_over_x.w));
+}
+
+// 
+// 8.2 Exponential Functions
+// 
+// These all operate component-wise. The description is per component.
+// 
+
+// 
+// Returns x raised to the y power, i.e., x^y.
+// Results are undefined if x < 0.
+// Results are undefined if x = 0 and y <= 0.
+// 
+// XXX
+float pow (float x, float y) {
+    return 0.0;
+}
+vec2 pow (vec2 x, vec2 y) {
+    return vec2 (pow (x.x, y.x), pow (x.y, y.y));
+}
+vec3 pow (vec3 x, vec3 y) {
+    return vec3 (pow (x.x, y.x), pow (x.y, y.y), pow (x.z, y.z));
+}
+vec4 pow (vec4 x, vec4 y) {
+    return vec4 (pow (x.x, y.x), pow (x.y, y.y), pow (x.z, y.z), pow (x.w, y.w));
+}
+
+// 
+// Returns the natural exponentiation of x, i.e., e^x.
+// 
+
+float exp (float x) {
+    return pow (2.71828183, x);
+}
+vec2 exp (vec2 x) {
+    return vec2 (exp (x.x), exp (x.y));
+}
+vec3 exp (vec3 x) {
+    return vec3 (exp (x.x), exp (x.y), exp (x.z));
+}
+vec4 exp (vec4 x) {
+    return vec4 (exp (x.x), exp (x.y), exp (x.z), exp (x.w));
+}
+
+// 
+// Returns the natural logarithm of x, i.e., returns the value y which satisfies the equation
+// x = e^y.
+// Results are undefined if x <= 0.
+// 
+
+float log (float x) {
+    return log2 (x) / log2 (2.71828183);
+}
+vec2 log (vec2 x) {
+    return vec2 (log (x.x), log (x.y));
+}
+vec3 log (vec3 x) {
+    return vec3 (log (x.x), log (x.y), log (x.z));
+}
+vec4 log (vec4 x) {
+    return vec4 (log (x.x), log (x.y), log (x.z), log (x.w));
+}
+
+// 
+// Returns 2 raised to the x power, i.e., 2^x
+// 
+
+float exp2 (float x) {
+    return pow (2.0, x);
+}
+vec2 exp2 (vec2 x) {
+    return vec2 (exp2 (x.x), exp2 (x.y));
+}
+vec3 exp2 (vec3 x) {
+    return vec3 (exp2 (x.x), exp2 (x.y), exp2 (x.z));
+}
+vec4 exp2 (vec4 x) {
+    return vec4 (exp2 (x.x), exp2 (x.y), exp2 (x.z), exp2 (x.w));
+}
+
+// 
+// Returns the base 2 logarithm of x, i.e., returns the value y which satisfies the equation
+// x = 2^y.
+// Results are undefined if x <= 0.
+// 
+// XXX
+float log2 (float x) {
+    return 0.0;
+}
+vec2 log2 (vec2 x) {
+    return vec2 (log2 (x.x), log2 (x.y));
+}
+vec3 log2 (vec3 x) {
+    return vec3 (log2 (x.x), log2 (x.y), log2 (x.z));
+}
+vec4 log2 (vec4 x) {
+    return vec4 (log2 (x.x), log2 (x.y), log2 (x.z), log2 (x.w));
+}
+
+// 
+// Returns the positive square root of x.
+// Results are undefined if x < 0.
+// 
+
+float sqrt (float x) {
+    return pow (x, 0.5);
+}
+vec2 sqrt (vec2 x) {
+    return vec2 (sqrt (x.x), sqrt (x.y));
+}
+vec3 sqrt (vec3 x) {
+    return vec3 (sqrt (x.x), sqrt (x.y), sqrt (x.z));
+}
+vec4 sqrt (vec4 x) {
+    return vec4 (sqrt (x.x), sqrt (x.y), sqrt (x.z), sqrt (x.w));
+}
+
+// 
+// Returns the reciprocal of the positive square root of x.
+// Results are undefined if x <= 0.
+// 
+
+float inversesqrt (float x) {
+    return 1.0 / sqrt (x);
+}
+vec2 inversesqrt (vec2 x) {
+    return vec2 (inversesqrt (x.x), inversesqrt (x.y));
+}
+vec3 inversesqrt (vec3 x) {
+    return vec3 (inversesqrt (x.x), inversesqrt (x.y), inversesqrt (x.z));
+}
+vec4 inversesqrt (vec4 x) {
+    return vec4 (inversesqrt (x.x), inversesqrt (x.y), inversesqrt (x.z), inversesqrt (x.w));
+}
+
+// 
+// 8.3 Common Functions
+// 
+// These all operate component-wise. The description is per component.
+// 
+
+// 
+// Returns x if x >= 0, otherwise it returns \96x
+// 
+
+float abs (float x) {
+    return x >= 0.0 ? x : -x;
+}
+vec2 abs (vec2 x) {
+    return vec2 (abs (x.x), abs (x.y));
+}
+vec3 abs (vec3 x) {
+    return vec3 (abs (x.x), abs (x.y), abs (x.z));
+}
+vec4 abs (vec4 x) {
+    return vec4 (abs (x.x), abs (x.y), abs (x.z), abs (x.w));
+}
+
+// 
+// Returns 1.0 if x > 0, 0.0 if x = 0, or \961.0 if x < 0
+// 
+
+float sign (float x) {
+    return x > 0.0 ? 1.0 : x < 0.0 ? -1.0 : 0.0;
+}
+vec2 sign (vec2 x) {
+    return vec2 (sign (x.x), sign (x.y));
+}
+vec3 sign (vec3 x) {
+    return vec3 (sign (x.x), sign (x.y), sign (x.z));
+}
+vec4 sign (vec4 x) {
+    return vec4 (sign (x.x), sign (x.y), sign (x.z), sign (x.w));
+}
+
+// 
+// Returns a value equal to the nearest integer that is less than or equal to x
+// 
+// XXX
+float floor (float x) {
+    return 0.0;
+}
+vec2 floor (vec2 x) {
+    return vec2 (floor (x.x), floor (x.y));
+}
+vec3 floor (vec3 x) {
+    return vec3 (floor (x.x), floor (x.y), floor (x.z));
+}
+vec4 floor (vec4 x) {
+    return vec4 (floor (x.x), floor (x.y), floor (x.z), floor (x.w));
+}
+
+// 
+// Returns a value equal to the nearest integer that is greater than or equal to x
+// 
+// XXX
+float ceil (float x) {
+    return 0.0;
+}
+vec2 ceil (vec2 x) {
+    return vec2 (ceil (x.x), ceil (x.y));
+}
+vec3 ceil (vec3 x) {
+    return vec3 (ceil (x.x), ceil (x.y), ceil (x.z));
+}
+vec4 ceil (vec4 x) {
+    return vec4 (ceil (x.x), ceil (x.y), ceil (x.z), ceil (x.w));
+}
+
+// 
+// Returns x \96 floor (x)
+// 
+
+float fract (float x) {
+    return x - floor (x);
+}
+vec2 fract (vec2 x) {
+    return vec2 (fract (x.x), fract (x.y));
+}
+vec3 fract (vec3 x) {
+    return vec3 (fract (x.x), fract (x.y), fract (x.z));
+}
+vec4 fract (vec4 x) {
+    return vec4 (fract (x.x), fract (x.y), fract (x.z), fract (x.w));
+}
+
+// 
+// Modulus. Returns x \96 y * floor (x/y)
+// 
+
+float mod (float x, float y) {
+    return x - y * floor (x / y);
+}
+vec2 mod (vec2 x, float y) {
+    return vec2 (mod (x.x, y), mod (x.y, y));
+}
+vec3 mod (vec3 x, float y) {
+    return vec3 (mod (x.x, y), mod (x.y, y), mod (x.z, y));
+}
+vec4 mod (vec4 x, float y) {
+    return vec4 (mod (x.x, y), mod (x.y, y), mod (x.z, y), mod (x.w, y));
+}
+vec2 mod (vec2 x, vec2 y) {
+    return vec2 (mod (x.x, y.x), mod (x.y, y.y));
+}
+vec3 mod (vec3 x, vec3 y) {
+    return vec3 (mod (x.x, y.x), mod (x.y, y.y), mod (x.z, y.z));
+}
+vec4 mod (vec4 x, vec4 y) {
+    return vec4 (mod (x.x, y.x), mod (x.y, y.y), mod (x.z, y.z), mod (x.w, y.w));
+}
+
+// 
+// Returns y if y < x, otherwise it returns x
+// 
+
+float min (float x, float y) {
+    return y < x ? y : x;
+}
+vec2 min (vec2 x, float y) {
+    return vec2 (min (x.x, y), min (x.y, y));
+}
+vec3 min (vec3 x, float y) {
+    return vec3 (min (x.x, y), min (x.y, y), min (x.z, y));
+}
+vec4 min (vec4 x, float y) {
+    return vec4 (min (x.x, y), min (x.y, y), min (x.z, y), min (x.w, y));
+}
+vec2 min (vec2 x, vec2 y) {
+    return vec2 (min (x.x, y.x), min (x.y, y.y));
+}
+vec3 min (vec3 x, vec3 y) {
+    return vec3 (min (x.x, y.x), min (x.y, y.y), min (x.z, y.z));
+}
+vec4 min (vec4 x, vec4 y) {
+    return vec4 (min (x.x, y.x), min (x.y, y.y), min (x.z, y.z), min (x.w, y.w));
+}
+
+// 
+// Returns y if x < y, otherwise it returns x
+// 
+
+float max (float x, float y) {
+    return min (y, x);
+}
+vec2 max (vec2 x, float y) {
+    return vec2 (max (x.x, y), max (x.y, y));
+}
+vec3 max (vec3 x, float y) {
+    return vec3 (max (x.x, y), max (x.y, y), max (x.z, y));
+}
+vec4 max (vec4 x, float y) {
+    return vec4 (max (x.x, y), max (x.y, y), max (x.z, y), max (x.w, y));
+}
+vec2 max (vec2 x, vec2 y) {
+    return vec2 (max (x.x, y.x), max (x.y, y.y));
+}
+vec3 max (vec3 x, vec3 y) {
+    return vec3 (max (x.x, y.x), max (x.y, y.y), max (x.z, y.z));
+}
+vec4 max (vec4 x, vec4 y) {
+    return vec4 (max (x.x, y.x), max (x.y, y.y), max (x.z, y.z), max (x.w, y.w));
+}
+
+// 
+// Returns min (max (x, minVal), maxVal)
+// 
+// Note that colors and depths written by fragment shaders will be clamped by the implementation
+// after the fragment shader runs.
+// 
+
+float clamp (float x, float minVal, float maxVal) {
+    return min (max (x, minVal), maxVal);
+}
+vec2 clamp (vec2 x, float minVal, float maxVal) {
+    return vec2 (clamp (x.x, minVal, maxVal), clamp (x.y, minVal, maxVal));
+}
+vec3 clamp (vec3 x, float minVal, float maxVal) {
+    return vec3 (clamp (x.x, minVal, maxVal), clamp (x.y, minVal, maxVal),
+        clamp (x.z, minVal, maxVal));
+}
+vec4 clamp (vec4 x, float minVal, float maxVal) {
+    return vec4 (clamp (x.x, minVal, maxVal), clamp (x.y, minVal, maxVal),
+        clamp (x.z, minVal, maxVal), clamp (x.w, minVal, maxVal));
+}
+vec2 clamp (vec2 x, vec2 minVal, vec2 maxVal) {
+    return vec2 (clamp (x.x, minVal.x, maxVal.x), clamp (x.y, minVal.y, maxVal.y));
+}
+vec3 clamp (vec3 x, vec3 minVal, vec3 maxVal) {
+    return vec3 (clamp (x.x, minVal.x, maxVal.x), clamp (x.y, minVal.y, maxVal.y),
+        clamp (x.z, minVal.z, maxVal.z));
+}
+vec4 clamp (vec4 x, vec4 minVal, vec4 maxVal) {
+    return vec4 (clamp (x.x, minVal.x, maxVal.y), clamp (x.y, minVal.y, maxVal.y),
+        clamp (x.z, minVal.z, maxVal.z), clamp (x.w, minVal.w, maxVal.w));
+}
+
+// 
+// Returns x * (1 \96 a) + y * a, i.e., the linear blend of x and y
+// 
+
+float mix (float x, float y, float a) {
+    return x * (1.0 - a) + y * a;
+}
+vec2 mix (vec2 x, vec2 y, float a) {
+    return vec2 (mix (x.x, y.x, a), mix (x.y, y.y, a));
+}
+vec3 mix (vec3 x, vec3 y, float a) {
+    return vec3 (mix (x.x, y.x, a), mix (x.y, y.y, a), mix (x.z, y.z, a));
+}
+vec4 mix (vec4 x, vec4 y, float a) {
+    return vec4 (mix (x.x, y.x, a), mix (x.y, y.y, a), mix (x.z, y.z, a), mix (x.w, y.w, a));
+}
+vec2 mix (vec2 x, vec2 y, vec2 a) {
+    return vec2 (mix (x.x, y.x, a.x), mix (x.y, y.y, a.y));
+}
+vec3 mix (vec3 x, vec3 y, vec3 a) {
+    return vec3 (mix (x.x, y.x, a.x), mix (x.y, y.y, a.y), mix (x.z, y.z, a.z));
+}
+vec4 mix (vec4 x, vec4 y, vec4 a) {
+    return vec4 (mix (x.x, y.x, a.x), mix (x.y, y.y, a.y), mix (x.z, y.z, a.z),
+        mix (x.w, y.w, a.w));
+}
+
+// 
+// Returns 0.0 if x < edge, otherwise it returns 1.0
+// 
+
+float step (float edge, float x) {
+    return x < edge ? 0.0 : 1.0;
+}
+vec2 step (float edge, vec2 x) {
+    return vec2 (step (edge, x.x), step (edge, x.y));
+}
+vec3 step (float edge, vec3 x) {
+    return vec3 (step (edge, x.x), step (edge, x.y), step (edge, x.z));
+}
+vec4 step (float edge, vec4 x) {
+    return vec4 (step (edge, x.x), step (edge, x.y), step (edge, x.z), step (edge, x.w));
+}
+vec2 step (vec2 edge, vec2 x) {
+    return vec2 (step (edge.x, x.x), step (edge.y, x.y));
+}
+vec3 step (vec3 edge, vec3 x) {
+    return vec3 (step (edge.x, x.x), step (edge.y, x.y), step (edge.z, x.z));
+}
+vec4 step (vec4 edge, vec4 x) {
+    return vec4 (step (edge.x, x.x), step (edge.y, x.y), step (edge.z, x.z), step (edge.w, x.w));
+}
+
+// 
+// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth Hermite interpolation
+// between 0 and 1 when edge0 < x < edge1. This is useful in cases where you would want a threshold
+// function with a smooth transition. This is equivalent to:
+// <type> t;
+// t = clamp ((x \96 edge0) / (edge1 \96 edge0), 0, 1);
+// return t * t * (3 \96 2 * t);
+// 
+
+float smoothstep (float edge0, float edge1, float x) {
+    const float t = clamp ((x - edge0) / (edge1 - edge0), 0.0, 1.0);
+    return t * t * (3.0 - 2.0 * t);
+}
+vec2 smoothstep (float edge0, float edge1, vec2 x) {
+    return vec2 (smoothstep (edge0, edge1, x.x), smoothstep (edge0, edge1, x.y));
+}
+vec3 smoothstep (float edge0, float edge1, vec3 x) {
+    return vec3 (smoothstep (edge0, edge1, x.x), smoothstep (edge0, edge1, x.y),
+        smoothstep (edge0, edge1, x.z));
+}
+vec4 smoothstep (float edge0, float edge1, vec4 x) {
+    return vec4 (smoothstep (edge0, edge1, x.x), smoothstep (edge0, edge1, x.y),
+        smoothstep (edge0, edge1, x.z), smoothstep (edge0, edge1, x.w));
+}
+vec2 smoothstep (vec2 edge0, vec2 edge1, vec2 x) {
+    return vec2 (smoothstep (edge0.x, edge1.x, x.x), smoothstep (edge0.y, edge1.y, x.y));
+}
+vec3 smoothstep (vec3 edge0, vec3 edge1, vec3 x) {
+    return vec3 (smoothstep (edge0.x, edge1.x, x.x), smoothstep (edge0.y, edge1.y, x.y),
+        smoothstep (edge0.z, edge1.z, x.z));
+}
+vec4 smoothstep (vec4 edge0, vec4 edge1, vec4 x) {
+    return vec4 (smoothstep (edge0.x, edge1.x, x.x), smoothstep (edge0.y, edge1.y, x.y),
+        smoothstep (edge0.z, edge1.z, x.z), smoothstep (edge0.w, edge1.w, x.w));
+}
+
+// 
+// 8.4 Geometric Functions
+// 
+// These operate on vectors as vectors, not component-wise.
+// 
+
+// 
+// Returns the dot product of x and y, i.e., result = x[0] * y[0] + x[1] * y[1] + ...
+// 
+
+float dot (float x, float y) {
+    return x * y;
+}
+float dot (vec2 x, vec2 y) {
+    return dot (x.x, y.x) + dot (x.y, y.y);
+}
+float dot (vec3 x, vec3 y) {
+    return dot (x.x, y.x) + dot (x.y, y.y) + dot (x.z, y.z);
+}
+float dot (vec4 x, vec4 y) {
+    return dot (x.x, y.x) + dot (x.y, y.y) + dot (x.z, y.z) + dot (x.w, y.w);
+}
+
+// 
+// Returns the length of vector x, i.e., sqrt (x[0] * x[0] + x[1] * x[1] + ...)
+// 
+
+float length (float x) {
+    return sqrt (dot (x, x));
+}
+float length (vec2 x) {
+    return sqrt (dot (x, x));
+}
+float length (vec3 x) {
+    return sqrt (dot (x, x));
+}
+float length (vec4 x) {
+    return sqrt (dot (x, x));
+}
+
+// 
+// Returns the distance between p0 and p1, i.e. length (p0 \96 p1)
+// 
+
+float distance (float x, float y) {
+    return length (x - y);
+}
+float distance (vec2 x, vec2 y) {
+    return length (x - y);
+}
+float distance (vec3 x, vec3 y) {
+    return length (x - y);
+}
+float distance (vec4 x, vec4 y) {
+    return length (x - y);
+}
+
+// 
+// Returns the cross product of x and y, i.e.
+// result.0 = x[1] * y[2] - y[1] * x[2]
+// result.1 = x[2] * y[0] - y[2] * x[0]
+// result.2 = x[0] * y[1] - y[0] * x[1]
+// 
+
+vec3 cross (vec3 x, vec3 y) {
+    return vec3 (x.y * y.z - y.y * x.z, x.z * y.x - y.z * x.x, x.x * y.y - y.x * x.y);
+}
+
+// 
+// Returns a vector in the same direction as x but with a length of 1.
+// 
+
+float normalize (float x) {
+    return 1.0;
+}
+vec2 normalize (vec2 x) {
+    return x / length (x);
+}
+vec3 normalize (vec3 x) {
+    return x / length (x);
+}
+vec4 normalize (vec4 x) {
+    return x / length (x);
+}
+
+// 
+// If dot (Nref, I) < 0 return N otherwise return \96N
+// 
+
+float faceforward (float N, float I, float Nref) {
+    return dot (Nref, I) < 0.0 ? N : -N;
+}
+vec2 faceforward (vec2 N, vec2 I, vec2 Nref) {
+    return dot (Nref, I) < 0.0 ? N : -N;
+}
+vec3 faceforward (vec3 N, vec3 I, vec3 Nref) {
+    return dot (Nref, I) < 0.0 ? N : -N;
+}
+vec4 faceforward (vec4 N, vec4 I, vec4 Nref) {
+    return dot (Nref, I) < 0.0 ? N : -N;
+}
+
+// 
+// For the incident vector I and surface orientation N, returns the reflection direction:
+// result = I - 2 * dot (N, I) * N
+// N must already be normalized in order to achieve the desired result.
+
+float reflect (float I, float N) {
+    return I - 2.0 * dot (N, I) * N;
+}
+vec2 reflect (vec2 I, vec2 N) {
+    return I - 2.0 * dot (N, I) * N;
+}
+vec3 reflect (vec3 I, vec3 N) {
+    return I - 2.0 * dot (N, I) * N;
+}
+vec4 reflect (vec4 I, vec4 N) {
+    return I - 2.0 * dot (N, I) * N;
+}
+
+//
+// For the incident vector I and surface normal N, and the ratio of inidices of refraction eta,
+// return the refraction vector. The returned result is computed by
+//
+// k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I))
+// if (k < 0.0)
+//   result = genType (0.0)
+// else
+//   result = eta * I - (eta * dot (N, I) + sqrt (k)) * N
+//
+// The input parameters for the incident vector I and the surface normal N must already be
+// normalized to get the desired results.
+//
+
+float refract (float I, float N, float eta) {
+    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
+    if (k < 0.0)
+        return 0.0;
+    return eta * I - (eta * dot (N, I) + sqrt (k)) * N;
+}
+vec2 refract (vec2 I, vec2 N, float eta) {
+    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
+    if (k < 0.0)
+        return vec2 (0.0);
+    return eta * I - (eta * dot (N, I) + sqrt (k)) * N;
+}
+vec3 refract (vec3 I, vec3 N, float eta) {
+    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
+    if (k < 0.0)
+        return vec3 (0.0);
+    return eta * I - (eta * dot (N, I) + sqrt (k)) * N;
+}
+vec4 refract (vec4 I, vec4 N, float eta) {
+    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
+    if (k < 0.0)
+        return vec4 (0.0);
+    return eta * I - (eta * dot (N, I) + sqrt (k)) * N;
+}
+
+// 
+// 8.5 Matrix Functions
+// 
+
+// 
+// Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product
+// of x[i][j] and y[i][j].
+// Note: to get linear algebraic matrix multiplication, use the multiply operator (*).
+// 
+
+mat2 matrixCompMult (mat2 x, mat2 y) {
+    return mat2 (
+        x[0].x * y[0].x, x[0].y * y[0].y,
+        x[1].x * y[1].x, x[1].y * y[1].y
+    );
+}
+mat3 matrixCompMult (mat3 x, mat3 y) {
+    return mat4 (
+        x[0].x * y[0].x, x[0].y * y[0].y, x[0].z * y[0].z,
+        x[1].x * y[1].x, x[1].y * y[1].y, x[1].z * y[1].z,
+        x[2].x * y[2].x, x[2].y * y[2].y, x[2].z * y[2].z
+    );
+}
+mat4 matrixCompMult (mat4 x, mat4 y) {
+    return mat4 (
+        x[0].x * y[0].x, x[0].y * y[0].y, x[0].z * y[0].z + x[0].w * y[0].w,
+        x[1].x * y[1].x, x[1].y * y[1].y, x[1].z * y[1].z + x[1].w * y[1].w,
+        x[2].x * y[2].x, x[2].y * y[2].y, x[2].z * y[2].z + x[2].w * y[2].w,
+        x[3].x * y[3].x, x[3].y * y[3].y, x[3].z * y[3].z + x[3].w * y[3].w
+    );
+}
+
+// 
+// 8.6 Vector Relational Functions
+// 
+// Relational and equality operators (<, <=, >, >=, ==, !=) are defined (or reserved) to produce
+// scalar Boolean results.
+// 
+
+// 
+// Returns the component-wise compare of x < y.
+// 
+
+bvec2 lessThan (vec2 x, vec2 y) {
+    return bvec2 (x.x < y.x, x.y < y.y);
+}
+bvec3 lessThan (vec3 x, vec3 y) {
+    return bvec3 (x.x < y.x, x.y < y.y, x.z < y.z);
+}
+bvec4 lessThan (vec4 x, vec4 y) {
+    return bvec4 (x.x < y.x, x.y < y.y, x.z < y.z, x.w < y.w);
+}
+bvec2 lessThan (ivec2 x, ivec2 y) {
+    return bvec2 (x.x < y.x, x.y < y.y);
+}
+bvec3 lessThan (ivec3 x, ivec3 y) {
+    return bvec3 (x.x < y.x, x.y < y.y, x.z < y.z);
+}
+bvec4 lessThan (ivec4 x, ivec4 y) {
+    return bvec4 (x.x < y.x, x.y < y.y, x.z < y.z, x.w < y.w);
+}
+
+// 
+// Returns the component-wise compare of x <= y.
+// 
+
+bvec2 lessThanEqual (vec2 x, vec2 y) {
+    return bvec2 (x.x <= y.x, x.y <= y.y);
+}
+bvec3 lessThanEqual (vec3 x, vec3 y) {
+    return bvec3 (x.x <= y.x, x.y <= y.y, x.z <= y.z);
+}
+bvec4 lessThanEqual (vec4 x, vec4 y) {
+    return bvec4 (x.x <= y.x, x.y <= y.y, x.z <= y.z, x.w <= y.w);
+}
+bvec2 lessThanEqual (ivec2 x, ivec2 y) {
+    return bvec2 (x.x <= y.x, x.y <= y.y);
+}
+bvec3 lessThanEqual (ivec3 x, ivec3 y) {
+    return bvec3 (x.x <= y.x, x.y <= y.y, x.z <= y.z);
+}
+bvec4 lessThanEqual (ivec4 x, ivec4 y) {
+    return bvec4 (x.x <= y.x, x.y <= y.y, x.z <= y.z, x.w <= y.w);
+}
+
+// 
+// Returns the component-wise compare of x > y.
+// 
+
+bvec2 greaterThan (vec2 x, vec2 y) {
+    return bvec2 (x.x > y.x, x.y > y.y);
+}
+bvec3 greaterThan (vec3 x, vec3 y) {
+    return bvec3 (x.x > y.x, x.y > y.y, x.z > y.z);
+}
+bvec4 greaterThan (vec4 x, vec4 y) {
+    return bvec4 (x.x > y.x, x.y > y.y, x.z > y.z, x.w > y.w);
+}
+bvec2 greaterThan (ivec2 x, ivec2 y) {
+    return bvec2 (x.x > y.x, x.y > y.y);
+}
+bvec3 greaterThan (ivec3 x, ivec3 y) {
+    return bvec3 (x.x > y.x, x.y > y.y, x.z > y.z);
+}
+bvec4 greaterThan (ivec4 x, ivec4 y) {
+    return bvec4 (x.x > y.x, x.y > y.y, x.z > y.z, x.w > y.w);
+}
+
+// 
+// Returns the component-wise compare of x >= y.
+// 
+
+bvec2 greaterThanEqual (vec2 x, vec2 y) {
+    return bvec2 (x.x >= y.x, x.y >= y.y);
+}
+bvec3 greaterThanEqual (vec3 x, vec3 y) {
+    return bvec3 (x.x >= y.x, x.y >= y.y, x.z >= y.z);
+}
+bvec4 greaterThanEqual (vec4 x, vec4 y) {
+    return bvec4 (x.x >= y.x, x.y >= y.y, x.z >= y.z, x.w >= y.w);
+}
+bvec2 greaterThanEqual (ivec2 x, ivec2 y) {
+    return bvec2 (x.x >= y.x, x.y >= y.y);
+}
+bvec3 greaterThanEqual (ivec3 x, ivec3 y) {
+    return bvec3 (x.x >= y.x, x.y >= y.y, x.z >= y.z);
+}
+bvec4 greaterThanEqual (ivec4 x, ivec4 y) {
+    return bvec4 (x.x >= y.x, x.y >= y.y, x.z >= y.z, x.w >= y.w);
+}
+
+// 
+// Returns the component-wise compare of x == y.
+// 
+
+bvec2 equal (vec2 x, vec2 y) {
+    return bvec2 (x.x == y.x, x.y == y.y);
+}
+bvec3 equal (vec3 x, vec3 y) {
+    return bvec3 (x.x == y.x, x.y == y.y, x.z == y.z);
+}
+bvec4 equal (vec4 x, vec4 y) {
+    return bvec4 (x.x == y.x, x.y == y.y, x.z == y.z, x.w == y.w);
+}
+bvec2 equal (ivec2 x, ivec2 y) {
+    return bvec2 (x.x == y.x, x.y == y.y);
+}
+bvec3 equal (ivec3 x, ivec3 y) {
+    return bvec3 (x.x == y.x, x.y == y.y, x.z == y.z);
+}
+bvec4 equal (ivec4 x, ivec4 y) {
+    return bvec4 (x.x == y.x, x.y == y.y, x.z == y.z, x.w == y.w);
+}
+
+// 
+// Returns the component-wise compare of x != y.
+// 
+
+bvec2 notEqual (vec2 x, vec2 y) {
+    return bvec2 (x.x != y.x, x.y != y.y);
+}
+bvec3 notEqual (vec3 x, vec3 y) {
+    return bvec3 (x.x != y.x, x.y != y.y, x.z != y.z);
+}
+bvec4 notEqual (vec4 x, vec4 y) {
+    return (bvec4 (x.x != y.x, x.y != y.y, x.z != y.z, x.w != y.w);
+}
+bvec2 notEqual (ivec2 x, ivec2 y) {
+    return (bvec2 (x.x != y.x, x.y != y.y);
+}
+bvec3 notEqual (ivec3 x, ivec3 y) {
+    return (bvec3 (x.x != y.x, x.y != y.y, x.z != y.z);
+}
+bvec4 notEqual (ivec4 x, ivec4 y) {
+    return (bvec4 (x.x != y.x, x.y != y.y, x.z != y.z, x.w != y.w);
+}
+
+// 
+// Returns true if any component of x is true.
+// 
+
+bool any (bvec2 x) {
+    return x.x || x.y;
+}
+bool any (bvec3 x) {
+    return x.x || x.y || x.z;
+}
+bool any (bvec4 x) {
+    return x.x || x.y || x.z || x.w;
+}
+
+// 
+// Returns true only if all components of x are true.
+// 
+
+bool all (bvec2 x) {
+    return x.x && x.y;
+}
+bool all (bvec3 x) {
+    return x.x && x.y && x.z;
+}
+bool all (bvec4 x) {
+    return x.x && x.y && x.z && x.w;
+}
+
+// 
+// Returns the component-wise logical complement of x.
+// 
+
+bvec2 not (bvec2 x) {
+    return bvec2 (!x.x, !x.y);
+}
+bvec3 not (bvec3 x) {
+    return bvec3 (!x.x, !x.y, !x.z);
+}
+bvec4 not (bvec4 x) {
+    return bvec4 (!x.x, !x.y, !x.z, !x.w);
+}
+
+// 
+// 8.7 Texture Lookup Functions
+// 
+// Texture lookup functions are available to both vertex and fragment shaders. However, level
+// of detail is not computed by fixed functionality for vertex shaders, so there are some
+// differences in operation between vertex and fragment texture lookups. The functions in the table
+// below provide access to textures through samplers, as set up through the OpenGL API. Texture
+// properties such as size, pixel format, number of dimensions, filtering method, number of mip-map
+// levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are
+// taken into account as the texture is accessed via the built-in functions defined below.
+// 
+// If a non-shadow texture call is made to a sampler that represents a depth texture with depth
+// comparisons turned on, then results are undefined. If a shadow texture call is made to a sampler
+// that represents a depth texture with depth comparisions turned off, the results are undefined.
+// If a shadow texture call is made to a sampler that does not represent a depth texture, then
+// results are undefined.
+// 
+// In all functions below, the bias parameter is optional for fragment shaders. The bias parameter
+// is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to
+// the calculated level of detail prior to performing the texture access operation. If the bias
+// parameter is not provided, then the implementation automatically selects level of detail:
+// For a texture that is not mip-mapped, the texture is used directly. If it is mip-mapped and
+// running in a fragment shader, the LOD computed by the implementation is used to do the texture
+// lookup. If it is mip-mapped and running on the vertex shader, then the base texture is used.
+// 
+// The built-ins suffixed with \93Lod\94 are allowed only in a vertex shader. For the \93Lod\94 functions,
+// lod is directly used as the level of detail.
+// 
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 1D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate coord.s is divided by
+// the last component of coord.
+// 
+// XXX
+vec4 texture1D (sampler1D sampler, float coord) {
+    return vec4 (0.0);
+}
+vec4 texture1DProj (sampler1D sampler, vec2 coord) {
+    return texture1D (sampler, coord.s / coord.t);
+}
+vec4 texture1DProj (sampler1D sampler, vec4 coord) {
+    return texture1D (sampler, coord.s / coord.q);
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 2D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate (coord.s, coord.t) is
+// divided by the last component of coord. The third component of coord is ignored for the vec4
+// coord variant.
+// 
+// XXX
+vec4 texture2D (sampler2D sampler, vec2 coord) {
+    return vec4 (0.0);
+}
+vec4 texture2DProj (sampler2D sampler, vec3 coord) {
+    return texture2D (sampler, vec2 (coord.s / coord.p, coord.t / coord.p));
+}
+vec4 texture2DProj (sampler2D sampler, vec4 coord) {
+    return texture2D (sampler, vec2 (coord.s / coord.q, coord.t / coord.q));
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 3D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate is divided by coord.q.
+// 
+// XXX
+vec4 texture3D (sampler3D sampler, vec3 coord) {
+    return vec4 (0.0);
+}
+vec4 texture3DProj (sampler3D sampler, vec4 coord) {
+    return texture3D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q));
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the cube map texture currently bound
+// to sampler. The direction of coord is used to select which face to do a 2-dimensional texture
+// lookup in, as described in section 3.8.6 in version 1.4 of the OpenGL specification.
+// 
+// XXX
+vec4 textureCube (samplerCube sampler, vec3 coord) {
+    return vec4 (0.0);
+}
+
+// 
+// Use texture coordinate coord to do a depth comparison lookup on the depth texture bound
+// to sampler, as described in section 3.8.14 of version 1.4 of the OpenGL specification. The 3rd
+// component of coord (coord.p) is used as the R value. The texture bound to sampler must be a
+// depth texture, or results are undefined. For the projective (\93Proj\94) version of each built-in,
+// the texture coordinate is divide by coord.q, giving a depth value R of coord.p/coord.q. The
+// second component of coord is ignored for the \931D\94 variants.
+// 
+// XXX
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord) {
+    return vec4 (0.0);
+}
+// XXX
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord) {
+    return vec4 (0.0);
+}
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord) {
+    return shadow1D (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q));
+}
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord) {
+    return shadow2D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q));
+}
+
+// 
+// 8.9 Noise Functions
+// 
+// Noise functions are available to both fragment and vertex shaders. They are stochastic functions
+// that can be used to increase visual complexity. Values returned by the following noise functions
+// give the appearance of randomness, but are not truly random. The noise functions below are
+// defined to have the following characteristics:
+// 
+// - The return value(s) are always in the range [-1,1], and cover at least the range [-0.6, 0.6],
+//   with a gaussian-like distribution.
+// \95 The return value(s) have an overall average of 0.0
+// \95 They are repeatable, in that a particular input value will always produce the same return value
+// \95 They are statistically invariant under rotation (i.e., no matter how the domain is rotated, it
+//   has the same statistical character)
+// \95 They have a statistical invariance under translation (i.e., no matter how the domain is
+//   translated, it has the same statistical character)
+// \95 They typically give different results under translation.
+// - The spatial frequency is narrowly concentrated, centered somewhere between 0.5 to 1.0.
+// 
+
+// 
+// Returns a 1D noise value based on the input value x.
+// 
+// XXX
+float noise1 (float x) {
+    return 0.0;
+}
+// XXX
+float noise1 (vec2 x) {
+    return 0.0;
+}
+// XXX
+float noise1 (vec3 x) {
+    return 0.0;
+}
+// XXX
+float noise1 (vec4 x) {
+    return 0.0;
+}
+
+// 
+// Returns a 2D noise value based on the input value x.
+// 
+// XXX
+vec2 noise2 (float x) {
+    return vec2 (0.0);
+}
+// XXX
+vec2 noise2 (vec2 x) {
+    return vec2 (0.0);
+}
+// XXX
+vec2 noise2 (vec3 x) {
+    return vec2 (0.0);
+}
+// XXX
+vec2 noise2 (vec4 x) {
+    return vec2 (0.0);
+}
+
+// 
+// Returns a 3D noise value based on the input value x.
+// 
+// XXX
+vec3 noise3 (float x) {
+    return vec3 (0.0);
+}
+// XXX
+vec3 noise3 (vec2 x) {
+    return vec3 (0.0);
+}
+// XXX
+vec3 noise3 (vec3 x) {
+    return vec3 (0.0);
+}
+// XXX
+vec3 noise3 (vec4 x) {
+    return vec3 (0.0);
+}
+
+// 
+// Returns a 4D noise value based on the input value x.
+// 
+// XXX
+vec4 noise4 (float x) {
+    return vec4 (0.0);
+}
+// XXX
+vec4 noise4 (vec2 x) {
+    return vec4 (0.0);
+}
+// XXX
+vec4 noise4 (vec3 x) {
+    return vec4 (0.0);
+}
+// XXX
+vec4 noise4 (vec4 x) {
+    return vec4 (0.0);
+}
+
index 6ccf0e7..ec28292 100755 (executable)
-\r
-// \r
-// TODO:\r
-// - implement texture1D, texture2D, texture3D, textureCube,\r
-// - implement shadow1D, shadow2D,\r
-// - implement dFdx, dFdy,\r
-// \r
-\r
-// \r
-// From Shader Spec, ver. 1.051\r
-// \r
-// The output of the fragment shader goes on to be processed by the fixed function operations at\r
-// the back end of the OpenGL pipeline. Fragment shaders interface with the back end of the OpenGL\r
-// pipeline using the built-in variables gl_FragColor and gl_FragDepth, or by executing the discard\r
-// keyword.\r
-// \r
-// These variables may be written more than once within a fragment shader. If so, the last value\r
-// assigned is the one used in the subsequent fixed function pipeline. The values written to these\r
-// variables may be read back after writing them. Reading from these variables before writing them\r
-// results in an undefined value. The fixed functionality computed depth for a fragment may be\r
-// obtained by reading gl_FragCoord.z, described below.\r
-// \r
-// Writing to gl_FragColor specifies the fragment color that will be used by the subsequent fixed\r
-// functionality pipeline. If subsequent fixed functionality consumes fragment color and an\r
-// execution of a fragment shader does not write a value to gl_FragColor then the fragment color\r
-// consumed is undefined.\r
-// \r
-// If the frame buffer is configured as a color index buffer then behavior is undefined when using\r
-// a fragment shader.\r
-// \r
-// Writing to gl_FragDepth will establish the depth value for the fragment being processed. If\r
-// depth buffering is enabled, and a shader does not write gl_FragDepth, then the fixed function\r
-// value for depth will be used as the fragment\92s depth value. If a shader statically assigns\r
-// a value to gl_FragDepth, and there is an execution path through the shader that does not set\r
-// gl_FragDepth, then the value of the fragment\92s depth may be undefined for some executions of\r
-// the shader. That is, if a shader statically writes gl_FragDepth, then it is responsible for\r
-// always writing it. There is also no guarantee that a shader can compute the same depth value\r
-// as the fixed function value; an implementation will provide invariant results within shaders\r
-// computing depth with the same source-level expression, but invariance is not provided between\r
-// shaders and fixed functionality.\r
-// \r
-// Writes to gl_FragColor and gl_FragDepth need not be clamped within a shader. The fixed\r
-// functionality pipeline following the fragment shader will clamp these values.\r
-// \r
-// If a shader executes the discard keyword, the fragment is discarded, and the values of\r
-// gl_FragDepth and gl_FragColor become irrelevant.\r
-// \r
-// The variable gl_FragCoord is available as a read-only variable from within fragment shaders\r
-// and it holds the window relative coordinates x, y, z, and 1/w values for the fragment. This\r
-// value is the result of the fixed functionality that interpolates primitives after vertex\r
-// processing to generate fragments. The z component is the depth value that would be used for\r
-// the fragment\92s depth if a shader contained no writes to gl_FragDepth. This is useful for\r
-// invariance if a shader conditionally computes gl_FragDepth but otherwise wants the fixed\r
-// functionality fragment depth.\r
-// \r
-// The fragment shader has access to the read-only built-in variable gl_FrontFacing whose value\r
-// is true if the fragment belongs to a front-facing primitive. One use of this is to emulate\r
-// two-sided lighting by selecting one of two colors calculated by the vertex shader.\r
-// \r
-// The built-in variables that are accessible from a fragment shader are intrinsically given types\r
-// as follows:\r
-// \r
-\r
-vec4 gl_FragCoord;\r
-bool gl_FrontFacing;\r
-vec4 gl_FragColor;\r
-float gl_FragDepth;\r
-\r
-// \r
-// However, they do not behave like variables with no qualifier; their behavior is as described\r
-// above. These built-in variables have global scope.\r
-// \r
-\r
-// \r
-// Unlike user-defined varying variables, the built-in varying variables don\92t have a strict\r
-// one-to-one correspondence between the vertex language and the fragment language. Two sets are\r
-// provided, one for each language. Their relationship is described below.\r
-// \r
-// The following varying variables are available to read from in a fragment shader. The gl_Color\r
-// and gl_SecondaryColor names are the same names as attributes passed to the vertex shader.\r
-// However, there is no name conflict, because attributes are visible only in vertex shaders\r
-// and the following are only visible in a fragment shader.\r
-// \r
-\r
-varying vec4 gl_Color;\r
-varying vec4 gl_SecondaryColor;\r
-varying vec4 gl_TexCoord[];                             // at most will be gl_MaxTextureCoordsARB\r
-varying float gl_FogFragCoord;\r
-\r
-// \r
-// The values in gl_Color and gl_SecondaryColor will be derived automatically by the system from\r
-// gl_FrontColor, gl_BackColor, gl_FrontSecondaryColor, and gl_BackSecondaryColor based on which\r
-// face is visible. If fixed functionality is used for vertex processing, then gl_FogFragCoord will\r
-// either be the z-coordinate of the fragment in eye space, or the interpolation of the fog\r
-// coordinate, as described in section 3.10 of the OpenGL 1.4 Specification. The gl_TexCoord[]\r
-// values are the interpolated gl_TexCoord[] values from a vertex shader or the texture coordinates\r
-// of any fixed pipeline based vertex functionality.\r
-// \r
-// Indices to the fragment shader gl_TexCoord array are as described above in the vertex shader\r
-// text.\r
-// \r
-\r
-// \r
-// The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar\r
-// and vector operations. Many of these built-in functions can be used in more than one type\r
-// of shader, but some are intended to provide a direct mapping to hardware and so are available\r
-// only for a specific type of shader.\r
-// \r
-// The built-in functions basically fall into three categories:\r
-// \r
-// \95 They expose some necessary hardware functionality in a convenient way such as accessing\r
-//   a texture map. There is no way in the language for these functions to be emulated by a shader.\r
-// \r
-// \95 They represent a trivial operation (clamp, mix, etc.) that is very simple for the user\r
-//   to write, but they are very common and may have direct hardware support. It is a very hard\r
-//   problem for the compiler to map expressions to complex assembler instructions.\r
-// \r
-// \95 They represent an operation graphics hardware is likely to accelerate at some point. The\r
-//   trigonometry functions fall into this category.\r
-// \r
-// Many of the functions are similar to the same named ones in common C libraries, but they support\r
-// vector input as well as the more traditional scalar input.\r
-// \r
-// Applications should be encouraged to use the built-in functions rather than do the equivalent\r
-// computations in their own shader code since the built-in functions are assumed to be optimal\r
-// (e.g., perhaps supported directly in hardware).\r
-// \r
-// User code can replace built-in functions with their own if they choose, by simply re-declaring\r
-// and defining the same name and argument list.\r
-// \r
-\r
-// \r
-// Texture Lookup Functions\r
-// \r
-// Texture lookup functions are available to both vertex and fragment shaders. However, level\r
-// of detail is not computed by fixed functionality for vertex shaders, so there are some\r
-// differences in operation between vertex and fragment texture lookups. The functions in the table\r
-// below provide access to textures through samplers, as set up through the OpenGL API. Texture\r
-// properties such as size, pixel format, number of dimensions, filtering method, number of mip-map\r
-// levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are\r
-// taken into account as the texture is accessed via the built-in functions defined below.\r
-// \r
-// If a non-shadow texture call is made to a sampler whose texture has depth comparisons enabled,\r
-// then results are undefined. If a shadow texture call is made to a sampler whose texture does not\r
-// have depth comparisions enabled, the results are also undefined.\r
-// \r
-// In all functions below, the bias parameter is optional for fragment shaders. The bias parameter\r
-// is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to\r
-// the calculated level of detail prior to performing the texture access operation. If the bias\r
-// parameter is not provided, then the implementation automatically selects level of detail:\r
-// For a texture that is not mip-mapped, the texture is used directly. If it is mip-mapped and\r
-// running in a fragment shader, the LOD computed by the implementation is used to do the texture\r
-// lookup. If it is mip-mapped and running on the vertex shader, then the base texture is used.\r
-// \r
-// The built-ins suffixed with \93Lod\94 are allowed only in a vertex shader. For the \93Lod\94 functions,\r
-// lod is directly used as the level of detail.\r
-// \r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 1D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate coord.s is divided by\r
-// the last component of coord.\r
-// \r
-// XXX\r
-vec4 texture1D (sampler1D sampler, float coord, float bias) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture1DProj (sampler1D sampler, vec2 coord, float bias) {\r
-    return texture1D (sampler, coord.s / coord.t, bias);\r
-}\r
-vec4 texture1DProj (sampler1D sampler, vec4 coord, float bias) {\r
-    return texture1D (sampler, coord.s / coord.q, bias);\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 2D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate (coord.s, coord.t) is\r
-// divided by the last component of coord. The third component of coord is ignored for the vec4\r
-// coord variant.\r
-// \r
-// XXX\r
-vec4 texture2D (sampler2D sampler, vec2 coord, float bias) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture2DProj (sampler2D sampler, vec3 coord, float bias) {\r
-    return texture2D (sampler, vec2 (coord.s / coord.p, coord.t / coord.p), bias);\r
-}\r
-vec4 texture2DProj (sampler2D sampler, vec4 coord, float bias) {\r
-    return texture2D (sampler, vec2 (coord.s / coord.q, coord.s / coord.q), bias);\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 3D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate is divided by coord.q.\r
-// \r
-// XXX\r
-vec4 texture3D (sampler3D sampler, vec3 coord, float bias) {\r
-    return vec4 (0.0);\r
-}   \r
-vec4 texture3DProj (sampler3D sampler, vec4 coord, float bias) {\r
-    return texture3DProj (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q),\r
-        bias);\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the cube map texture currently bound\r
-// to sampler. The direction of coord is used to select which face to do a 2-dimensional texture\r
-// lookup in, as described in section 3.8.6 in version 1.4 of the OpenGL specification.\r
-// \r
-// XXX\r
-vec4 textureCube (samplerCube sampler, vec3 coord, float bias) {\r
-    return vec4 (0.0);\r
-}\r
-\r
-// \r
-// Use texture coordinate coord to do a depth comparison lookup on the depth texture bound\r
-// to sampler, as described in section 3.8.14 of version 1.4 of the OpenGL specification. The 3rd\r
-// component of coord (coord.p) is used as the R value. The texture bound to sampler must be a\r
-// depth texture, or results are undefined. For the projective (\93Proj\94) version of each built-in,\r
-// the texture coordinate is divide by coord.q, giving a depth value R of coord.p/coord.q. The\r
-// second component of coord is ignored for the \931D\94 variants.\r
-// \r
-// XXX\r
-vec4 shadow1D (sampler1DShadow sampler, vec3 coord, float bias) {\r
-    return vec4 (0.0);\r
-}\r
-// XXX\r
-vec4 shadow2D (sampler2DShadow sampler, vec3 coord, float bias) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord, float bias) {\r
-    return shadow1D (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q), bias);\r
-}\r
-vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord, float bias) {\r
-    return shadow2D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q), bias);\r
-}\r
-\r
-// \r
-// Fragment processing functions are only available in shaders intended for use on the fragment\r
-// processor. Derivatives may be computationally expensive and/or numerically unstable. Therefore,\r
-// an OpenGL implementation may approximate the true derivatives by using a fast but not entirely\r
-// accurate derivative computation.\r
-// \r
-// The expected behavior of a derivative is specified using forward/backward differencing.\r
-// \r
-// Forward differencing:\r
-// \r
-// F(x+dx) - F(x) ~ dFdx(x) * dx            1a\r
-// dFdx(x) ~ (F(x+dx) - F(x)) / dx          1b\r
-// \r
-// Backward differencing:\r
-// \r
-// F(x-dx) - F(x) ~ -dFdx(x) * dx           2a\r
-// dFdx(x) ~ (F(x) - F(x-dx)) / dx          2b\r
-// \r
-// With single-sample rasterization, dx <= 1.0 in equations 1b and 2b. For multi-sample\r
-// rasterization, dx < 2.0 in equations 1b and 2b.\r
-// \r
-// dFdy is approximated similarly, with y replacing x.\r
-// \r
-// A GL implementation may use the above or other methods to perform the calculation, subject\r
-// to the following conditions:\r
-// \r
-// 1) The method may use piecewise linear approximations. Such linear approximations imply that\r
-//    higher order derivatives, dFdx(dFdx(x)) and above, are undefined.\r
-// \r
-// 2) The method may assume that the function evaluated is continuous. Therefore derivatives within\r
-//    the body of a non-uniform conditional are undefined.\r
-// \r
-// 3) The method may differ per fragment, subject to the constraint that the method may vary by\r
-//    window coordinates, not screen coordinates. The invariance requirement described in section\r
-//    3.1 of the OpenGL 1.4 specification is relaxed for derivative calculations, because\r
-//    the method may be a function of fragment location.\r
-// \r
-// Other properties that are desirable, but not required, are:\r
-// \r
-// 4) Functions should be evaluated within the interior of a primitive (interpolated, not\r
-//    extrapolated).\r
-// \r
-// 5) Functions for dFdx should be evaluated while holding y constant. Functions for dFdy should\r
-//    be evaluated while holding x constant. However, mixed higher order derivatives, like\r
-//    dFdx(dFdy(y)) and dFdy(dFdx(x)) are undefined.\r
-// \r
-// In some implementations, varying degrees of derivative accuracy may be obtained by providing\r
-// GL hints (section 5.6 of the OpenGL 1.4 specification), allowing a user to make an image\r
-// quality versus speed tradeoff.\r
-// \r
-\r
-// \r
-// Returns the derivative in x using local differencing for the input argument p.\r
-// \r
-// XXX\r
-float dFdx (float p) {\r
-    return 0.0;\r
-}\r
-// XXX\r
-vec2 dFdx (vec2 p) {\r
-    return vec2 (0.0);\r
-}\r
-// XXX\r
-vec3 dFdx (vec3 p) {\r
-    return vec3 (0.0);\r
-}\r
-// XXX\r
-vec4 dFdx (vec4 p) {\r
-    return vec4 (0.0);\r
-}\r
-\r
-// \r
-// Returns the derivative in y using local differencing for the input argument p.\r
-// \r
-// These two functions are commonly used to estimate the filter width used to anti-alias procedural\r
-// textures.We are assuming that the expression is being evaluated in parallel on a SIMD array so\r
-// that at any given point in time the value of the function is known at the grid points\r
-// represented by the SIMD array. Local differencing between SIMD array elements can therefore\r
-// be used to derive dFdx, dFdy, etc.\r
-// \r
-// XXX\r
-float dFdy (float p) {\r
-    return 0.0;\r
-}\r
-// XXX\r
-vec2 dFdy (vec2 p) {\r
-    return vec2 (0.0);\r
-}\r
-// XXX\r
-vec3 dFdy (vec3 p) {\r
-    return vec3 (0.0);\r
-}\r
-// XXX\r
-vec4 dFdy (vec4 p) {\r
-    return vec4 (0.0);\r
-}\r
-\r
-// \r
-// Returns the sum of the absolute derivative in x and y using local differencing for the input\r
-// argument p, i.e.:\r
-// \r
-// return = abs (dFdx (p)) + abs (dFdy (p));\r
-// \r
-\r
-float fwidth (float p) {\r
-    return abs (dFdx (p)) + abs (dFdy (p));\r
-}\r
-vec2 fwidth (vec2 p) {\r
-    return abs (dFdx (p)) + abs (dFdy (p));\r
-}\r
-vec3 fwidth (vec3 p) {\r
-    return abs (dFdx (p)) + abs (dFdy (p));\r
-}\r
-vec4 fwidth (vec4 p) {\r
-    return abs (dFdx (p)) + abs (dFdy (p));\r
-}\r
-\r
+
+// 
+// TODO:
+// - implement texture1D, texture2D, texture3D, textureCube,
+// - implement shadow1D, shadow2D,
+// - implement dFdx, dFdy,
+// 
+
+// 
+// From Shader Spec, ver. 1.10, rev. 59
+// 
+// The output of the fragment shader is processed by the fixed function operations at the back end
+// of the OpenGL pipeline. Fragment shaders output values to the OpenGL pipeline using the built-in
+// variables gl_FragColor, gl_FragData and gl_FragDepth, unless the discard keyword is executed.
+// 
+// These variables may be written more than once within a fragment shader. If so, the last value
+// assigned is the one used in the subsequent fixed function pipeline. The values written to these
+// variables may be read back after writing them. Reading from these variables before writing them
+// results in an undefined value. The fixed functionality computed depth for a fragment may be
+// obtained by reading gl_FragCoord.z, described below.
+// 
+// Writing to gl_FragColor specifies the fragment color that will be used by the subsequent fixed
+// functionality pipeline. If subsequent fixed functionality consumes fragment color and an
+// execution of a fragment shader does not write a value to gl_FragColor then the fragment color
+// consumed is undefined.
+// 
+// If the frame buffer is configured as a color index buffer then behavior is undefined when using
+// a fragment shader.
+// 
+// Writing to gl_FragDepth will establish the depth value for the fragment being processed. If
+// depth buffering is enabled, and a shader does not write gl_FragDepth, then the fixed function
+// value for depth will be used as the fragment\92s depth value. If a shader statically assigns
+// a value to gl_FragDepth, and there is an execution path through the shader that does not set
+// gl_FragDepth, then the value of the fragment's depth may be undefined for executions of the
+// shader that take that path. That is, if a shader statically contains a write gl_FragDepth, then
+// it is responsible for always writing it.
+//
+// (A shader contains a static assignment to a variable x if, after pre-processing, the shader
+// contains statement that would write x, whether or not run-time flow of control will cause
+// that statement to be executed.)
+//
+// The variable gl_FragData is an array. Writing to gl_FragData[n] specifies the fragment data
+// that will be used by the subsequent fixed functionality pipeline for data n. If subsequent
+// fixed functionality consumes fragment data and an execution of a fragment shader does not
+// write a value to it, then the fragment data consumed is undefined.
+//
+// If a shader statically assigns a value to gl_FragColor, it may not assign a value to any element
+// of gl_FragData. If a shader statically writes a value to any element of gl_FragData, it may not
+// assign a value to gl_FragColor. That is, a shader may assign values to either gl_FragColor or
+// gl_FragData, but not both.
+// 
+// If a shader executes the discard keyword, the fragment is discarded, and the values of
+// gl_FragDepth, gl_FragColor and gl_FragData become irrelevant.
+// 
+// The variable gl_FragCoord is available as a read-only variable from within fragment shaders
+// and it holds the window relative coordinates x, y, z, and 1/w values for the fragment. This
+// value is the result of the fixed functionality that interpolates primitives after vertex
+// processing to generate fragments. The z component is the depth value that would be used for
+// the fragment\92s depth if a shader contained no writes to gl_FragDepth. This is useful for
+// invariance if a shader conditionally computes gl_FragDepth but otherwise wants the fixed
+// functionality fragment depth.
+// 
+// The fragment shader has access to the read-only built-in variable gl_FrontFacing whose value
+// is true if the fragment belongs to a front-facing primitive. One use of this is to emulate
+// two-sided lighting by selecting one of two colors calculated by the vertex shader.
+// 
+// The built-in variables that are accessible from a fragment shader are intrinsically given types
+// as follows:
+// 
+
+vec4 gl_FragCoord;
+bool gl_FrontFacing;
+vec4 gl_FragColor;
+vec4 gl_FragData[gl_MaxDrawBuffers];
+float gl_FragDepth;
+
+// 
+// However, they do not behave like variables with no qualifier; their behavior is as described
+// above. These built-in variables have global scope.
+// 
+
+// 
+// Unlike user-defined varying variables, the built-in varying variables don\92t have a strict
+// one-to-one correspondence between the vertex language and the fragment language. Two sets are
+// provided, one for each language. Their relationship is described below.
+// 
+// The following varying variables are available to read from in a fragment shader. The gl_Color
+// and gl_SecondaryColor names are the same names as attributes passed to the vertex shader.
+// However, there is no name conflict, because attributes are visible only in vertex shaders
+// and the following are only visible in a fragment shader.
+// 
+
+varying vec4 gl_Color;
+varying vec4 gl_SecondaryColor;
+varying vec4 gl_TexCoord[];                             // at most will be gl_MaxTextureCoords
+varying float gl_FogFragCoord;
+
+// 
+// The values in gl_Color and gl_SecondaryColor will be derived automatically by the system from
+// gl_FrontColor, gl_BackColor, gl_FrontSecondaryColor, and gl_BackSecondaryColor based on which
+// face is visible. If fixed functionality is used for vertex processing, then gl_FogFragCoord will
+// either be the z-coordinate of the fragment in eye space, or the interpolation of the fog
+// coordinate, as described in section 3.10 of the OpenGL 1.4 Specification. The gl_TexCoord[]
+// values are the interpolated gl_TexCoord[] values from a vertex shader or the texture coordinates
+// of any fixed pipeline based vertex functionality.
+// 
+// Indices to the fragment shader gl_TexCoord array are as described above in the vertex shader
+// text.
+// 
+
+// 
+// The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar
+// and vector operations. Many of these built-in functions can be used in more than one type
+// of shader, but some are intended to provide a direct mapping to hardware and so are available
+// only for a specific type of shader.
+// 
+// The built-in functions basically fall into three categories:
+// 
+// \95 They expose some necessary hardware functionality in a convenient way such as accessing
+//   a texture map. There is no way in the language for these functions to be emulated by a shader.
+// 
+// \95 They represent a trivial operation (clamp, mix, etc.) that is very simple for the user
+//   to write, but they are very common and may have direct hardware support. It is a very hard
+//   problem for the compiler to map expressions to complex assembler instructions.
+// 
+// \95 They represent an operation graphics hardware is likely to accelerate at some point. The
+//   trigonometry functions fall into this category.
+// 
+// Many of the functions are similar to the same named ones in common C libraries, but they support
+// vector input as well as the more traditional scalar input.
+// 
+// Applications should be encouraged to use the built-in functions rather than do the equivalent
+// computations in their own shader code since the built-in functions are assumed to be optimal
+// (e.g., perhaps supported directly in hardware).
+// 
+// User code can replace built-in functions with their own if they choose, by simply re-declaring
+// and defining the same name and argument list.
+// 
+
+// 
+// 8.7 Texture Lookup Functions
+// 
+// Texture lookup functions are available to both vertex and fragment shaders. However, level
+// of detail is not computed by fixed functionality for vertex shaders, so there are some
+// differences in operation between vertex and fragment texture lookups. The functions in the table
+// below provide access to textures through samplers, as set up through the OpenGL API. Texture
+// properties such as size, pixel format, number of dimensions, filtering method, number of mip-map
+// levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are
+// taken into account as the texture is accessed via the built-in functions defined below.
+// 
+// If a non-shadow texture call is made to a sampler that represents a depth texture with depth
+// comparisons turned on, then results are undefined. If a shadow texture call is made to a sampler
+// that represents a depth texture with depth comparisions turned off, the results are undefined.
+// If a shadow texture call is made to a sampler that does not represent a depth texture, then
+// results are undefined.
+// 
+// In all functions below, the bias parameter is optional for fragment shaders. The bias parameter
+// is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to
+// the calculated level of detail prior to performing the texture access operation. If the bias
+// parameter is not provided, then the implementation automatically selects level of detail:
+// For a texture that is not mip-mapped, the texture is used directly. If it is mip-mapped and
+// running in a fragment shader, the LOD computed by the implementation is used to do the texture
+// lookup. If it is mip-mapped and running on the vertex shader, then the base texture is used.
+// 
+// The built-ins suffixed with \93Lod\94 are allowed only in a vertex shader. For the \93Lod\94 functions,
+// lod is directly used as the level of detail.
+// 
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 1D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate coord.s is divided by
+// the last component of coord.
+// 
+// XXX
+vec4 texture1D (sampler1D sampler, float coord, float bias) {
+    return vec4 (0.0);
+}
+vec4 texture1DProj (sampler1D sampler, vec2 coord, float bias) {
+    return texture1D (sampler, coord.s / coord.t, bias);
+}
+vec4 texture1DProj (sampler1D sampler, vec4 coord, float bias) {
+    return texture1D (sampler, coord.s / coord.q, bias);
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 2D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate (coord.s, coord.t) is
+// divided by the last component of coord. The third component of coord is ignored for the vec4
+// coord variant.
+// 
+// XXX
+vec4 texture2D (sampler2D sampler, vec2 coord, float bias) {
+    return vec4 (0.0);
+}
+vec4 texture2DProj (sampler2D sampler, vec3 coord, float bias) {
+    return texture2D (sampler, vec2 (coord.s / coord.p, coord.t / coord.p), bias);
+}
+vec4 texture2DProj (sampler2D sampler, vec4 coord, float bias) {
+    return texture2D (sampler, vec2 (coord.s / coord.q, coord.s / coord.q), bias);
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 3D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate is divided by coord.q.
+// 
+// XXX
+vec4 texture3D (sampler3D sampler, vec3 coord, float bias) {
+    return vec4 (0.0);
+}   
+vec4 texture3DProj (sampler3D sampler, vec4 coord, float bias) {
+    return texture3DProj (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q),
+        bias);
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the cube map texture currently bound
+// to sampler. The direction of coord is used to select which face to do a 2-dimensional texture
+// lookup in, as described in section 3.8.6 in version 1.4 of the OpenGL specification.
+// 
+// XXX
+vec4 textureCube (samplerCube sampler, vec3 coord, float bias) {
+    return vec4 (0.0);
+}
+
+// 
+// Use texture coordinate coord to do a depth comparison lookup on the depth texture bound
+// to sampler, as described in section 3.8.14 of version 1.4 of the OpenGL specification. The 3rd
+// component of coord (coord.p) is used as the R value. The texture bound to sampler must be a
+// depth texture, or results are undefined. For the projective (\93Proj\94) version of each built-in,
+// the texture coordinate is divide by coord.q, giving a depth value R of coord.p/coord.q. The
+// second component of coord is ignored for the \931D\94 variants.
+// 
+// XXX
+vec4 shadow1D (sampler1DShadow sampler, vec3 coord, float bias) {
+    return vec4 (0.0);
+}
+// XXX
+vec4 shadow2D (sampler2DShadow sampler, vec3 coord, float bias) {
+    return vec4 (0.0);
+}
+vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord, float bias) {
+    return shadow1D (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q), bias);
+}
+vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord, float bias) {
+    return shadow2D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q), bias);
+}
+
+//
+// 8.8 Fragment Processing Functions
+// 
+// Fragment processing functions are only available in shaders intended for use on the fragment
+// processor. Derivatives may be computationally expensive and/or numerically unstable. Therefore,
+// an OpenGL implementation may approximate the true derivatives by using a fast but not entirely
+// accurate derivative computation.
+// 
+// The expected behavior of a derivative is specified using forward/backward differencing.
+// 
+// Forward differencing:
+// 
+// F(x+dx) - F(x) ~ dFdx(x) * dx            1a
+// dFdx(x) ~ (F(x+dx) - F(x)) / dx          1b
+// 
+// Backward differencing:
+// 
+// F(x-dx) - F(x) ~ -dFdx(x) * dx           2a
+// dFdx(x) ~ (F(x) - F(x-dx)) / dx          2b
+// 
+// With single-sample rasterization, dx <= 1.0 in equations 1b and 2b. For multi-sample
+// rasterization, dx < 2.0 in equations 1b and 2b.
+// 
+// dFdy is approximated similarly, with y replacing x.
+// 
+// A GL implementation may use the above or other methods to perform the calculation, subject
+// to the following conditions:
+// 
+// 1) The method may use piecewise linear approximations. Such linear approximations imply that
+//    higher order derivatives, dFdx(dFdx(x)) and above, are undefined.
+// 
+// 2) The method may assume that the function evaluated is continuous. Therefore derivatives within
+//    the body of a non-uniform conditional are undefined.
+// 
+// 3) The method may differ per fragment, subject to the constraint that the method may vary by
+//    window coordinates, not screen coordinates. The invariance requirement described in section
+//    3.1 of the OpenGL 1.4 specification is relaxed for derivative calculations, because
+//    the method may be a function of fragment location.
+// 
+// Other properties that are desirable, but not required, are:
+// 
+// 4) Functions should be evaluated within the interior of a primitive (interpolated, not
+//    extrapolated).
+// 
+// 5) Functions for dFdx should be evaluated while holding y constant. Functions for dFdy should
+//    be evaluated while holding x constant. However, mixed higher order derivatives, like
+//    dFdx(dFdy(y)) and dFdy(dFdx(x)) are undefined.
+// 
+// In some implementations, varying degrees of derivative accuracy may be obtained by providing
+// GL hints (section 5.6 of the OpenGL 1.4 specification), allowing a user to make an image
+// quality versus speed tradeoff.
+// 
+
+// 
+// Returns the derivative in x using local differencing for the input argument p.
+// 
+// XXX
+float dFdx (float p) {
+    return 0.0;
+}
+// XXX
+vec2 dFdx (vec2 p) {
+    return vec2 (0.0);
+}
+// XXX
+vec3 dFdx (vec3 p) {
+    return vec3 (0.0);
+}
+// XXX
+vec4 dFdx (vec4 p) {
+    return vec4 (0.0);
+}
+
+// 
+// Returns the derivative in y using local differencing for the input argument p.
+// 
+// These two functions are commonly used to estimate the filter width used to anti-alias procedural
+// textures.We are assuming that the expression is being evaluated in parallel on a SIMD array so
+// that at any given point in time the value of the function is known at the grid points
+// represented by the SIMD array. Local differencing between SIMD array elements can therefore
+// be used to derive dFdx, dFdy, etc.
+// 
+// XXX
+float dFdy (float p) {
+    return 0.0;
+}
+// XXX
+vec2 dFdy (vec2 p) {
+    return vec2 (0.0);
+}
+// XXX
+vec3 dFdy (vec3 p) {
+    return vec3 (0.0);
+}
+// XXX
+vec4 dFdy (vec4 p) {
+    return vec4 (0.0);
+}
+
+// 
+// Returns the sum of the absolute derivative in x and y using local differencing for the input
+// argument p, i.e.:
+// 
+// return = abs (dFdx (p)) + abs (dFdy (p));
+// 
+
+float fwidth (float p) {
+    return abs (dFdx (p)) + abs (dFdy (p));
+}
+vec2 fwidth (vec2 p) {
+    return abs (dFdx (p)) + abs (dFdy (p));
+}
+vec3 fwidth (vec3 p) {
+    return abs (dFdx (p)) + abs (dFdy (p));
+}
+vec4 fwidth (vec4 p) {
+    return abs (dFdx (p)) + abs (dFdy (p));
+}
+
index ed89be9..cb04362 100755 (executable)
-\r
-// \r
-// TODO:\r
-// - what to do with ftransform? can it stay in the current form?\r
-// - implement texture1DLod, texture2DLod, texture3DLod, textureCubeLod,\r
-// - implement shadow1DLod, shadow2DLod,\r
-// \r
-\r
-// \r
-// From Shader Spec, ver. 1.051\r
-// \r
-// Some OpenGL operations still continue to occur in fixed functionality in between the vertex\r
-// processor and the fragment processor. Other OpenGL operations continue to occur in fixed\r
-// functionality after the fragment processor. Shaders communicate with the fixed functionality\r
-// of OpenGL through the use of built-in variables.\r
-// \r
-// The variable gl_Position is available only in the vertex language and is intended for writing\r
-// the homogeneous vertex position. All executions of a well-formed vertex shader must write\r
-// a value into this variable. It can be written at any time during shader execution. It may also\r
-// be read back by the shader after being written. This value will be used by primitive assembly,\r
-// clipping, culling, and other fixed functionality operations that operate on primitives after\r
-// vertex processing has occurred. Compilers may generate a diagnostic message if they detect\r
-// gl_Position is not written, or read before being written, but not all such cases are detectable.\r
-// Results are undefined if a vertex shader is executed and does not write gl_Position.\r
-// \r
-// The variable gl_PointSize is available only in the vertex language and is intended for a vertex\r
-// shader to write the size of the point to be rasterized. It is measured in pixels.\r
-// \r
-// The variable gl_ClipVertex is available only in the vertex language and provides a place for\r
-// vertex shaders to write the coordinate to be used with the user clipping planes. The user must\r
-// ensure the clip vertex and user clipping planes are defined in the same coordinate space. User\r
-// clip planes work properly only under linear transform. It is undefined what happens under\r
-// non-linear transform.\r
-// \r
-// These built-in vertex shader variables for communicating with fixed functionality are\r
-// intrinsically declared with the following types:\r
-// \r
-\r
-vec4 gl_Position;                                       // must be written to\r
-float gl_PointSize;                                     // may be written to\r
-vec4 gl_ClipVertex;                                     // may be written to\r
-\r
-// \r
-// If gl_PointSize or gl_ClipVertex are not written to, their values are undefined. Any of these\r
-// variables can be read back by the shader after writing to them, to retrieve what was written.\r
-// Reading them before writing them results in undefined behavior. If they are written more than\r
-// once, it is the last value written that is consumed by the subsequent operations.\r
-// \r
-// These built-in variables have global scope.\r
-// \r
-\r
-// \r
-// The following attribute names are built into the OpenGL vertex language and can be used from\r
-// within a vertex shader to access the current values of attributes declared by OpenGL. All page\r
-// numbers and notations are references to the OpenGL 1.4 specification.\r
-// \r
-\r
-// \r
-// Vertex Attributes, p. 19.\r
-// \r
-\r
-attribute vec4 gl_Color;\r
-attribute vec4 gl_SecondaryColor;\r
-attribute vec3 gl_Normal;\r
-attribute vec4 gl_Vertex;\r
-attribute vec4 gl_MultiTexCoord0;\r
-attribute vec4 gl_MultiTexCoord1;\r
-attribute vec4 gl_MultiTexCoord2;\r
-attribute vec4 gl_MultiTexCoord3;\r
-attribute vec4 gl_MultiTexCoord4;\r
-attribute vec4 gl_MultiTexCoord5;\r
-attribute vec4 gl_MultiTexCoord6;\r
-attribute vec4 gl_MultiTexCoord7;\r
-attribute float gl_FogCoord;\r
-\r
-// \r
-// Unlike user-defined varying variables, the built-in varying variables don\92t have a strict\r
-// one-to-one correspondence between the vertex language and the fragment language. Two sets are\r
-// provided, one for each language. Their relationship is described below.\r
-// \r
-// The following built-in varying variables are available to write to in a vertex shader.\r
-// A particular one should be written to if any functionality in a corresponding fragment shader\r
-// or fixed pipeline uses it or state derived from it. Otherwise, behavior is undefined.\r
-//\r
-\r
-varying vec4 gl_FrontColor;\r
-varying vec4 gl_BackColor;\r
-varying vec4 gl_FrontSecondaryColor;\r
-varying vec4 gl_BackSecondaryColor;\r
-varying vec4 gl_TexCoord[];                             // at most will be gl_MaxTextureCoordsARB\r
-varying float gl_FogFragCoord;\r
-\r
-// \r
-// For gl_FogFragCoord, the value written will be used as the \93c\94 value on page 160 of the\r
-// OpenGL 1.4 Specification by the fixed functionality pipeline. For example, if the z-coordinate\r
-// of the fragment in eye space is desired as \93c\94, then that's what the vertex shader should write\r
-// into gl_FogFragCoord.\r
-// \r
-// As with all arrays, indices used to subscript gl_TexCoord must either be integral constant\r
-// expressions, or this array must be re-declared by the shader with a size. The size can be\r
-// at most gl_MaxTextureCoordsARB. Using indexes close to 0 may aid the implementation\r
-// in preserving varying resources.\r
-// \r
-\r
-// \r
-// The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar\r
-// and vector operations. Many of these built-in functions can be used in more than one type\r
-// of shader, but some are intended to provide a direct mapping to hardware and so are available\r
-// only for a specific type of shader.\r
-// \r
-// The built-in functions basically fall into three categories:\r
-// \r
-// \95 They expose some necessary hardware functionality in a convenient way such as accessing\r
-//   a texture map. There is no way in the language for these functions to be emulated by a shader.\r
-// \r
-// \95 They represent a trivial operation (clamp, mix, etc.) that is very simple for the user\r
-//   to write, but they are very common and may have direct hardware support. It is a very hard\r
-//   problem for the compiler to map expressions to complex assembler instructions.\r
-// \r
-// \95 They represent an operation graphics hardware is likely to accelerate at some point. The\r
-//   trigonometry functions fall into this category.\r
-// \r
-// Many of the functions are similar to the same named ones in common C libraries, but they support\r
-// vector input as well as the more traditional scalar input.\r
-// \r
-// Applications should be encouraged to use the built-in functions rather than do the equivalent\r
-// computations in their own shader code since the built-in functions are assumed to be optimal\r
-// (e.g., perhaps supported directly in hardware).\r
-// \r
-// User code can replace built-in functions with their own if they choose, by simply re-declaring\r
-// and defining the same name and argument list.\r
-// \r
-\r
-// \r
-// Geometric Functions\r
-// \r
-// These operate on vectors as vectors, not component-wise.\r
-// \r
-\r
-// \r
-// For vertex shaders only. This function will ensure that the incoming vertex value will be\r
-// transformed in a way that produces exactly the same result as would be produced by OpenGL\92s\r
-// fixed functionality transform. It is intended to be used to compute gl_Position, e.g.,\r
-// gl_Position = ftransform()\r
-// This function should be used, for example, when an application is rendering the same geometry in\r
-// separate passes, and one pass uses the fixed functionality path to render and another pass uses\r
-// programmable shaders.\r
-// \r
-\r
-vec4 ftransform () {\r
-    return gl_ModelViewProjectionMatrix * gl_Vertex;\r
-}\r
-\r
-// \r
-// Texture Lookup Functions\r
-// \r
-// Texture lookup functions are available to both vertex and fragment shaders. However, level\r
-// of detail is not computed by fixed functionality for vertex shaders, so there are some\r
-// differences in operation between vertex and fragment texture lookups. The functions in the table\r
-// below provide access to textures through samplers, as set up through the OpenGL API. Texture\r
-// properties such as size, pixel format, number of dimensions, filtering method, number of mip-map\r
-// levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are\r
-// taken into account as the texture is accessed via the built-in functions defined below.\r
-// \r
-// If a non-shadow texture call is made to a sampler whose texture has depth comparisons enabled,\r
-// then results are undefined. If a shadow texture call is made to a sampler whose texture does not\r
-// have depth comparisions enabled, the results are also undefined.\r
-// \r
-// In all functions below, the bias parameter is optional for fragment shaders. The bias parameter\r
-// is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to\r
-// the calculated level of detail prior to performing the texture access operation. If the bias\r
-// parameter is not provided, then the implementation automatically selects level of detail:\r
-// For a texture that is not mip-mapped, the texture is used directly. If it is mip-mapped and\r
-// running in a fragment shader, the LOD computed by the implementation is used to do the texture\r
-// lookup. If it is mip-mapped and running on the vertex shader, then the base texture is used.\r
-// \r
-// The built-ins suffixed with \93Lod\94 are allowed only in a vertex shader. For the \93Lod\94 functions,\r
-// lod is directly used as the level of detail.\r
-// \r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 1D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate coord.s is divided by\r
-// the last component of coord.\r
-// \r
-// XXX\r
-vec4 texture1DLod (sampler1D sampler, float coord, float lod) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture1DProjLod (sampler1D sampler, vec2 coord, float lod) {\r
-    return texture1DLod (sampler, coord.s / coord.t, lod);\r
-}\r
-vec4 texture1DProjLod (sampler1D sampler, vec4 coord, float lod) {\r
-    return texture1DLod (sampler, coord.s / coord.q, lod);\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 2D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate (coord.s, coord.t) is\r
-// divided by the last component of coord. The third component of coord is ignored for the vec4\r
-// coord variant.\r
-// \r
-// XXX\r
-vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod) {\r
-    return texture2DLod (sampler, vec2 (coord.s / coord.p, coord.t / coord.p), lod);\r
-}\r
-vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod) {\r
-    return texture2DLod (sampler, vec2 (coord.s / coord.q, coord.t / coord.q), lod);\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the 3D texture currently bound\r
-// to sampler. For the projective (\93Proj\94) versions, the texture coordinate is divided by coord.q.\r
-// \r
-// XXX\r
-vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 texture3DProjLod (sampler3D sampler, vec4 coord, float lod) {\r
-    return texture3DLod (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.s / coord.q),\r
-        lod);\r
-}\r
-\r
-// \r
-// Use the texture coordinate coord to do a texture lookup in the cube map texture currently bound\r
-// to sampler. The direction of coord is used to select which face to do a 2-dimensional texture\r
-// lookup in, as described in section 3.8.6 in version 1.4 of the OpenGL specification.\r
-// \r
-// XXX\r
-vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod) {\r
-    return vec4 (0.0);\r
-}\r
-\r
-// \r
-// Use texture coordinate coord to do a depth comparison lookup on the depth texture bound\r
-// to sampler, as described in section 3.8.14 of version 1.4 of the OpenGL specification. The 3rd\r
-// component of coord (coord.p) is used as the R value. The texture bound to sampler must be a\r
-// depth texture, or results are undefined. For the projective (\93Proj\94) version of each built-in,\r
-// the texture coordinate is divide by coord.q, giving a depth value R of coord.p/coord.q. The\r
-// second component of coord is ignored for the \931D\94 variants.\r
-// \r
-// XXX\r
-vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod) {\r
-    return vec4 (0.0);\r
-}\r
-// XXX\r
-vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod) {\r
-    return vec4 (0.0);\r
-}\r
-vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod) {\r
-    return shadow1DLod (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q), lod);\r
-}\r
-vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod) {\r
-    return shadow2DLod (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q),\r
-        lod);\r
-}\r
-\r
+
+// 
+// TODO:
+// - what to do with ftransform? can it stay in the current form?
+// - implement texture1DLod, texture2DLod, texture3DLod, textureCubeLod,
+// - implement shadow1DLod, shadow2DLod,
+// 
+
+// 
+// From Shader Spec, ver. 1.10, rev. 59
+// 
+// Some OpenGL operations still continue to occur in fixed functionality in between the vertex
+// processor and the fragment processor. Other OpenGL operations continue to occur in fixed
+// functionality after the fragment processor. Shaders communicate with the fixed functionality
+// of OpenGL through the use of built-in variables.
+// 
+// The variable gl_Position is available only in the vertex language and is intended for writing
+// the homogeneous vertex position. All executions of a well-formed vertex shader must write
+// a value into this variable. It can be written at any time during shader execution. It may also
+// be read back by the shader after being written. This value will be used by primitive assembly,
+// clipping, culling, and other fixed functionality operations that operate on primitives after
+// vertex processing has occurred. Compilers may generate a diagnostic message if they detect
+// gl_Position is not written, or read before being written, but not all such cases are detectable.
+// Results are undefined if a vertex shader is executed and does not write gl_Position.
+// 
+// The variable gl_PointSize is available only in the vertex language and is intended for a vertex
+// shader to write the size of the point to be rasterized. It is measured in pixels.
+// 
+// The variable gl_ClipVertex is available only in the vertex language and provides a place for
+// vertex shaders to write the coordinate to be used with the user clipping planes. The user must
+// ensure the clip vertex and user clipping planes are defined in the same coordinate space. User
+// clip planes work properly only under linear transform. It is undefined what happens under
+// non-linear transform.
+// 
+// These built-in vertex shader variables for communicating with fixed functionality are
+// intrinsically declared with the following types:
+// 
+
+vec4 gl_Position;                                       // must be written to
+float gl_PointSize;                                     // may be written to
+vec4 gl_ClipVertex;                                     // may be written to
+
+// 
+// If gl_PointSize or gl_ClipVertex are not written to, their values are undefined. Any of these
+// variables can be read back by the shader after writing to them, to retrieve what was written.
+// Reading them before writing them results in undefined behavior. If they are written more than
+// once, it is the last value written that is consumed by the subsequent operations.
+// 
+// These built-in variables have global scope.
+// 
+
+// 
+// The following attribute names are built into the OpenGL vertex language and can be used from
+// within a vertex shader to access the current values of attributes declared by OpenGL. All page
+// numbers and notations are references to the OpenGL 1.4 specification.
+// 
+
+// 
+// Vertex Attributes, p. 19.
+// 
+
+attribute vec4 gl_Color;
+attribute vec4 gl_SecondaryColor;
+attribute vec3 gl_Normal;
+attribute vec4 gl_Vertex;
+attribute vec4 gl_MultiTexCoord0;
+attribute vec4 gl_MultiTexCoord1;
+attribute vec4 gl_MultiTexCoord2;
+attribute vec4 gl_MultiTexCoord3;
+attribute vec4 gl_MultiTexCoord4;
+attribute vec4 gl_MultiTexCoord5;
+attribute vec4 gl_MultiTexCoord6;
+attribute vec4 gl_MultiTexCoord7;
+attribute float gl_FogCoord;
+
+// 
+// Unlike user-defined varying variables, the built-in varying variables don\92t have a strict
+// one-to-one correspondence between the vertex language and the fragment language. Two sets are
+// provided, one for each language. Their relationship is described below.
+// 
+// The following built-in varying variables are available to write to in a vertex shader.
+// A particular one should be written to if any functionality in a corresponding fragment shader
+// or fixed pipeline uses it or state derived from it. Otherwise, behavior is undefined.
+//
+
+varying vec4 gl_FrontColor;
+varying vec4 gl_BackColor;
+varying vec4 gl_FrontSecondaryColor;
+varying vec4 gl_BackSecondaryColor;
+varying vec4 gl_TexCoord[];                             // at most will be gl_MaxTextureCoords
+varying float gl_FogFragCoord;
+
+// 
+// For gl_FogFragCoord, the value written will be used as the \93c\94 value on page 160 of the
+// OpenGL 1.4 Specification by the fixed functionality pipeline. For example, if the z-coordinate
+// of the fragment in eye space is desired as \93c\94, then that's what the vertex shader should write
+// into gl_FogFragCoord.
+// 
+// As with all arrays, indices used to subscript gl_TexCoord must either be an integral constant
+// expressions, or this array must be re-declared by the shader with a size. The size can be
+// at most gl_MaxTextureCoords. Using indexes close to 0 may aid the implementation
+// in preserving varying resources.
+// 
+
+// 
+// The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar
+// and vector operations. Many of these built-in functions can be used in more than one type
+// of shader, but some are intended to provide a direct mapping to hardware and so are available
+// only for a specific type of shader.
+// 
+// The built-in functions basically fall into three categories:
+// 
+// \95 They expose some necessary hardware functionality in a convenient way such as accessing
+//   a texture map. There is no way in the language for these functions to be emulated by a shader.
+// 
+// \95 They represent a trivial operation (clamp, mix, etc.) that is very simple for the user
+//   to write, but they are very common and may have direct hardware support. It is a very hard
+//   problem for the compiler to map expressions to complex assembler instructions.
+// 
+// \95 They represent an operation graphics hardware is likely to accelerate at some point. The
+//   trigonometry functions fall into this category.
+// 
+// Many of the functions are similar to the same named ones in common C libraries, but they support
+// vector input as well as the more traditional scalar input.
+// 
+// Applications should be encouraged to use the built-in functions rather than do the equivalent
+// computations in their own shader code since the built-in functions are assumed to be optimal
+// (e.g., perhaps supported directly in hardware).
+// 
+// User code can replace built-in functions with their own if they choose, by simply re-declaring
+// and defining the same name and argument list.
+// 
+
+// 
+// Geometric Functions
+// 
+// These operate on vectors as vectors, not component-wise.
+// 
+
+// 
+// For vertex shaders only. This function will ensure that the incoming vertex value will be
+// transformed in a way that produces exactly the same result as would be produced by OpenGL\92s
+// fixed functionality transform. It is intended to be used to compute gl_Position, e.g.,
+// gl_Position = ftransform()
+// This function should be used, for example, when an application is rendering the same geometry in
+// separate passes, and one pass uses the fixed functionality path to render and another pass uses
+// programmable shaders.
+// 
+
+vec4 ftransform () {
+    return gl_ModelViewProjectionMatrix * gl_Vertex;
+}
+
+// 
+// 8.7 Texture Lookup Functions
+// 
+// Texture lookup functions are available to both vertex and fragment shaders. However, level
+// of detail is not computed by fixed functionality for vertex shaders, so there are some
+// differences in operation between vertex and fragment texture lookups. The functions in the table
+// below provide access to textures through samplers, as set up through the OpenGL API. Texture
+// properties such as size, pixel format, number of dimensions, filtering method, number of mip-map
+// levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are
+// taken into account as the texture is accessed via the built-in functions defined below.
+// 
+// If a non-shadow texture call is made to a sampler that represents a depth texture with depth
+// comparisons turned on, then results are undefined. If a shadow texture call is made to a sampler
+// that represents a depth texture with depth comparisions turned off, the results are undefined.
+// If a shadow texture call is made to a sampler that does not represent a depth texture, then
+// results are undefined.
+// 
+// In all functions below, the bias parameter is optional for fragment shaders. The bias parameter
+// is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to
+// the calculated level of detail prior to performing the texture access operation. If the bias
+// parameter is not provided, then the implementation automatically selects level of detail:
+// For a texture that is not mip-mapped, the texture is used directly. If it is mip-mapped and
+// running in a fragment shader, the LOD computed by the implementation is used to do the texture
+// lookup. If it is mip-mapped and running on the vertex shader, then the base texture is used.
+// 
+// The built-ins suffixed with \93Lod\94 are allowed only in a vertex shader. For the \93Lod\94 functions,
+// lod is directly used as the level of detail.
+// 
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 1D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate coord.s is divided by
+// the last component of coord.
+// 
+// XXX
+vec4 texture1DLod (sampler1D sampler, float coord, float lod) {
+    return vec4 (0.0);
+}
+vec4 texture1DProjLod (sampler1D sampler, vec2 coord, float lod) {
+    return texture1DLod (sampler, coord.s / coord.t, lod);
+}
+vec4 texture1DProjLod (sampler1D sampler, vec4 coord, float lod) {
+    return texture1DLod (sampler, coord.s / coord.q, lod);
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 2D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate (coord.s, coord.t) is
+// divided by the last component of coord. The third component of coord is ignored for the vec4
+// coord variant.
+// 
+// XXX
+vec4 texture2DLod (sampler2D sampler, vec2 coord, float lod) {
+    return vec4 (0.0);
+}
+vec4 texture2DProjLod (sampler2D sampler, vec3 coord, float lod) {
+    return texture2DLod (sampler, vec2 (coord.s / coord.p, coord.t / coord.p), lod);
+}
+vec4 texture2DProjLod (sampler2D sampler, vec4 coord, float lod) {
+    return texture2DLod (sampler, vec2 (coord.s / coord.q, coord.t / coord.q), lod);
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the 3D texture currently bound
+// to sampler. For the projective (\93Proj\94) versions, the texture coordinate is divided by coord.q.
+// 
+// XXX
+vec4 texture3DLod (sampler3D sampler, vec3 coord, float lod) {
+    return vec4 (0.0);
+}
+vec4 texture3DProjLod (sampler3D sampler, vec4 coord, float lod) {
+    return texture3DLod (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.s / coord.q),
+        lod);
+}
+
+// 
+// Use the texture coordinate coord to do a texture lookup in the cube map texture currently bound
+// to sampler. The direction of coord is used to select which face to do a 2-dimensional texture
+// lookup in, as described in section 3.8.6 in version 1.4 of the OpenGL specification.
+// 
+// XXX
+vec4 textureCubeLod (samplerCube sampler, vec3 coord, float lod) {
+    return vec4 (0.0);
+}
+
+// 
+// Use texture coordinate coord to do a depth comparison lookup on the depth texture bound
+// to sampler, as described in section 3.8.14 of version 1.4 of the OpenGL specification. The 3rd
+// component of coord (coord.p) is used as the R value. The texture bound to sampler must be a
+// depth texture, or results are undefined. For the projective (\93Proj\94) version of each built-in,
+// the texture coordinate is divide by coord.q, giving a depth value R of coord.p/coord.q. The
+// second component of coord is ignored for the \931D\94 variants.
+// 
+// XXX
+vec4 shadow1DLod (sampler1DShadow sampler, vec3 coord, float lod) {
+    return vec4 (0.0);
+}
+// XXX
+vec4 shadow2DLod (sampler2DShadow sampler, vec3 coord, float lod) {
+    return vec4 (0.0);
+}
+vec4 shadow1DProjLod(sampler1DShadow sampler, vec4 coord, float lod) {
+    return shadow1DLod (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q), lod);
+}
+vec4 shadow2DProjLod(sampler2DShadow sampler, vec4 coord, float lod) {
+    return shadow2DLod (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q),
+        lod);
+}
+