String8 ProgramCache::generateFragmentShader(const Key& needs) { Formatter fs; if (needs.getTextureTarget() == Key::TEXTURE_EXT) { fs << "#extension GL_OES_EGL_image_external : require"; } // default precision is required-ish in fragment shaders fs << "precision mediump float;"; if (needs.getTextureTarget() == Key::TEXTURE_EXT) { fs << "uniform samplerExternalOES sampler;" << "varying vec2 outTexCoords;"; } else if (needs.getTextureTarget() == Key::TEXTURE_2D) { fs << "uniform sampler2D sampler;" << "varying vec2 outTexCoords;"; } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) { fs << "uniform vec4 color;"; } if (needs.hasPlaneAlpha()) { fs << "uniform float alphaPlane;"; } if (needs.hasColorMatrix()) { fs << "uniform mat4 colorMatrix;"; } fs << "void main(void) {" << indent; if (needs.isTexturing()) { fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; } else { fs << "gl_FragColor = color;"; } if (needs.isOpaque()) { fs << "gl_FragColor.a = 1.0;"; } if (needs.hasPlaneAlpha()) { // modulate the alpha value with planeAlpha if (needs.isPremultiplied()) { // ... and the color too if we're premultiplied fs << "gl_FragColor *= alphaPlane;"; } else { fs << "gl_FragColor.a *= alphaPlane;"; } } if (needs.hasColorMatrix()) { if (!needs.isOpaque() && needs.isPremultiplied()) { // un-premultiply if needed before linearization fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;"; } fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(2.2));"; fs << "gl_FragColor = colorMatrix*gl_FragColor;"; fs << "gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2));"; if (!needs.isOpaque() && needs.isPremultiplied()) { // and re-premultiply if needed after gamma correction fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;"; } } fs << dedent << "}"; return fs.getString(); }
String8 ProgramCache::generateVertexShader(const Key& needs) { Formatter vs; if (needs.isTexturing()) { vs << "attribute vec4 texCoords;" << "varying vec2 outTexCoords;"; } vs << "attribute vec4 position;" << "uniform mat4 projection;" << "uniform mat4 texture;" << "void main(void) {" << indent << "gl_Position = projection * position;"; if (needs.isTexturing()) { vs << "outTexCoords = (texture * texCoords).st;"; } vs << dedent << "}"; return vs.getString(); }