[RT in One Weekend Series 2] Output an Image (번역)

목차: Series 1: Index and Overview (Link)
이전 글: Series 1: Index and Overview (Link)
다음 글: Series 3: The “vec3” Class (Link)

글을 작성(번역)하기 이전에 먼저 개발 환경에 대해서 정리하였다.

  • OS: macOS Mojave Version 10.14.4
  • G++: 4.2.1
  • Image Viewer: Mac Preview 10.1

C/C++ 등의 언어를 처음 배우면 가장 먼저 Hello World를 출력하는 코드를 작성한다. Ray Tracer을 개발하기 위해서는 이미지(결과물)를 출력하는 코드부터 작성할 계획이다. 보통 우리가 보는 이미지 파일 (.jpg 등)은 데이터(이미지) 압축을 한 결과물이다. 본 Ray Tracer의 결과물은 “Plain Text PPM (.ppm)” 으로 저장한다. Plain Text PPM은 Text 형태 포맷으로 된 이미지 파일이다. Editor에서 정해진 규칙에 따라 RGB 색상 값을 저장하면 결과 이미지를 확인할 수 있다.

PPM Format 규칙은 아래와 같다.

  • 첫 줄에 Color 값을 저장하는 Type을 설정함 (예: P3 [ASCII 형태])
  • 다음 줄에 Column, Row 사이즈를 설정함 (예: 3 2 [3 Columns * 2 Rows = 6 Pixels])
  • 다음 줄에 Max Color Value 값을 설정함 (예: 255 [R,G,B의 각 색상 Max 값은 255를 의미함])
  • 다음 줄부터는 각 Pixel의 RGB 값을 저장함. Pixel 값은 왼쪽부터 오른쪽, 위에서 부터 아래로 작성을 해야 함
    • 예를 들어서 3 * 2의 경우 제일 위 Row 제일 왼쪽 Column의 값부터 작성을 진행함

그림 1: 위키피디아 PPM Format 관련 그림 (출처 2)

그림 1은 위키피디아에 공개된 PPM 파일 Format 예제 코드와 그림이다 (출처 2).

그럼 이제 Hello World에 해당하는 코드를 한번 작성해보자. 작성하는 코드는 Pixel 값들을 조금씩 변경하여 제대로 된 결과물(PPM 파일)을 출력하는지 확인하기 위한 코드이다. Column 사이즈는 400, Row 사이즈는 200으로 설정한다. 공개된 노트에는 200 * 100으로 되어 있으나 조금 더 큰 이미지에서 결과를 확인하기 위해서 사이즈를 조절하였다. 사이즈를 4배 정도 늘려서 연산량도 대략 4배가 늘어날 것으로 추측한다. 그리고 왼쪽부터 오른쪽으로 R(Red) 값을 0부터 255로 순서대로 증가시킨다. 이와 더불어 위에서 아래 방향으로 G(Green) 값을 255부터 0 순서대로 감소시킨다. B(Blue)값은 0.2로 고정한다.

//MK: PPM 파일로 이미지 출력하는 예제 (출처 1)
#include <iostream>
#include <fstream>

using namespace std;

int main(){
    int nx = 400;
    int ny = 200;
    string fileName = "Ch1.ppm";
    ofstream writeFile(fileName.data());
    if(writeFile.is_open()){
        writeFile.flush();
        writeFile << "P3\n" << nx << " " << ny << "\n255\n";
        for(int j = ny - 1; j >= 0; j--){
            for(int i = 0; i < nx; i++){
                float r = float(i) / float(nx);
                float g = float(j) / float (ny);
                float b = 0.2;
                int ir = int(255.99 * r);
                int ig = int(255.99 * g);
                int ib = int(255.99 * b);
                writeFile << ir << " " << ig << " " << ib << "\n";
            }
        }
        writeFile.close();
    }
    return 0;
}

위 코드는 앞에서 설명한 내용을 C++로 작성한 것이다. 코드를 컴파일하여서 실행하면 그림 2와 같은 이미지가 생성된다.  만약 해당 결과물을 확인할 수 없다면 “\n”, ” ” 등과 같이 사소한 실수를 했을 가능성이 높다.

그림 2: 결과이미지

그림 2는 JPG 파일로 저장되어 있다. PPM 파일의 경우 워드프레스에서 지원하지 않아서 업로드 하지 못하였다.

출처

  1. http://www.realtimerendering.com/raytracing/Ray%20Tracing%20in%20a%20Weekend.pdf
  2. https://en.wikipedia.org/wiki/Netpbm_format

4 thoughts on “[RT in One Weekend Series 2] Output an Image (번역)”

  1. ppm파일만 생성되고 그림이 안뜨는데
    이유가 무엇일까요??
    혹시 몰라서 나와있는 코드를 그대로 복붙했는데도 똑같네요

    Reply
    • 안녕하세요.
      맥같은 경우 기본 이미지 뷰어가 PPM파일을 지원합니다.
      윈도우의 경우 PPM을 보기 위한 이미지 뷰어가 필요합니다.
      구글에서 PPM Viewer로 검색을 하시면 많은 뷰어를 찾으실 수 있습니다.
      이미지 뷰어중 FastStone Image Viewer은 PPM 파일을 지원하는 것으로 알고 있습니다.
      글 읽어주셔서 감사합니다.

      Reply
      • 아 그러면 혹시 ppm 폼 말고 이미지나 애니메이션형태로 출력하려면 어떻게 해야하나요??

        Reply
        • 안냥하세요. 매번 답변이 조금씩 늦네요 ㅠㅠ
          PPM도 이미지 파일 중 하나로 알고 있습니다. 일반적으로 사용하는 JPG 파일등은 이미지 압축이 된 형태라 단순히 파일에 출력하는 방식으로 이미지를 출력할 수 있는지 잘 모르겠습니다. 제가 올려놓은 JPG 이미지 파일은 PPM 파일을 JPG 형태로 변환한 결과입니다. 그리고 애니메이션 파일 형태는 잘 모르겠습니다. 혹시 다른 형태로 출력이 가능한지 확인해보고 방법이 있으면 추가로 답변을 정리하도록 하겠습니다.
          감사합니다.

          Reply

Leave a Reply to RT Cancel reply