+// Convert RGB to grayscale, using Rec. 709 coefficients.
+class GrayscaleConversion {
+public:
+ GrayscaleConversion();
+ void exec(GLint tex, GLint gray_tex, int width, int height);
+
+private:
+ PersistentFBOSet<1> fbos;
+ GLuint gray_vs_obj;
+ GLuint gray_fs_obj;
+ GLuint gray_program;
+ GLuint gray_vao;
+
+ GLuint uniform_tex;
+};
+
+GrayscaleConversion::GrayscaleConversion()
+{
+ gray_vs_obj = compile_shader(read_file("vs.vert"), GL_VERTEX_SHADER);
+ gray_fs_obj = compile_shader(read_file("gray.frag"), GL_FRAGMENT_SHADER);
+ gray_program = link_program(gray_vs_obj, gray_fs_obj);
+
+ // Set up the VAO containing all the required position/texcoord data.
+ glCreateVertexArrays(1, &gray_vao);
+ glBindVertexArray(gray_vao);
+
+ GLint position_attrib = glGetAttribLocation(gray_program, "position");
+ glEnableVertexArrayAttrib(gray_vao, position_attrib);
+ glVertexAttribPointer(position_attrib, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+
+ uniform_tex = glGetUniformLocation(gray_program, "tex");
+}
+
+void GrayscaleConversion::exec(GLint tex, GLint gray_tex, int width, int height)
+{
+ glUseProgram(gray_program);
+ bind_sampler(gray_program, uniform_tex, 0, tex, nearest_sampler);
+
+ glViewport(0, 0, width, height);
+ fbos.render_to(gray_tex);
+ glBindVertexArray(gray_vao);
+ glUseProgram(gray_program);
+ glDisable(GL_BLEND);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+}
+