title: sRGB on iOS OpenGL ES 2.0
body: <p>According to very <a href="https://stackoverflow.com/a/14493502/340947">few related topics that I could find</a> I am gathering that the exponentiation step to obtain proper lighting computations perhaps must be done within the final fragment shader on an iOS app. </p>
  
  <p>I have been profiling with the latest and greatest Xcode 5 OpenGL debugger and the exponentiation of the fragment accounts for a significant amount of computation. It was the line that took the longest time in the entire shader (the rest of the performance got sucked out by the various <code>norm</code> calls needed for point-lights). </p>
  
  <p><code>glEnable(GL_FRAMEBUFFER_SRGB);</code> unfortunately does not work as <code>GL_FRAMEBUFFER_SRGB</code> is not declared. </p>
  
  <p>Of course the actual enum I should be using for GL ES may be different. </p>
  
  <p>According to <a href="https://developer.apple.com/library/ios/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/OpenGLESPlatforms/OpenGLESPlatforms.html" rel="nofollow noreferrer">Apple</a>: </p>
  
  <blockquote>
    <p>The following extensions are supported for the SGX 543 and 554
    processors only:</p>
    
    <p>EXT_color_buffer_half_float<br>
    EXT_occlusion_query_boolean<br>
    EXT_pvrtc_sRGB<br>
    EXT_shadow_samplers<br>
    EXT_sRGB<br>
    EXT_texture_rg<br>
    OES_texture_half_float_linear</p>
  </blockquote>
  
  <p>Well, that's nice, the newest device that does not have a 543 or 554 is the iPhone 4.</p>
  
  <p>From <a href="http://www.khronos.org/registry/gles/extensions/EXT/EXT_sRGB.txt" rel="nofollow noreferrer">the extension's text file</a> it looks like I can set <code>SRGB8_ALPHA8_EXT</code> to the <code>internalformat</code> parameter of <code>RenderbufferStorage</code>, but nothing is said of how to get the normal final framebuffer to apply sRGB for us for free. </p>
  
  <p>Now the sRGB correction seems like the missing step to get the correct colors. What I've been doing in my app to deal with the horrible "underexposed" colors is manually applying gamma correction like this in the fragment shader: </p>
  
  <pre><code>mediump float gammaf = 1.0/1.8; // this line declared outside of `main()`
  // it specifies a constant 1.8 gamma
  mediump vec4 gamma = vec4(gammaf, gammaf, gammaf, 1.0);
  gl_FragColor = pow(color, gamma); // last line of `main()`
  </code></pre>
  
  <p>Now I recognize that the typical render pipeline involves one or more renders to a texture followed by a FS quad draw, which will afford me the opportunity to make use of an <code>SRGB8_ALPHA_EXT</code> renderbuffer, but what am I supposed to do without one? Am I SOL? </p>
  
  <p>If that is the case, the <code>pow</code> call is sucking up so much time that it almost seems like I can squeeze some more perf out of it by building a 1D texture to sample and use as a gamma lookup table. This texture could then be used to tweak the output color intensities in custom ways (and get a much better approximation to sRGB compared to just the raw exponentiation). But it just all seems kind of wrong because supposedly sRGB is free.</p>
  
  <p>Also somewhat alarming is the absence of any mention of the string <code>srgb</code> anywhere in the GL ES 2.0 spec. <a href="http://www.g-truc.net/post-0263.html" rel="nofollow noreferrer">According to the makers of <code>glm</code></a> GL ES simply ignores sRGB entirely.</p>
  
  <p>I know that I have used my code to render textures (I made a basic OpenGL powered image viewer that renders PVRTC textures) and they did not get "dimmed". I think what is happening there is that due to GL ES 2's lack of sRGB awareness, the textures are loaded in as being in linear space and written back out in the same way. In that situation, since no lighting gets applied (all colors got multiplied by <code>1.0</code>) nothing bad happened to the results.</p>