const char *sphere_ao_render_vs =
  "//\n"
  "// Input\n"
  "//\n"
  "#version 400\n"
  "precision highp float;\n"
  "// sphere position: model coordinates\n"
  "in vec3 a_pos;\n"
  "// sphere corner: [-r, -r], [r, -r], [r, r], [-r, r]\n"
  "in vec2 a_corner;\n"
  "// offset for the center of the sphere's AO map texture tile\n"
  "in vec2 a_tileOffset;\n"
  "// color: RGB\n"
  "in vec3 a_color;\n"
  "\n"
  "//\n"
  "// Output\n"
  "//\n"
  "\n"
  "// normalized corner\n"
  "out vec2 v_corner;\n"
  "// color\n"
  "out vec3 v_color;\n"
  "// position in eye-coordinate space\n"
  "out vec4 v_eyePos;\n"
  "// sphere radius\n"
  "out float v_radius;\n"
  "// AO tile offset\n"
  "out vec2 v_tileOffset;\n"
  "\n"
  "//\n"
  "// Uniforms\n"
  "//\n"
  "\n"
  "// model-view matrix\n"
  "uniform mat4 u_modelView;\n"
  "// projection matrix\n"
  "uniform mat4 u_projection;\n"
  "\n"
  "#define CONTOUR_LINES\n"
  "#ifdef CONTOUR_LINES\n"
  "const float contourWidth = 0.3;\n"
  "#endif\n"
  "\n"
  "\n"
  "void main()\n"
  "{\n"
  "  // pass through AO tile offset & color\n"
  "  v_tileOffset = a_tileOffset;\n"
  "  v_color = a_color;\n"
  "  // extract radius from unnormalized corner attribute\n"
  "  v_radius = abs(a_corner.x);\n"
  "  // normalize corner to be in [-1, 1] range\n"
  "#ifdef CONTOUR_LINES\n"
  "  v_corner = a_corner / v_radius + sign(a_corner) * vec2(contourWidth, contourWidth);\n"
  "#else\n"
  "  v_corner = a_corner / v_radius;\n"
  "#endif\n"
  "  // compute eye-coordinate sphere position\n"
  "  v_eyePos = u_modelView * vec4(a_pos, 1.0);\n"
  "\n"
  "  // test if the closest point on the sphere would be clipped\n"
  "  vec4 clipTestNear = v_eyePos;\n"
  "  // z-axis points to eye (camera), add radius to sphere position\n"
  "  clipTestNear.z += v_radius;\n"
  "  // project the eye-coordinate sphere position\n"
  "  clipTestNear = u_projection * clipTestNear;\n"
  "  if (clipTestNear.z > -clipTestNear.w) {\n"
  "    // not clipped, calculate clip coordinate\n"
  "    gl_Position = v_eyePos;\n"
  "#ifdef CONTOUR_LINES\n"
  "    gl_Position.xy += a_corner + sign(a_corner) * vec2(contourWidth, contourWidth);\n"
  "    //gl_Position.xy += a_corner;\n"
  "#else\n"
  "    gl_Position.xy += a_corner;\n"
  "#endif\n"
  "    gl_Position = u_projection * gl_Position;\n"
  "  } else {\n"
  "    // clipped, invalidate the clip coordinate to ensure that it will be clipped\n"
  "    gl_Position.w = 0.0;\n"
  "  }\n"
  "}\n"
  "\n";
