Render to texture
<p>I've been pulling hairs for quite some time now getting render to texture functionality getting to work using c &amp; opengl. I'm using glfw3 and a subset of opengl es2 (so later i can compile this program using emscripten to webgl). I havent gotten to the emscripten part yet, because when i run this program "native" it just only shows the color of the main opengl buffer i clear (and not the texture i attached to the fbo).</p>

<p>I've gone through all tutorials and stackoverflow questions i could find on this subject (opengl es / webgl), some of the more comprehensive tutorials / questions i referred to where:</p>

<pre><code>http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/
https://open.gl/framebuffers
http://in2gpu.com/2014/09/24/render-to-texture-in-opengl/
http://stackoverflow.com/questions/8439697/opengl-es-2-0-render-to-texture
http://stackoverflow.com/questions/9629763/opengl-render-to-texture-via-fbo-incorrect-display-vs-normal-texture/9630654#9630654
http://www.gamedev.net/topic/660287-fbo-render-to-texture-not-working/
</code></pre>

<p>I think i followed all the steps and suggestions they offer..</p>

<p>The relevant function for my fbo setup is:</p>

<pre><code>// generate a FBO to draw in
glGenFramebuffers(1, &amp;fbo);

// The actual texture to attach to the fbo which we're going to render to
glGenTextures(1, &amp;texture);

// make our fbo active
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, texture);

// Create an empty 512x512 texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

// Set "texture" as our colour attachement #0
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

// Set the list of draw buffers.
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers

// Always check that our framebuffer is ok
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
    error_callback(-1, "Cannot initialize framebuffer");
}

// Render to the texture (should show up as a blue square)
glViewport(0, 0, 512, 512);
glClearColor(0, 0, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);

