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 prepare(TexturePtr screen_texture) 
  {
    OpenGLState state;
    state.bind_texture(screen_texture);
    state.activate();

    glBegin(GL_QUADS);
    glTexCoord2f(0,600);
    glVertex2f(0,0);

    glTexCoord2f(800,600);
    glVertex2f(800,0);

    glTexCoord2f(800, 0);
    glVertex2f(800, 600);

    glTexCoord2f(0, 0);
    glVertex2f(0,600);
    glEnd();
  }
  void render(unsigned int mask)
  {
#if 0
    Display::push_framebuffer(framebuffer);
    glClear(GL_COLOR_BUFFER_BIT);
    draw_particles();
    Display::pop_framebuffer();

    if (1) {
      OpenGLState state;

      glUseProgram(shader_program.get_handle());    
      shader_program.set_uniform1i("screen",      0);
      shader_program.set_uniform1i("particles",   1);
            
      state.bind_texture(tmp_texture, 0);
      state.bind_texture(framebuffer.get_texture(), 1);
      state.color(Color(1.0f, 1.0f, 1.0f, 1.0f));
      state.activate();

      glBegin(GL_QUADS);
      glTexCoord2f(0,0);
      glVertex2f(0,0);

      glTexCoord2f(800,0);
      glVertex2f(800,0);

      glTexCoord2f(800,600);
      glVertex2f(800, 600);

      glTexCoord2f(0, 600);
      glVertex2f(0,600);
      glEnd();

      glUseProgram(0);
    }
#endif
  }
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();
}