#if defined(PURE_OPENGL_ES_2)
/* these are the shaders for the IPhone (Compiled but not used yet) */
const char* default_vs =
"const int a_MaxLights=4;\n"
"struct st_LightSourceParameters { \n"
"  vec4 ambient;\n"
"  vec4 diffuse;\n"
"  vec4 specular;\n"
"  vec4 position;\n"
"  vec4 halfVector;\n"
"  vec3 spotDirection;\n"
"  float spotExponent;\n"
"  float spotCutoff;\n"
"  float spotCosCutoff;\n"
"  float constantAttenuation;\n"
"  float linearAttenuation;\n"
"  float quadraticAttenuation;\n"
"}; \n"
"uniform st_LightSourceParameters u_LightSource[a_MaxLights];\n"
"struct FogParameters {\n"
"  vec4 color;\n"
"  float density;\n"
"  float start;\n"
"  float end;\n"
"  float scale;\n"
"};\n"
"uniform FogParameters st_Fog;\n"
"uniform mat4 u_ModelViewMatrix;\n"
"uniform mat3 u_NormalMatrix;\n"
"attribute vec4 a_Vertex;\n"
"attribute vec3 a_Normal;\n"
"attribute vec4 a_Color;\n"
"varying vec3 N, L0, H0, L1, H1;\n"
"varying vec4 D0, A0, D1, A1;\n"
"varying float fog;\n"
"varying float v_FogFragCoord;\n"
"void main()\n"
"{\n"
"  N = normalize(u_NormalMatrix * a_Normal);\n"
"  vec3 eye_pos = vec3(u_ModelViewMatrix * a_Vertex);\n"
"  vec3 aux = vec3(u_LightSource[0].position - vec4(eye_pos, 1.0));\n"
"  L0 = normalize(aux);\n"
"  H0 = normalize(u_LightSource[0].halfVector.xyz);\n"
"  aux = vec3(u_LightSource[1].position - vec4(eye_pos, 1.0));\n"
"  L1 = normalize(aux);\n"
"  H1 = normalize(u_LightSource[1].halfVector.xyz);\n"
"  A0 = u_LightSource[0].ambient * a_Color;\n"
"  D0 = u_LightSource[0].diffuse * a_Color;\n"
"  A1 = u_LightSource[1].ambient * a_Color;\n"
"  D1 = u_LightSource[1].diffuse * a_Color;\n"
"  v_FogFragCoord = -eye_pos.z;\n"
"  fog = (st_Fog.end - v_FogFragCoord) * st_Fog.scale;\n"
"  gl_Position =  u_ModelViewMatrix * a_Vertex; // this was converted from ftransform(), is that right?\n"
"}\n"
;
const char* default_fs =
"precision mediump float;\n"
"const int a_MaxLights=4;\n"
"struct st_LightSourceParameters { \n"
"  vec4 ambient;\n"
"  vec4 diffuse;\n"
"  vec4 specular;\n"
"  vec4 position;\n"
"  vec4 halfVector;\n"
"  vec3 spotDirection;\n"
"  float spotExponent;\n"
"  float spotCutoff;\n"
"  float spotCosCutoff;\n"
"  float constantAttenuation;\n"
"  float linearAttenuation;\n"
"  float quadraticAttenuation;\n"
"}; \n"
"uniform st_LightSourceParameters u_LightSource[a_MaxLights];\n"
"struct gl_MaterialParameters {\n"
"  vec4 emission;\n"
"  vec4 ambient;\n"
"  vec4 diffuse;\n"
"  vec4 specular;\n"
"  float shininess;\n"
"};\n"
"uniform gl_MaterialParameters st_FrontMaterial;\n"
"varying vec3 N, L0, H0, L1, H1;\n"
"varying vec4 D0, A0, D1, A1;\n"
"uniform float fog_r;\n"
"uniform float fog_g;\n"
"uniform float fog_b;\n"
"uniform float fog_enabled;\n"
"varying float fog;\n"
"void main()\n"
"{\n"
"  vec3 n, h;\n"
"  float NdotL, NdotH;\n"
"  vec4 color = A0 + A1;\n"
"  n = normalize(N);\n"
"  NdotL = max(dot(n, normalize(L0)), 0.0);\n"
"  float shininess = st_FrontMaterial.shininess;\n"
"  if (NdotL > 0.0) {\n"
"      color += D0 * NdotL;\n"
"      h = normalize(H0);\n"
"      NdotH = max(dot(n, h), 0.0);\n"
"      color += u_LightSource[0].specular * pow(NdotH, shininess);\n"
"  }\n"
"  NdotL = max(dot(n, normalize(L1)), 0.0);\n"
"  if (NdotL > 0.0) {\n"
"      color += D1 * NdotL;\n"
"      h = normalize(H1);\n"
"      NdotH = max(dot(n, h), 0.0);\n"
"      color += u_LightSource[1].specular * pow(NdotH, shininess);\n"
"  }\n"
"  vec3 fog_color = vec3(fog_r, fog_g, fog_b);\n"
"  float cfog = mix(1.0, clamp(fog, 0.0, 1.0), fog_enabled);\n"
"  gl_FragColor = vec4(mix(fog_color, color.rgb, cfog), color.a);\n"
"}\n"
;
#elif defined(OPENGL_ES_2)
/* these are the shaders that uses ES2 */
const char* default_vs =
"attribute vec4 a_Vertex;\n"
"attribute vec3 a_Normal;\n"
"attribute vec4 a_Color;\n"
"attribute float a_Accessibility; /* This is for ambient occlusion, 1.0 by default */\n"
"varying vec3 packed_data_0 ;\n"
"varying vec4 packed_data_1 ;\n"
"varying vec4 packed_data_2 ;\n"
"varying vec4 packed_data_3 ;\n"
"varying vec4 packed_data_4 ;\n"
"//varying vec3 N;\n"
"#define NORMAL  packed_data_0\n"
"#define COLOR packed_data_3\n"
"#define fog packed_data_1.w\n"
"#define E 2.718281828459045\n"
"/* this doesn't work for setting fog_color, need to set the values independently */\n"
"//#define fog_color ( packed_data_1.x, packed_data_1.y, packed_data_1.z )\n"
"uniform bool lighting_enabled;\n"
"uniform bool bg_gradient;\n"
"uniform vec3 fog_color_top;\n"
"uniform vec3 fog_color_bottom;\n"
"uniform float ambient_occlusion_scale;\n"
"uniform int accessibility_mode;\n"
"void main()\n"
"{\n"
"  NORMAL = normalize(gl_NormalMatrix * a_Normal);\n"
"  vec3 eye_pos = vec3(gl_ModelViewMatrix * a_Vertex);\n"
"  vec3 fog_color;\n"
"  if (accessibility_mode == 1){\n"
"    COLOR = vec4(clamp(a_Color.xyz * (1.-(ambient_occlusion_scale*a_Accessibility)), 0., 1.), a_Color.w);\n"
"  } else if (accessibility_mode == 2){\n"
"    COLOR = vec4(a_Color.xyz * cos(90.*radians(clamp(ambient_occlusion_scale*a_Accessibility, 0., 1.))), a_Color.w);\n"
"  } else {\n"
"    COLOR = vec4(clamp(a_Color.xyz * (1. / (1. + pow(E, 0.5 * (ambient_occlusion_scale * a_Accessibility - 10.)))), 0., 1.), a_Color.w);\n"
"  }\n"
"  \n"
"  // This was breaking fog on ATI/Linux\n"
"  //  gl_FogFragCoord = -eye_pos.z;\n"
"  //  fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;\n"
"  fog = (gl_Fog.end - abs(eye_pos.z)) * gl_Fog.scale;\n"
"  gl_Position = gl_ModelViewProjectionMatrix * a_Vertex;\n"
"  if (bg_gradient){\n"
"    fog_color = mix(fog_color_bottom, fog_color_top, (1. + gl_Position.y/gl_Position.w)/2.);\n"
"  } else {\n"
"    fog_color = fog_color_top;\n"
"  }\n"
"  /* setting fog_color */\n"
"  packed_data_1.x = fog_color.x; packed_data_1.y = fog_color.y; packed_data_1.z = fog_color.z;\n"
"}\n"
;
const char* default_fs =
"varying vec3 packed_data_0 ;\n"
"varying vec4 packed_data_1 ;\n"
"varying vec4 packed_data_2 ;\n"
"varying vec4 packed_data_3 ;\n"
"varying vec4 packed_data_4 ;\n"
"//varying vec3 N;\n"
"#define NORMAL packed_data_0.xyz\n"
"#define COLOR packed_data_3\n"
"#define fog (packed_data_1.w )\n"
"#define fog_color packed_data_1.x, packed_data_1.y, packed_data_1.z\n"
"uniform float fog_enabled;\n"
"uniform bool lighting_enabled;\n"
"uniform bool two_sided_lighting_enabled;\n"
"uniform bool bg_gradient;\n"
"uniform int light_count;\n"
"uniform vec4 interior_color;\n"
"uniform float interior_color_threshold;\n"
"uniform float shininess;\n"
"uniform float shininess_0;\n"
"uniform bool use_interior_color_threshold;\n"
"uniform int spec_count;\n"
"uniform float spec_value;\n"
"uniform float spec_value_0;\n"
"uniform int stereo_flag;\n"
"uniform mat3 matR;\n"
"uniform mat3 matL;\n"
"uniform float gamma;\n"
"vec4 ComputeColorForLight(bool is_interior, bool two_sided_lighting_enabled,\n"
"                          vec3 L, vec3 H, vec4 ambient, vec4 diffuse, float spec, float shine){\n"
"  float NdotL, NdotH;\n"
"  vec4 ret_val = vec4(0.);\n"
"  if (!is_interior){\n"
"    ret_val += ambient * COLOR;\n"
"    NdotL = dot(NORMAL, L);\n"
"    if (NdotL > 0.0) {\n"
"       ret_val += diffuse * NdotL * COLOR;\n"
"       NdotH = max(dot(NORMAL, H), 0.0);\n"
"       ret_val += spec * pow(NdotH, shine);\n"
"    }\n"
"  }\n"
"  if (two_sided_lighting_enabled && is_interior){\n"
"    NdotL = dot(-NORMAL, L);\n"
"    if (NdotL > 0.0) {\n"
"       ret_val += diffuse * NdotL * COLOR;\n"
"       NdotH = max(dot(-NORMAL, H), 0.0);\n"
"       ret_val += spec * pow(NdotH, shine);\n"
"    }\n"
"  }\n"
"  return ret_val;\n"
"}\n"
"void main()\n"
"{\n"
"  vec4 final_color = vec4(0.);\n"
"  if (lighting_enabled){\n"
"    bool is_interior = false;\n"
"    if (use_interior_color_threshold){\n"
"      vec3 viewV = vec3(0.,0.,-1.);\n"
"      float dotp = dot(NORMAL, viewV);\n"
"      is_interior = ( dotp > interior_color_threshold );\n"
"    }\n"
"    if (!two_sided_lighting_enabled && is_interior){\n"
"      final_color = interior_color;\n"
"    } else {\n"
"      final_color = (gl_LightModel.ambient) * COLOR;\n"
"      if (light_count>0){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[0].position)),\n"
"                                            normalize(vec3(gl_LightSource[0].halfVector.xyz)),\n"
"                                            gl_LightSource[0].ambient,\n"
"                                            gl_LightSource[0].diffuse,\n"
"                                            spec_value_0, shininess_0);\n"
"      if (light_count>1){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[1].position)),\n"
"                                            normalize(vec3(gl_LightSource[1].halfVector.xyz)),\n"
"                                            gl_LightSource[1].ambient,\n"
"                                            gl_LightSource[1].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>2){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[2].position)),\n"
"                                            normalize(vec3(gl_LightSource[2].halfVector.xyz)),\n"
"                                            gl_LightSource[2].ambient,\n"
"                                            gl_LightSource[2].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>3){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[3].position)),\n"
"                                            normalize(vec3(gl_LightSource[3].halfVector.xyz)),\n"
"                                            gl_LightSource[3].ambient,\n"
"                                            gl_LightSource[3].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>4){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[4].position)),\n"
"                                            normalize(vec3(gl_LightSource[4].halfVector.xyz)),\n"
"                                            gl_LightSource[4].ambient,\n"
"                                            gl_LightSource[4].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>5){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[5].position)),\n"
"                                            normalize(vec3(gl_LightSource[5].halfVector.xyz)),\n"
"                                            gl_LightSource[5].ambient,\n"
"                                            gl_LightSource[5].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>6){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[6].position)),\n"
"                                            normalize(vec3(gl_LightSource[6].halfVector.xyz)),\n"
"                                            gl_LightSource[6].ambient,\n"
"                                            gl_LightSource[6].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>7){\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled,\n"
"                                            normalize(vec3(gl_LightSource[7].position)),\n"
"                                            normalize(vec3(gl_LightSource[7].halfVector.xyz)),\n"
"                                            gl_LightSource[7].ambient,\n"
"                                            gl_LightSource[7].diffuse,\n"
"                                            spec_value, shininess);\n"
"      }}}}}}}}\n"
"    }\n"
"/*\n"
"      for (i=0; i<light_count;i++){\n"
"        vec3 L = normalize(vec3(gl_LightSource[i].position));\n"
"        vec3 H = normalize(vec3(gl_LightSource[i].halfVector.xyz));\n"
"	vec4 ambient = gl_LightSource[i].ambient;\n"
"	vec4 diffuse = gl_LightSource[i].diffuse;\n"
"        float spec = 0., shine = 0.;\n"
"        if (i==0){\n"
"          spec = spec_value_0;\n"
"	  shine = shininess_0;\n"
"        } else if (spec_count >= i){\n"
"          spec = spec_value;\n"
"	  shine = shininess;\n"
"        }\n"
"	final_color += ComputeColorForLight(is_interior, two_sided_lighting_enabled, L, H, ambient, diffuse, spec, shine);\n"
"      }\n"
"    }\n"
"*/\n"
"  } else {\n"
"    final_color = COLOR;\n"
"  }\n"
"  float cfog = mix(1.0, clamp(fog, 0.0, 1.0), fog_enabled);\n"
"  vec4 f = vec4(mix(vec3(fog_color), final_color.rgb, cfog), COLOR.a);\n"
"  if(stereo_flag==-1)\n"
"    gl_FragColor = vec4(matL * pow(f.rgb,vec3(gamma,gamma,gamma)), f.a);\n"
"  else if (stereo_flag==0)\n"
"    gl_FragColor = f;\n"
"  else if (stereo_flag==1)\n"
"    gl_FragColor = vec4(matR * pow(f.rgb, vec3(gamma,gamma,gamma)), f.a);\n"
"}\n"
;
#else
/* these are the original default shaders */
const char* default_vs =
"varying vec3 N, L0, H0, L1, H1;\n"
"varying vec4 D0, A0, D1, A1;\n"
"varying float fog;\n"
"varying vec3 fog_color;\n"
"uniform bool lighting_enabled;\n"
"uniform bool bg_gradient;\n"
"uniform vec3 fog_color_top;\n"
"uniform vec3 fog_color_bottom;\n"
"void main()\n"
"{\n"
"  N = normalize(gl_NormalMatrix * gl_Normal);\n"
"  vec3 eye_pos = vec3(gl_ModelViewMatrix * gl_Vertex);\n"
"  vec3 aux = vec3(gl_LightSource[0].position - vec4(eye_pos, 1.0));\n"
"  if (lighting_enabled){\n"
"    L0 = normalize(aux);\n"
"    H0 = normalize(gl_LightSource[0].halfVector.xyz);\n"
"    aux = vec3(gl_LightSource[1].position - vec4(eye_pos, 1.0));\n"
"    L1 = normalize(aux);\n"
"    H1 = normalize(gl_LightSource[1].halfVector.xyz);\n"
"    A0 = gl_LightSource[0].ambient * gl_Color;\n"
"    D0 = gl_LightSource[0].diffuse * gl_Color;\n"
"    A1 = gl_LightSource[1].ambient * gl_Color;\n"
"    D1 = gl_LightSource[1].diffuse * gl_Color;\n"
"    A0.a = gl_Color.a;\n"
"    A1.a = 0.;\n"
"  } else {\n"
"    A0 = gl_Color;\n"
"  }\n"
"  gl_FogFragCoord = -eye_pos.z;\n"
"  fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;\n"
"  gl_Position = gl_ModelViewProjectionMatrix * a_Vertex;\n"
"  if (bg_gradient){\n"
"    fog_color = mix(fog_color_bottom, fog_color_top, (1. + gl_Position.y/gl_Position.w)/2.);\n"
"  } else {\n"
"    fog_color = fog_color_top;\n"
"  }\n"
"  gl_Position = ftransform();\n"
"}\n"
;
const char* default_fs =
"varying vec3 N, L0, H0, L1, H1;\n"
"varying vec4 D0, A0, D1, A1;\n"
"uniform float fog_r;\n"
"uniform float fog_g;\n"
"uniform float fog_b;\n"
"uniform float fog_enabled;\n"
"uniform bool lighting_enabled;\n"
"varying float fog;\n"
"void main()\n"
"{\n"
"  vec3 n, h;\n"
"  float NdotL, NdotH;\n"
"  vec4 color;\n"
"  n = normalize(N);\n"
"  NdotL = max(dot(n, normalize(L0)), 0.0);\n"
"  float shininess = gl_FrontMaterial.shininess;\n"
"  color = A0;\n"
"  if (lighting_enabled){\n"
"    color = A0 + A1;\n"
"    if (NdotL > 0.0) {\n"
"      color += D0 * NdotL;\n"
"      h = normalize(H0);\n"
"      NdotH = max(dot(n, h), 0.0);\n"
"      color += gl_LightSource[0].specular * pow(NdotH, shininess);\n"
"    }\n"
"    NdotL = max(dot(n, normalize(L1)), 0.0);\n"
"    if (NdotL > 0.0) {\n"
"      color += D1 * NdotL;\n"
"      h = normalize(H1);\n"
"      NdotH = max(dot(n, h), 0.0);\n"
"      color += gl_LightSource[1].specular * pow(NdotH, shininess);\n"
"    }\n"
"  }\n"
"  float cfog = mix(1.0, clamp(fog, 0.0, 1.0), fog_enabled);\n"
"  gl_FragColor = vec4(mix(color.rgb, fog_color, cfog), A0.a);\n"
"}\n"
;
#endif
#ifndef _PYMOL_PURE_OPENGL_ES
/* Volume shaders (not used for IPhone yet */
const char* volume_vs =
"varying float fog;\n"
"void main()\n"
"{\n"
"  vec4 vertex = gl_ModelViewMatrix * gl_Vertex;\n"
"  gl_TexCoord[0] = gl_MultiTexCoord0;\n"
"  gl_ClipVertex = vertex;\n"
"  gl_Position = ftransform();\n"
"  gl_FogFragCoord = -vertex.z;\n"
"  fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;\n"
"}\n"
;
const char* volume_fs =
"uniform sampler3D volumeTex;\n"
"uniform sampler1D colorTex;\n"
"uniform float fog_r;\n"
"uniform float fog_g;\n"
"uniform float fog_b;\n"
"uniform float fog_enabled;\n"
"varying float fog;\n"
"void main()\n"
"{\n"
"  vec3 fog_color = vec3(fog_r, fog_g, fog_b);\n"
"  vec4 color = texture1D(colorTex, texture3D(volumeTex, gl_TexCoord[0].xyz).x);\n"
"  if (color.a == 0.0) discard;\n"
"  float cfog = mix(1.0, clamp(fog, 0.0, 1.0), fog_enabled);\n"
"  gl_FragColor = vec4(vec3(mix(fog_color, color.rgb, cfog)), color.a);\n"
"}\n"
;
const char* sphere_vs =
"// Sphere impostor vertex shader\n"
"uniform bool lighting_enabled;\n"
"uniform float sphere_size_scale;\n"
"uniform float horizontal_adjustment;\n"
"uniform float vertical_adjustment;\n"
"attribute vec4 a_vertex_radius;\n"
"attribute vec4 a_Color;\n"
"attribute float a_rightUpFlags;\n"
"varying vec4 COLOR;\n"
"varying vec3 sphere_center;\n"
"varying vec3 point;\n"
"varying float radius2;\n"
"void main(void)\n"
"{\n"
"    // Get billboard attributes\n"
"    float radius = a_vertex_radius.w * sphere_size_scale;\n"
"    float right = -1. + 2.*mod(a_rightUpFlags, 2.);\n"
"    float up = -1. + 2.*floor(mod(a_rightUpFlags/2., 2.));\n"
"    vec4 a_Vertex = vec4(a_vertex_radius.xyz, 1.);\n"
"    COLOR = a_Color;\n"
"    radius2 = radius * radius; // compute squared radius \n"
"    vec3 right_vector = vec3(gl_ModelViewMatrix[0][0],\n"
"            gl_ModelViewMatrix[1][0], gl_ModelViewMatrix[2][0]);\n"
"    vec3 up_vector = vec3(gl_ModelViewMatrix[0][1],\n"
"            gl_ModelViewMatrix[1][1], gl_ModelViewMatrix[2][1]);\n"
"    // We need to project the vertex out to the edge of the square, which\n"
"    // is the following distance:\n"
"    // float corner_distance = sqrt(2.0 * radius2);\n"
"    // but since we need to normalize the corner vector computed below\n"
"    // which has length sqrt(2.0), we can simply use radius as corner distance\n"
"    // to compute vertex position of screen-oriented quad.\n"
"    // Compute corner vector\n"
"    vec3 corner_direction =  (vertical_adjustment*up) * up_vector + (horizontal_adjustment*right) * right_vector;\n"
"    // Calculate vertex of screen-oriented quad (billboard)\n"
"    vec4 vertex = vec4(a_Vertex.xyz + radius * corner_direction, 1.);\n"
"    // Calculate vertex position in modelview space\n"
"    vec4 eye_space_pos = gl_ModelViewMatrix * vertex;\n"
"    // Compute sphere position in modelview space\n"
"    vec4 tmppos = gl_ModelViewMatrix * a_Vertex;\n"
"    sphere_center = tmppos.xyz / tmppos.w;\n"
"    // Compute ray direction and origin point\n"
"    point = eye_space_pos.xyz / eye_space_pos.w;\n"
"    // Pass the transformed vertex for clipping plane calculations\n"
"    gl_ClipVertex = eye_space_pos;\n"
"    // Pass transformed vertex\n"
"    gl_Position = gl_ModelViewProjectionMatrix * vertex;\n"
"}\n"
;
const char* sphere_fs =
"// Sphere impostor fragment shader\n"
"uniform bool lighting_enabled;\n"
"uniform float ortho;\n"
"uniform float fog_enabled;\n"
"uniform bool bg_gradient;\n"
"uniform vec3 fog_color_top;\n"
"uniform vec3 fog_color_bottom;\n"
"uniform float inv_height;\n"
"uniform int light_count;\n"
"uniform float shininess;\n"
"uniform float shininess_0;\n"
"uniform int spec_count;\n"
"uniform float spec_value;\n"
"uniform float spec_value_0;\n"
"uniform int stereo_flag;\n"
"uniform mat3 matL;\n"
"uniform mat3 matR;\n"
"uniform float gamma;\n"
"varying vec4 COLOR;\n"
"varying vec3 sphere_center;\n"
"varying float radius2;\n"
"varying vec3 point;\n"
"// varying fog;\n"
"vec4 ComputeColorForLight(vec3 N, vec3 L, vec3 H, vec4 ambient, vec4 diffuse, float spec, float shine){\n"
"  float NdotL, NdotH;\n"
"  vec4 ret_val = vec4(0.);\n"
"  ret_val += ambient * COLOR;\n"
"  NdotL = dot(N, L);\n"
"  if (NdotL > 0.0) {\n"
"    ret_val += diffuse * NdotL * COLOR;\n"
"    NdotH = max(dot(N, H), 0.0);\n"
"    ret_val += spec * pow(NdotH, shine);\n"
"  }\n"
"  return ret_val;\n"
"}\n"
"void main(void)\n"
"{\n"
"    vec3 ray_origin = mix(vec3(0.,0.,0.), point, ortho);\n"
"    vec3 ray_direction = mix(normalize(point), vec3(0., 0., 1.), ortho);\n"
"    vec3 sphere_direction = mix(sphere_center, ray_origin - sphere_center, ortho);\n"
"    // Calculate sphere-ray intersection\n"
"    float b = dot(sphere_direction, ray_direction);\n"
"    float position = b * b + radius2 - dot(sphere_direction, sphere_direction);\n"
"    // Check if the ray missed the sphere\n"
"    if (position < 0.0)\n"
"       discard;\n"
"    // Calculate nearest point of intersection\n"
"    float nearest = mix(b - sqrt(position), sqrt(position) - b, ortho);\n"
"    // Calculate intersection point on the sphere surface.  The ray\n"
"    // origin is at the quad (center point), so we need to project\n"
"    // back towards the user to get the front face.\n"
"    vec3 ipoint = nearest * ray_direction + ray_origin;\n"
"    // Calculate normal at the intersection point\n"
"    vec3 N = normalize(ipoint - sphere_center);\n"
"    // Calculate depth in clipping space \n"
"    vec2 clipZW = ipoint.z * gl_ProjectionMatrix[2].zw +\n"
"        gl_ProjectionMatrix[3].zw;\n"
"    float depth = 0.5 + 0.5 * clipZW.x / clipZW.y;\n"
"    // this is a workaround necessary for Mac\n"
"    // otherwise the modified fragment won't clip properly\n"
"    if (depth <= 0.0)\n"
"      discard;\n"
"    if (depth >= 1.0)\n"
"      discard;\n"
"    if (COLOR.a <= 1.0)\n"
"      gl_FragDepth = depth;\n"
"    else\n"
"      gl_FragDepth = 1.0;\n"
"    vec4 color;\n"
"    vec3 L0 = normalize(vec3(gl_LightSource[0].position) - ipoint);\n"
"    float NdotL = max(dot(N, L0), 0.0);\n"
"    float NdotH;\n"
"    vec4 final_color = (gl_LightModel.ambient) * COLOR;\n"
"    if (light_count>0){\n"
"      final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[0].position)),\n"
"                                          normalize(vec3(gl_LightSource[0].halfVector.xyz)),\n"
"                                          gl_LightSource[0].ambient,\n"
"                                          gl_LightSource[0].diffuse,\n"
"                                          spec_value_0, shininess_0);\n"
"      if (light_count>1){\n"
"	final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[1].position)),\n"
"                                            normalize(vec3(gl_LightSource[1].halfVector.xyz)),\n"
"                                            gl_LightSource[1].ambient,\n"
"                                            gl_LightSource[1].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>2){\n"
"	final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[2].position)),\n"
"                                            normalize(vec3(gl_LightSource[2].halfVector.xyz)),\n"
"                                            gl_LightSource[2].ambient,\n"
"                                            gl_LightSource[2].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>3){\n"
"	final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[3].position)),\n"
"                                            normalize(vec3(gl_LightSource[3].halfVector.xyz)),\n"
"                                            gl_LightSource[3].ambient,\n"
"                                            gl_LightSource[3].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>4){\n"
"	final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[4].position)),\n"
"                                            normalize(vec3(gl_LightSource[4].halfVector.xyz)),\n"
"                                            gl_LightSource[4].ambient,\n"
"                                            gl_LightSource[4].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>5){\n"
"	final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[5].position)),\n"
"                                            normalize(vec3(gl_LightSource[5].halfVector.xyz)),\n"
"                                            gl_LightSource[5].ambient,\n"
"                                            gl_LightSource[5].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>6){\n"
"	final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[6].position)),\n"
"                                            normalize(vec3(gl_LightSource[6].halfVector.xyz)),\n"
"                                            gl_LightSource[6].ambient,\n"
"                                            gl_LightSource[6].diffuse,\n"
"                                            spec_value, shininess);\n"
"      if (light_count>7){\n"
"	final_color += ComputeColorForLight(N, normalize(vec3(gl_LightSource[7].position)),\n"
"                                            normalize(vec3(gl_LightSource[7].halfVector.xyz)),\n"
"                                            gl_LightSource[7].ambient,\n"
"                                            gl_LightSource[7].diffuse,\n"
"                                            spec_value, shininess);\n"
"    }}}}}}}}\n"
"/*\n"
"    int i;\n"
"    for (i=0; i<light_count;i++){\n"
"      vec3 L = normalize(gl_LightSource[i].position.xyz);\n"
"      vec3 H = normalize(gl_LightSource[i].halfVector.xyz);\n"
"      float spec = 0., shine = 0.;\n"
"      if (i==0){\n"
"        spec = spec_value_0;\n"
"        shine = shininess_0;\n"
"      } else if (spec_count >= i){\n"
"        spec = spec_value;\n"
"        shine = shininess;\n"
"      }\n"
"      final_color += gl_LightSource[i].ambient * COLOR;\n"
"      NdotL = dot(N, L);\n"
"      if (NdotL > 0.0) {\n"
"        final_color += gl_LightSource[i].diffuse * NdotL * COLOR;\n"
"        NdotH = max(dot(N, H), 0.0);\n"
"        final_color += spec * pow(NdotH, shine);\n"
"      }\n"
"    }\n"
"*/\n"
"    float fog = clamp((gl_Fog.end + ipoint.z) * gl_Fog.scale, 0.0, 1.0);\n"
"    fog = mix(1.0, fog, fog_enabled);\n"
"    vec3 fog_color;\n"
"    if (bg_gradient){\n"
"      fog_color = mix(fog_color_bottom, fog_color_top, gl_FragCoord.y * inv_height);\n"
"    } else {\n"
"      fog_color = fog_color_top;\n"
"    }\n"
"    final_color.rgb = mix(fog_color, final_color.rgb, fog);\n"
"    vec4 f = vec4(final_color.rgb, COLOR.a);\n"
"  if(stereo_flag==-1)\n"
"    gl_FragColor = vec4(matL * pow(f.rgb,vec3(gamma,gamma,gamma)), f.a);\n"
"  else if (stereo_flag==0)\n"
"    gl_FragColor = f;\n"
"  else if (stereo_flag==1)\n"
"    gl_FragColor = vec4(matR * pow(f.rgb, vec3(gamma,gamma,gamma)), f.a);\n"
"}\n"
;
const char* spheredirect_vs =
"// Sphere impostor vertex shader\n"
"uniform bool lighting_enabled;\n"
"uniform float sphere_size_scale;\n"
"attribute vec4 sphere_attributes;\n"
"varying vec4 COLOR;\n"
"varying vec3 sphere_center;\n"
"varying float radius2;\n"
"varying vec3 point;\n"
"void main(void)\n"
"{\n"
"    // Get billboard attributes\n"
"    float right = sphere_attributes.x;\n"
"    float up = sphere_attributes.y;\n"
"    float radius = sphere_attributes.z * sphere_size_scale;\n"
"    COLOR = gl_Color;\n"
"    radius2 = radius * radius; // compute squared radius \n"
"    vec3 right_vector = vec3(gl_ModelViewMatrix[0][0],\n"
"            gl_ModelViewMatrix[1][0], gl_ModelViewMatrix[2][0]);\n"
"    vec3 up_vector = vec3(gl_ModelViewMatrix[0][1],\n"
"            gl_ModelViewMatrix[1][1], gl_ModelViewMatrix[2][1]);\n"
"    // We need to project the vertex out to the edge of the square, which\n"
"    // is the following distance:\n"
"    // float corner_distance = sqrt(2.0 * radius2);\n"
"    // but since we need to normalize the corner vector computed below\n"
"    // which has length sqrt(2.0), we can simply use radius as corner distance\n"
"    // to compute vertex position of screen-oriented quad.\n"
"    // Compute corner vector\n"
"    vec3 corner_direction =  up * up_vector + right * right_vector;\n"
"    // Calculate vertex of screen-oriented quad (billboard)\n"
"    vec4 vertex = vec4(gl_Vertex.xyz + radius * corner_direction, 1.);\n"
"    // Calculate vertex position in modelview space\n"
"    vec4 eye_space_pos = gl_ModelViewMatrix * vertex;\n"
"    // Compute sphere position in modelview space\n"
"    vec4 tmppos = gl_ModelViewMatrix * gl_Vertex;\n"
"    sphere_center = vec3(tmppos) / tmppos.w;\n"
"    // Compute ray direction and origin point\n"
"    point = vec3(eye_space_pos) / eye_space_pos.w;\n"
"    // Pass fog coordinate\n"
"    gl_FogFragCoord = abs(sphere_center.z); \n"
"    // Pass the transformed vertex for clipping plane calculations\n"
"    gl_ClipVertex = eye_space_pos;\n"
"    vec3 eye_pos = vec3(gl_ModelViewMatrix * gl_Vertex);\n"
"    // Pass transformed vertex\n"
"    gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vertex;\n"
"}\n"
;
const char* cylinder_vs =
"// cylinder imposter vertex shader\n"
"attribute vec4 attr_origin;\n"
"attribute vec4 attr_axis;\n"
"attribute vec4 attr_colors;\n"
"attribute vec4 attr_colors2;\n"
"uniform float uni_radius;\n"
"//varying vec3 point; // surface point\n"
"//varying vec3 axis; // cylinder axis\n"
"//varying vec3 base; // cylinder base\n"
"//varying vec3 end; // cylinder end\n"
"//varying vec3 U; // cylinder base plane coordinates\n"
"//varying vec3 V;\n"
"//varying float radius; // radius\n"
"//varying float cap; // should we draw the endcap\n"
"//varying float inv_sqr_height;\n"
"varying vec4 packed_data_0 ;\n"
"varying vec4 packed_data_1 ;\n"
"varying vec4 packed_data_2 ;\n"
"varying vec4 packed_data_3 ;\n"
"varying vec4 packed_data_4 ;\n"
"varying vec4 packed_data_5 ;\n"
"#define point ( packed_data_0.xyz )\n"
"#define axis ( packed_data_1.xyz )\n"
"#define base ( packed_data_2.xyz )\n"
"#define end ( packed_data_3.xyz )\n"
"#define U ( packed_data_4.xyz )\n"
"#define V ( packed_data_5.xyz )\n"
"#define radius (packed_data_3.w)\n"
"#define cap (packed_data_4.w)\n"
"#define inv_sqr_height (packed_data_5.w)\n"
"varying vec4 color1;\n"
"varying vec4 color2;\n"
"void main(void)\n"
"{\n"
"    if (uni_radius!=0.0){\n"
"        radius = uni_radius * attr_origin.w;\n"
"    } else {\n"
"        radius = attr_origin.w;\n"
"    }\n"
"    color1 = attr_colors;\n"
"    color2 = attr_colors2;\n"
"    float packed_flags = attr_axis.w;\n"
"    vec4 flags = mod(vec4(packed_flags/262144.0, packed_flags/4096.0, \n"
"                          packed_flags/64.0, packed_flags), 64.0);\n"
"    cap = flags.x;\n"
"    float right_v = flags.y;\n"
"    float up_v = flags.z;\n"
"    float out_v = flags.w;\n"
"    // calculate reciprocal of squared height\n"
"    inv_sqr_height = length(attr_axis.xyz);\n"
"    inv_sqr_height *= inv_sqr_height;\n"
"    inv_sqr_height = 1.0 / inv_sqr_height;\n"
"    // h is a normalized cylinder axis\n"
"    vec3 h = normalize(attr_axis.xyz);\n"
"    // axis is the cylinder axis in modelview coordinates\n"
"    axis =  normalize(gl_NormalMatrix * h);\n"
"    // u, v, h is local system of coordinates\n"
"    vec3 u = cross(h, vec3(1.0, 0.0, 0.0));\n"
"    if (dot(u,u) < 0.001) \n"
"      u = cross(h, vec3(0.0, 1.0, 0.0));\n"
"    u = normalize(u);\n"
"    vec3 v = normalize(cross(u, h));\n"
"    // transform to modelview coordinates\n"
"    U = normalize(gl_NormalMatrix * u);\n"
"    V = normalize(gl_NormalMatrix * v);\n"
"    \n"
"    // compute bounding box vertex position\n"
"    vec4 vertex = vec4(attr_origin.xyz, 1.0); \n"
"    vertex.xyz += up_v * attr_axis.xyz;\n"
"    vertex.xyz += (2.0 * right_v - 1.0) * radius * u;\n"
"    vertex.xyz += (2.0 * out_v - 1.0) * radius * v;\n"
"    vertex.xyz += (2.0 * up_v - 1.0) * radius * h;\n"
"    vec4 base4 = gl_ModelViewMatrix * vec4(attr_origin.xyz, 1.0);\n"
"    base = base4.xyz / base4.w;\n"
"    vec4 end4 = gl_ModelViewMatrix * vec4(attr_origin.xyz + 1.0 * attr_axis.xyz, 1.0);\n"
"    end = end4.xyz / end4.w;\n"
"    vec4 tvertex = gl_ModelViewMatrix * vertex;\n"
"    point = tvertex.xyz / tvertex.w;\n"
"    gl_Position = gl_ModelViewProjectionMatrix * vertex;\n"
"}\n"
;
const char* cylinder_fs =
"// cylinder imposter fragment shader\n"
"uniform bool lighting_enabled;\n"
"uniform float fog_enabled;\n"
"uniform bool bg_gradient;\n"
"uniform vec3 fog_color_top;\n"
"uniform vec3 fog_color_bottom;\n"
"uniform float inv_height;\n"
"uniform float ortho;\n"
"uniform float flat_caps;\n"
"uniform bool filter_front_facing;\n"
"uniform bool two_sided_lighting_enabled;\n"
"uniform int light_count;\n"
"uniform float shininess;\n"
"uniform float shininess_0;\n"
"uniform int spec_count;\n"
"uniform float spec_value;\n"
"uniform float spec_value_0;\n"
"uniform float half_bond;\n"
"uniform int stereo_flag;\n"
"uniform mat3 matR;\n"
"uniform mat3 matL;\n"
"uniform float gamma;\n"
"//varying vec3 point; // surface point\n"
"//varying vec3 axis; // cylinder axis\n"
"//varying vec3 base; // cylinder base\n"
"//varying vec3 end; // cylinder end\n"
"//varying vec3 U; // cylinder base plane coordinates\n"
"//varying vec3 V;\n"
"//varying float radius; // radius\n"
"//varying float cap; // should we draw the endcap\n"
"//varying float inv_sqr_height;\n"
"varying vec4 packed_data_0 ;\n"
"varying vec4 packed_data_1 ;\n"
"varying vec4 packed_data_2 ;\n"
"varying vec4 packed_data_3 ;\n"
"varying vec4 packed_data_4 ;\n"
"varying vec4 packed_data_5 ;\n"
"// point -> surface_point b/c preprocessor replaces _point\n"
"#define surface_point ( packed_data_0.xyz )\n"
"#define axis ( packed_data_1.xyz )\n"
"#define base ( packed_data_2.xyz )\n"
"// end -> end_cyl\n"
"#define end_cyl packed_data_3.xyz\n"
"#define U ( packed_data_4.xyz )\n"
"#define V ( packed_data_5.xyz )\n"
"#define radius ( packed_data_3.w )\n"
"#define cap ( packed_data_4.w )\n"
"#define inv_sqr_height ( packed_data_5.w )\n"
"varying vec4 color1;\n"
"varying vec4 color2;\n"
"vec4 ComputeColorForLight(vec3 N, vec3 L, vec3 H, vec4 ambient, vec4 diffuse, float spec, float shine, vec4 color){\n"
"  float NdotL, NdotH;\n"
"  vec4 ret_val = vec4(0.);\n"
"  ret_val += ambient * color;\n"
"  NdotL = dot(N, L);\n"
"  if (NdotL > 0.0) {\n"
"    ret_val += diffuse * NdotL * color;\n"
"    NdotH = max(dot(N, H), 0.0);\n"
"    ret_val += spec * pow(NdotH, shine);\n"
"  }\n"
"  return ret_val;\n"
"}\n"
"void main(void)\n"
"{\n"
"    // cull back face - otherwise we are drawing all pixels twice\n"
"    // this change gives roughly 2x speedup\n"
"    if (filter_front_facing && !gl_FrontFacing) \n"
"      discard; \n"
"    vec3 ray_target = surface_point;\n"
"    vec3 ray_origin = vec3(0.0);\n"
"    vec3 ray_direction = mix(normalize(ray_origin - ray_target), vec3(0.0, 0.0, 1.0), ortho);\n"
"    // basis is local system of coordinates for the cylinder\n"
"    mat3 basis = mat3(U, V, axis);\n"
"    vec3 diff = ray_target - 0.5 * (base + end_cyl);\n"
"    vec3 P = diff * basis;\n"
"    // angle (cos) between cylinder cylinder_axis and ray direction\n"
"    float dz = dot(axis, ray_direction);\n"
"    float radius2 = radius*radius;\n"
"    // calculate distance to the cylinder from ray origin\n"
"    vec3 D = vec3(dot(U, ray_direction),\n"
"                  dot(V, ray_direction),\n"
"                  dz);\n"
"    float a0 = P.x*P.x + P.y*P.y - radius2;\n"
"    float a1 = P.x*D.x + P.y*D.y;\n"
"    float a2 = D.x*D.x + D.y*D.y;\n"
"    // calculate a dicriminant of the above quadratic equation\n"
"    float d = a1*a1 - a0*a2;\n"
"    if (d < 0.0)\n"
"        // outside of the cylinder\n"
"        discard;\n"
"    float dist = (-a1 + sqrt(d))/a2;\n"
"    // point of intersection on cylinder surface\n"
"    vec3 new_point = ray_target + dist * ray_direction;\n"
"    vec3 tmp_point = new_point - base;\n"
"    vec3 normal = normalize(tmp_point - axis * dot(tmp_point, axis));\n"
"    float ratio = dot(new_point-base, vec3(end_cyl-base)) * inv_sqr_height;\n"
"    ray_origin = mix(ray_origin, surface_point, ortho);\n"
"    /* cap :  4 bits : 1st - frontcap\n"
"                       2nd - endcap\n"
"                       3rd - frontcap round\n"
"                       4th - endcap round\n"
"     */\n"
"    int icap = int(cap);\n"
"    vec4 color;\n"
"    if (icap > 15){\n"
"       float dp = clamp(-half_bond*new_point.z*inv_height, 0., .5);\n"
"       color = mix(color1, color2, smoothstep(.5 - dp, .5 + dp, ratio));\n"
"       icap = icap - 16;\n"
"    } else {\n"
"       color = mix(color1, color2, ratio);\n"
"    }\n"
"    float frontcap = 0.0, frontcapround = 0.0;\n"
"    float endcap = 0.0, endcapround = 0.0;\n"
"    if (icap == 1 || icap == 3 || icap == 5 || icap == 7 ||\n"
"        icap == 9 || icap == 11 || icap == 13 || icap == 15)\n"
"        frontcap = 1.0;\n"
"    if (icap == 2 || icap == 3 || icap == 6 || icap == 7 ||\n"
"        icap == 10 || icap == 11 || icap == 14 || icap == 15)\n"
"        endcap = 1.0;\n"
"    if (frontcap > 0.5 && flat_caps < 0.5 &&\n"
"        ((icap > 3 && icap < 8) ||\n"
"         icap > 11))\n"
"        frontcapround = 1.0;\n"
"    if (endcap > 0.5 && flat_caps < 0.5 && icap > 7)\n"
"        endcapround = 1.0;\n"
"    // test front cap\n"
"    float cap_test = dot((new_point - base), axis);\n"
"    // to calculate caps, simply check the angle between\n"
"    // the point of intersection - cylinder end vector\n"
"    // and a cap plane normal (which is the cylinder cylinder_axis)\n"
"    // if the angle < 0, the point is outside of cylinder\n"
"    // test front cap\n"
"    // flat\n"
"    if (frontcapround < 0.5 && cap_test < 0.0) {\n"
"      // ray-plane intersection\n"
"      color = color1;\n"
"      float dNV = dot(-axis, ray_direction);\n"
"      if (dNV < 0.0) discard;\n"
"      float near = dot(-axis, (base)) / dNV;\n"
"      new_point = ray_direction * near + ray_origin;\n"
"      // within the cap radius?\n"
"      if (dot(new_point - base, new_point-base) > radius2) discard;\n"
"      normal = -axis;\n"
"    }\n"
"    // round\n"
"    if (frontcapround > 0.5 && cap_test < 0.0) {\n"
"      if ( frontcap < 1.0)\n"
"        discard;\n"
"      color = color1;\n"
"      vec3 sphere_direction = mix(base, ray_origin - base, ortho);\n"
"      float b = dot(sphere_direction, ray_direction);\n"
"      float pos = b*b + radius2 -dot(sphere_direction, sphere_direction);\n"
"      if ( pos < 0.0)\n"
"        discard;\n"
"      float near = mix(b + sqrt(pos), sqrt(pos) - b, ortho);\n"
"      new_point = near * ray_direction + ray_origin;     \n"
"      normal = normalize( new_point - base ); \n"
"    }\n"
"    // test end cap\n"
"    cap_test = dot((new_point - end_cyl), axis);\n"
"    // flat\n"
"    if (endcapround < 0.5 && cap_test > 0.0) {\n"
"      // ray-plane intersection\n"
"      color = color1;\n"
"      float dNV = dot(axis, ray_direction);\n"
"      if (dNV < 0.0) discard;\n"
"      float near = dot(axis, end_cyl) / dNV;\n"
"      new_point = ray_direction * near + ray_origin;\n"
"      // within the cap radius?\n"
"      if (dot(new_point - end_cyl, new_point-base) > radius2) discard;\n"
"      normal = axis;\n"
"    }\n"
"    // round\n"
"    if (endcapround > 0.5 && cap_test > 0.0) {\n"
"      if ( endcap < 1.0)\n"
"        discard;\n"
"      color = color2;\n"
"      vec3 sphere_direction = mix(end_cyl, ray_origin - end_cyl, ortho);\n"
"      float b = dot(sphere_direction, ray_direction);\n"
"      float pos = b*b + radius2 -dot(sphere_direction, sphere_direction);\n"
"      if ( pos < 0.0)\n"
"        discard;\n"
"      float near = mix(b + sqrt(pos), sqrt(pos) - b, ortho);\n"
"      new_point = near * ray_direction + ray_origin;\n"
"      normal = normalize( new_point - end_cyl );\n"
"    }\n"
"    vec2 clipZW = new_point.z * gl_ProjectionMatrix[2].zw +\n"
"        gl_ProjectionMatrix[3].zw;\n"
"    float depth = 0.5 + 0.5 * clipZW.x / clipZW.y;\n"
"    // this is a workaround necessary for Mac\n"
"    // otherwise the modified fragment won't clip properly\n"
"    if (depth <= 0.0)\n"
"      discard;\n"
"    if (depth >= 1.0)\n"
"      discard;\n"
"    gl_FragDepth = depth;\n"
"  vec4 final_color;\n"
"  int i;\n"
"  float NdotL, NdotH;\n"
"  final_color = (gl_LightModel.ambient) * color;\n"
"  if (light_count>0){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[0].position)),\n"
"                                        normalize(vec3(gl_LightSource[0].halfVector.xyz)),\n"
"                                        gl_LightSource[0].ambient,\n"
"                                        gl_LightSource[0].diffuse,\n"
"                                        spec_value_0, shininess_0, color);\n"
"  if (light_count>1){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[1].position)),\n"
"                                        normalize(vec3(gl_LightSource[1].halfVector.xyz)),\n"
"                                        gl_LightSource[1].ambient,\n"
"                                        gl_LightSource[1].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>2){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[2].position)),\n"
"                                        normalize(vec3(gl_LightSource[2].halfVector.xyz)),\n"
"                                        gl_LightSource[2].ambient,\n"
"                                        gl_LightSource[2].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>3){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[3].position)),\n"
"                                        normalize(vec3(gl_LightSource[3].halfVector.xyz)),\n"
"                                        gl_LightSource[3].ambient,\n"
"                                        gl_LightSource[3].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>4){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[4].position)),\n"
"                                        normalize(vec3(gl_LightSource[4].halfVector.xyz)),\n"
"                                        gl_LightSource[4].ambient,\n"
"                                        gl_LightSource[4].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>5){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[5].position)),\n"
"                                        normalize(vec3(gl_LightSource[5].halfVector.xyz)),\n"
"                                        gl_LightSource[5].ambient,\n"
"                                        gl_LightSource[5].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>6){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[6].position)),\n"
"                                        normalize(vec3(gl_LightSource[6].halfVector.xyz)),\n"
"                                        gl_LightSource[6].ambient,\n"
"                                        gl_LightSource[6].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>7){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[7].position)),\n"
"                                        normalize(vec3(gl_LightSource[7].halfVector.xyz)),\n"
"                                        gl_LightSource[7].ambient,\n"
"                                        gl_LightSource[7].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  }}}}}}}}\n"
"/*\n"
"  for (i=0; i<light_count; i++){\n"
"    vec3 L = normalize(gl_LightSource[i].position.xyz);\n"
"    vec3 H = normalize(gl_LightSource[i].halfVector.xyz);\n"
"    float spec = 0., shine = 0.;\n"
"    if (i==0){\n"
"      spec = spec_value_0;\n"
"      shine = shininess_0;\n"
"    } else if (spec_count >= i){\n"
"      spec = spec_value;\n"
"      shine = shininess;\n"
"    }\n"
"    final_color += gl_LightSource[i].ambient * color;\n"
"    NdotL = dot(normal, L);\n"
"    if (NdotL > 0.0) {\n"
"      final_color += gl_LightSource[i].diffuse * NdotL * color;\n"
"      NdotH = max(dot(normal, H), 0.0);\n"
"      final_color += spec * pow(NdotH, shine);\n"
"    }\n"
"// I don't think we need two sided lighting for cylinders since we do not\n"
"   draw the insides of the cylinders \n"
"    if (two_sided_lighting_enabled){\n"
"      NdotL = dot(-normal, L);\n"
"      if (NdotL > 0.0) {\n"
"        final_color += gl_LightSource[i].diffuse * NdotL * color;\n"
"        NdotH = max(dot(-normal, H), 0.0);\n"
"        final_color += spec * pow(NdotH, shine);\n"
"      }\n"
"    }\n"
"//\n"
"  }\n"
"*/\n"
"  float fog = clamp((gl_Fog.end + new_point.z) * gl_Fog.scale, 0.0, 1.0);\n"
"  fog = mix(1.0, fog, fog_enabled);\n"
"    \n"
"  vec3 fog_color;\n"
"  if (bg_gradient){\n"
"    fog_color = mix(fog_color_bottom, fog_color_top, gl_FragCoord.y * inv_height);\n"
"  } else {\n"
"    fog_color = fog_color_top;\n"
"  }\n"
"  final_color.rgb = mix(fog_color, final_color.rgb, fog);\n"
"  vec4 f = vec4(final_color.rgb, color.a);\n"
"  if(stereo_flag==-1)\n"
"    gl_FragColor = vec4(matL * pow(f.rgb,vec3(gamma,gamma,gamma)), f.a);\n"
"  else if (stereo_flag==0)\n"
"    gl_FragColor = f;\n"
"  else if (stereo_flag==1)\n"
"    gl_FragColor = vec4(matR * pow(f.rgb, vec3(gamma,gamma,gamma)), f.a);\n"
"}\n"
;
const char* cylinder_no_ff_fs =
"// cylinder imposter fragment shader\n"
"uniform bool lighting_enabled;\n"
"uniform float fog_enabled;\n"
"uniform bool bg_gradient;\n"
"uniform vec3 fog_color_top;\n"
"uniform vec3 fog_color_bottom;\n"
"uniform float inv_height;\n"
"uniform float ortho;\n"
"uniform float flat_caps;\n"
"uniform bool filter_front_facing;\n"
"uniform bool two_sided_lighting_enabled;\n"
"uniform int light_count;\n"
"uniform float shininess;\n"
"uniform float shininess_0;\n"
"uniform int spec_count;\n"
"uniform float spec_value;\n"
"uniform float spec_value_0;\n"
"uniform float half_bond;\n"
"uniform int stereo_flag;\n"
"uniform mat3 matR;\n"
"uniform mat3 matL;\n"
"uniform float gamma;\n"
"//varying vec3 point; // surface point\n"
"//varying vec3 axis; // cylinder axis\n"
"//varying vec3 base; // cylinder base\n"
"//varying vec3 end; // cylinder end\n"
"//varying vec3 U; // cylinder base plane coordinates\n"
"//varying vec3 V;\n"
"//varying float radius; // radius\n"
"//varying float cap; // should we draw the endcap\n"
"//varying float inv_sqr_height;\n"
"varying vec4 packed_data_0 ;\n"
"varying vec4 packed_data_1 ;\n"
"varying vec4 packed_data_2 ;\n"
"varying vec4 packed_data_3 ;\n"
"varying vec4 packed_data_4 ;\n"
"varying vec4 packed_data_5 ;\n"
"// point -> surface_point b/c preprocessor replaces _point\n"
"#define surface_point ( packed_data_0.xyz )\n"
"#define axis ( packed_data_1.xyz )\n"
"#define base ( packed_data_2.xyz )\n"
"// end -> end_cyl\n"
"#define end_cyl packed_data_3.xyz\n"
"#define U ( packed_data_4.xyz )\n"
"#define V ( packed_data_5.xyz )\n"
"#define radius ( packed_data_3.w )\n"
"#define cap ( packed_data_4.w )\n"
"#define inv_sqr_height ( packed_data_5.w )\n"
"varying vec4 color1;\n"
"varying vec4 color2;\n"
"vec4 ComputeColorForLight(vec3 N, vec3 L, vec3 H, vec4 ambient, vec4 diffuse, float spec, float shine, vec4 color){\n"
"  float NdotL, NdotH;\n"
"  vec4 ret_val = vec4(0.);\n"
"  ret_val += ambient * color;\n"
"  NdotL = dot(N, L);\n"
"  if (NdotL > 0.0) {\n"
"    ret_val += diffuse * NdotL * color;\n"
"    NdotH = max(dot(N, H), 0.0);\n"
"    ret_val += spec * pow(NdotH, shine);\n"
"  }\n"
"  return ret_val;\n"
"}\n"
"void main(void)\n"
"{\n"
"    // cull back face - otherwise we are drawing all pixels twice\n"
"    // this change gives roughly 2x speedup\n"
"//    if (filter_front_facing && !gl_FrontFacing) \n"
"//      discard; \n"
"    vec3 ray_target = surface_point;\n"
"    vec3 ray_origin = vec3(0.0);\n"
"    vec3 ray_direction = mix(normalize(ray_origin - ray_target), vec3(0.0, 0.0, 1.0), ortho);\n"
"    // basis is local system of coordinates for the cylinder\n"
"    mat3 basis = mat3(U, V, axis);\n"
"    vec3 diff = ray_target - 0.5 * (base + end_cyl);\n"
"    vec3 P = diff * basis;\n"
"    // angle (cos) between cylinder cylinder_axis and ray direction\n"
"    float dz = dot(axis, ray_direction);\n"
"    float radius2 = radius*radius;\n"
"    // calculate distance to the cylinder from ray origin\n"
"    vec3 D = vec3(dot(U, ray_direction),\n"
"                  dot(V, ray_direction),\n"
"                  dz);\n"
"    float a0 = P.x*P.x + P.y*P.y - radius2;\n"
"    float a1 = P.x*D.x + P.y*D.y;\n"
"    float a2 = D.x*D.x + D.y*D.y;\n"
"    // calculate a dicriminant of the above quadratic equation\n"
"    float d = a1*a1 - a0*a2;\n"
"    if (d < 0.0)\n"
"        // outside of the cylinder\n"
"        discard;\n"
"    float dist = (-a1 + sqrt(d))/a2;\n"
"    // point of intersection on cylinder surface\n"
"    vec3 new_point = ray_target + dist * ray_direction;\n"
"    vec3 tmp_point = new_point - base;\n"
"    vec3 normal = normalize(tmp_point - axis * dot(tmp_point, axis));\n"
"    float ratio = dot(new_point-base, vec3(end_cyl-base)) * inv_sqr_height;\n"
"    ray_origin = mix(ray_origin, surface_point, ortho);\n"
"    /* cap :  4 bits : 1st - frontcap\n"
"                       2nd - endcap\n"
"                       3rd - frontcap round\n"
"                       4th - endcap round\n"
"     */\n"
"    int icap = int(cap);\n"
"    vec4 color;\n"
"    if (icap > 15){\n"
"       float dp = clamp(-half_bond*new_point.z*inv_height, 0., .5);\n"
"       color = mix(color1, color2, smoothstep(.5 - dp, .5 + dp, ratio));\n"
"       icap = icap - 16;\n"
"    } else {\n"
"       color = mix(color1, color2, ratio);\n"
"    }\n"
"    float frontcap = 0.0, frontcapround = 0.0;\n"
"    float endcap = 0.0, endcapround = 0.0;\n"
"    if (icap == 1 || icap == 3 || icap == 5 || icap == 7 ||\n"
"        icap == 9 || icap == 11 || icap == 13 || icap == 15)\n"
"        frontcap = 1.0;\n"
"    if (icap == 2 || icap == 3 || icap == 6 || icap == 7 ||\n"
"        icap == 10 || icap == 11 || icap == 14 || icap == 15)\n"
"        endcap = 1.0;\n"
"    if (frontcap > 0.5 && flat_caps < 0.5 &&\n"
"        ((icap > 3 && icap < 8) ||\n"
"         icap > 11))\n"
"        frontcapround = 1.0;\n"
"    if (endcap > 0.5 && flat_caps < 0.5 && icap > 7)\n"
"        endcapround = 1.0;\n"
"    // test front cap\n"
"    float cap_test = dot((new_point - base), axis);\n"
"    // to calculate caps, simply check the angle between\n"
"    // the point of intersection - cylinder end vector\n"
"    // and a cap plane normal (which is the cylinder cylinder_axis)\n"
"    // if the angle < 0, the point is outside of cylinder\n"
"    // test front cap\n"
"    // flat\n"
"    if (frontcapround < 0.5 && cap_test < 0.0) {\n"
"      // ray-plane intersection\n"
"      color = color1;\n"
"      float dNV = dot(-axis, ray_direction);\n"
"      if (dNV < 0.0) discard;\n"
"      float near = dot(-axis, (base)) / dNV;\n"
"      new_point = ray_direction * near + ray_origin;\n"
"      // within the cap radius?\n"
"      if (dot(new_point - base, new_point-base) > radius2) discard;\n"
"      normal = -axis;\n"
"    }\n"
"    // round\n"
"    if (frontcapround > 0.5 && cap_test < 0.0) {\n"
"      if ( frontcap < 1.0)\n"
"        discard;\n"
"      color = color1;\n"
"      vec3 sphere_direction = mix(base, ray_origin - base, ortho);\n"
"      float b = dot(sphere_direction, ray_direction);\n"
"      float pos = b*b + radius2 -dot(sphere_direction, sphere_direction);\n"
"      if ( pos < 0.0)\n"
"        discard;\n"
"      float near = mix(b + sqrt(pos), sqrt(pos) - b, ortho);\n"
"      new_point = near * ray_direction + ray_origin;     \n"
"      normal = normalize( new_point - base ); \n"
"    }\n"
"    // test end cap\n"
"    cap_test = dot((new_point - end_cyl), axis);\n"
"    // flat\n"
"    if (endcapround < 0.5 && cap_test > 0.0) {\n"
"      // ray-plane intersection\n"
"      color = color1;\n"
"      float dNV = dot(axis, ray_direction);\n"
"      if (dNV < 0.0) discard;\n"
"      float near = dot(axis, end_cyl) / dNV;\n"
"      new_point = ray_direction * near + ray_origin;\n"
"      // within the cap radius?\n"
"      if (dot(new_point - end_cyl, new_point-base) > radius2) discard;\n"
"      normal = axis;\n"
"    }\n"
"    // round\n"
"    if (endcapround > 0.5 && cap_test > 0.0) {\n"
"      if ( endcap < 1.0)\n"
"        discard;\n"
"      color = color2;\n"
"      vec3 sphere_direction = mix(end_cyl, ray_origin - end_cyl, ortho);\n"
"      float b = dot(sphere_direction, ray_direction);\n"
"      float pos = b*b + radius2 -dot(sphere_direction, sphere_direction);\n"
"      if ( pos < 0.0)\n"
"        discard;\n"
"      float near = mix(b + sqrt(pos), sqrt(pos) - b, ortho);\n"
"      new_point = near * ray_direction + ray_origin;\n"
"      normal = normalize( new_point - end_cyl );\n"
"    }\n"
"    vec2 clipZW = new_point.z * gl_ProjectionMatrix[2].zw +\n"
"        gl_ProjectionMatrix[3].zw;\n"
"    float depth = 0.5 + 0.5 * clipZW.x / clipZW.y;\n"
"    // this is a workaround necessary for Mac\n"
"    // otherwise the modified fragment won't clip properly\n"
"    if (depth <= 0.0)\n"
"      discard;\n"
"    if (depth >= 1.0)\n"
"      discard;\n"
"    gl_FragDepth = depth;\n"
"  vec4 final_color;\n"
"  int i;\n"
"  float NdotL, NdotH;\n"
"  final_color = (gl_LightModel.ambient) * color;\n"
"  if (light_count>0){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[0].position)),\n"
"                                        normalize(vec3(gl_LightSource[0].halfVector.xyz)),\n"
"                                        gl_LightSource[0].ambient,\n"
"                                        gl_LightSource[0].diffuse,\n"
"                                        spec_value_0, shininess_0, color);\n"
"  if (light_count>1){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[1].position)),\n"
"                                        normalize(vec3(gl_LightSource[1].halfVector.xyz)),\n"
"                                        gl_LightSource[1].ambient,\n"
"                                        gl_LightSource[1].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>2){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[2].position)),\n"
"                                        normalize(vec3(gl_LightSource[2].halfVector.xyz)),\n"
"                                        gl_LightSource[2].ambient,\n"
"                                        gl_LightSource[2].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>3){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[3].position)),\n"
"                                        normalize(vec3(gl_LightSource[3].halfVector.xyz)),\n"
"                                        gl_LightSource[3].ambient,\n"
"                                        gl_LightSource[3].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>4){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[4].position)),\n"
"                                        normalize(vec3(gl_LightSource[4].halfVector.xyz)),\n"
"                                        gl_LightSource[4].ambient,\n"
"                                        gl_LightSource[4].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>5){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[5].position)),\n"
"                                        normalize(vec3(gl_LightSource[5].halfVector.xyz)),\n"
"                                        gl_LightSource[5].ambient,\n"
"                                        gl_LightSource[5].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>6){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[6].position)),\n"
"                                        normalize(vec3(gl_LightSource[6].halfVector.xyz)),\n"
"                                        gl_LightSource[6].ambient,\n"
"                                        gl_LightSource[6].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  if (light_count>7){\n"
"    final_color += ComputeColorForLight(normal, normalize(vec3(gl_LightSource[7].position)),\n"
"                                        normalize(vec3(gl_LightSource[7].halfVector.xyz)),\n"
"                                        gl_LightSource[7].ambient,\n"
"                                        gl_LightSource[7].diffuse,\n"
"                                        spec_value, shininess, color);\n"
"  }}}}}}}}\n"
"/*\n"
"  for (i=0; i<light_count; i++){\n"
"    vec3 L = normalize(gl_LightSource[i].position.xyz);\n"
"    vec3 H = normalize(gl_LightSource[i].halfVector.xyz);\n"
"    float spec = 0., shine = 0.;\n"
"    if (i==0){\n"
"      spec = spec_value_0;\n"
"      shine = shininess_0;\n"
"    } else if (spec_count >= i){\n"
"      spec = spec_value;\n"
"      shine = shininess;\n"
"    }\n"
"    final_color += gl_LightSource[i].ambient * color;\n"
"    NdotL = dot(normal, L);\n"
"    if (NdotL > 0.0) {\n"
"      final_color += gl_LightSource[i].diffuse * NdotL * color;\n"
"      NdotH = max(dot(normal, H), 0.0);\n"
"      final_color += spec * pow(NdotH, shine);\n"
"    }\n"
"// I don't think we need two sided lighting for cylinders since we do not\n"
"   draw the insides of the cylinders \n"
"    if (two_sided_lighting_enabled){\n"
"      NdotL = dot(-normal, L);\n"
"      if (NdotL > 0.0) {\n"
"        final_color += gl_LightSource[i].diffuse * NdotL * color;\n"
"        NdotH = max(dot(-normal, H), 0.0);\n"
"        final_color += spec * pow(NdotH, shine);\n"
"      }\n"
"    }\n"
"//\n"
"  }\n"
"*/\n"
"  float fog = clamp((gl_Fog.end + new_point.z) * gl_Fog.scale, 0.0, 1.0);\n"
"  fog = mix(1.0, fog, fog_enabled);\n"
"    \n"
"  vec3 fog_color;\n"
"  if (bg_gradient){\n"
"    fog_color = mix(fog_color_bottom, fog_color_top, gl_FragCoord.y * inv_height);\n"
"  } else {\n"
"    fog_color = fog_color_top;\n"
"  }\n"
"  final_color.rgb = mix(fog_color, final_color.rgb, fog);\n"
"  vec4 f = vec4(final_color.rgb, color.a);\n"
"  if(stereo_flag==-1)\n"
"    gl_FragColor = vec4(matL * pow(f.rgb,vec3(gamma,gamma,gamma)), f.a);\n"
"  else if (stereo_flag==0)\n"
"    gl_FragColor = f;\n"
"  else if (stereo_flag==1)\n"
"    gl_FragColor = vec4(matR * pow(f.rgb, vec3(gamma,gamma,gamma)), f.a);\n"
"}\n"
;
const char* sphere_arb_vs =
"!!ARBvp1.0\n"
"# input contains the sphere radius in model coordinates\n"
"PARAM sphereRadius = program.env[0];\n"
"PARAM half = {0.5, 0.5, 0.0, 2.0 };\n"
"PARAM zero = {0.0, 0.0, 0.0, 1.0 };\n"
"ATTRIB vertexPosition  = vertex.position;\n"
"ATTRIB vertexNormal    = vertex.normal;\n"
"ATTRIB textureCoord    = vertex.texcoord;\n"
"OUTPUT outputPosition  = result.position;\n"
"TEMP   pos, rad, shf, txt, tip;\n"
"# Transform the vertex by the modelview matrix to get into the frame of the camera\n"
"DP4    pos.x, state.matrix.modelview.row[0], vertexPosition;\n"
"DP4    pos.y, state.matrix.modelview.row[1], vertexPosition;\n"
"DP4    pos.z, state.matrix.modelview.row[2], vertexPosition;\n"
"DP4    pos.w, state.matrix.modelview.row[3], vertexPosition;\n"
"# copy current texture coords\n"
"MOV    txt.xyzw, textureCoord.xyzw;\n"
"# scale the radius by a factor of two\n"
"MUL    rad.xy, 2.0, sphereRadius.z;\n"
"# shift the texture coordinates to the origin\n"
"SUB    shf.xy, textureCoord, {0.5, 0.5, 0.0, 0.0};\n"
"# multiply them to get the vertex offset\n"
"MUL    shf.xy, rad, shf;\n"
"# define the new vertex for corner of sphere\n"
"ADD    pos.xy, pos, shf;\n"
"# apply the projection matrix to get clip coordinates \n"
"DP4    outputPosition.x, state.matrix.projection.row[0], pos;\n"
"DP4    outputPosition.y, state.matrix.projection.row[1], pos;\n"
"DP4    shf.z, state.matrix.projection.row[2], pos;\n"
"DP4    shf.w, state.matrix.projection.row[3], pos;\n"
"MOV    outputPosition.zw, shf;\n"
"# compute camera position for front tip of the sphere\n"
"ADD    pos.z, pos.z, sphereRadius;\n"
"# compute Zc and Wc for front tip of the sphere\n"
"DP4    tip.z, state.matrix.projection.row[2], pos;\n"
"DP4    tip.w, state.matrix.projection.row[3], pos;\n"
"# compute 1/Wc for sphere tip \n"
"RCP    rad.z, tip.w;\n"
"# put sphere center Zc into tip.w \n"
"MOV    tip.w, shf.z;\n"
"# compute 1/Wc for sphere center \n"
"RCP    rad.w, shf.w;\n"
"# compute Z/Wc for both sphere tip (->txt.z) and center (->txt.w) \n"
"MUL    txt.zw, tip, rad;\n"
"# move into range 0.0-1.0 to get the normalized depth coordinate (0.5*(Zc/Wc)+0.5) \n"
"ADD    txt.zw, {0.0,0.0,1.0,1.0}, txt;\n"
"MUL    txt.zw, {0.0,0.0,0.5,0.5}, txt;\n"
"# Pass the color through\n"
"MOV    result.color, vertex.color;\n"
"# Pass texture through\n"
"MOV    result.texcoord, txt;\n"
"END\n"
;
const char* sphere_arb_fs =
"!!ARBfp1.0\n"
"PARAM fogInfo = program.env[0];\n"
"PARAM fogColor = state.fog.color;\n"
"ATTRIB fogCoord = fragment.fogcoord;\n"
"TEMP pln, norm, depth, color, light, spec, fogFactor;\n"
"# fully clip spheres that hit the camera\n"
"KIL fragment.texcoord.z;\n"
"# move texture coordinates to origin\n"
"MOV norm.z, 0;\n"
"SUB norm.xy, fragment.texcoord, {0.5,0.5,0.0,0.0};\n"
"# compute x^2 + y^2, if > 0.25 then kill the pixel -- not in sphere\n"
"# kill pixels that aren't in the center circle\n"
"DP3 pln.z, norm, norm;\n"
"SUB pln.z, 0.25, pln.z;\n"
"KIL pln.z;\n"
"# build a complete unit normal\n"
"MUL pln.z, 4.0, pln.z;\n"
"RSQ pln.z, pln.z;\n"
"MUL norm.xy, 2.0, norm;\n"
"RCP norm.z, pln.z;\n"
"# interpolate the Zndc coordinate on the sphere \n"
"LRP depth.z, norm.z, fragment.texcoord.z, fragment.texcoord.w;\n"
"MOV result.depth.z, depth.z;\n"
"# light0\n"
"DP3 light, state.light[1].half, norm;\n"
"MOV light.w, 60.0;\n"
"LIT light, light;\n"
"# ambient\n"
"MOV color.xyzw, {0.06,0.06,0.06,1.0};\n"
"ADD color.xyz, light.y, 0.1;\n"
"MUL color.xyz, fragment.color, color;\n"
"MUL spec.xyz, light.z, 0.5;\n"
"ADD color.xyz, color,spec;\n"
"# apply fog using linear interp over Zndc\n"
"MAX fogFactor.x, depth.z, fogInfo.x;\n"
"SUB fogFactor.x, fogFactor.x, fogInfo.x;\n"
"MUL fogFactor.x, fogFactor.x, fogInfo.y;\n"
"LRP color.xyz, fogFactor.x, fogColor, color;\n"
"MOV result.color, color;\n"
"END\n"
;
#endif
