void
BasicCompositorImpl::render(SceneContext& sc, SceneGraph* sg, const GraphicContextState& gc_state)
{
  // Resize Lightmap, only needed in the editor, FIXME: move this into a 'set_size()' call
  if (m_lightmap->get_width()  != m_window.width /LIGHTMAP_DIV ||
      m_lightmap->get_height() != m_window.height/LIGHTMAP_DIV)
  {
    m_lightmap = Surface::create(m_window.width / LIGHTMAP_DIV, m_window.height / LIGHTMAP_DIV);
  }

  if (sc.get_render_mask() & SceneContext::LIGHTMAPSCREEN)
  {
    // Render the lightmap to the framebuffers->lightmap
    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    glScalef(1.0f / LIGHTMAP_DIV, 1.0f / LIGHTMAP_DIV, 1.0f);
    sc.light().render();
    glPopMatrix();

    if (sg)
    {
      glPushMatrix();
      glScalef(1.0f / LIGHTMAP_DIV, 1.0f / LIGHTMAP_DIV, 1.0f);
      glMultMatrixf(gc_state.get_matrix().matrix);
      sg->render(SceneContext::LIGHTMAP);
      glPopMatrix();
    }

    { // Copy lightmap to a texture
      OpenGLState state;
        
      state.bind_texture(m_lightmap->get_texture());
      state.activate();

      glCopyTexSubImage2D(GL_TEXTURE_2D, 
                          0,    // mipmap level
                          0, 0, // xoffset, yoffset
                          0, // x
                          m_window.height - static_cast<GLsizei>(m_lightmap->get_height()), // y (OpenGL is upside down)
                          static_cast<GLsizei>(m_lightmap->get_width()), 
                          static_cast<GLsizei>(m_lightmap->get_height()));
    }
  }

  if (sc.get_render_mask() & SceneContext::COLORMAP)
  {
    // Render the colormap to the framebuffers->screen
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    sc.color().render();

    if (sg)
    {
      glPushMatrix();
      glMultMatrixf(gc_state.get_matrix().matrix);
      sg->render(SceneContext::COLORMAP);
      glPopMatrix();
    }
  }

  if (sc.get_render_mask() & SceneContext::LIGHTMAP)
  { // Renders the lightmap to the screen     
    OpenGLState state;

    state.bind_texture(m_lightmap->get_texture());

    state.enable(GL_BLEND);
    state.set_blend_func(GL_DST_COLOR, GL_ZERO);
    state.activate();

    glBegin(GL_QUADS);

    glTexCoord2f(m_lightmap->get_uv().left, m_lightmap->get_uv().bottom);
    glVertex2i(0, 0);

    glTexCoord2f(m_lightmap->get_uv().right, m_lightmap->get_uv().bottom);
    glVertex2i(m_viewport.width, 0);

    glTexCoord2f(m_lightmap->get_uv().right, m_lightmap->get_uv().top);
    glVertex2i(m_viewport.width, m_viewport.height);

    glTexCoord2f(m_lightmap->get_uv().left, m_lightmap->get_uv().top);
    glVertex2i(0, m_viewport.height);

    glEnd();
  }

  if (sc.get_render_mask() & SceneContext::HIGHLIGHTMAP)
  {
    sc.highlight().render();

    if (sg)
    {
      glPushMatrix();
      glMultMatrixf(gc_state.get_matrix().matrix);
      sg->render(SceneContext::HIGHLIGHTMAP);
      glPopMatrix();
    }
  }

  if (sc.get_render_mask() & SceneContext::CONTROLMAP)
  {
    sc.control().render();

    if (sg)
    {
      glPushMatrix();
      glMultMatrixf(gc_state.get_matrix().matrix);
      sg->render(SceneContext::CONTROLMAP);
      glPopMatrix();
    }
  }
  
  // Clear all DrawingContexts
  sc.color().clear();
  sc.light().clear();
  sc.highlight().clear();
  sc.control().clear(); 
}
void
FramebufferCompositorImpl::render(SceneContext& sc, SceneGraph* sg, const GraphicContextState& gc_state)
{
  if (sc.get_render_mask() & SceneContext::LIGHTMAPSCREEN)
  {
    // Render the lightmap to framebuffers->lightmap
    Display::push_framebuffer(m_lightmap);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    glTranslatef(0.0f, static_cast<float>(m_viewport.height - (m_viewport.height / LIGHTMAP_DIV)), 0.0f);
    glScalef(1.0f / LIGHTMAP_DIV, 1.0f / LIGHTMAP_DIV, 1.0f / LIGHTMAP_DIV);

    sc.light().render();

    if (sg)
    {
      glPushMatrix();
      glMultMatrixf(gc_state.get_matrix().matrix);
      sg->render(SceneContext::LIGHTMAP);
      glPopMatrix();
    }

    glPopMatrix();
    
    Display::pop_framebuffer();
  }

  { // Render the main screen
    Display::push_framebuffer(m_screen);

    if (sc.get_render_mask() & SceneContext::COLORMAP)
    {
      // Render the colormap to framebuffers->screen
      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      sc.color().render();

      if (sg)
      {
        glPushMatrix();
        glMultMatrixf(gc_state.get_matrix().matrix);
        sg->render(SceneContext::COLORMAP);
        glPopMatrix();
      }
    }

    if (sc.get_render_mask() & SceneContext::LIGHTMAP)
    { // Renders the lightmap to the screen
      render_lightmap(sc, sg);
    }

    if (sc.get_render_mask() & SceneContext::HIGHLIGHTMAP)
    {
      sc.highlight().render();

      if (sg)
      {
        glPushMatrix();
        glMultMatrixf(gc_state.get_matrix().matrix);
        sg->render(SceneContext::HIGHLIGHTMAP);
        glPopMatrix();
      }
    }

    if (sc.get_render_mask() & SceneContext::CONTROLMAP)
    {
      sc.control().render();

      if (sg)
      {
        glPushMatrix();
        glMultMatrixf(gc_state.get_matrix().matrix);
        sg->render(SceneContext::CONTROLMAP);
        glPopMatrix();
      }
    }

    Display::pop_framebuffer();
  }

  if (1) 
  {
    // Render the screen framebuffer to the actual screen 
    OpenGLState state;

    state.bind_texture(m_screen->get_texture(), 0);

    state.activate();

    glBegin(GL_QUADS);
    {
      glTexCoord2i(0, 1);
      glVertex2i(0, 0);

      glTexCoord2i(1, 1);
      glVertex2i(m_viewport.width, 0);

      glTexCoord2i(1, 0);
      glVertex2i(m_viewport.width, m_viewport.height);

      glTexCoord2i(0, 0);
      glVertex2i(0.0f, m_viewport.height);
    }
    glEnd();
  }

  // Clear all DrawingContexts
  sc.color().clear();
  sc.light().clear();
  sc.highlight().clear();
  sc.control().clear();
}