본문으로 바로가기

5장 연습문제 5.1

문제

배경의 클리어 색상을 수정해서 색상을 부드럽게 변경시켜보자.

  • 조건1: 검은색으로 시작해서 수초에 걸쳐 푸른색으로 부드럽게 변경시켜본다. 그런다음 다른 색상으로 수초에 걸쳐 부드럽게 변경한다.
  • 조건2: 부드러운 전이가 가능하도록 Game::Update에서 deltaTime을 사용하는 방법을고려하자.

풀이

배경색을 결정하는 함수는 Game::GenerateOutput()에 있는 glClearColor()함수이다. 여기서 초기화된 색상이 결정되고 glClear(GL_COLOR_BUFFER_BIT) 함수에서 결정된 색상으로 화면이 초기화 된다. 따라서 매 출력시 마다 glClearColor()에 다른 색상을 전달하면 아래와 같이 배경색이 변화는 모습을 볼 수 있다.

Exercise_5_1 전체 소스코드

구현 결과물

▲ 연습문제 5.1 시연 영상

1단계 추가 변수 선언

  • 배경색 조작을 쉽게 할 수 있도록 아래와 같이 RGBColor 구조체를 Game.h 에 선언하고, mBGColor 변수를 선언과함께 검은색으로 초기화 하였다.
typedef struct _RGBColor {
    float R;
    float G;
    float B;
}RGBColor;

// 배경색
RGBColor mBGColor = { 0.2f, 0.2f, 0.2f };
  • 이어서 색상 변화의 상태기계를 나타낼 BGColorState를 열거형으로 Game.h에 선언하고 toBlue로 초기화 하였다.
enum BGColorState
{
    toBlue, toGreen, toBlack
};
// 색상 변화 상태
BGColorState mBGColorState = toBlue;

2단계 색상 선택

  • Game::GenerateOutput()에 있는 glClearColor()의 매개변수를 다음과 같이 상수에서 변수로 변경한다.
void Game::GenerateOutput()
{
    // 색상을 회색으로 설정
    glClearColor(mBGColor.R, mBGColor.G, mBGColor.B, 1.0f);
    // 색상 버퍼 초기화
    glClear(GL_COLOR_BUFFER_BIT);
    // ... (이하 생략)...

3단계 Update()

  • 기존의 Game::UpdateGame()함수에 색상을 변하는 코드를 넣기에는 가독성이 떨어져서 별도의 함수 Game::UpdateBG(float deltaTime)을 다음과 같이 정의하였다.
void Game::UpdateBG(float deltaTime)
{
    // 색상의 변화율
    float transitionRate = deltaTime / 4;

    // toBlue 상태라면
    if (mBGColorState == toBlue) {
        mBGColor.B += (transitionRate);

        // 파랑색이 됐다면 toGreen 상태 변경
        if (mBGColor.B > 0.85f)
            mBGColorState = toGreen;
    }
    // toGreen 상태라면
    else if(mBGColorState == toGreen)
    {
        mBGColor.B -= (transitionRate);
        mBGColor.G += (transitionRate);

        // 초록색이 됐다면 toBlack 상태로 변경
        if (mBGColor.G > 0.85f)
            mBGColorState = toBlack;
    }
    // toBlack 상태라면
    else
    {
        mBGColor.G -= (transitionRate);
        // 검정색이 됐다면 색상 초기화 후 toBlue 상태로 변경
        if (mBGColor.G < 0.2f) {
            mBGColor = { 0.2f, 0.2f, 0.2f };
            mBGColorState = toBlue;
        }
    }
}
  • 마지막으로 Game::UpdateGame() 함수에서 엑터를 갱신하기 전에 UpdateBG(deltaTime)을 호출하면 완성.
void Game::UpdateGame()
{
  // 마지막 프레임 이후로 16ms가 경과할 때 까지 대기
  while (!SDL_TICKS_PASSED(SDL_GetTicks(), mTicksCount + 16))
      ;

  // ... (생략) ...

  //Game의 Update 함수 호출
  UpdateBG(deltaTime);

  // ... (생략) ...

 

2021.04.17 추가

교재에서 제공된 Math.h의 가장 아래(1021번째 줄)에 보면 다음과 같이 색상에 대한 코드가 이미 입력되어 있었습니다.

namespace Color
{
    static const Vector3 Black(0.0f, 0.0f, 0.0f);
    static const Vector3 White(1.0f, 1.0f, 1.0f);
    static const Vector3 Red(1.0f, 0.0f, 0.0f);
    static const Vector3 Green(0.0f, 1.0f, 0.0f);
    static const Vector3 Blue(0.0f, 0.0f, 1.0f);
    static const Vector3 Yellow(1.0f, 1.0f, 0.0f);
    static const Vector3 LightYellow(1.0f, 1.0f, 0.88f);
    static const Vector3 LightBlue(0.68f, 0.85f, 0.9f);
    static const Vector3 LightPink(1.0f, 0.71f, 0.76f);
    static const Vector3 LightGreen(0.56f, 0.93f, 0.56f);
}

이 과제를 할 당시에는 이부분을 알지 못해서 색상값을 직접 입력하는 방식으로 구현하였습니다. 또한 Math.h에 있는 코드처럼 BGColor를 따로 구조체로 선언할 필요없이 Vector3bgColor의 타입으로 그대로 사용하는 것이 더 간결한 코드가 될 것 같습니다. 그래서 제가 작성한 코드를 보다 더 간결하게 수정하기 위해서는 다음과 같은 방법을 고려할 수 있을 것이 좋을 것 같아서 추가합니다.

// 검은색으로 bgColor 초기화
Vector3 bgColor{ Color::Black };

// bgColor에 파랑색 대입
bgColor = Color::Blue;