void
FramebufferCompositorImpl::render_lightmap(SceneContext& /*sc*/, SceneGraph* /*sg*/)
{
  OpenGLState state;

  state.bind_texture(m_lightmap->get_texture());
      
  state.enable(GL_BLEND);
  state.set_blend_func(GL_DST_COLOR, GL_ZERO); // multiply the lightmap with the screen
  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, m_viewport.height);
  }
  glEnd();
}
  void draw_particles()
  {
    glPushMatrix();
    glMultMatrixf(get_modelview().matrix);
    
    OpenGLState state;
    
    state.bind_texture(surface->get_texture());
    state.set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    state.enable(GL_BLEND);
    state.activate();    

    glBegin(GL_QUADS);
    for(ParticleSystem::Particles::iterator i = psys.begin(); i != psys.end(); ++i)
    {
      if (i->t != -1.0f)
      {
        float p = 1.0f - psys.get_progress(i->t);
        Color color(psys.get_color_start().r * p + psys.get_color_stop().r * (1.0f - p),
                    psys.get_color_start().g * p + psys.get_color_stop().g * (1.0f - p),
                    psys.get_color_start().b * p + psys.get_color_stop().b * (1.0f - p),
                    psys.get_color_start().a * p + psys.get_color_stop().a * (1.0f - p));

        // scale
        float scale  = psys.get_size_start() + 
          psys.get_progress(i->t) * (psys.get_size_stop() - psys.get_size_start());
          
        float width  = surface->get_width()  * scale;
        float height = surface->get_height() * scale;
              
        // rotate
        float x_rot = width/2;
        float y_rot = height/2; 

        if (i->angle != 0)
        {
          float s = sinf(math::pi * i->angle/180.0f);
          float c = cosf(math::pi * i->angle/180.0f);
          x_rot = (width/2) * c - (height/2) * s;
          y_rot = (width/2) * s + (height/2) * c;
        }

        glColor4f(color.r, color.g, color.b, color.a);
        glTexCoord2f(0, 0);
        glVertex2f(i->x - x_rot, i->y - y_rot);
        glTexCoord2f(1, 0);
        glVertex2f(i->x + y_rot, i->y - x_rot);
        glTexCoord2f(1, 1);
        glVertex2f(i->x + x_rot, i->y + y_rot);
        glTexCoord2f(0, 1);
        glVertex2f(i->x - y_rot, i->y + x_rot);
      }
    }
    glEnd();

    glPopMatrix();
  }
void
VertexArrayDrawingRequest::draw(int start, int end)
{
  assert(!vertices.empty());
  assert(texcoords.empty() || int(texcoords.size()/2) == num_vertices());
  assert(colors.empty() || int(colors.size()/4) == num_vertices());

  OpenGLState state;

  glClear(GL_DEPTH_BUFFER_BIT);
  state.disable(GL_DEPTH_TEST);
  state.enable(GL_BLEND);
  state.set_blend_func(blend_sfactor, blend_dfactor);
  
  if (texture)
    {
      state.bind_texture(texture);
    }

  if (!colors.empty())
    {
      state.enable_client_state(GL_COLOR_ARRAY);
      glColorPointer(4, GL_UNSIGNED_BYTE, 0, &*colors.begin());
    }
  else
    {
      state.disable_client_state(GL_COLOR_ARRAY);
      state.color(Color(1.0f, 1.0f, 1.0f));
    }

  if (!texcoords.empty())
    {
      state.enable_client_state(GL_TEXTURE_COORD_ARRAY);
      glTexCoordPointer(2, GL_FLOAT, 0, &*texcoords.begin());
    }
  else
    {
      state.disable_client_state(GL_TEXTURE_COORD_ARRAY);
    }

  // FIXME: Might be worth to not use VertexArrays when we have a pretty small number of vertices
  state.disable_client_state(GL_NORMAL_ARRAY);
  state.enable_client_state(GL_VERTEX_ARRAY);

  glVertexPointer  (3, GL_FLOAT, 0, &*vertices.begin());

  state.activate();

  glPushMatrix();
  glMultMatrixf(modelview.matrix);

  glDrawArrays(mode, start, end);

  glPopMatrix();
}
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(); 
}