Войти
Подсказки

Плавный переход от цветного изображения к черно-белому.

Автор:

Часто бывает нужно заменить отрендереное на экран цветное изображение на черно-белое (например, при установке игровой паузы). Мой способ выглядит так:

// m_iWidth & m_iHeight - текущее разрешение экрана
#define m_iWidth 640
#define m_iHeight 480

// нам потребуются 2 буффера:
m_pFrame = new ubyte [m_iWidth*m_iHeight*3];
m_pBuffer = new ubyte [m_iWidth*m_iHeight*3];

void ReplaceBW (float fValue)
{  
  if (!fValue || !m_pFrame || !m_pBuffer) // если fValue == 0, значит изображение полностью цветное
    return;
  
  glDisable(GL_TEXTURE_2D);

  if (fValue <= 1.0f)
  {
    // 1. get image from screen
    glFlush();
    glFinish();
    glReadPixels (0, 0, m_iWidth, m_iHeight, GL_RGB, GL_UNSIGNED_BYTE, m_pFrame);
  
    // 2. convert to bw
    int j = 0, k = int(fValue*255.0f), s = 0, r, g, b;
    for (int i=0; i<m_iWidth*m_iHeight; i++)
    {
      r = m_pFrame[j];
      g = m_pFrame[j+1];
      b = m_pFrame[j+2];
      s = (r + 2*g + b)*k >> 2; // "реальное" соотношение 0.3*r + 0.59*g + 0.11*b, зато это намного быстрее
      m_pBuffer[j+0] = (r*(255-k) + s) >> 8;
      m_pBuffer[j+1] = (g*(255-k) + s) >> 8;
      m_pBuffer[j+2] = (b*(255-k) + s) >> 8;
      j += 3;
    }
  }

  // 3. draw to frame buffer
  glRasterPos2i(-m_iWidth/2, -m_iHeight/2);
  glDrawPixels(m_iWidth, m_iHeight, GL_RGB, GL_UNSIGNED_BYTE, m_pBuffer);
}

Обратите внимание на условие

if (fValue <= 1.0f)

Оно нам нужно вот для чего:
Например у нас в программе есть обработчик паузы:

void OnPause(void)
{
  GamePause = 1.0f;
  m_fPauseAlpha = 0.0f;
}

Тогда отрисовка игры может выглядеть так:

    if (GamePause.Float())
    {
      if (m_fPauseAlpha < 1.0f)
        m_world->Draw (m_dGameTime);
      ReplaceBW(m_fPauseAlpha);
      m_fPauseAlpha += m_dTime;
    }
    else
      m_world->Draw (m_dGameTime);

т.е. Пока изображение не стало "окончательно черно-белым"  мы перерисовываем игру, постепенно делая изображение все более черно-белым, как только оно становится "окончательно черно-белым" игровой мир больше не перерисовывается, а его изображение берется из m_pBuffer (вот поэтому нам и нужны были 2 буффера).

Конечно описанный метод не являеться самым быстрым, в разных ситуациях возможны другие решения, зато он универсален, работает на любом железе.

1 марта 2004