// unbind textures and buffers
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// upload quad data
glGenBuffers(1, &amp;vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
</code></pre>

<p>The relevant piece of code for drawing my fbo is:</p>

<pre><code>glBindFramebuffer(GL_FRAMEBUFFER, 0);

glViewport(0, 0, 1024, 768);
glClearColor(1.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(u_texture, 0);

// Bind buffer with quad data for vertex shader
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(a_position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), BUFFER_OFFSET(0));
glEnableVertexAttribArray(a_position);

glDrawArrays(GL_TRIANGLES, 0, 6);

glActiveTexture(0);
glBindTexture(GL_TEXTURE_2D, 0);
</code></pre>

<p>And here is the full code for a minimal self contained version that i'm using:</p>

<pre><code>#include &lt;GL/glew.h&gt;
#include &lt;GLFW/glfw3.h&gt;

// include some standard libraries
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

// include support libraries including their implementation
#define SHADER_IMPLEMENTATION
#include "shaders.h"

#define BUFFER_OFFSET(i) ((void*)(i))

char *VERTEX_SHADER_SRC = 
  "#version 100\n"
  "attribute vec4 a_position;\n"
  "varying vec2 v_uvcoord;\n"
  "void main() {\n"
  "  gl_Position = a_position;\n"
  "  v_uvcoord = (a_position.xy + 0.5) * 2;\n"
  "}\n";


char *FRAGMENT_SHADER_SRC = 
  "#version 100\n"
  "precision mediump float;\n"
  "varying vec2 v_uvcoord;\n"
  "uniform sampler2D u_texture;\n"
  "void main() {\n"
  "   gl_FragColor = texture2D(u_texture, v_uvcoord);\n"
  "   //test: gl_FragColor = vec4(0,0,1,1);\n"
  "}\n";

GLuint shader_program = NO_SHADER;
GLFWwindow* window;

// Shader attributes
GLuint a_position = -1;
GLuint u_texture = -1;

// FBO
GLuint fbo = 0;
// Target texture
GLuint texture;
// The fullscreen quad's VBO
GLuint vbo;

// The NDC quad vertices
static const GLfloat quad_data[] = {
  -0.5f, -0.5f, 0.0f, 0.0f,
   0.5f, -0.5f, 0.0f, 0.0f,
  -0.5f,  0.5f, 0.0f, 0.0f,
  -0.5f,  0.5f, 0.0f, 0.0f,
   0.5f, -0.5f, 0.0f, 0.0f,
   0.5f,  0.5f, 0.0f, 0.0f,
};


// function for logging errors
void error_callback(int error, const char* description) {
  // output to stderr
  fprintf(stderr, "%i: %s\n", error, description);
};


void load_shaders() {
    GLuint vertexShader = NO_SHADER, fragmentShader = NO_SHADER;

    shaderSetErrorCallback(error_callback);

    vertexShader = shaderCompile(GL_VERTEX_SHADER, VERTEX_SHADER_SRC);
    fragmentShader = shaderCompile(GL_FRAGMENT_SHADER, FRAGMENT_SHADER_SRC);
    shader_program = shaderLink(2, vertexShader, fragmentShader);
    glDeleteShader(fragmentShader);
    glDeleteShader(vertexShader);

    a_position = glGetAttribLocation(shader_program, "a_position");
    u_texture = glGetUniformLocation(shader_program, "u_texture");
};


void load_objects() {

    // generate a FBO to draw in
    glGenFramebuffers(1, &amp;fbo);

    // The actual texture to attach to the fbo which we're going to render to
    glGenTextures(1, &amp;texture);

    // make our fbo active
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    // "Bind" the newly created texture : all future texture functions will modify this texture
    glBindTexture(GL_TEXTURE_2D, texture);

    // Create an empty 512x512 texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // Set "texture" as our colour attachement #0
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

    // Set the list of draw buffers.
    GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
    glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers

    // Always check that our framebuffer is ok
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        error_callback(-1, "Cannot initialize framebuffer");
    }

    // Render to the texture (should show up as a blue square)
    glViewport(0, 0, 512, 512);
    glClearColor(0, 0, 1, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    // unbind textures and buffers
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // upload quad data
    glGenBuffers(1, &amp;vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
};


void draw_objects() {

glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glViewport(0, 0, 1024, 768);
    glClearColor(1.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glUniform1i(u_texture, 0);

    // Bind buffer with quad data for vertex shader
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer(a_position, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), BUFFER_OFFSET(0));
    glEnableVertexAttribArray(a_position);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glActiveTexture(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}


static void do_render() {
    glUseProgram(shader_program);      
    draw_objects();
    glUseProgram(0);

    // swap our buffers around so the user sees our new frame
    glfwSwapBuffers(window);
    glfwPollEvents();
}


void unload_objects() {
    glActiveTexture(0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glDeleteTextures(1, &amp;texture);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glDeleteFramebuffers(1, &amp;fbo);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glDeleteBuffers(1, &amp;vbo);
};


void unload_shaders() {
  if (shader_program != NO_SHADER) {
    glDeleteProgram(shader_program);
    shader_program = NO_SHADER;
  };
};


static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
  if (key == GLFW_KEY_ESCAPE &amp;&amp; action == GLFW_PRESS)
    glfwSetWindowShouldClose(window, GL_TRUE);
};


int main(void) {

  // tell GLFW how to inform us of issues
  glfwSetErrorCallback(error_callback);

  // see if we can initialize GLFW
  if (!glfwInit()) {
    exit(EXIT_FAILURE);    
  };

  // create our window
  window = glfwCreateWindow(1024, 768, "Hello GL", NULL, NULL);
  if (window) {
    GLenum err;

    // make our context current
    glfwMakeContextCurrent(window);

    // init GLEW
    glewExperimental=1;
    err = glewInit();
    if (err != GLEW_OK) {
      error_callback(err, glewGetErrorString(err)); 
         exit(EXIT_FAILURE); 
    };

    // tell GLFW how to inform us of keyboard input
    glfwSetKeyCallback(window, key_callback);

    // load, compile and link our shader(s)
    load_shaders();

    // load our objects
    load_objects();

    //emscripten_set_main_loop(do_render, 0, 1);
    while (!glfwWindowShouldClose(window)) {
     do_render();
    };

    // close our window
    glfwDestroyWindow(window);  
  };

  // lets be nice and cleanup
  unload_objects();
  unload_shaders();

  // the end....
  glfwTerminate();
};
</code></pre>

<p>And for reference the shader lib used:</p>

<pre><code>/********************************************************
 * shaders.h - shader library by Bastiaan Olij 2015
 * 
 * Public domain, use as you say fit, disect, change,
 * or otherwise, all at your own risk
 *
 * This library is given as a single file implementation.
 * Include this in any file that requires it but in one
 * file, and one file only, proceed it with:
 * #define SHADER_IMPLEMENTATION
 *
 * Note that OpenGL headers need to be included before 
 * this file is included as it uses several of its 
 * functions.
 *
 * This library does not contain any logic to load
 * shaders from disk.
 *
 * Revision history:
 * 0.1  09-03-2015  First version with basic functions
 *
 ********************************************************/

#ifndef shadersh
#define shadersh

// standard libraries we need...
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdarg.h&gt;

// and handy defines
#define NO_SHADER 0xFFFFFFFF

enum shaderErrors {
  SHADER_ERR_UNKNOWN = -1,
  SHADER_ERR_NOCOMPILE = -2,
  SHADER_ERR_NOLINK = -3
};

#ifdef __cplusplus
extern "C" {
#endif

typedef void(* ShaderError)(int, const char*);

void shaderSetErrorCallback(ShaderError pCallback);
GLuint shaderCompile(GLenum pShaderType, const GLchar* pShaderText);
GLuint shaderLink(GLuint pNumShaders, ...);

#ifdef __cplusplus
};
#endif  

#ifdef SHADER_IMPLEMENTATION

ShaderError shaderErrCallback = NULL;

// sets our error callback method which is modelled after 
// GLFWs error handler so you can use the same one
void shaderSetErrorCallback(ShaderError pCallback) {
  shaderErrCallback = pCallback;
};

// Compiles the text in pShaderText and returns a shader object
// pShaderType defines what type of shader we are compiling
// i.e. GL_VERTEX_SHADER
// On failure returns NO_SHADER
// On success returns a shader ID that can be used to link our program. 
// Note that you must discard the shader ID with glDeleteShader
// You can do this after a program has been successfully compiled
GLuint shaderCompile(GLenum pShaderType, const GLchar * pShaderText) {
    GLint compiled = 0;
  GLuint shader;
    const GLchar *stringptrs[1];

    // create our shader
    shader = glCreateShader(pShaderType);

    // compile our shader
    stringptrs[0] = pShaderText;
    glShaderSource(shader, 1, stringptrs, NULL);
    glCompileShader(shader);

    // check our status
    glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;compiled);
    if (!compiled) { 
        GLint len = 0;
        char type[50];

        switch (pShaderType) {
            case GL_VERTEX_SHADER: {
                strcpy(type, "vertex");
            } break;
            case GL_TESS_CONTROL_SHADER: {
                strcpy(type, "tessellation control");
            } break;
            case GL_TESS_EVALUATION_SHADER: {
                strcpy(type, "tessellation evaluation");
            } break;
            case GL_GEOMETRY_SHADER: {
                strcpy(type, "geometry");
            } break;
            case GL_FRAGMENT_SHADER: {
                strcpy(type, "fragment");
            } break;
            default: {
                strcpy(type, "unknown");
            } break;
        };

        glGetShaderiv(shader, GL_INFO_LOG_LENGTH , &amp;len); 
        if ((len &gt; 1) &amp;&amp; (shaderErrCallback != NULL)) {
            GLchar* compiler_log;

      // allocate enough space for our prefix and error
      compiler_log = (GLchar*) malloc(len+50);

      // write out our prefix first
      sprintf(compiler_log, "Error compiling %s shader: ", type);

      // append our error
            glGetShaderInfoLog(shader, len, 0, &amp;compiler_log[strlen(compiler_log)]);

      // and inform our calling logic
      shaderErrCallback(SHADER_ERR_NOCOMPILE, compiler_log);

      free(compiler_log);
    } else if (shaderErrCallback != NULL) {
      char error[250];
      sprintf(error,"Unknown error compiling %s shader", type);
      shaderErrCallback(SHADER_ERR_UNKNOWN, error);
    };

    glDeleteShader(shader);
    shader = NO_SHADER;
  };

  return shader;
};

// Links any number of programs into a shader program
// To compile and link a shader:
// ----
// GLuint vertexShader, fragmentShader, shaderProgram;
// vertexShader = shaderCompile(GL_VERTEX_SHADER, vsText);
// fragmentShader = shaderCompile(GL_FRAGMENT_SHADER, vsText);
// shaderProgram = shaderLink(2, vertexShader, fragmentShader);
// glDeleteShader(vertexShader);
// glDeleteShader(fragmentShader);
// ----
// Returns NO_SHADER on failure
// Returns program ID on success
// You must call glDeleteProgram to cleanup the program after you are done.
GLuint shaderLink(GLuint pNumShaders, ...) {
  GLuint program;
  va_list shaders;
  int s;

  // create our shader program...
  program = glCreateProgram();

  // now add our compiled code...
  va_start(shaders, pNumShaders);

  for (s = 0; s &lt; pNumShaders &amp;&amp; program != NO_SHADER; s++) {
    GLuint shader = va_arg(shaders, GLuint);

    if (shader == NO_SHADER) {
      // assume we've set our error when the shader failed to compile...
      glDeleteProgram(program);
      program = NO_SHADER;
    } else {
      glAttachShader(program, shader);
    };
  };

  va_end(shaders);

  // and try and link our program
  if (program != NO_SHADER) {
    GLint   linked = 0;

    glLinkProgram(program);

    // and check whether it all went OK..
    glGetProgramiv(program, GL_LINK_STATUS, &amp;linked);       
    if (!linked) {
        GLint len = 0;

        glGetProgramiv(program, GL_INFO_LOG_LENGTH , &amp;len); 
        if ((len &gt; 1) &amp;&amp; (shaderErrCallback != NULL)) {
            GLchar* compiler_log;

        // allocate enough space for our prefix and error
        compiler_log = (GLchar*) malloc(len+50);

        // write out our prefix first
        strcpy(compiler_log, "Error linking shader program: ");

        // append our error
            glGetProgramInfoLog(program, len, 0, &amp;compiler_log[strlen(compiler_log)]);

        // and inform our calling logic
        shaderErrCallback(SHADER_ERR_NOLINK, compiler_log);

            free(compiler_log);
      } else if (shaderErrCallback != NULL) {
        char error[250];
        strcpy(error,"Unknown error linking shader program");
        shaderErrCallback(SHADER_ERR_UNKNOWN, error);
        };

        glDeleteProgram(program);
        program = NO_SHADER;
    };    
  };

  return program;
};


#endif

#endif
</code></pre>

<p>When i compile this using:
    cc <code>pkg-config --cflags glfw3</code> -o rtt rtt.c <code>pkg-config --static --libs glfw3 glew</code></p>

<p>I just get an red screen (the main framebuffer i clear), but i expect a blue rectangle to appear in the middle of the screen (the texture which i cleared to blue before). And even if i uncomment the test line in the fragment shader no blue rectangle is shown!</p>

<p>Does anyone see what im missing here?</p>

<p>Thanks in advance!</p>

<p>Martijn</p>